2 * Win32 'syslevel' routines
4 * Copyright 1998 Ulrich Weigand
11 #include "stackframe.h"
12 #include "debugtools.h"
14 DEFAULT_DEBUG_CHANNEL(win32
);
16 static SYSLEVEL Win16Mutex
= { CRITICAL_SECTION_INIT("Win16Mutex"), 1 };
18 /* Global variable to save current TEB while in 16-bit code */
19 WORD SYSLEVEL_Win16CurrentTeb
= 0;
22 /************************************************************************
23 * GetpWin16Lock (KERNEL32.93)
25 VOID WINAPI
GetpWin16Lock(SYSLEVEL
**lock
)
30 /************************************************************************
31 * GetpWin16Lock (KERNEL.449)
33 SEGPTR WINAPI
GetpWin16Lock16(void)
35 static SYSLEVEL
*w16Mutex
;
36 static SEGPTR segpWin16Mutex
;
40 w16Mutex
= &Win16Mutex
;
41 segpWin16Mutex
= MapLS( &w16Mutex
);
43 return segpWin16Mutex
;
46 /************************************************************************
47 * _CreateSysLevel (KERNEL.438)
49 VOID WINAPI
_CreateSysLevel(SYSLEVEL
*lock
, INT level
)
51 InitializeCriticalSection( &lock
->crst
);
54 TRACE("(%p, %d): handle is %d\n",
55 lock
, level
, lock
->crst
.LockSemaphore
);
58 /************************************************************************
59 * _EnterSysLevel (KERNEL32.97)
60 * _EnterSysLevel (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)
93 * _LeaveSysLevel (KERNEL.440)
95 VOID WINAPI
_LeaveSysLevel(SYSLEVEL
*lock
)
97 TEB
*teb
= NtCurrentTeb();
99 TRACE("(%p, level %d): thread %p (fs %04x, pid %ld) count before %ld\n",
100 lock
, lock
->level
, teb
->tid
, teb
->teb_sel
, (long) getpid(),
101 teb
->sys_count
[lock
->level
] );
103 if ( teb
->sys_count
[lock
->level
] <= 0 || teb
->sys_mutex
[lock
->level
] != lock
)
105 ERR("(%p, level %d): Invalid state: count %ld mutex %p.\n",
106 lock
, lock
->level
, teb
->sys_count
[lock
->level
],
107 teb
->sys_mutex
[lock
->level
] );
111 if ( --teb
->sys_count
[lock
->level
] == 0 )
112 teb
->sys_mutex
[lock
->level
] = NULL
;
115 LeaveCriticalSection( &lock
->crst
);
117 TRACE("(%p, level %d): thread %p (fs %04x, pid %ld) count after %ld\n",
118 lock
, lock
->level
, teb
->tid
, teb
->teb_sel
, (long) getpid(),
119 teb
->sys_count
[lock
->level
] );
122 /************************************************************************
125 VOID WINAPI
_KERNEL32_86(SYSLEVEL
*lock
)
127 _LeaveSysLevel(lock
);
130 /************************************************************************
131 * _ConfirmSysLevel (KERNEL32.95)
132 * _ConfirmSysLevel (KERNEL.436)
134 DWORD WINAPI
_ConfirmSysLevel(SYSLEVEL
*lock
)
136 if ( lock
&& lock
->crst
.OwningThread
== GetCurrentThreadId() )
137 return lock
->crst
.RecursionCount
;
142 /************************************************************************
143 * _CheckNotSysLevel (KERNEL32.94)
144 * _CheckNotSysLevel (KERNEL.437)
146 VOID WINAPI
_CheckNotSysLevel(SYSLEVEL
*lock
)
148 if (lock
&& lock
->crst
.OwningThread
== GetCurrentThreadId() && lock
->crst
.RecursionCount
)
150 ERR( "Holding lock %p level %d\n", lock
, lock
->level
);
156 /************************************************************************
157 * _EnterWin16Lock [KERNEL.480]
159 VOID WINAPI
_EnterWin16Lock(void)
161 _EnterSysLevel(&Win16Mutex
);
164 /************************************************************************
165 * _LeaveWin16Lock [KERNEL.481]
167 VOID WINAPI
_LeaveWin16Lock(void)
169 _LeaveSysLevel(&Win16Mutex
);
172 /************************************************************************
173 * _ConfirmWin16Lock (KERNEL32.96)
175 DWORD WINAPI
_ConfirmWin16Lock(void)
177 return _ConfirmSysLevel(&Win16Mutex
);
180 /************************************************************************
181 * ReleaseThunkLock (KERNEL32.48)
183 VOID WINAPI
ReleaseThunkLock(DWORD
*mutex_count
)
185 DWORD count
= _ConfirmSysLevel(&Win16Mutex
);
186 *mutex_count
= count
;
189 _LeaveSysLevel(&Win16Mutex
);
192 /************************************************************************
193 * RestoreThunkLock (KERNEL32.49)
195 VOID WINAPI
RestoreThunkLock(DWORD mutex_count
)
197 while (mutex_count
-- > 0)
198 _EnterSysLevel(&Win16Mutex
);
201 /************************************************************************
202 * SYSLEVEL_CheckNotLevel
204 VOID
SYSLEVEL_CheckNotLevel( INT level
)
208 for ( i
= 3; i
>= level
; i
-- )
209 if ( NtCurrentTeb()->sys_count
[i
] > 0 )
211 ERR("(%d): Holding lock of level %d!\n",