blob: e6bb1124a106cccddbd7c921009b2ac6ca1c57f1 [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 Julliardafb49ea2000-09-29 20:48:04 +00009#include "ntddk.h"
Alexandre Julliard767e6f61998-08-09 12:47:43 +000010#include "syslevel.h"
11#include "heap.h"
Alexandre Julliard916f9752000-02-26 16:51:13 +000012#include "selectors.h"
Alexandre Julliard767e6f61998-08-09 12:47:43 +000013#include "stackframe.h"
Alexandre Julliard15657091999-05-23 10:25:25 +000014#include "debugtools.h"
Alexandre Julliard767e6f61998-08-09 12:47:43 +000015
Alexandre Julliardafb49ea2000-09-29 20:48:04 +000016DEFAULT_DEBUG_CHANNEL(win32);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000017
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000018static SYSLEVEL Win16Mutex;
Alexandre Julliard767e6f61998-08-09 12:47:43 +000019static SEGPTR segpWin16Mutex;
20
Alexandre Julliard85ed45e1998-08-22 19:03:56 +000021/* Global variable to save current TEB while in 16-bit code */
22WORD SYSLEVEL_Win16CurrentTeb = 0;
23
Ulrich Weigand2e30f6f1998-10-11 18:59:11 +000024/* TEB of initial process for emergency use */
25WORD SYSLEVEL_EmergencyTeb = 0;
26
Alexandre Julliard767e6f61998-08-09 12:47:43 +000027
28/************************************************************************
29 * SYSLEVEL_Init
30 */
31void SYSLEVEL_Init(void)
32{
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000033 SYSLEVEL **w16Mutex = SEGPTR_ALLOC(sizeof(SYSLEVEL *));
Alexandre Julliard767e6f61998-08-09 12:47:43 +000034
35 *w16Mutex = &Win16Mutex;
36 segpWin16Mutex = SEGPTR_GET(w16Mutex);
37
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000038 _CreateSysLevel( &Win16Mutex, 1 );
Alexandre Julliard767e6f61998-08-09 12:47:43 +000039}
40
41/************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +000042 * GetpWin16Lock (KERNEL32.93)
Alexandre Julliard767e6f61998-08-09 12:47:43 +000043 */
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000044VOID WINAPI GetpWin16Lock(SYSLEVEL **lock)
Alexandre Julliard767e6f61998-08-09 12:47:43 +000045{
46 *lock = &Win16Mutex;
47}
48
49/************************************************************************
50 * GetpWin16Lock16 (KERNEL.449)
51 */
52SEGPTR WINAPI GetpWin16Lock16(void)
53{
54 return segpWin16Mutex;
55}
56
57/************************************************************************
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000058 * _CreateSysLevel (KERNEL.438)
Alexandre Julliard767e6f61998-08-09 12:47:43 +000059 */
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000060VOID WINAPI _CreateSysLevel(SYSLEVEL *lock, INT level)
Alexandre Julliard767e6f61998-08-09 12:47:43 +000061{
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000062 InitializeCriticalSection( &lock->crst );
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000063 lock->level = level;
64
Alexandre Julliard15657091999-05-23 10:25:25 +000065 TRACE("(%p, %d): handle is %d\n",
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000066 lock, level, lock->crst.LockSemaphore );
67}
68
69/************************************************************************
70 * _EnterSysLevel (KERNEL32.97) (KERNEL.439)
71 */
72VOID WINAPI _EnterSysLevel(SYSLEVEL *lock)
73{
Alexandre Julliard0a860a01999-06-22 11:43:42 +000074 TEB *teb = NtCurrentTeb();
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000075 int i;
76
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +000077 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(),
Alexandre Julliard0a860a01999-06-22 11:43:42 +000079 teb->sys_count[lock->level] );
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000080
81 for ( i = 3; i > lock->level; i-- )
Alexandre Julliard0a860a01999-06-22 11:43:42 +000082 if ( teb->sys_count[i] > 0 )
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000083 {
Alexandre Julliard15657091999-05-23 10:25:25 +000084 ERR("(%p, level %d): Holding %p, level %d. Expect deadlock!\n",
Alexandre Julliard0a860a01999-06-22 11:43:42 +000085 lock, lock->level, teb->sys_mutex[i], i );
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000086 }
87
88 EnterCriticalSection( &lock->crst );
89
Alexandre Julliard0a860a01999-06-22 11:43:42 +000090 teb->sys_count[lock->level]++;
91 teb->sys_mutex[lock->level] = lock;
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000092
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +000093 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(),
Alexandre Julliard0a860a01999-06-22 11:43:42 +000095 teb->sys_count[lock->level] );
Alexandre Julliard85ed45e1998-08-22 19:03:56 +000096
97 if (lock == &Win16Mutex)
Alexandre Julliard916f9752000-02-26 16:51:13 +000098 SYSLEVEL_Win16CurrentTeb = __get_fs();
Alexandre Julliard767e6f61998-08-09 12:47:43 +000099}
100
101/************************************************************************
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000102 * _LeaveSysLevel (KERNEL32.98) (KERNEL.440)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000103 */
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000104VOID WINAPI _LeaveSysLevel(SYSLEVEL *lock)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000105{
Alexandre Julliard0a860a01999-06-22 11:43:42 +0000106 TEB *teb = NtCurrentTeb();
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000107
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +0000108 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(),
Alexandre Julliard0a860a01999-06-22 11:43:42 +0000110 teb->sys_count[lock->level] );
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000111
Alexandre Julliard0a860a01999-06-22 11:43:42 +0000112 if ( teb->sys_count[lock->level] <= 0 || teb->sys_mutex[lock->level] != lock )
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000113 {
Alexandre Julliard15657091999-05-23 10:25:25 +0000114 ERR("(%p, level %d): Invalid state: count %ld mutex %p.\n",
Alexandre Julliard0a860a01999-06-22 11:43:42 +0000115 lock, lock->level, teb->sys_count[lock->level],
116 teb->sys_mutex[lock->level] );
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000117 }
118 else
119 {
Alexandre Julliard0a860a01999-06-22 11:43:42 +0000120 if ( --teb->sys_count[lock->level] == 0 )
121 teb->sys_mutex[lock->level] = NULL;
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000122 }
123
124 LeaveCriticalSection( &lock->crst );
125
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +0000126 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(),
Alexandre Julliard0a860a01999-06-22 11:43:42 +0000128 teb->sys_count[lock->level] );
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000129}
130
131/************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000132 * _KERNEL32_86 (KERNEL32.86)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000133 */
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000134VOID WINAPI _KERNEL32_86(SYSLEVEL *lock)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000135{
136 _LeaveSysLevel(lock);
137}
138
139/************************************************************************
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000140 * _ConfirmSysLevel (KERNEL32.95) (KERNEL.436)
141 */
142DWORD WINAPI _ConfirmSysLevel(SYSLEVEL *lock)
143{
144 if ( lock && lock->crst.OwningThread == GetCurrentThreadId() )
145 return lock->crst.RecursionCount;
146 else
147 return 0L;
148}
149
150/************************************************************************
151 * _CheckNotSysLevel (KERNEL32.94) (KERNEL.437)
152 */
153VOID WINAPI _CheckNotSysLevel(SYSLEVEL *lock)
154{
Alexandre Julliard15657091999-05-23 10:25:25 +0000155 FIXME("(%p)\n", lock);
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000156}
157
158
159/************************************************************************
Marcus Meissnera763ed91998-10-22 17:02:25 +0000160 * SYSLEVEL_EnterWin16Lock [KERNEL.480]
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000161 */
Andreas Mohrc21650e1998-10-11 17:37:53 +0000162VOID WINAPI SYSLEVEL_EnterWin16Lock(VOID)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000163{
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000164 _EnterSysLevel(&Win16Mutex);
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000165}
166
167/************************************************************************
Marcus Meissnera763ed91998-10-22 17:02:25 +0000168 * SYSLEVEL_LeaveWin16Lock [KERNEL.481]
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000169 */
Andreas Mohrc21650e1998-10-11 17:37:53 +0000170VOID WINAPI SYSLEVEL_LeaveWin16Lock(VOID)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000171{
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000172 _LeaveSysLevel(&Win16Mutex);
173}
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000174/************************************************************************
175 * _ConfirmWin16Lock (KERNEL32.96)
176 */
177DWORD WINAPI _ConfirmWin16Lock(void)
178{
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000179 return _ConfirmSysLevel(&Win16Mutex);
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000180}
181
182/************************************************************************
183 * ReleaseThunkLock (KERNEL32.48)
184 */
185VOID WINAPI ReleaseThunkLock(DWORD *mutex_count)
186{
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000187 DWORD count = _ConfirmSysLevel(&Win16Mutex);
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000188 *mutex_count = count;
189
190 while (count-- > 0)
191 _LeaveSysLevel(&Win16Mutex);
192}
193
194/************************************************************************
195 * RestoreThunkLock (KERNEL32.49)
196 */
197VOID WINAPI RestoreThunkLock(DWORD mutex_count)
198{
199 while (mutex_count-- > 0)
200 _EnterSysLevel(&Win16Mutex);
201}
202
203/************************************************************************
204 * SYSLEVEL_ReleaseWin16Lock
205 */
206VOID SYSLEVEL_ReleaseWin16Lock(VOID)
207{
Ulrich Weigand3dff7bb1999-07-11 13:58:31 +0000208 /* entry_point is never used again once the entry point has
209 been called. Thus we re-use it to hold the Win16Lock count */
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000210
Ulrich Weigand3dff7bb1999-07-11 13:58:31 +0000211 ReleaseThunkLock(&CURRENT_STACK16->entry_point);
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000212}
213
214/************************************************************************
215 * SYSLEVEL_RestoreWin16Lock
216 */
217VOID SYSLEVEL_RestoreWin16Lock(VOID)
218{
Ulrich Weigand3dff7bb1999-07-11 13:58:31 +0000219 RestoreThunkLock(CURRENT_STACK16->entry_point);
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000220}
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000221
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000222/************************************************************************
223 * SYSLEVEL_CheckNotLevel
224 */
225VOID SYSLEVEL_CheckNotLevel( INT level )
226{
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000227 INT i;
228
229 for ( i = 3; i >= level; i-- )
Alexandre Julliard0a860a01999-06-22 11:43:42 +0000230 if ( NtCurrentTeb()->sys_count[i] > 0 )
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000231 {
Alexandre Julliard15657091999-05-23 10:25:25 +0000232 ERR("(%d): Holding lock of level %d!\n",
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000233 level, i );
Alexandre Julliardafb49ea2000-09-29 20:48:04 +0000234 DbgBreakPoint();
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000235 break;
236 }
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000237}
238