2 * Win32 'syslevel' routines
4 * Copyright 1998 Ulrich Weigand
11 #include "selectors.h"
12 #include "stackframe.h"
13 #include "debugtools.h"
15 DEFAULT_DEBUG_CHANNEL(win32
)
17 static SYSLEVEL Win16Mutex
;
18 static SEGPTR segpWin16Mutex
;
20 /* Global variable to save current TEB while in 16-bit code */
21 WORD SYSLEVEL_Win16CurrentTeb
= 0;
23 /* TEB of initial process for emergency use */
24 WORD SYSLEVEL_EmergencyTeb
= 0;
27 /************************************************************************
30 void SYSLEVEL_Init(void)
32 SYSLEVEL
**w16Mutex
= SEGPTR_ALLOC(sizeof(SYSLEVEL
*));
34 *w16Mutex
= &Win16Mutex
;
35 segpWin16Mutex
= SEGPTR_GET(w16Mutex
);
37 _CreateSysLevel( &Win16Mutex
, 1 );
40 /************************************************************************
41 * GetpWin16Lock (KERNEL32.93)
43 VOID WINAPI
GetpWin16Lock(SYSLEVEL
**lock
)
48 /************************************************************************
49 * GetpWin16Lock16 (KERNEL.449)
51 SEGPTR WINAPI
GetpWin16Lock16(void)
53 return segpWin16Mutex
;
56 /************************************************************************
57 * _CreateSysLevel (KERNEL.438)
59 VOID WINAPI
_CreateSysLevel(SYSLEVEL
*lock
, INT level
)
61 InitializeCriticalSection( &lock
->crst
);
64 TRACE("(%p, %d): handle is %d\n",
65 lock
, level
, lock
->crst
.LockSemaphore
);
68 /************************************************************************
69 * _EnterSysLevel (KERNEL32.97) (KERNEL.439)
71 VOID WINAPI
_EnterSysLevel(SYSLEVEL
*lock
)
73 TEB
*teb
= NtCurrentTeb();
76 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(),
78 teb
->sys_count
[lock
->level
] );
80 for ( i
= 3; i
> lock
->level
; i
-- )
81 if ( teb
->sys_count
[i
] > 0 )
83 ERR("(%p, level %d): Holding %p, level %d. Expect deadlock!\n",
84 lock
, lock
->level
, teb
->sys_mutex
[i
], i
);
87 EnterCriticalSection( &lock
->crst
);
89 teb
->sys_count
[lock
->level
]++;
90 teb
->sys_mutex
[lock
->level
] = lock
;
92 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(),
94 teb
->sys_count
[lock
->level
] );
96 if (lock
== &Win16Mutex
)
97 SYSLEVEL_Win16CurrentTeb
= __get_fs();
100 /************************************************************************
101 * _LeaveSysLevel (KERNEL32.98) (KERNEL.440)
103 VOID WINAPI
_LeaveSysLevel(SYSLEVEL
*lock
)
105 TEB
*teb
= NtCurrentTeb();
107 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(),
109 teb
->sys_count
[lock
->level
] );
111 if ( teb
->sys_count
[lock
->level
] <= 0 || teb
->sys_mutex
[lock
->level
] != lock
)
113 ERR("(%p, level %d): Invalid state: count %ld mutex %p.\n",
114 lock
, lock
->level
, teb
->sys_count
[lock
->level
],
115 teb
->sys_mutex
[lock
->level
] );
119 if ( --teb
->sys_count
[lock
->level
] == 0 )
120 teb
->sys_mutex
[lock
->level
] = NULL
;
123 LeaveCriticalSection( &lock
->crst
);
125 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(),
127 teb
->sys_count
[lock
->level
] );
130 /************************************************************************
131 * _KERNEL32_86 (KERNEL32.86)
133 VOID WINAPI
_KERNEL32_86(SYSLEVEL
*lock
)
135 _LeaveSysLevel(lock
);
138 /************************************************************************
139 * _ConfirmSysLevel (KERNEL32.95) (KERNEL.436)
141 DWORD WINAPI
_ConfirmSysLevel(SYSLEVEL
*lock
)
143 if ( lock
&& lock
->crst
.OwningThread
== GetCurrentThreadId() )
144 return lock
->crst
.RecursionCount
;
149 /************************************************************************
150 * _CheckNotSysLevel (KERNEL32.94) (KERNEL.437)
152 VOID WINAPI
_CheckNotSysLevel(SYSLEVEL
*lock
)
154 FIXME("(%p)\n", lock
);
158 /************************************************************************
159 * SYSLEVEL_EnterWin16Lock [KERNEL.480]
161 VOID WINAPI
SYSLEVEL_EnterWin16Lock(VOID
)
163 _EnterSysLevel(&Win16Mutex
);
166 /************************************************************************
167 * SYSLEVEL_LeaveWin16Lock [KERNEL.481]
169 VOID WINAPI
SYSLEVEL_LeaveWin16Lock(VOID
)
171 _LeaveSysLevel(&Win16Mutex
);
173 /************************************************************************
174 * _ConfirmWin16Lock (KERNEL32.96)
176 DWORD WINAPI
_ConfirmWin16Lock(void)
178 return _ConfirmSysLevel(&Win16Mutex
);
181 /************************************************************************
182 * ReleaseThunkLock (KERNEL32.48)
184 VOID WINAPI
ReleaseThunkLock(DWORD
*mutex_count
)
186 DWORD count
= _ConfirmSysLevel(&Win16Mutex
);
187 *mutex_count
= count
;
190 _LeaveSysLevel(&Win16Mutex
);
193 /************************************************************************
194 * RestoreThunkLock (KERNEL32.49)
196 VOID WINAPI
RestoreThunkLock(DWORD mutex_count
)
198 while (mutex_count
-- > 0)
199 _EnterSysLevel(&Win16Mutex
);
202 /************************************************************************
203 * SYSLEVEL_ReleaseWin16Lock
205 VOID
SYSLEVEL_ReleaseWin16Lock(VOID
)
207 /* entry_point is never used again once the entry point has
208 been called. Thus we re-use it to hold the Win16Lock count */
210 ReleaseThunkLock(&CURRENT_STACK16
->entry_point
);
213 /************************************************************************
214 * SYSLEVEL_RestoreWin16Lock
216 VOID
SYSLEVEL_RestoreWin16Lock(VOID
)
218 RestoreThunkLock(CURRENT_STACK16
->entry_point
);
221 /************************************************************************
222 * SYSLEVEL_CheckNotLevel
224 VOID
SYSLEVEL_CheckNotLevel( INT level
)
228 for ( i
= 3; i
>= level
; i
-- )
229 if ( NtCurrentTeb()->sys_count
[i
] > 0 )
231 ERR("(%d): Holding lock of level %d!\n",