syslevel.c 5.67 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3 4 5 6 7
/*
 * Win32 'syslevel' routines
 *
 * Copyright 1998 Ulrich Weigand
 */

#include <unistd.h>
8
#include <sys/types.h>
9
#include "ntddk.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
10 11 12
#include "syslevel.h"
#include "heap.h"
#include "stackframe.h"
13
#include "debugtools.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
14

15
DEFAULT_DEBUG_CHANNEL(win32);
16

17
static SYSLEVEL Win16Mutex = { CRITICAL_SECTION_INIT, 1 };
Alexandre Julliard's avatar
Alexandre Julliard committed
18

Alexandre Julliard's avatar
Alexandre Julliard committed
19 20 21
/* Global variable to save current TEB while in 16-bit code */
WORD SYSLEVEL_Win16CurrentTeb = 0;

Alexandre Julliard's avatar
Alexandre Julliard committed
22 23

/************************************************************************
24
 *           GetpWin16Lock    (KERNEL32.93)
Alexandre Julliard's avatar
Alexandre Julliard committed
25
 */
26
VOID WINAPI GetpWin16Lock(SYSLEVEL **lock)
Alexandre Julliard's avatar
Alexandre Julliard committed
27 28 29 30 31 32 33
{
    *lock = &Win16Mutex;
}

/************************************************************************
 *           GetpWin16Lock16    (KERNEL.449)
 */
