| /* |
| * Win32 kernel functions |
| * |
| * Copyright 1995 Martin von Loewis |
| * Copyright 1997 Onno Hovers |
| */ |
| |
| #include <stdio.h> |
| #include <unistd.h> |
| #include <string.h> |
| #include <sys/ipc.h> |
| #include <sys/sem.h> |
| #include "windows.h" |
| #include "winbase.h" |
| #include "winerror.h" |
| #include "stddebug.h" |
| #include "debug.h" |
| #include "xmalloc.h" |
| |
| |
| /* |
| * FIXME: |
| * The c functions do not protect from non-interlocked accesses |
| * This is no problem as long as we do not have multiple Win32 threads |
| * or processes. |
| * The assembly macro's do protect from non-interlocked access, |
| * but they will only work for i386 systems with GCC. |
| */ |
| |
| /************************************************************************ |
| * InterlockedIncrement [KERNEL32] * |
| * * |
| * InterlockedIncrement adds 1 to a long variable and returns * |
| * - a negative number if the result < 0 * |
| * - zero if the result == 0 * |
| * - a positive number if the result > 0 * |
| * * |
| * The returned number need not be equal to the result!!!! * |
| ************************************************************************/ |
| |
| LONG InterlockedIncrement(LPLONG lpAddend) |
| { |
| #if defined(__i386__)&&defined(__GNUC__) |
| long ret; |
| __asm__ |
| ( |
| "\tlock\n" /* for SMP systems */ |
| "\tincl (%1)\n" |
| "\tje 2f\n" |
| "\tjl 1f\n" |
| "\tincl %0\n" |
| "\tjmp 2f\n" |
| "1:\tdec %0\n" |
| "2:\n" |
| :"=r" (ret):"r" (lpAddend), "0" (0): "memory" |
| ); |
| return ret; |
| #else |
| LONG ret; |
| /* StopAllThreadsAndProcesses() */ |
| |
| (*lpAddend)++; |
| ret=*lpAddend; |
| |
| /* ResumeAllThreadsAndProcesses() */ |
| return ret; |
| #endif |
| } |
| |
| /************************************************************************ |
| * InterlockedDecrement [KERNEL32] * |
| * * |
| * InterlockedIncrement adds 1 to a long variable and returns * |
| * - a negative number if the result < 0 * |
| * - zero if the result == 0 * |
| * - a positive number if the result > 0 * |
| * * |
| * The returned number need not be equal to the result!!!! * |
| ************************************************************************/ |
| |
| LONG InterlockedDecrement(LPLONG lpAddend) |
| { |
| #if defined(__i386__)&&defined(__GNUC__) |
| LONG ret; |
| __asm__ |
| ( |
| "\tlock\n" /* for SMP systems */ |
| "\tdecl (%1)\n" |
| "\tje 2f\n" |
| "\tjl 1f\n" |
| "\tincl %0\n" |
| "\tjmp 2f\n" |
| "1:\tdec %0\n" |
| "2:\n" |
| :"=r" (ret):"r" (lpAddend), "0" (0): "memory" |
| ); |
| return ret; |
| #else |
| LONG ret; |
| /* StopAllThreadsAndProcesses() */ |
| |
| (*lpAddend)--; |
| ret=*lpAddend; |
| |
| /* ResumeAllThreadsAndProcesses() */ |
| return ret; |
| #endif |
| } |
| |
| /************************************************************************ |
| * InterlockedExchange [KERNEL32] * |
| ************************************************************************/ |
| |
| LONG InterlockedExchange(LPLONG target, LONG value) |
| { |
| #if defined(__i386__)&&defined(__GNUC__) |
| LONG ret; |
| __asm__ |
| ( |
| |
| "\tlock\n" /* for SMP systems */ |
| "\txchgl %0,(%1)\n" |
| :"=r" (ret):"r" (target), "0" (value):"memory" |
| ); |
| return ret; |
| #else |
| LONG ret; |
| /* StopAllThreadsAndProcesses() */ |
| |
| ret=*target; |
| *target=value; |
| |
| /* ResumeAllThreadsAndProcesses() */ |
| return ret; |
| #endif |
| } |
| |
| /* AAARGHH some CriticalSection functions get called before we |
| * have a threadid |
| */ |
| |
| #define GetCurrentThreadId() (-1) |
| |
| /************************************************************************ |
| * InitializeCriticalSection [KERNEL32] * |
| ************************************************************************/ |
| |
| void InitializeCriticalSection(CRITICAL_SECTION *pcritical) |
| { |
| pcritical->LockCount=-1; |
| pcritical->RecursionCount=0; |
| pcritical->LockSemaphore=(HANDLE32) semget(IPC_PRIVATE,1,IPC_CREAT); |
| pcritical->OwningThread=(HANDLE32) -1; |
| pcritical->Reserved=0; |
| } |
| |
| /************************************************************************ |
| * DeleteCriticalSection [KERNEL32] * |
| ************************************************************************/ |
| |
| void DeleteCriticalSection(CRITICAL_SECTION *pcritical) |
| { |
| semctl((int) pcritical->LockSemaphore,0,IPC_RMID,(union semun)NULL); |
| pcritical->Reserved=-1; |
| } |
| |
| /************************************************************************ |
| * EnterCriticalSection [KERNEL32] * |
| ************************************************************************/ |
| |
| void EnterCriticalSection (CRITICAL_SECTION *pcritical) |
| { |
| if( InterlockedIncrement(&(pcritical->LockCount))) |
| { |
| if( pcritical->OwningThread!= (HANDLE32) GetCurrentThreadId() ) |
| { |
| struct sembuf sop; |
| |
| sop.sem_num=0; |
| sop.sem_op=0; |
| sop.sem_flg=0; |
| semop((int) pcritical->LockSemaphore,&sop,0); |
| |
| pcritical->OwningThread = (HANDLE32) GetCurrentThreadId(); |
| } |
| } |
| else |
| { |
| pcritical->OwningThread =(HANDLE32) GetCurrentThreadId(); |
| } |
| pcritical->RecursionCount++; |
| } |
| |
| /************************************************************************ |
| * TryEnterCriticalSection [KERNEL32] * |
| ************************************************************************/ |
| |
| BOOL32 TryEnterCriticalSection (CRITICAL_SECTION *pcritical) |
| { |
| if( InterlockedIncrement(&(pcritical->LockCount))) |
| { |
| if( pcritical->OwningThread!= (HANDLE32) GetCurrentThreadId() ) |
| return FALSE; |
| } |
| else |
| { |
| pcritical->OwningThread =(HANDLE32) GetCurrentThreadId(); |
| } |
| pcritical->RecursionCount++; |
| |
| return TRUE; |
| } |
| |
| /************************************************************************ |
| * LeaveCriticalSection [KERNEL32] * |
| ************************************************************************/ |
| |
| void LeaveCriticalSection (CRITICAL_SECTION *pcritical) |
| { |
| /* do we actually own this critical section ??? */ |
| if( pcritical->OwningThread!= (HANDLE32) GetCurrentThreadId()) |
| return; |
| |
| pcritical->RecursionCount--; |
| if( pcritical->RecursionCount==0) |
| { |
| pcritical->OwningThread=(HANDLE32)-1; |
| if(InterlockedDecrement(&(pcritical->LockCount))>=0) |
| { |
| struct sembuf sop; |
| |
| sop.sem_num=0; |
| sop.sem_op=1; |
| sop.sem_flg=0; |
| semop((int) pcritical->LockSemaphore,&sop,0); |
| } |
| } |
| else |
| { |
| InterlockedDecrement(&(pcritical->LockCount)); |
| } |
| } |
| |
| /************************************************************************ |
| * ReinitializeCriticalSection [KERNEL32] * |
| ************************************************************************/ |
| |
| void ReinitializeCriticalSection(CRITICAL_SECTION *lpCrit) |
| { |
| /* hmm ?????? */ |
| } |
| |
| /************************************************************************ |
| * MakeCriticalSectionGlobal [KERNEL32] * |
| ************************************************************************/ |
| |
| void MakeCriticalSectionGlobal(CRITICAL_SECTION *lpCrit) |
| { |
| /* nothing (SysV Semaphores are already global) */ |
| return; |
| } |
| |