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
;
19 static SEGPTR segpWin16Mutex
;
21 /* Global variable to save current TEB while in 16-bit code */
22 WORD SYSLEVEL_Win16CurrentTeb
= 0;
24 /* TEB of initial process for emergency use */
25 WORD SYSLEVEL_EmergencyTeb
= 0;
28 /************************************************************************
31 void SYSLEVEL_Init(void)
33 SYSLEVEL
**w16Mutex
= SEGPTR_ALLOC(sizeof(SYSLEVEL
*));
35 *w16Mutex
= &Win16Mutex
;
36 segpWin16Mutex
= SEGPTR_GET(w16Mutex
);
38 _CreateSysLevel( &Win16Mutex
, 1 );
41 /************************************************************************
42 * GetpWin16Lock (KERNEL32.93)
44 VOID WINAPI
GetpWin16Lock(SYSLEVEL
**lock
)
49 /************************************************************************
50 * GetpWin16Lock16 (KERNEL.449)
52 SEGPTR WINAPI
GetpWin16Lock16(void)
54 return segpWin16Mutex
;
57 /************************************************************************
58 * _CreateSysLevel (KERNEL.438)
60 VOID WINAPI
_CreateSysLevel(SYSLEVEL
*lock
, INT level
)
62 InitializeCriticalSection( &lock
->crst
);
65 TRACE("(%p, %d): handle is %d\n",
66 lock
, level
, lock
->crst
.LockSemaphore
);
69 /************************************************************************
70 * _EnterSysLevel (KERNEL32.97) (KERNEL.439)
72 VOID WINAPI
_EnterSysLevel(SYSLEVEL
*lock
)
74 TEB
*teb
= NtCurrentTeb();
77 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(),
79 teb
->sys_count
[lock
->level
] );
81 for ( i
= 3; i
> lock
->level
; i
-- )
82 if ( teb
->sys_count
[i
] > 0 )
84 ERR("(%p, level %d): Holding %p, level %d. Expect deadlock!\n",
85 lock
, lock
->level
, teb
->sys_mutex
[i
], i
);
88 EnterCriticalSection( &lock
->crst
);
90 teb
->sys_count
[lock
->level
]++;
91 teb
->sys_mutex
[lock
->level
] = lock
;
93 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(),
95 teb
->sys_count
[lock
->level
] );
97 if (lock
== &Win16Mutex
)
98 SYSLEVEL_Win16CurrentTeb
= __get_fs();
101 /************************************************************************
102 * _LeaveSysLevel (KERNEL32.98) (KERNEL.440)
104 VOID WINAPI
_LeaveSysLevel(SYSLEVEL
*lock
)
106 TEB
*teb
= NtCurrentTeb();
108 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(),
110 teb
->sys_count
[lock
->level
] );
112 if ( teb
->sys_count
[lock
->level
] <= 0 || teb
->sys_mutex
[lock
->level
] != lock
)
114 ERR("(%p, level %d): Invalid state: count %ld mutex %p.\n",
115 lock
, lock
->level
, teb
->sys_count
[lock
->level
],
116 teb
->sys_mutex
[lock
->level
] );
120 if ( --teb
->sys_count
[lock
->level
] == 0 )
121 teb
->sys_mutex
[lock
->level
] = NULL
;
124 LeaveCriticalSection( &lock
->crst
);
126 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(),
128 teb
->sys_count
[lock
->level
] );
131 /************************************************************************
132 * _KERNEL32_86 (KERNEL32.86)
134 VOID WINAPI
_KERNEL32_86(SYSLEVEL
*lock
)
136 _LeaveSysLevel(lock
);
139 /************************************************************************
140 * _ConfirmSysLevel (KERNEL32.95) (KERNEL.436)
142 DWORD WINAPI
_ConfirmSysLevel(SYSLEVEL
*lock
)
144 if ( lock
&& lock
->crst
.OwningThread
== GetCurrentThreadId() )
145 return lock
->crst
.RecursionCount
;
150 /************************************************************************
151 * _CheckNotSysLevel (KERNEL32.94) (KERNEL.437)
153 VOID WINAPI
_CheckNotSysLevel(SYSLEVEL
*lock
)
155 FIXME("(%p)\n", lock
);
159 /************************************************************************
160 * SYSLEVEL_EnterWin16Lock [KERNEL.480]
162 VOID WINAPI
SYSLEVEL_EnterWin16Lock(VOID
)
164 _EnterSysLevel(&Win16Mutex
);
167 /************************************************************************
168 * SYSLEVEL_LeaveWin16Lock [KERNEL.481]
170 VOID WINAPI
SYSLEVEL_LeaveWin16Lock(VOID
)
172 _LeaveSysLevel(&Win16Mutex
);
174 /************************************************************************
175 * _ConfirmWin16Lock (KERNEL32.96)
177 DWORD WINAPI
_ConfirmWin16Lock(void)
179 return _ConfirmSysLevel(&Win16Mutex
);
182 /************************************************************************
183 * ReleaseThunkLock (KERNEL32.48)
185 VOID WINAPI
ReleaseThunkLock(DWORD
*mutex_count
)
187 DWORD count
= _ConfirmSysLevel(&Win16Mutex
);
188 *mutex_count
= count
;
191 _LeaveSysLevel(&Win16Mutex
);
194 /************************************************************************
195 * RestoreThunkLock (KERNEL32.49)
197 VOID WINAPI
RestoreThunkLock(DWORD mutex_count
)
199 while (mutex_count
-- > 0)
200 _EnterSysLevel(&Win16Mutex
);
203 /************************************************************************
204 * SYSLEVEL_ReleaseWin16Lock
206 VOID
SYSLEVEL_ReleaseWin16Lock(VOID
)
208 /* entry_point is never used again once the entry point has
209 been called. Thus we re-use it to hold the Win16Lock count */
211 ReleaseThunkLock(&CURRENT_STACK16
->entry_point
);
214 /************************************************************************
215 * SYSLEVEL_RestoreWin16Lock
217 VOID
SYSLEVEL_RestoreWin16Lock(VOID
)
219 RestoreThunkLock(CURRENT_STACK16
->entry_point
);
222 /************************************************************************
223 * SYSLEVEL_CheckNotLevel
225 VOID
SYSLEVEL_CheckNotLevel( INT level
)
229 for ( i
= 3; i
>= level
; i
-- )
230 if ( NtCurrentTeb()->sys_count
[i
] > 0 )
232 ERR("(%d): Holding lock of level %d!\n",