2 * Win32 'syslevel' routines
4 * Copyright 1998 Ulrich Weigand
12 #include "selectors.h"
13 #include "stackframe.h"
14 #include "debugtools.h"
16 DEFAULT_DEBUG_CHANNEL(win32
);
18 static SYSLEVEL Win16Mutex
= { CRITICAL_SECTION_INIT
, 1 };
20 /* Global variable to save current TEB while in 16-bit code */
21 WORD SYSLEVEL_Win16CurrentTeb
= 0;
24 /************************************************************************
25 * GetpWin16Lock (KERNEL32.93)
27 VOID WINAPI
GetpWin16Lock(SYSLEVEL
**lock
)
32 /************************************************************************
33 * GetpWin16Lock16 (KERNEL.449)
35 SEGPTR WINAPI
GetpWin16Lock16(void)
37 static SEGPTR segpWin16Mutex
;
40 SYSLEVEL
**w16Mutex
= SEGPTR_ALLOC(sizeof(SYSLEVEL
*));
41 *w16Mutex
= &Win16Mutex
;
42 segpWin16Mutex
= SEGPTR_GET(w16Mutex
);
44 return segpWin16Mutex
;
47 /************************************************************************
48 * _CreateSysLevel (KERNEL.438)
50 VOID WINAPI
_CreateSysLevel(SYSLEVEL
*lock
, INT level
)
52 InitializeCriticalSection( &lock
->crst
);
55 TRACE("(%p, %d): handle is %d\n",
56 lock
, level
, lock
->crst
.LockSemaphore
);
59 /************************************************************************
60 * _EnterSysLevel (KERNEL32.97) (KERNEL.439)
62 VOID WINAPI
_EnterSysLevel(SYSLEVEL
*lock
)
64 TEB
*teb
= NtCurrentTeb();
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
] );
71 for ( i
= 3; i
> lock
->level
; i
-- )
72 if ( teb
->sys_count
[i
] > 0 )
74 ERR("(%p, level %d): Holding %p, level %d. Expect deadlock!\n",
75 lock
, lock
->level
, teb
->sys_mutex
[i
], i
);
78 EnterCriticalSection( &lock
->crst
);
80 teb
->sys_count
[lock
->level
]++;
81 teb
->sys_mutex
[lock
->level
] = lock
;
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
] );
87 if (lock
== &Win16Mutex
)
88 SYSLEVEL_Win16CurrentTeb
= __get_fs();
91 /************************************************************************
92 * _LeaveSysLevel (KERNEL32.98) (KERNEL.440)
94 VOID WINAPI
_LeaveSysLevel(SYSLEVEL
*lock
)
96 TEB
*teb
= NtCurrentTeb();
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
] );
102 if ( teb
->sys_count
[lock
->level
] <= 0 || teb
->sys_mutex
[lock
->level
] != lock
)
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
] );
110 if ( --teb
->sys_count
[lock
->level
] == 0 )
111 teb
->sys_mutex
[lock
->level
] = NULL
;
114 LeaveCriticalSection( &lock
->crst
);
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
] );
121 /************************************************************************
122 * _KERNEL32_86 (KERNEL32.86)
124 VOID WINAPI
_KERNEL32_86(SYSLEVEL
*lock
)
126 _LeaveSysLevel(lock
);
129 /************************************************************************
130 * _ConfirmSysLevel (KERNEL32.95) (KERNEL.436)
132 DWORD WINAPI
_ConfirmSysLevel(SYSLEVEL
*lock
)
134 if ( lock
&& lock
->crst
.OwningThread
== GetCurrentThreadId() )
135 return lock
->crst
.RecursionCount
;
140 /************************************************************************
141 * _CheckNotSysLevel (KERNEL32.94) (KERNEL.437)
143 VOID WINAPI
_CheckNotSysLevel(SYSLEVEL
*lock
)
145 FIXME("(%p)\n", lock
);
149 /************************************************************************
150 * _EnterWin16Lock [KERNEL.480]
152 VOID WINAPI
_EnterWin16Lock(void)
154 _EnterSysLevel(&Win16Mutex
);
157 /************************************************************************
158 * _LeaveWin16Lock [KERNEL.481]
160 VOID WINAPI
_LeaveWin16Lock(void)
162 _LeaveSysLevel(&Win16Mutex
);
165 /************************************************************************
166 * _ConfirmWin16Lock (KERNEL32.96)
168 DWORD WINAPI
_ConfirmWin16Lock(void)
170 return _ConfirmSysLevel(&Win16Mutex
);
173 /************************************************************************
174 * ReleaseThunkLock (KERNEL32.48)
176 VOID WINAPI
ReleaseThunkLock(DWORD
*mutex_count
)
178 DWORD count
= _ConfirmSysLevel(&Win16Mutex
);
179 *mutex_count
= count
;
182 _LeaveSysLevel(&Win16Mutex
);
185 /************************************************************************
186 * RestoreThunkLock (KERNEL32.49)
188 VOID WINAPI
RestoreThunkLock(DWORD mutex_count
)
190 while (mutex_count
-- > 0)
191 _EnterSysLevel(&Win16Mutex
);
194 /************************************************************************
195 * SYSLEVEL_CheckNotLevel
197 VOID
SYSLEVEL_CheckNotLevel( INT level
)
201 for ( i
= 3; i
>= level
; i
-- )
202 if ( NtCurrentTeb()->sys_count
[i
] > 0 )
204 ERR("(%d): Holding lock of level %d!\n",