- Introduce a significant design decision.
[wine/wine-kai.git] / scheduler / syslevel.c
blob9d849e837f76c09145e0ce4037e14e8ad6bdf3ad
1 /*
2 * Win32 'syslevel' routines
4 * Copyright 1998 Ulrich Weigand
5 */
7 #include <unistd.h>
8 #include <sys/types.h>
9 #include "ntddk.h"
10 #include "syslevel.h"
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)
27 *lock = &Win16Mutex;
30 /************************************************************************
31 * GetpWin16Lock (KERNEL.449)
33 SEGPTR WINAPI GetpWin16Lock16(void)
35 static SYSLEVEL *w16Mutex;
36 static SEGPTR segpWin16Mutex;
38 if (!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 );
52 lock->level = level;
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();
65 int i;
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] );
109 else
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 /************************************************************************
123 * @ (KERNEL32.86)
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;
138 else
139 return 0L;
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 );
151 DbgBreakPoint();
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;
188 while (count-- > 0)
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 )
206 INT i;
208 for ( i = 3; i >= level; i-- )
209 if ( NtCurrentTeb()->sys_count[i] > 0 )
211 ERR("(%d): Holding lock of level %d!\n",
212 level, i );
213 DbgBreakPoint();
214 break;