Added an unknown VxD error code.
[wine] / scheduler / syslevel.c
1 /*
2  * Win32 'syslevel' routines
3  *
4  * Copyright 1998 Ulrich Weigand
5  */
6
7 #include <unistd.h>
8 #include <sys/types.h>
9 #include "ntddk.h"
10 #include "syslevel.h"
11 #include "heap.h"
12 #include "stackframe.h"
13 #include "debugtools.h"
14
15 DEFAULT_DEBUG_CHANNEL(win32);
16
17 static SYSLEVEL Win16Mutex = { CRITICAL_SECTION_INIT, 1 };
18
19 /* Global variable to save current TEB while in 16-bit code */
20 WORD SYSLEVEL_Win16CurrentTeb = 0;
21
22
23 /************************************************************************
24  *           GetpWin16Lock    (KERNEL32.93)
25  */
26 VOID WINAPI GetpWin16Lock(SYSLEVEL **lock)
27 {
28     *lock = &Win16Mutex;
29 }
30
31 /************************************************************************
32  *           GetpWin16Lock    (KERNEL.449)
33  */
34 SEGPTR WINAPI GetpWin16Lock16(void)
35 {
36     static SEGPTR segpWin16Mutex;
37     if (!segpWin16Mutex)
38     {
39         SYSLEVEL **w16Mutex = SEGPTR_ALLOC(sizeof(SYSLEVEL *));
40         *w16Mutex = &Win16Mutex;
41         segpWin16Mutex = SEGPTR_GET(w16Mutex);
42     }
43     return segpWin16Mutex;
44 }
45
46 /************************************************************************
47  *           _CreateSysLevel    (KERNEL.438)
48  */
49 VOID WINAPI _CreateSysLevel(SYSLEVEL *lock, INT level)
50 {
51     InitializeCriticalSection( &lock->crst );
52     lock->level = level;
53
54     TRACE("(%p, %d): handle is %d\n", 
55                   lock, level, lock->crst.LockSemaphore );
56 }
57
58 /************************************************************************
59  *           _EnterSysLevel    (KERNEL32.97) (KERNEL.439)
60  */
61 VOID WINAPI _EnterSysLevel(SYSLEVEL *lock)
62 {
63     TEB *teb = NtCurrentTeb();
64     int i;
65
66     TRACE("(%p, level %d): thread %p (fs %04x, pid %ld) count before %ld\n", 
67                   lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
68                   teb->sys_count[lock->level] );
69
70     for ( i = 3; i > lock->level; i-- )
71         if ( teb->sys_count[i] > 0 )
72         {
73             ERR("(%p, level %d): Holding %p, level %d. Expect deadlock!\n", 
74                         lock, lock->level, teb->sys_mutex[i], i );
75         }
76
77     EnterCriticalSection( &lock->crst );
78
79     teb->sys_count[lock->level]++;
80     teb->sys_mutex[lock->level] = lock;
81
82     TRACE("(%p, level %d): thread %p (fs %04x, pid %ld) count after  %ld\n",
83                   lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(), 
84                   teb->sys_count[lock->level] );
85
86     if (lock == &Win16Mutex)
87         SYSLEVEL_Win16CurrentTeb = __get_fs();
88 }
89
90 /************************************************************************
91  *           _LeaveSysLevel    (KERNEL32.98) (KERNEL.440)
92  */
93 VOID WINAPI _LeaveSysLevel(SYSLEVEL *lock)
94 {
95     TEB *teb = NtCurrentTeb();
96
97     TRACE("(%p, level %d): thread %p (fs %04x, pid %ld) count before %ld\n", 
98                   lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
99                   teb->sys_count[lock->level] );
100
101     if ( teb->sys_count[lock->level] <= 0 || teb->sys_mutex[lock->level] != lock )
102     {
103         ERR("(%p, level %d): Invalid state: count %ld mutex %p.\n",
104                     lock, lock->level, teb->sys_count[lock->level], 
105                     teb->sys_mutex[lock->level] );
106     }
107     else
108     {
109         if ( --teb->sys_count[lock->level] == 0 )
110             teb->sys_mutex[lock->level] = NULL;
111     }
112
113     LeaveCriticalSection( &lock->crst );
114
115     TRACE("(%p, level %d): thread %p (fs %04x, pid %ld) count after  %ld\n",
116                   lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(), 
117                   teb->sys_count[lock->level] );
118 }
119
120 /************************************************************************
121  *              _KERNEL32_86 (KERNEL32.86)
122  */
123 VOID WINAPI _KERNEL32_86(SYSLEVEL *lock)
124 {
125     _LeaveSysLevel(lock);
126 }
127
128 /************************************************************************
129  *           _ConfirmSysLevel    (KERNEL32.95) (KERNEL.436)
130  */
131 DWORD WINAPI _ConfirmSysLevel(SYSLEVEL *lock)
132 {
133     if ( lock && lock->crst.OwningThread == GetCurrentThreadId() )
134         return lock->crst.RecursionCount;
135     else
136         return 0L;
137 }
138
139 /************************************************************************
140  *           _CheckNotSysLevel    (KERNEL32.94) (KERNEL.437)
141  */
142 VOID WINAPI _CheckNotSysLevel(SYSLEVEL *lock)
143 {
144     FIXME("(%p)\n", lock);
145 }
146
147
148 /************************************************************************
149  *           _EnterWin16Lock                    [KERNEL.480]
150  */
151 VOID WINAPI _EnterWin16Lock(void)
152 {
153     _EnterSysLevel(&Win16Mutex);
154 }
155
156 /************************************************************************
157  *           _LeaveWin16Lock            [KERNEL.481]
158  */
159 VOID WINAPI _LeaveWin16Lock(void)
160 {
161     _LeaveSysLevel(&Win16Mutex);
162 }
163
164 /************************************************************************
165  *           _ConfirmWin16Lock    (KERNEL32.96)
166  */
167 DWORD WINAPI _ConfirmWin16Lock(void)
168 {
169     return _ConfirmSysLevel(&Win16Mutex);
170 }
171
172 /************************************************************************
173  *           ReleaseThunkLock    (KERNEL32.48)
174  */
175 VOID WINAPI ReleaseThunkLock(DWORD *mutex_count)
176 {
177     DWORD count = _ConfirmSysLevel(&Win16Mutex);
178     *mutex_count = count;
179
180     while (count-- > 0)
181         _LeaveSysLevel(&Win16Mutex);
182 }
183
184 /************************************************************************
185  *           RestoreThunkLock    (KERNEL32.49)
186  */
187 VOID WINAPI RestoreThunkLock(DWORD mutex_count)
188 {
189     while (mutex_count-- > 0)
190         _EnterSysLevel(&Win16Mutex);
191 }
192
193 /************************************************************************
194  *           SYSLEVEL_CheckNotLevel
195  */
196 VOID SYSLEVEL_CheckNotLevel( INT level )
197 {
198     INT i;
199
200     for ( i = 3; i >= level; i-- )
201         if ( NtCurrentTeb()->sys_count[i] > 0 )
202         {
203             ERR("(%d): Holding lock of level %d!\n", 
204                        level, i );
205             DbgBreakPoint();
206             break;
207         }
208 }