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 = { CRITICAL_SECTION_INIT, 1 };
20 /* Global variable to save current TEB while in 16-bit code */
21 WORD SYSLEVEL_Win16CurrentTeb = 0;
24 /************************************************************************
25 * GetpWin16Lock (KERNEL32.93)
27 VOID WINAPI GetpWin16Lock(SYSLEVEL **lock)
32 /************************************************************************
33 * GetpWin16Lock16 (KERNEL.449)
35 SEGPTR WINAPI GetpWin16Lock16(void)
37 static SEGPTR segpWin16Mutex;
40 SYSLEVEL **w16Mutex = SEGPTR_ALLOC(sizeof(SYSLEVEL *));
41 *w16Mutex = &Win16Mutex;
42 segpWin16Mutex = SEGPTR_GET(w16Mutex);
44 return segpWin16Mutex;
47 /************************************************************************
48 * _CreateSysLevel (KERNEL.438)
50 VOID WINAPI _CreateSysLevel(SYSLEVEL *lock, INT level)
52 InitializeCriticalSection( &lock->crst );
55 TRACE("(%p, %d): handle is %d\n",
56 lock, level, lock->crst.LockSemaphore );
59 /************************************************************************
60 * _EnterSysLevel (KERNEL32.97) (KERNEL.439)
62 VOID WINAPI _EnterSysLevel(SYSLEVEL *lock)
64 TEB *teb = NtCurrentTeb();
67 TRACE("(%p, level %d): thread %p (fs %04x, pid %ld) count before %ld\n",
68 lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
69 teb->sys_count[lock->level] );
71 for ( i = 3; i > lock->level; i-- )
72 if ( teb->sys_count[i] > 0 )
74 ERR("(%p, level %d): Holding %p, level %d. Expect deadlock!\n",
75 lock, lock->level, teb->sys_mutex[i], i );
78 EnterCriticalSection( &lock->crst );
80 teb->sys_count[lock->level]++;
81 teb->sys_mutex[lock->level] = lock;
83 TRACE("(%p, level %d): thread %p (fs %04x, pid %ld) count after %ld\n",
84 lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
85 teb->sys_count[lock->level] );
87 if (lock == &Win16Mutex)
88 SYSLEVEL_Win16CurrentTeb = __get_fs();
91 /************************************************************************
92 * _LeaveSysLevel (KERNEL32.98) (KERNEL.440)
94 VOID WINAPI _LeaveSysLevel(SYSLEVEL *lock)
96 TEB *teb = NtCurrentTeb();
98 TRACE("(%p, level %d): thread %p (fs %04x, pid %ld) count before %ld\n",
99 lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
100 teb->sys_count[lock->level] );
102 if ( teb->sys_count[lock->level] <= 0 || teb->sys_mutex[lock->level] != lock )
104 ERR("(%p, level %d): Invalid state: count %ld mutex %p.\n",
105 lock, lock->level, teb->sys_count[lock->level],
106 teb->sys_mutex[lock->level] );
110 if ( --teb->sys_count[lock->level] == 0 )
111 teb->sys_mutex[lock->level] = NULL;
114 LeaveCriticalSection( &lock->crst );
116 TRACE("(%p, level %d): thread %p (fs %04x, pid %ld) count after %ld\n",
117 lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
118 teb->sys_count[lock->level] );
121 /************************************************************************
122 * _KERNEL32_86 (KERNEL32.86)
124 VOID WINAPI _KERNEL32_86(SYSLEVEL *lock)
126 _LeaveSysLevel(lock);
129 /************************************************************************
130 * _ConfirmSysLevel (KERNEL32.95) (KERNEL.436)
132 DWORD WINAPI _ConfirmSysLevel(SYSLEVEL *lock)
134 if ( lock && lock->crst.OwningThread == GetCurrentThreadId() )
135 return lock->crst.RecursionCount;
140 /************************************************************************
141 * _CheckNotSysLevel (KERNEL32.94) (KERNEL.437)
143 VOID WINAPI _CheckNotSysLevel(SYSLEVEL *lock)
145 FIXME("(%p)\n", lock);
149 /************************************************************************
150 * _EnterWin16Lock [KERNEL.480]
152 VOID WINAPI _EnterWin16Lock(void)
154 _EnterSysLevel(&Win16Mutex);
157 /************************************************************************
158 * _LeaveWin16Lock [KERNEL.481]
160 VOID WINAPI _LeaveWin16Lock(void)
162 _LeaveSysLevel(&Win16Mutex);
165 /************************************************************************
166 * _ConfirmWin16Lock (KERNEL32.96)
168 DWORD WINAPI _ConfirmWin16Lock(void)
170 return _ConfirmSysLevel(&Win16Mutex);
173 /************************************************************************
174 * ReleaseThunkLock (KERNEL32.48)
176 VOID WINAPI ReleaseThunkLock(DWORD *mutex_count)
178 DWORD count = _ConfirmSysLevel(&Win16Mutex);
179 *mutex_count = count;
182 _LeaveSysLevel(&Win16Mutex);
185 /************************************************************************
186 * RestoreThunkLock (KERNEL32.49)
188 VOID WINAPI RestoreThunkLock(DWORD mutex_count)
190 while (mutex_count-- > 0)
191 _EnterSysLevel(&Win16Mutex);
194 /************************************************************************
195 * SYSLEVEL_CheckNotLevel
197 VOID SYSLEVEL_CheckNotLevel( INT level )
201 for ( i = 3; i >= level; i-- )
202 if ( NtCurrentTeb()->sys_count[i] > 0 )
204 ERR("(%d): Holding lock of level %d!\n",