2 * Win32 'syslevel' routines
4 * Copyright 1998 Ulrich Weigand
12 #include "selectors.h"
13 #include "stackframe.h"
14 #include "debugtools.h"
16 DEFAULT_DEBUG_CHANNEL(win32);
18 static SYSLEVEL Win16Mutex;
19 static SEGPTR segpWin16Mutex;
21 /* Global variable to save current TEB while in 16-bit code */
22 WORD SYSLEVEL_Win16CurrentTeb = 0;
24 /* TEB of initial process for emergency use */
25 WORD SYSLEVEL_EmergencyTeb = 0;
28 /************************************************************************
31 void SYSLEVEL_Init(void)
33 SYSLEVEL **w16Mutex = SEGPTR_ALLOC(sizeof(SYSLEVEL *));
35 *w16Mutex = &Win16Mutex;
36 segpWin16Mutex = SEGPTR_GET(w16Mutex);
38 _CreateSysLevel( &Win16Mutex, 1 );
41 /************************************************************************
42 * GetpWin16Lock (KERNEL32.93)
44 VOID WINAPI GetpWin16Lock(SYSLEVEL **lock)
49 /************************************************************************
50 * GetpWin16Lock16 (KERNEL.449)
52 SEGPTR WINAPI GetpWin16Lock16(void)
54 return segpWin16Mutex;
57 /************************************************************************
58 * _CreateSysLevel (KERNEL.438)
60 VOID WINAPI _CreateSysLevel(SYSLEVEL *lock, INT level)
62 InitializeCriticalSection( &lock->crst );
65 TRACE("(%p, %d): handle is %d\n",
66 lock, level, lock->crst.LockSemaphore );
69 /************************************************************************
70 * _EnterSysLevel (KERNEL32.97) (KERNEL.439)
72 VOID WINAPI _EnterSysLevel(SYSLEVEL *lock)
74 TEB *teb = NtCurrentTeb();
77 TRACE("(%p, level %d): thread %p (fs %04x, pid %ld) count before %ld\n",
78 lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
79 teb->sys_count[lock->level] );
81 for ( i = 3; i > lock->level; i-- )
82 if ( teb->sys_count[i] > 0 )
84 ERR("(%p, level %d): Holding %p, level %d. Expect deadlock!\n",
85 lock, lock->level, teb->sys_mutex[i], i );
88 EnterCriticalSection( &lock->crst );
90 teb->sys_count[lock->level]++;
91 teb->sys_mutex[lock->level] = lock;
93 TRACE("(%p, level %d): thread %p (fs %04x, pid %ld) count after %ld\n",
94 lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
95 teb->sys_count[lock->level] );
97 if (lock == &Win16Mutex)
98 SYSLEVEL_Win16CurrentTeb = __get_fs();
101 /************************************************************************
102 * _LeaveSysLevel (KERNEL32.98) (KERNEL.440)
104 VOID WINAPI _LeaveSysLevel(SYSLEVEL *lock)
106 TEB *teb = NtCurrentTeb();
108 TRACE("(%p, level %d): thread %p (fs %04x, pid %ld) count before %ld\n",
109 lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
110 teb->sys_count[lock->level] );
112 if ( teb->sys_count[lock->level] <= 0 || teb->sys_mutex[lock->level] != lock )
114 ERR("(%p, level %d): Invalid state: count %ld mutex %p.\n",
115 lock, lock->level, teb->sys_count[lock->level],
116 teb->sys_mutex[lock->level] );
120 if ( --teb->sys_count[lock->level] == 0 )
121 teb->sys_mutex[lock->level] = NULL;
124 LeaveCriticalSection( &lock->crst );
126 TRACE("(%p, level %d): thread %p (fs %04x, pid %ld) count after %ld\n",
127 lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
128 teb->sys_count[lock->level] );
131 /************************************************************************
132 * _KERNEL32_86 (KERNEL32.86)
134 VOID WINAPI _KERNEL32_86(SYSLEVEL *lock)
136 _LeaveSysLevel(lock);
139 /************************************************************************
140 * _ConfirmSysLevel (KERNEL32.95) (KERNEL.436)
142 DWORD WINAPI _ConfirmSysLevel(SYSLEVEL *lock)
144 if ( lock && lock->crst.OwningThread == GetCurrentThreadId() )
145 return lock->crst.RecursionCount;
150 /************************************************************************
151 * _CheckNotSysLevel (KERNEL32.94) (KERNEL.437)
153 VOID WINAPI _CheckNotSysLevel(SYSLEVEL *lock)
155 FIXME("(%p)\n", lock);
159 /************************************************************************
160 * SYSLEVEL_EnterWin16Lock [KERNEL.480]
162 VOID WINAPI SYSLEVEL_EnterWin16Lock(VOID)
164 _EnterSysLevel(&Win16Mutex);
167 /************************************************************************
168 * SYSLEVEL_LeaveWin16Lock [KERNEL.481]
170 VOID WINAPI SYSLEVEL_LeaveWin16Lock(VOID)
172 _LeaveSysLevel(&Win16Mutex);
174 /************************************************************************
175 * _ConfirmWin16Lock (KERNEL32.96)
177 DWORD WINAPI _ConfirmWin16Lock(void)
179 return _ConfirmSysLevel(&Win16Mutex);
182 /************************************************************************
183 * ReleaseThunkLock (KERNEL32.48)
185 VOID WINAPI ReleaseThunkLock(DWORD *mutex_count)
187 DWORD count = _ConfirmSysLevel(&Win16Mutex);
188 *mutex_count = count;
191 _LeaveSysLevel(&Win16Mutex);
194 /************************************************************************
195 * RestoreThunkLock (KERNEL32.49)
197 VOID WINAPI RestoreThunkLock(DWORD mutex_count)
199 while (mutex_count-- > 0)
200 _EnterSysLevel(&Win16Mutex);
203 /************************************************************************
204 * SYSLEVEL_ReleaseWin16Lock
206 VOID SYSLEVEL_ReleaseWin16Lock(VOID)
208 /* entry_point is never used again once the entry point has
209 been called. Thus we re-use it to hold the Win16Lock count */
211 ReleaseThunkLock(&CURRENT_STACK16->entry_point);
214 /************************************************************************
215 * SYSLEVEL_RestoreWin16Lock
217 VOID SYSLEVEL_RestoreWin16Lock(VOID)
219 RestoreThunkLock(CURRENT_STACK16->entry_point);
222 /************************************************************************
223 * SYSLEVEL_CheckNotLevel
225 VOID SYSLEVEL_CheckNotLevel( INT level )
229 for ( i = 3; i >= level; i-- )
230 if ( NtCurrentTeb()->sys_count[i] > 0 )
232 ERR("(%d): Holding lock of level %d!\n",