- created server object for handling async i/o
[wine] / scheduler / syslevel.c
1 /*
2  * Win32 'syslevel' routines
3  *
4  * Copyright 1998 Ulrich Weigand
5  */
6
7 #include <unistd.h>
8 #include <sys/types.h>
9 #include "ntddk.h"
10 #include "syslevel.h"
11 #include "heap.h"
12 #include "selectors.h"
13 #include "stackframe.h"
14 #include "debugtools.h"
15
16 DEFAULT_DEBUG_CHANNEL(win32);
17
18 static SYSLEVEL Win16Mutex;
19 static SEGPTR segpWin16Mutex;
20
21 /* Global variable to save current TEB while in 16-bit code */
22 WORD SYSLEVEL_Win16CurrentTeb = 0;
23
24 /* TEB of initial process for emergency use */
25 WORD SYSLEVEL_EmergencyTeb = 0;
26
27
28 /************************************************************************
29  *           SYSLEVEL_Init
30  */
31 void SYSLEVEL_Init(void)
32 {
33     SYSLEVEL **w16Mutex = SEGPTR_ALLOC(sizeof(SYSLEVEL *));
34
35     *w16Mutex = &Win16Mutex;
36     segpWin16Mutex = SEGPTR_GET(w16Mutex);
37
38     _CreateSysLevel( &Win16Mutex, 1 );
39 }
40
41 /************************************************************************
42  *           GetpWin16Lock    (KERNEL32.93)
43  */
44 VOID WINAPI GetpWin16Lock(SYSLEVEL **lock)
45 {
46     *lock = &Win16Mutex;
47 }
48
49 /************************************************************************
50  *           GetpWin16Lock16    (KERNEL.449)
51  */
52 SEGPTR WINAPI GetpWin16Lock16(void) 
53
54     return segpWin16Mutex;
55 }
56
57 /************************************************************************
58  *           _CreateSysLevel    (KERNEL.438)
59  */
60 VOID WINAPI _CreateSysLevel(SYSLEVEL *lock, INT level)
61 {
62     InitializeCriticalSection( &lock->crst );
63     lock->level = level;
64
65     TRACE("(%p, %d): handle is %d\n", 
66                   lock, level, lock->crst.LockSemaphore );
67 }
68
69 /************************************************************************
70  *           _EnterSysLevel    (KERNEL32.97) (KERNEL.439)
71  */
72 VOID WINAPI _EnterSysLevel(SYSLEVEL *lock)
73 {
74     TEB *teb = NtCurrentTeb();
75     int i;
76
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] );
80
81     for ( i = 3; i > lock->level; i-- )
82         if ( teb->sys_count[i] > 0 )
83         {
84             ERR("(%p, level %d): Holding %p, level %d. Expect deadlock!\n", 
85                         lock, lock->level, teb->sys_mutex[i], i );
86         }
87
88     EnterCriticalSection( &lock->crst );
89
90     teb->sys_count[lock->level]++;
91     teb->sys_mutex[lock->level] = lock;
92
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] );
96
97     if (lock == &Win16Mutex)
98         SYSLEVEL_Win16CurrentTeb = __get_fs();
99 }
100
101 /************************************************************************
102  *           _LeaveSysLevel    (KERNEL32.98) (KERNEL.440)
103  */
104 VOID WINAPI _LeaveSysLevel(SYSLEVEL *lock)
105 {
106     TEB *teb = NtCurrentTeb();
107
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] );
111
112     if ( teb->sys_count[lock->level] <= 0 || teb->sys_mutex[lock->level] != lock )
113     {
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] );
117     }
118     else
119     {
120         if ( --teb->sys_count[lock->level] == 0 )
121             teb->sys_mutex[lock->level] = NULL;
122     }
123
124     LeaveCriticalSection( &lock->crst );
125
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] );
129 }
130
131 /************************************************************************
132  *              _KERNEL32_86 (KERNEL32.86)
133  */
134 VOID WINAPI _KERNEL32_86(SYSLEVEL *lock)
135 {
136     _LeaveSysLevel(lock);
137 }
138
139 /************************************************************************
140  *           _ConfirmSysLevel    (KERNEL32.95) (KERNEL.436)
141  */
142 DWORD WINAPI _ConfirmSysLevel(SYSLEVEL *lock)
143 {
144     if ( lock && lock->crst.OwningThread == GetCurrentThreadId() )
145         return lock->crst.RecursionCount;
146     else
147         return 0L;
148 }
149
150 /************************************************************************
151  *           _CheckNotSysLevel    (KERNEL32.94) (KERNEL.437)
152  */
153 VOID WINAPI _CheckNotSysLevel(SYSLEVEL *lock)
154 {
155     FIXME("(%p)\n", lock);
156 }
157
158
159 /************************************************************************
160  *           SYSLEVEL_EnterWin16Lock                    [KERNEL.480]
161  */
162 VOID WINAPI SYSLEVEL_EnterWin16Lock(VOID)
163 {
164     _EnterSysLevel(&Win16Mutex);
165 }
166
167 /************************************************************************
168  *           SYSLEVEL_LeaveWin16Lock            [KERNEL.481]
169  */
170 VOID WINAPI SYSLEVEL_LeaveWin16Lock(VOID)
171 {
172     _LeaveSysLevel(&Win16Mutex);
173 }
174 /************************************************************************
175  *           _ConfirmWin16Lock    (KERNEL32.96)
176  */
177 DWORD WINAPI _ConfirmWin16Lock(void)
178 {
179     return _ConfirmSysLevel(&Win16Mutex);
180 }
181
182 /************************************************************************
183  *           ReleaseThunkLock    (KERNEL32.48)
184  */
185 VOID WINAPI ReleaseThunkLock(DWORD *mutex_count)
186 {
187     DWORD count = _ConfirmSysLevel(&Win16Mutex);
188     *mutex_count = count;
189
190     while (count-- > 0)
191         _LeaveSysLevel(&Win16Mutex);
192 }
193
194 /************************************************************************
195  *           RestoreThunkLock    (KERNEL32.49)
196  */
197 VOID WINAPI RestoreThunkLock(DWORD mutex_count)
198 {
199     while (mutex_count-- > 0)
200         _EnterSysLevel(&Win16Mutex);
201 }
202
203 /************************************************************************
204  *           SYSLEVEL_ReleaseWin16Lock
205  */
206 VOID SYSLEVEL_ReleaseWin16Lock(VOID)
207 {
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 */
210
211     ReleaseThunkLock(&CURRENT_STACK16->entry_point);
212 }
213
214 /************************************************************************
215  *           SYSLEVEL_RestoreWin16Lock
216  */
217 VOID SYSLEVEL_RestoreWin16Lock(VOID)
218 {
219     RestoreThunkLock(CURRENT_STACK16->entry_point);
220 }
221
222 /************************************************************************
223  *           SYSLEVEL_CheckNotLevel
224  */
225 VOID SYSLEVEL_CheckNotLevel( INT level )
226 {
227     INT i;
228
229     for ( i = 3; i >= level; i-- )
230         if ( NtCurrentTeb()->sys_count[i] > 0 )
231         {
232             ERR("(%d): Holding lock of level %d!\n", 
233                        level, i );
234             DbgBreakPoint();
235             break;
236         }
237 }
238