blob: dabc37c4ef6c20e5c27417b42b0a40f901ef5a71 [file] [log] [blame]
Alexandre Julliard02e90081998-01-04 17:49:09 +00001/*
2 * Win32 critical sections
3 *
4 * Copyright 1998 Alexandre Julliard
5 */
6
Alexandre Julliard02e90081998-01-04 17:49:09 +00007#include <assert.h>
8#include <errno.h>
9#include <stdio.h>
Alexandre Julliard60ce85c1998-02-01 18:33:27 +000010#include <sys/types.h>
Alexandre Julliard02e90081998-01-04 17:49:09 +000011#include "winerror.h"
12#include "winbase.h"
Alexandre Julliard6f1b6421999-11-24 01:14:04 +000013#include "ntddk.h"
Alexandre Julliard02e90081998-01-04 17:49:09 +000014#include "heap.h"
Alexandre Julliard06c275a1999-05-02 14:32:27 +000015#include "debugtools.h"
Alexandre Julliard02e90081998-01-04 17:49:09 +000016#include "thread.h"
17
Alexandre Julliard416a00d2000-04-08 20:50:06 +000018DEFAULT_DEBUG_CHANNEL(win32);
19DECLARE_DEBUG_CHANNEL(relay);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000020
Alexandre Julliard416a00d2000-04-08 20:50:06 +000021/***********************************************************************
Alexandre Julliardbaa15562000-09-29 00:31:23 +000022 * InitializeCriticalSection (KERNEL32.472)
Alexandre Julliard02e90081998-01-04 17:49:09 +000023 */
24void WINAPI InitializeCriticalSection( CRITICAL_SECTION *crit )
25{
Alexandre Julliardbaa15562000-09-29 00:31:23 +000026 NTSTATUS ret = RtlInitializeCriticalSection( crit );
27 if (ret) RtlRaiseStatus( ret );
Alexandre Julliard02e90081998-01-04 17:49:09 +000028}
29
Alexandre Julliard02e90081998-01-04 17:49:09 +000030/***********************************************************************
31 * MakeCriticalSectionGlobal (KERNEL32.515)
32 */
33void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit )
34{
Alexandre Julliardbaa15562000-09-29 00:31:23 +000035 /* let's assume that only one thread at a time will try to do this */
36 HANDLE sem = crit->LockSemaphore;
Alexandre Julliardafb49ea2000-09-29 20:48:04 +000037 if (!sem) NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 );
Alexandre Julliardbaa15562000-09-29 00:31:23 +000038 crit->LockSemaphore = ConvertToGlobalHandle( sem );
Alexandre Julliard02e90081998-01-04 17:49:09 +000039}
40
41
42/***********************************************************************
Alexandre Julliard60ce85c1998-02-01 18:33:27 +000043 * ReinitializeCriticalSection (KERNEL32.581)
44 */
45void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit )
46{
Ulrich Weiganda9880741999-04-25 11:03:59 +000047 if ( !crit->LockSemaphore )
Alexandre Julliardbaa15562000-09-29 00:31:23 +000048 RtlInitializeCriticalSection( crit );
Alexandre Julliard60ce85c1998-02-01 18:33:27 +000049}
Bertho Stultiens77f08f31999-04-15 16:42:50 +000050
51
52/***********************************************************************
53 * UninitializeCriticalSection (KERNEL32.703)
54 */
55void WINAPI UninitializeCriticalSection( CRITICAL_SECTION *crit )
56{
Alexandre Julliardbaa15562000-09-29 00:31:23 +000057 RtlDeleteCriticalSection( crit );
Bertho Stultiens77f08f31999-04-15 16:42:50 +000058}
Ulrich Weiganda9880741999-04-25 11:03:59 +000059
Alexandre Julliardca3c9ba2000-03-07 13:14:27 +000060#ifdef __i386__
61
Patrik Stridvall7980a502000-06-07 02:15:39 +000062/***********************************************************************
63 * InterlockCompareExchange (KERNEL32.@)
64 */
Patrik Stridvall98fde732000-03-24 20:43:33 +000065PVOID WINAPI InterlockedCompareExchange( PVOID *dest, PVOID xchg, PVOID compare );
Alexandre Julliardca3c9ba2000-03-07 13:14:27 +000066__ASM_GLOBAL_FUNC(InterlockedCompareExchange,
67 "movl 12(%esp),%eax\n\t"
68 "movl 8(%esp),%ecx\n\t"
69 "movl 4(%esp),%edx\n\t"
70 "lock; cmpxchgl %ecx,(%edx)\n\t"
71 "ret $12");
72
Patrik Stridvall7980a502000-06-07 02:15:39 +000073/***********************************************************************
74 * InterlockedExchange (KERNEL32.@)
75 */
Patrik Stridvall98fde732000-03-24 20:43:33 +000076LONG WINAPI InterlockedExchange( PLONG dest, LONG val );
Alexandre Julliardca3c9ba2000-03-07 13:14:27 +000077__ASM_GLOBAL_FUNC(InterlockedExchange,
78 "movl 8(%esp),%eax\n\t"
79 "movl 4(%esp),%edx\n\t"
80 "lock; xchgl %eax,(%edx)\n\t"
81 "ret $8");
82
Patrik Stridvall7980a502000-06-07 02:15:39 +000083/***********************************************************************
84 * InterlockedExchangeAdd (KERNEL32.@)
85 */
Patrik Stridvall98fde732000-03-24 20:43:33 +000086LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr );
Alexandre Julliardca3c9ba2000-03-07 13:14:27 +000087__ASM_GLOBAL_FUNC(InterlockedExchangeAdd,
88 "movl 8(%esp),%eax\n\t"
89 "movl 4(%esp),%edx\n\t"
90 "lock; xaddl %eax,(%edx)\n\t"
91 "ret $8");
92
Patrik Stridvall7980a502000-06-07 02:15:39 +000093/***********************************************************************
94 * InterlockedIncrement (KERNEL32.@)
95 */
Patrik Stridvall98fde732000-03-24 20:43:33 +000096LONG WINAPI InterlockedIncrement( PLONG dest );
Alexandre Julliardca3c9ba2000-03-07 13:14:27 +000097__ASM_GLOBAL_FUNC(InterlockedIncrement,
98 "movl 4(%esp),%edx\n\t"
99 "movl $1,%eax\n\t"
100 "lock; xaddl %eax,(%edx)\n\t"
101 "incl %eax\n\t"
102 "ret $4");
103
Patrik Stridvall7980a502000-06-07 02:15:39 +0000104/***********************************************************************
105 * InterlockDecrement (KERNEL32.@)
106 */
Patrik Stridvall98fde732000-03-24 20:43:33 +0000107LONG WINAPI InterlockedDecrement( PLONG dest );
Alexandre Julliardca3c9ba2000-03-07 13:14:27 +0000108__ASM_GLOBAL_FUNC(InterlockedDecrement,
109 "movl 4(%esp),%edx\n\t"
110 "movl $-1,%eax\n\t"
111 "lock; xaddl %eax,(%edx)\n\t"
112 "decl %eax\n\t"
113 "ret $4");
114
Ulrich Weigandafd6a4b2000-06-04 01:48:05 +0000115#elif defined(__sparc__) && defined(__sun__)
116
117/*
118 * As the earlier Sparc processors lack necessary atomic instructions,
119 * I'm simply falling back to the library-provided _lwp_mutex routines
120 * to ensure mutual exclusion in a way appropriate for the current
121 * architecture.
122 *
123 * FIXME: If we have the compare-and-swap instruction (Sparc v9 and above)
124 * we could use this to speed up the Interlocked operations ...
125 */
126
127#include <synch.h>
128static lwp_mutex_t interlocked_mutex = DEFAULTMUTEX;
129
Patrik Stridvall7980a502000-06-07 02:15:39 +0000130/***********************************************************************
131 * InterlockedCompareExchange (KERNEL32.@)
132 */
Ulrich Weigandafd6a4b2000-06-04 01:48:05 +0000133PVOID WINAPI InterlockedCompareExchange( PVOID *dest, PVOID xchg, PVOID compare )
134{
135 _lwp_mutex_lock( &interlocked_mutex );
136
137 if ( *dest == compare )
138 *dest = xchg;
139 else
140 compare = *dest;
141
142 _lwp_mutex_unlock( &interlocked_mutex );
143 return compare;
144}
145
Patrik Stridvall7980a502000-06-07 02:15:39 +0000146/***********************************************************************
147 * InterlockedExchange (KERNEL32.@)
148 */
Ulrich Weigandafd6a4b2000-06-04 01:48:05 +0000149LONG WINAPI InterlockedExchange( PLONG dest, LONG val )
150{
151 LONG retv;
152 _lwp_mutex_lock( &interlocked_mutex );
153
154 retv = *dest;
155 *dest = val;
156
157 _lwp_mutex_unlock( &interlocked_mutex );
158 return retv;
159}
160
Patrik Stridvall7980a502000-06-07 02:15:39 +0000161/***********************************************************************
162 * InterlockedExchangeAdd (KERNEL32.@)
163 */
Ulrich Weigandafd6a4b2000-06-04 01:48:05 +0000164LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr )
165{
166 LONG retv;
167 _lwp_mutex_lock( &interlocked_mutex );
168
169 retv = *dest;
170 *dest += incr;
171
172 _lwp_mutex_unlock( &interlocked_mutex );
173 return retv;
174}
175
Patrik Stridvall7980a502000-06-07 02:15:39 +0000176/***********************************************************************
177 * InterlockedIncrement (KERNEL32.@)
178 */
Ulrich Weigandafd6a4b2000-06-04 01:48:05 +0000179LONG WINAPI InterlockedIncrement( PLONG dest )
180{
181 LONG retv;
182 _lwp_mutex_lock( &interlocked_mutex );
183
184 retv = ++*dest;
185
186 _lwp_mutex_unlock( &interlocked_mutex );
187 return retv;
188}
189
Patrik Stridvall7980a502000-06-07 02:15:39 +0000190/***********************************************************************
191 * InterlockedDecrement (KERNEL32.@)
192 */
Ulrich Weigandafd6a4b2000-06-04 01:48:05 +0000193LONG WINAPI InterlockedDecrement( PLONG dest )
194{
195 LONG retv;
196 _lwp_mutex_lock( &interlocked_mutex );
197
198 retv = --*dest;
199
200 _lwp_mutex_unlock( &interlocked_mutex );
201 return retv;
202}
203
204#else
Alexandre Julliardca3c9ba2000-03-07 13:14:27 +0000205#error You must implement the Interlocked* functions for your CPU
Ulrich Weigandafd6a4b2000-06-04 01:48:05 +0000206#endif