Added launching of a debugger when unhandled exception occurs.
[wine.git] / scheduler / syslevel.c
blob5a7523e406e1332b2dbf2f9a4c28225503de7025
1 /*
2 * Win32 'syslevel' routines
4 * Copyright 1998 Ulrich Weigand
5 */
7 #include <unistd.h>
8 #include <sys/types.h>
9 #include "syslevel.h"
10 #include "heap.h"
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 /************************************************************************
28 * SYSLEVEL_Init
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)
45 *lock = &Win16Mutex;
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 );
62 lock->level = level;
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();
74 int i;
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] );
117 else
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;
145 else
146 return 0L;
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;
189 while (count-- > 0)
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 )
226 INT i;
228 for ( i = 3; i >= level; i-- )
229 if ( NtCurrentTeb()->sys_count[i] > 0 )
231 ERR("(%d): Holding lock of level %d!\n",
232 level, i );
233 DebugBreak();
234 break;