34 35 36 37 38 39 40 41 42
SEGPTR WINAPI GetpWin16Lock16(void)
{
    static SEGPTR segpWin16Mutex;
    if (!segpWin16Mutex)
    {
        SYSLEVEL **w16Mutex = SEGPTR_ALLOC(sizeof(SYSLEVEL *));
        *w16Mutex = &Win16Mutex;
        segpWin16Mutex = SEGPTR_GET(w16Mutex);
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
43 44 45 46
    return segpWin16Mutex;
}

/************************************************************************
47
 *           _CreateSysLevel    (KERNEL.438)
Alexandre Julliard's avatar
Alexandre Julliard committed
48
 */
49
VOID WINAPI _CreateSysLevel(SYSLEVEL *lock, INT level)
Alexandre Julliard's avatar
Alexandre Julliard committed
50
{
51 52 53
    InitializeCriticalSection( &lock->crst );
    lock->level = level;

54
    TRACE("(%p, %d): handle is %d\n", 
55 56 57 58 59 60 61 62
                  lock, level, lock->crst.LockSemaphore );
}

/************************************************************************
 *           _EnterSysLevel    (KERNEL32.97) (KERNEL.439)
 */
VOID WINAPI _EnterSysLevel(SYSLEVEL *lock)
{
63
    TEB *teb = NtCurrentTeb();
64 65
    int i;

Patrik Stridvall's avatar
Patrik Stridvall committed
66 67
    TRACE("(%p, level %d): thread %p (fs %04x, pid %ld) count before %ld\n", 
                  lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
68
                  teb->sys_count[lock->level] );
69 70

    for ( i = 3; i > lock->level; i-- )
71
        if ( teb->sys_count[i] > 0 )
72
        {
73
            ERR("(%p, level %d): Holding %p, level %d. Expect deadlock!\n", 
74
                        lock, lock->level, teb->sys_mutex[i], i );
75 76 77 78
        }

    EnterCriticalSection( &lock->crst );

79 80
    teb->sys_count[lock->level]++;
    teb->sys_mutex[lock->level] = lock;
81

Patrik Stridvall's avatar
Patrik Stridvall committed
82 83
    TRACE("(%p, level %d): thread %p (fs %04x, pid %ld) count after  %ld\n",
                  lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(), 
84
                  teb->sys_count[lock->level] );
Alexandre Julliard's avatar
Alexandre Julliard committed
85 86

    if (lock == &Win16Mutex)
87
        SYSLEVEL_Win16CurrentTeb = __get_fs();
Alexandre Julliard's avatar
Alexandre Julliard committed
88 89 90
}

/************************************************************************
91
 *           _LeaveSysLevel    (KERNEL32.98) (KERNEL.440)
Alexandre Julliard's avatar
Alexandre Julliard committed
92
 */
93
VOID WINAPI _LeaveSysLevel(SYSLEVEL *lock)
Alexandre Julliard's avatar
Alexandre Julliard committed
94
{
95
    TEB *teb = NtCurrentTeb();
96

Patrik Stridvall's avatar
Patrik Stridvall committed
97 98
    TRACE("(%p, level %d): thread %p (fs %04x, pid %ld) count before %ld\n", 
                  lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
99
                  teb->sys_count[lock->level] );
100

101
    if ( teb->sys_count[lock->level] <= 0 || teb->sys_mutex[lock->level] != lock )
102
    {
103
        ERR("(%p, level %d): Invalid state: count %ld mutex %p.\n",
104 105
                    lock, lock->level, teb->sys_count[lock->level], 
                    teb->sys_mutex[lock->level] );
106 107 108
    }
    else
    {
109 110
        if ( --teb->sys_count[lock->level] == 0 )
            teb->sys_mutex[lock->level] = NULL;
111 112 113 114
    }

    LeaveCriticalSection( &lock->crst );

Patrik Stridvall's avatar
Patrik Stridvall committed
115 116
    TRACE("(%p, level %d): thread %p (fs %04x, pid %ld) count after  %ld\n",
                  lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(), 
117
                  teb->sys_count[lock->level] );
Alexandre Julliard's avatar
Alexandre Julliard committed
118 119 120
}

/************************************************************************
121
 *		_KERNEL32_86 (KERNEL32.86)
Alexandre Julliard's avatar
Alexandre Julliard committed
122
 */
123
VOID WINAPI _KERNEL32_86(SYSLEVEL *lock)
Alexandre Julliard's avatar
Alexandre Julliard committed
124 125 126 127 128
{
    _LeaveSysLevel(lock);
}

/************************************************************************
129
 *           _ConfirmSysLevel    (KERNEL32.95) (KERNEL.436)
Alexandre Julliard's avatar
Alexandre Julliard committed
130
 */
131
DWORD WINAPI _ConfirmSysLevel(SYSLEVEL *lock)
Alexandre Julliard's avatar
Alexandre Julliard committed
132
{
133 134 135 136
    if ( lock && lock->crst.OwningThread == GetCurrentThreadId() )
        return lock->crst.RecursionCount;
    else
        return 0L;
Alexandre Julliard's avatar
Alexandre Julliard committed
137 138 139
}

/************************************************************************
140
 *           _CheckNotSysLevel    (KERNEL32.94) (KERNEL.437)
Alexandre Julliard's avatar
Alexandre Julliard committed
141
 */
142
VOID WINAPI _CheckNotSysLevel(SYSLEVEL *lock)
Alexandre Julliard's avatar
Alexandre Julliard committed
143
{
144
    FIXME("(%p)\n", lock);
Alexandre Julliard's avatar
Alexandre Julliard committed
145 146
}

147

Alexandre Julliard's avatar
Alexandre Julliard committed
148
/************************************************************************
149
 *           _EnterWin16Lock			[KERNEL.480]
Alexandre Julliard's avatar
Alexandre Julliard committed
150
 */
151
VOID WINAPI _EnterWin16Lock(void)
Alexandre Julliard's avatar
Alexandre Julliard committed
152
{
153
    _EnterSysLevel(&Win16Mutex);
Alexandre Julliard's avatar
Alexandre Julliard committed
154 155 156
}

/************************************************************************
157
 *           _LeaveWin16Lock		[KERNEL.481]
Alexandre Julliard's avatar
Alexandre Julliard committed
158
 */
159
VOID WINAPI _LeaveWin16Lock(void)
Alexandre Julliard's avatar
Alexandre Julliard committed
160
{
161
    _LeaveSysLevel(&Win16Mutex);
Alexandre Julliard's avatar
Alexandre Julliard committed
162
}
163

Alexandre Julliard's avatar
Alexandre Julliard committed
164 165 166 167 168
/************************************************************************
 *           _ConfirmWin16Lock    (KERNEL32.96)
 */
DWORD WINAPI _ConfirmWin16Lock(void)
{
169
    return _ConfirmSysLevel(&Win16Mutex);
Alexandre Julliard's avatar
Alexandre Julliard committed
170 171 172 173 174 175 176
}

/************************************************************************
 *           ReleaseThunkLock    (KERNEL32.48)
 */
VOID WINAPI ReleaseThunkLock(DWORD *mutex_count)
{
177
    DWORD count = _ConfirmSysLevel(&Win16Mutex);
Alexandre Julliard's avatar
Alexandre Julliard committed
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
    *mutex_count = count;

    while (count-- > 0)
        _LeaveSysLevel(&Win16Mutex);
}

/************************************************************************
 *           RestoreThunkLock    (KERNEL32.49)
 */
VOID WINAPI RestoreThunkLock(DWORD mutex_count)
{
    while (mutex_count-- > 0)
        _EnterSysLevel(&Win16Mutex);
}

193 194 195 196 197 198 199 200
/************************************************************************
 *           SYSLEVEL_CheckNotLevel
 */
VOID SYSLEVEL_CheckNotLevel( INT level )
{
    INT i;

    for ( i = 3; i >= level; i-- )
201
        if ( NtCurrentTeb()->sys_count[i] > 0 )
202
        {
203
            ERR("(%d): Holding lock of level %d!\n", 
204
                       level, i );
205
            DbgBreakPoint();
206 207
            break;
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
208
}