blob: aeb3692c7340dabd626ef13ab7d245060ac264a5 [file] [log] [blame]
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001/*
2 * Win32 'syslevel' routines
3 *
4 * Copyright 1998 Ulrich Weigand
5 */
6
7#include <unistd.h>
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +00008#include <sys/types.h>
Alexandre Julliard767e6f61998-08-09 12:47:43 +00009#include "syslevel.h"
10#include "heap.h"
11#include "stackframe.h"
Alexandre Julliard15657091999-05-23 10:25:25 +000012#include "debugtools.h"
Alexandre Julliard767e6f61998-08-09 12:47:43 +000013
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000014DEFAULT_DEBUG_CHANNEL(win32)
15
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000016static SYSLEVEL Win16Mutex;
Alexandre Julliard767e6f61998-08-09 12:47:43 +000017static SEGPTR segpWin16Mutex;
18
Alexandre Julliard85ed45e1998-08-22 19:03:56 +000019/* Global variable to save current TEB while in 16-bit code */
20WORD SYSLEVEL_Win16CurrentTeb = 0;
21
Ulrich Weigand2e30f6f1998-10-11 18:59:11 +000022/* TEB of initial process for emergency use */
23WORD SYSLEVEL_EmergencyTeb = 0;
24
Alexandre Julliard767e6f61998-08-09 12:47:43 +000025
26/************************************************************************
27 * SYSLEVEL_Init
28 */
29void SYSLEVEL_Init(void)
30{
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000031 SYSLEVEL **w16Mutex = SEGPTR_ALLOC(sizeof(SYSLEVEL *));
Alexandre Julliard767e6f61998-08-09 12:47:43 +000032
33 *w16Mutex = &Win16Mutex;
34 segpWin16Mutex = SEGPTR_GET(w16Mutex);
35
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000036 _CreateSysLevel( &Win16Mutex, 1 );
Alexandre Julliard767e6f61998-08-09 12:47:43 +000037}
38
39/************************************************************************
40 * GetpWin16Lock32 (KERNEL32.93)
41 */
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000042VOID WINAPI GetpWin16Lock(SYSLEVEL **lock)
Alexandre Julliard767e6f61998-08-09 12:47:43 +000043{
44 *lock = &Win16Mutex;
45}
46
47/************************************************************************
48 * GetpWin16Lock16 (KERNEL.449)
49 */
50SEGPTR WINAPI GetpWin16Lock16(void)
51{
52 return segpWin16Mutex;
53}
54
55/************************************************************************
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000056 * _CreateSysLevel (KERNEL.438)
Alexandre Julliard767e6f61998-08-09 12:47:43 +000057 */
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000058VOID WINAPI _CreateSysLevel(SYSLEVEL *lock, INT level)
Alexandre Julliard767e6f61998-08-09 12:47:43 +000059{
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000060 InitializeCriticalSection( &lock->crst );
61 MakeCriticalSectionGlobal( &lock->crst );
62 lock->level = level;
63
Alexandre Julliard15657091999-05-23 10:25:25 +000064 TRACE("(%p, %d): handle is %d\n",
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000065 lock, level, lock->crst.LockSemaphore );
66}
67
68/************************************************************************
69 * _EnterSysLevel (KERNEL32.97) (KERNEL.439)
70 */
71VOID WINAPI _EnterSysLevel(SYSLEVEL *lock)
72{
Alexandre Julliard0a860a01999-06-22 11:43:42 +000073 TEB *teb = NtCurrentTeb();
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000074 int i;
75
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +000076 TRACE("(%p, level %d): thread %p (fs %04x, pid %ld) count before %ld\n",
77 lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
Alexandre Julliard0a860a01999-06-22 11:43:42 +000078 teb->sys_count[lock->level] );
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000079
80 for ( i = 3; i > lock->level; i-- )
Alexandre Julliard0a860a01999-06-22 11:43:42 +000081 if ( teb->sys_count[i] > 0 )
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000082 {
Alexandre Julliard15657091999-05-23 10:25:25 +000083 ERR("(%p, level %d): Holding %p, level %d. Expect deadlock!\n",
Alexandre Julliard0a860a01999-06-22 11:43:42 +000084 lock, lock->level, teb->sys_mutex[i], i );
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000085 }
86
87 EnterCriticalSection( &lock->crst );
88
Alexandre Julliard0a860a01999-06-22 11:43:42 +000089 teb->sys_count[lock->level]++;
90 teb->sys_mutex[lock->level] = lock;
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000091
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +000092 TRACE("(%p, level %d): thread %p (fs %04x, pid %ld) count after %ld\n",
93 lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
Alexandre Julliard0a860a01999-06-22 11:43:42 +000094 teb->sys_count[lock->level] );
Alexandre Julliard85ed45e1998-08-22 19:03:56 +000095
96 if (lock == &Win16Mutex)
97 GET_FS( SYSLEVEL_Win16CurrentTeb );
Alexandre Julliard767e6f61998-08-09 12:47:43 +000098}
99
100/************************************************************************
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000101 * _LeaveSysLevel (KERNEL32.98) (KERNEL.440)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000102 */
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000103VOID WINAPI _LeaveSysLevel(SYSLEVEL *lock)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000104{
Alexandre Julliard0a860a01999-06-22 11:43:42 +0000105 TEB *teb = NtCurrentTeb();
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000106
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +0000107 TRACE("(%p, level %d): thread %p (fs %04x, pid %ld) count before %ld\n",
108 lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
Alexandre Julliard0a860a01999-06-22 11:43:42 +0000109 teb->sys_count[lock->level] );
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000110
Alexandre Julliard0a860a01999-06-22 11:43:42 +0000111 if ( teb->sys_count[lock->level] <= 0 || teb->sys_mutex[lock->level] != lock )
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000112 {
Alexandre Julliard15657091999-05-23 10:25:25 +0000113 ERR("(%p, level %d): Invalid state: count %ld mutex %p.\n",
Alexandre Julliard0a860a01999-06-22 11:43:42 +0000114 lock, lock->level, teb->sys_count[lock->level],
115 teb->sys_mutex[lock->level] );
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000116 }
117 else
118 {
Alexandre Julliard0a860a01999-06-22 11:43:42 +0000119 if ( --teb->sys_count[lock->level] == 0 )
120 teb->sys_mutex[lock->level] = NULL;
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000121 }
122
123 LeaveCriticalSection( &lock->crst );
124
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +0000125 TRACE("(%p, level %d): thread %p (fs %04x, pid %ld) count after %ld\n",
126 lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
Alexandre Julliard0a860a01999-06-22 11:43:42 +0000127 teb->sys_count[lock->level] );
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000128}
129
130/************************************************************************
131 * (KERNEL32.86)
132 */
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000133VOID WINAPI _KERNEL32_86(SYSLEVEL *lock)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000134{
135 _LeaveSysLevel(lock);
136}
137
138/************************************************************************
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000139 * _ConfirmSysLevel (KERNEL32.95) (KERNEL.436)
140 */
141DWORD WINAPI _ConfirmSysLevel(SYSLEVEL *lock)
142{
143 if ( lock && lock->crst.OwningThread == GetCurrentThreadId() )
144 return lock->crst.RecursionCount;
145 else
146 return 0L;
147}
148
149/************************************************************************
150 * _CheckNotSysLevel (KERNEL32.94) (KERNEL.437)
151 */
152VOID WINAPI _CheckNotSysLevel(SYSLEVEL *lock)
153{
Alexandre Julliard15657091999-05-23 10:25:25 +0000154 FIXME("(%p)\n", lock);
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000155}
156
157
158/************************************************************************
Marcus Meissnera763ed91998-10-22 17:02:25 +0000159 * SYSLEVEL_EnterWin16Lock [KERNEL.480]
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000160 */
Andreas Mohrc21650e1998-10-11 17:37:53 +0000161VOID WINAPI SYSLEVEL_EnterWin16Lock(VOID)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000162{
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000163 _EnterSysLevel(&Win16Mutex);
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000164}
165
166/************************************************************************
Marcus Meissnera763ed91998-10-22 17:02:25 +0000167 * SYSLEVEL_LeaveWin16Lock [KERNEL.481]
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000168 */
Andreas Mohrc21650e1998-10-11 17:37:53 +0000169VOID WINAPI SYSLEVEL_LeaveWin16Lock(VOID)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000170{
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000171 _LeaveSysLevel(&Win16Mutex);
172}
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000173/************************************************************************
174 * _ConfirmWin16Lock (KERNEL32.96)
175 */
176DWORD WINAPI _ConfirmWin16Lock(void)
177{
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000178 return _ConfirmSysLevel(&Win16Mutex);
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000179}
180
181/************************************************************************
182 * ReleaseThunkLock (KERNEL32.48)
183 */
184VOID WINAPI ReleaseThunkLock(DWORD *mutex_count)
185{
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000186 DWORD count = _ConfirmSysLevel(&Win16Mutex);
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000187 *mutex_count = count;
188
189 while (count-- > 0)
190 _LeaveSysLevel(&Win16Mutex);
191}
192
193/************************************************************************
194 * RestoreThunkLock (KERNEL32.49)
195 */
196VOID WINAPI RestoreThunkLock(DWORD mutex_count)
197{
198 while (mutex_count-- > 0)
199 _EnterSysLevel(&Win16Mutex);
200}
201
202/************************************************************************
203 * SYSLEVEL_ReleaseWin16Lock
204 */
205VOID SYSLEVEL_ReleaseWin16Lock(VOID)
206{
Ulrich Weigand3dff7bb1999-07-11 13:58:31 +0000207 /* entry_point is never used again once the entry point has
208 been called. Thus we re-use it to hold the Win16Lock count */
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000209
Ulrich Weigand3dff7bb1999-07-11 13:58:31 +0000210 ReleaseThunkLock(&CURRENT_STACK16->entry_point);
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000211}
212
213/************************************************************************
214 * SYSLEVEL_RestoreWin16Lock
215 */
216VOID SYSLEVEL_RestoreWin16Lock(VOID)
217{
Ulrich Weigand3dff7bb1999-07-11 13:58:31 +0000218 RestoreThunkLock(CURRENT_STACK16->entry_point);
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000219}
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000220
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000221/************************************************************************
222 * SYSLEVEL_CheckNotLevel
223 */
224VOID SYSLEVEL_CheckNotLevel( INT level )
225{
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000226 INT i;
227
228 for ( i = 3; i >= level; i-- )
Alexandre Julliard0a860a01999-06-22 11:43:42 +0000229 if ( NtCurrentTeb()->sys_count[i] > 0 )
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000230 {
Alexandre Julliard15657091999-05-23 10:25:25 +0000231 ERR("(%d): Holding lock of level %d!\n",
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000232 level, i );
Alexandre Julliard55e1af91999-06-18 18:24:47 +0000233 DebugBreak();
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000234 break;
235 }
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000236}
237