Implemented NtDuplicateObject.
[wine] / scheduler / critsection.c
1 /*
2  * Win32 critical sections
3  *
4  * Copyright 1998 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <assert.h>
25 #include <errno.h>
26 #include <stdio.h>
27 #include <sys/types.h>
28
29 #include "winerror.h"
30 #include "winbase.h"
31 #include "winternl.h"
32 #include "wine/debug.h"
33 #include "thread.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(win32);
36 WINE_DECLARE_DEBUG_CHANNEL(relay);
37
38 /***********************************************************************
39  *           InitializeCriticalSection   (KERNEL32.@)
40  */
41 void WINAPI InitializeCriticalSection( CRITICAL_SECTION *crit )
42 {
43     NTSTATUS ret = RtlInitializeCriticalSection( crit );
44     if (ret) RtlRaiseStatus( ret );
45 }
46
47 /***********************************************************************
48  *           InitializeCriticalSectionAndSpinCount   (KERNEL32.@)
49  */
50 BOOL WINAPI InitializeCriticalSectionAndSpinCount( CRITICAL_SECTION *crit, DWORD spincount )
51 {
52     NTSTATUS ret = RtlInitializeCriticalSectionAndSpinCount( crit, spincount );
53     if (ret) RtlRaiseStatus( ret );
54     return !ret;
55 }
56
57 /***********************************************************************
58  *           SetCriticalSectionSpinCount   (KERNEL32.@)
59  * This function is available on NT4SP3 or later, but not Win98
60  * It is SMP related
61  */
62 DWORD WINAPI SetCriticalSectionSpinCount( CRITICAL_SECTION *crit, DWORD spincount )
63 {
64     ULONG_PTR oldspincount = crit->SpinCount;
65     if(spincount) FIXME("critsection=%p: spincount=%ld not supported\n", crit, spincount);
66     crit->SpinCount = spincount;
67     return oldspincount;
68 }
69
70 /***********************************************************************
71  *           MakeCriticalSectionGlobal   (KERNEL32.@)
72  */
73 void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit )
74 {
75     /* let's assume that only one thread at a time will try to do this */
76     HANDLE sem = crit->LockSemaphore;
77     if (!sem) NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 );
78     crit->LockSemaphore = ConvertToGlobalHandle( sem );
79 }
80
81
82 /***********************************************************************
83  *           ReinitializeCriticalSection   (KERNEL32.@)
84  */
85 void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit )
86 {
87     if ( !crit->LockSemaphore )
88         RtlInitializeCriticalSection( crit );
89 }
90
91
92 /***********************************************************************
93  *           UninitializeCriticalSection   (KERNEL32.@)
94  */
95 void WINAPI UninitializeCriticalSection( CRITICAL_SECTION *crit )
96 {
97     RtlDeleteCriticalSection( crit );
98 }
99
100 #ifdef __i386__
101
102 /***********************************************************************
103  *              InterlockedCompareExchange (KERNEL32.@)
104  */
105 /* LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare ); */
106 __ASM_GLOBAL_FUNC(InterlockedCompareExchange,
107                   "movl 12(%esp),%eax\n\t"
108                   "movl 8(%esp),%ecx\n\t"
109                   "movl 4(%esp),%edx\n\t"
110                   "lock; cmpxchgl %ecx,(%edx)\n\t"
111                   "ret $12");
112
113 /***********************************************************************
114  *              InterlockedExchange (KERNEL32.@)
115  */
116 /* LONG WINAPI InterlockedExchange( PLONG dest, LONG val ); */
117 __ASM_GLOBAL_FUNC(InterlockedExchange,
118                   "movl 8(%esp),%eax\n\t"
119                   "movl 4(%esp),%edx\n\t"
120                   "lock; xchgl %eax,(%edx)\n\t"
121                   "ret $8");
122
123 /***********************************************************************
124  *              InterlockedExchangeAdd (KERNEL32.@)
125  */
126 /* LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ); */
127 __ASM_GLOBAL_FUNC(InterlockedExchangeAdd,
128                   "movl 8(%esp),%eax\n\t"
129                   "movl 4(%esp),%edx\n\t"
130                   "lock; xaddl %eax,(%edx)\n\t"
131                   "ret $8");
132
133 /***********************************************************************
134  *              InterlockedIncrement (KERNEL32.@)
135  */
136 /* LONG WINAPI InterlockedIncrement( PLONG dest ); */
137 __ASM_GLOBAL_FUNC(InterlockedIncrement,
138                   "movl 4(%esp),%edx\n\t"
139                   "movl $1,%eax\n\t"
140                   "lock; xaddl %eax,(%edx)\n\t"
141                   "incl %eax\n\t"
142                   "ret $4");
143
144 /***********************************************************************
145  *              InterlockedDecrement (KERNEL32.@)
146  */
147 __ASM_GLOBAL_FUNC(InterlockedDecrement,
148                   "movl 4(%esp),%edx\n\t"
149                   "movl $-1,%eax\n\t"
150                   "lock; xaddl %eax,(%edx)\n\t"
151                   "decl %eax\n\t"
152                   "ret $4");
153
154 #else  /* __i386__ */
155
156 /***********************************************************************
157  *              InterlockedCompareExchange (KERNEL32.@)
158  */
159 LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare )
160 {
161     return interlocked_cmpxchg( dest, xchg, compare );
162 }
163
164 /***********************************************************************
165  *              InterlockedExchange (KERNEL32.@)
166  */
167 LONG WINAPI InterlockedExchange( PLONG dest, LONG val )
168 {
169     return interlocked_xchg( dest, val );
170 }
171
172 /***********************************************************************
173  *              InterlockedExchangeAdd (KERNEL32.@)
174  */
175 LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr )
176 {
177     return interlocked_xchg_add( dest, incr );
178 }
179
180 /***********************************************************************
181  *              InterlockedIncrement (KERNEL32.@)
182  */
183 LONG WINAPI InterlockedIncrement( PLONG dest )
184 {
185     return interlocked_xchg_add( dest, 1 ) + 1;
186 }
187
188 /***********************************************************************
189  *              InterlockedDecrement (KERNEL32.@)
190  */
191 LONG WINAPI InterlockedDecrement( PLONG dest )
192 {
193     return interlocked_xchg_add( dest, -1 ) - 1;
194 }
195
196 #endif  /* __i386__ */