Release 970329
[wine/multimedia.git] / win32 / thread.c
blob93153a09f4a650a7a358d480ff3a3f5aaa3463f5
1 /*
2 * Win32 kernel functions
4 * Copyright 1995 Martin von Loewis
5 * Copyright 1997 Onno Hovers
6 */
8 #include <stdio.h>
9 #include <unistd.h>
10 #include <string.h>
11 #include <sys/ipc.h>
12 #include <sys/sem.h>
13 #include "windows.h"
14 #include "winbase.h"
15 #include "winerror.h"
16 #include "stddebug.h"
17 #include "debug.h"
18 #include "xmalloc.h"
22 * FIXME:
23 * The c functions do not protect from non-interlocked accesses
24 * This is no problem as long as we do not have multiple Win32 threads
25 * or processes.
26 * The assembly macro's do protect from non-interlocked access,
27 * but they will only work for i386 systems with GCC.
30 /************************************************************************
31 * InterlockedIncrement [KERNEL32] *
32 * *
33 * InterlockedIncrement adds 1 to a long variable and returns *
34 * - a negative number if the result < 0 *
35 * - zero if the result == 0 *
36 * - a positive number if the result > 0 *
37 * *
38 * The returned number need not be equal to the result!!!! *
39 ************************************************************************/
41 LONG InterlockedIncrement(LPLONG lpAddend)
43 #if defined(__i386__)&&defined(__GNUC__)
44 long ret;
45 __asm__
47 "\tlock\n" /* for SMP systems */
48 "\tincl (%1)\n"
49 "\tje 2f\n"
50 "\tjl 1f\n"
51 "\tincl %0\n"
52 "\tjmp 2f\n"
53 "1:\tdec %0\n"
54 "2:\n"
55 :"=r" (ret):"r" (lpAddend), "0" (0): "memory"
57 return ret;
58 #else
59 LONG ret;
60 /* StopAllThreadsAndProcesses() */
62 (*lpAddend)++;
63 ret=*lpAddend;
65 /* ResumeAllThreadsAndProcesses() */
66 return ret;
67 #endif
70 /************************************************************************
71 * InterlockedDecrement [KERNEL32] *
72 * *
73 * InterlockedIncrement adds 1 to a long variable and returns *
74 * - a negative number if the result < 0 *
75 * - zero if the result == 0 *
76 * - a positive number if the result > 0 *
77 * *
78 * The returned number need not be equal to the result!!!! *
79 ************************************************************************/
81 LONG InterlockedDecrement(LPLONG lpAddend)
83 #if defined(__i386__)&&defined(__GNUC__)
84 LONG ret;
85 __asm__
87 "\tlock\n" /* for SMP systems */
88 "\tdecl (%1)\n"
89 "\tje 2f\n"
90 "\tjl 1f\n"
91 "\tincl %0\n"
92 "\tjmp 2f\n"
93 "1:\tdec %0\n"
94 "2:\n"
95 :"=r" (ret):"r" (lpAddend), "0" (0): "memory"
97 return ret;
98 #else
99 LONG ret;
100 /* StopAllThreadsAndProcesses() */
102 (*lpAddend)--;
103 ret=*lpAddend;
105 /* ResumeAllThreadsAndProcesses() */
106 return ret;
107 #endif
110 /************************************************************************
111 * InterlockedExchange [KERNEL32] *
112 ************************************************************************/
114 LONG InterlockedExchange(LPLONG target, LONG value)
116 #if defined(__i386__)&&defined(__GNUC__)
117 LONG ret;
118 __asm__
121 "\tlock\n" /* for SMP systems */
122 "\txchgl %0,(%1)\n"
123 :"=r" (ret):"r" (target), "0" (value):"memory"
125 return ret;
126 #else
127 LONG ret;
128 /* StopAllThreadsAndProcesses() */
130 ret=*target;
131 *target=value;
133 /* ResumeAllThreadsAndProcesses() */
134 return ret;
135 #endif
138 /* AAARGHH some CriticalSection functions get called before we
139 * have a threadid
142 #define GetCurrentThreadId() (-1)
144 /************************************************************************
145 * InitializeCriticalSection [KERNEL32] *
146 ************************************************************************/
148 void InitializeCriticalSection(CRITICAL_SECTION *pcritical)
150 pcritical->LockCount=-1;
151 pcritical->RecursionCount=0;
152 pcritical->LockSemaphore=(HANDLE32) semget(IPC_PRIVATE,1,IPC_CREAT);
153 pcritical->OwningThread=(HANDLE32) -1;
154 pcritical->Reserved=0;
157 /************************************************************************
158 * DeleteCriticalSection [KERNEL32] *
159 ************************************************************************/
161 void DeleteCriticalSection(CRITICAL_SECTION *pcritical)
163 semctl((int) pcritical->LockSemaphore,0,IPC_RMID,(union semun)NULL);
164 pcritical->Reserved=-1;
167 /************************************************************************
168 * EnterCriticalSection [KERNEL32] *
169 ************************************************************************/
171 void EnterCriticalSection (CRITICAL_SECTION *pcritical)
173 if( InterlockedIncrement(&(pcritical->LockCount)))
175 if( pcritical->OwningThread!= (HANDLE32) GetCurrentThreadId() )
177 struct sembuf sop;
179 sop.sem_num=0;
180 sop.sem_op=0;
181 sop.sem_flg=0;
182 semop((int) pcritical->LockSemaphore,&sop,0);
184 pcritical->OwningThread = (HANDLE32) GetCurrentThreadId();
187 else
189 pcritical->OwningThread =(HANDLE32) GetCurrentThreadId();
191 pcritical->RecursionCount++;
194 /************************************************************************
195 * TryEnterCriticalSection [KERNEL32] *
196 ************************************************************************/
198 BOOL32 TryEnterCriticalSection (CRITICAL_SECTION *pcritical)
200 if( InterlockedIncrement(&(pcritical->LockCount)))
202 if( pcritical->OwningThread!= (HANDLE32) GetCurrentThreadId() )
203 return FALSE;
205 else
207 pcritical->OwningThread =(HANDLE32) GetCurrentThreadId();
209 pcritical->RecursionCount++;
211 return TRUE;
214 /************************************************************************
215 * LeaveCriticalSection [KERNEL32] *
216 ************************************************************************/
218 void LeaveCriticalSection (CRITICAL_SECTION *pcritical)
220 /* do we actually own this critical section ??? */
221 if( pcritical->OwningThread!= (HANDLE32) GetCurrentThreadId())
222 return;
224 pcritical->RecursionCount--;
225 if( pcritical->RecursionCount==0)
227 pcritical->OwningThread=(HANDLE32)-1;
228 if(InterlockedDecrement(&(pcritical->LockCount))>=0)
230 struct sembuf sop;
232 sop.sem_num=0;
233 sop.sem_op=1;
234 sop.sem_flg=0;
235 semop((int) pcritical->LockSemaphore,&sop,0);
238 else
240 InterlockedDecrement(&(pcritical->LockCount));
244 /************************************************************************
245 * ReinitializeCriticalSection [KERNEL32] *
246 ************************************************************************/
248 void ReinitializeCriticalSection(CRITICAL_SECTION *lpCrit)
250 /* hmm ?????? */
253 /************************************************************************
254 * MakeCriticalSectionGlobal [KERNEL32] *
255 ************************************************************************/
257 void MakeCriticalSectionGlobal(CRITICAL_SECTION *lpCrit)
259 /* nothing (SysV Semaphores are already global) */
260 return;