Moved standard syslevel APIs declaration to winbase.h.
[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 = { CRITICAL_SECTION_INIT, 1 };
19
20 /* Global variable to save current TEB while in 16-bit code */
21 WORD SYSLEVEL_Win16CurrentTeb = 0;
22
23
24 /************************************************************************
25  *           GetpWin16Lock    (KERNEL32.93)
26  */
27 VOID WINAPI GetpWin16Lock(SYSLEVEL **lock)
28 {
29     *lock = &Win16Mutex;
30 }
31
32 /************************************************************************
33  *           GetpWin16Lock16    (KERNEL.449)
34  */
35 SEGPTR WINAPI GetpWin16Lock16(void)
36 {
37     static SEGPTR segpWin16Mutex;
38     if (!segpWin16Mutex)
39     {
40         SYSLEVEL **w16Mutex = SEGPTR_ALLOC(sizeof(SYSLEVEL *));
41         *w16Mutex = &Win16Mutex;
42         segpWin16Mutex = SEGPTR_GET(w16Mutex);
43     }
44     return segpWin16Mutex;
45 }
46
47 /************************************************************************
48  *           _CreateSysLevel    (KERNEL.438)
49  */
50 VOID WINAPI _CreateSysLevel(SYSLEVEL *lock, INT level)
51 {
52     InitializeCriticalSection( &lock->crst );
53     lock->level = level;
54
55     TRACE("(%p, %d): handle is %d\n", 
56                   lock, level, lock->crst.LockSemaphore );
57 }
58
59 /************************************************************************
60  *           _EnterSysLevel    (KERNEL32.97) (KERNEL.439)
61  */
62 VOID WINAPI _EnterSysLevel(SYSLEVEL *lock)
63 {
64     TEB *teb = NtCurrentTeb();
65     int i;
66
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] );
70
71     for ( i = 3; i > lock->level; i-- )
72         if ( teb->sys_count[i] > 0 )
73         {
74             ERR("(%p, level %d): Holding %p, level %d. Expect deadlock!\n", 
75                         lock, lock->level, teb->sys_mutex[i], i );
76         }
77
78     EnterCriticalSection( &lock->crst );
79
80     teb->sys_count[lock->level]++;
81     teb->sys_mutex[lock->level] = lock;
82
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] );
86
87     if (lock == &Win16Mutex)
88         SYSLEVEL_Win16CurrentTeb = __get_fs();
89 }
90
91 /************************************************************************
92  *           _LeaveSysLevel    (KERNEL32.98) (KERNEL.440)
93  */
94 VOID WINAPI _LeaveSysLevel(SYSLEVEL *lock)
95 {
96     TEB *teb = NtCurrentTeb();
97
98     TRACE("(%p, level %d): thread %p (fs %04x, pid %ld) count before %ld\n", 
99                   lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
100                   teb->sys_count[lock->level] );
101
102     if ( teb->sys_count[lock->level] <= 0 || teb->sys_mutex[lock->level] != lock )
103     {
104         ERR("(%p, level %d): Invalid state: count %ld mutex %p.\n",
105                     lock, lock->level, teb->sys_count[lock->level], 
106                     teb->sys_mutex[lock->level] );
107     }
108     else
109     {
110         if ( --teb->sys_count[lock->level] == 0 )
111             teb->sys_mutex[lock->level] = NULL;
112     }
113
114     LeaveCriticalSection( &lock->crst );
115
116     TRACE("(%p, level %d): thread %p (fs %04x, pid %ld) count after  %ld\n",
117                   lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(), 
118                   teb->sys_count[lock->level] );
119 }
120
121 /************************************************************************
122  *              _KERNEL32_86 (KERNEL32.86)
123  */
124 VOID WINAPI _KERNEL32_86(SYSLEVEL *lock)
125 {
126     _LeaveSysLevel(lock);
127 }
128
129 /************************************************************************
130  *           _ConfirmSysLevel    (KERNEL32.95) (KERNEL.436)
131  */
132 DWORD WINAPI _ConfirmSysLevel(SYSLEVEL *lock)
133 {
134     if ( lock && lock->crst.OwningThread == GetCurrentThreadId() )
135         return lock->crst.RecursionCount;
136     else
137         return 0L;
138 }
139
140 /************************************************************************
141  *           _CheckNotSysLevel    (KERNEL32.94) (KERNEL.437)
142  */
143 VOID WINAPI _CheckNotSysLevel(SYSLEVEL *lock)
144 {
145     FIXME("(%p)\n", lock);
146 }
147
148
149 /************************************************************************
150  *           _EnterWin16Lock                    [KERNEL.480]
151  */
152 VOID WINAPI _EnterWin16Lock(void)
153 {
154     _EnterSysLevel(&Win16Mutex);
155 }
156
157 /************************************************************************
158  *           _LeaveWin16Lock            [KERNEL.481]
159  */
160 VOID WINAPI _LeaveWin16Lock(void)
161 {
162     _LeaveSysLevel(&Win16Mutex);
163 }
164
165 /************************************************************************
166  *           _ConfirmWin16Lock    (KERNEL32.96)
167  */
168 DWORD WINAPI _ConfirmWin16Lock(void)
169 {
170     return _ConfirmSysLevel(&Win16Mutex);
171 }
172
173 /************************************************************************
174  *           ReleaseThunkLock    (KERNEL32.48)
175  */
176 VOID WINAPI ReleaseThunkLock(DWORD *mutex_count)
177 {
178     DWORD count = _ConfirmSysLevel(&Win16Mutex);
179     *mutex_count = count;
180
181     while (count-- > 0)
182         _LeaveSysLevel(&Win16Mutex);
183 }
184
185 /************************************************************************
186  *           RestoreThunkLock    (KERNEL32.49)
187  */
188 VOID WINAPI RestoreThunkLock(DWORD mutex_count)
189 {
190     while (mutex_count-- > 0)
191         _EnterSysLevel(&Win16Mutex);
192 }
193
194 /************************************************************************
195  *           SYSLEVEL_CheckNotLevel
196  */
197 VOID SYSLEVEL_CheckNotLevel( INT level )
198 {
199     INT i;
200
201     for ( i = 3; i >= level; i-- )
202         if ( NtCurrentTeb()->sys_count[i] > 0 )
203         {
204             ERR("(%d): Holding lock of level %d!\n", 
205                        level, i );
206             DbgBreakPoint();
207             break;
208         }
209 }