Ignore trailing spaces in DOSFS_ToDosFCBFormat.
[wine/multimedia.git] / scheduler / syslevel.c
blobea677bc0c59b535ddc06966f14d822286c9bce66
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 * GetpWin16Lock32 (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 MakeCriticalSectionGlobal( &lock->crst );
63 lock->level = level;
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();
75 int i;
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] );
118 else
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)
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;
146 else
147 return 0L;
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;
190 while (count-- > 0)
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 )
227 INT i;
229 for ( i = 3; i >= level; i-- )
230 if ( NtCurrentTeb()->sys_count[i] > 0 )
232 ERR("(%d): Holding lock of level %d!\n",
233 level, i );
234 DebugBreak();
235 break;