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