Pass the main exe name in the CREATE_PROCESS debug event.
[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 "selectors.h"
12 #include "stackframe.h"
13 #include "debugtools.h"
14
15 DEFAULT_DEBUG_CHANNEL(win32)
16
17 static SYSLEVEL Win16Mutex;
18 static SEGPTR segpWin16Mutex;
19
20 /* Global variable to save current TEB while in 16-bit code */
21 WORD SYSLEVEL_Win16CurrentTeb = 0;
22
23 /* TEB of initial process for emergency use */
24 WORD SYSLEVEL_EmergencyTeb = 0;
25
26
27 /************************************************************************
28  *           SYSLEVEL_Init
29  */
30 void SYSLEVEL_Init(void)
31 {
32     SYSLEVEL **w16Mutex = SEGPTR_ALLOC(sizeof(SYSLEVEL *));
33
34     *w16Mutex = &Win16Mutex;
35     segpWin16Mutex = SEGPTR_GET(w16Mutex);
36
37     _CreateSysLevel( &Win16Mutex, 1 );
38 }
39
40 /************************************************************************
41  *           GetpWin16Lock    (KERNEL32.93)
42  */
43 VOID WINAPI GetpWin16Lock(SYSLEVEL **lock)
44 {
45     *lock = &Win16Mutex;
46 }
47
48 /************************************************************************
49  *           GetpWin16Lock16    (KERNEL.449)
50  */
51 SEGPTR WINAPI GetpWin16Lock16(void) 
52
53     return segpWin16Mutex;
54 }
55
56 /************************************************************************
57  *           _CreateSysLevel    (KERNEL.438)
58  */
59 VOID WINAPI _CreateSysLevel(SYSLEVEL *lock, INT level)
60 {
61     InitializeCriticalSection( &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     TEB *teb = NtCurrentTeb();
74     int i;
75
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] );
79
80     for ( i = 3; i > lock->level; i-- )
81         if ( teb->sys_count[i] > 0 )
82         {
83             ERR("(%p, level %d): Holding %p, level %d. Expect deadlock!\n", 
84                         lock, lock->level, teb->sys_mutex[i], i );
85         }
86
87     EnterCriticalSection( &lock->crst );
88
89     teb->sys_count[lock->level]++;
90     teb->sys_mutex[lock->level] = lock;
91
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] );
95
96     if (lock == &Win16Mutex)
97         SYSLEVEL_Win16CurrentTeb = __get_fs();
98 }
99
100 /************************************************************************
101  *           _LeaveSysLevel    (KERNEL32.98) (KERNEL.440)
102  */
103 VOID WINAPI _LeaveSysLevel(SYSLEVEL *lock)
104 {
105     TEB *teb = NtCurrentTeb();
106
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] );
110
111     if ( teb->sys_count[lock->level] <= 0 || teb->sys_mutex[lock->level] != lock )
112     {
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] );
116     }
117     else
118     {
119         if ( --teb->sys_count[lock->level] == 0 )
120             teb->sys_mutex[lock->level] = NULL;
121     }
122
123     LeaveCriticalSection( &lock->crst );
124
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] );
128 }
129
130 /************************************************************************
131  *              _KERNEL32_86 (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     /* entry_point is never used again once the entry point has
208        been called.  Thus we re-use it to hold the Win16Lock count */
209
210     ReleaseThunkLock(&CURRENT_STACK16->entry_point);
211 }
212
213 /************************************************************************
214  *           SYSLEVEL_RestoreWin16Lock
215  */
216 VOID SYSLEVEL_RestoreWin16Lock(VOID)
217 {
218     RestoreThunkLock(CURRENT_STACK16->entry_point);
219 }
220
221 /************************************************************************
222  *           SYSLEVEL_CheckNotLevel
223  */
224 VOID SYSLEVEL_CheckNotLevel( INT level )
225 {
226     INT i;
227
228     for ( i = 3; i >= level; i-- )
229         if ( NtCurrentTeb()->sys_count[i] > 0 )
230         {
231             ERR("(%d): Holding lock of level %d!\n", 
232                        level, i );
233             DebugBreak();
234             break;
235         }
236 }
237