Rewrote module TLS support and moved it to ntdll.
[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 <stdio.h>
26 #include <sys/types.h>
27
28 #include "winerror.h"
29 #include "winbase.h"
30 #include "winternl.h"
31 #include "wine/debug.h"
32 #include "thread.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(win32);
35 WINE_DECLARE_DEBUG_CHANNEL(relay);
36
37 /***********************************************************************
38  *           InitializeCriticalSection   (KERNEL32.@)
39  */
40 void WINAPI InitializeCriticalSection( CRITICAL_SECTION *crit )
41 {
42     NTSTATUS ret = RtlInitializeCriticalSection( crit );
43     if (ret) RtlRaiseStatus( ret );
44 }
45
46 /***********************************************************************
47  *           InitializeCriticalSectionAndSpinCount   (KERNEL32.@)
48  */
49 BOOL WINAPI InitializeCriticalSectionAndSpinCount( CRITICAL_SECTION *crit, DWORD spincount )
50 {
51     NTSTATUS ret = RtlInitializeCriticalSectionAndSpinCount( crit, spincount );
52     if (ret) RtlRaiseStatus( ret );
53     return !ret;
54 }
55
56 /***********************************************************************
57  *           SetCriticalSectionSpinCount   (KERNEL32.@)
58  * This function is available on NT4SP3 or later, but not Win98
59  * It is SMP related
60  */
61 DWORD WINAPI SetCriticalSectionSpinCount( CRITICAL_SECTION *crit, DWORD spincount )
62 {
63     ULONG_PTR oldspincount = crit->SpinCount;
64     if(spincount) FIXME("critsection=%p: spincount=%ld not supported\n", crit, spincount);
65     crit->SpinCount = spincount;
66     return oldspincount;
67 }
68
69 /***********************************************************************
70  *           MakeCriticalSectionGlobal   (KERNEL32.@)
71  */
72 void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit )
73 {
74     /* let's assume that only one thread at a time will try to do this */
75     HANDLE sem = crit->LockSemaphore;
76     if (!sem) NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 );
77     crit->LockSemaphore = ConvertToGlobalHandle( sem );
78 }
79
80
81 /***********************************************************************
82  *           ReinitializeCriticalSection   (KERNEL32.@)
83  */
84 void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit )
85 {
86     if ( !crit->LockSemaphore )
87         RtlInitializeCriticalSection( crit );
88 }
89
90
91 /***********************************************************************
92  *           UninitializeCriticalSection   (KERNEL32.@)
93  */
94 void WINAPI UninitializeCriticalSection( CRITICAL_SECTION *crit )
95 {
96     RtlDeleteCriticalSection( crit );
97 }
98
99 #ifdef __i386__
100
101 /***********************************************************************
102  *              InterlockedCompareExchange (KERNEL32.@)
103  */
104 /* LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare ); */
105 __ASM_GLOBAL_FUNC(InterlockedCompareExchange,
106                   "movl 12(%esp),%eax\n\t"
107                   "movl 8(%esp),%ecx\n\t"
108                   "movl 4(%esp),%edx\n\t"
109                   "lock; cmpxchgl %ecx,(%edx)\n\t"
110                   "ret $12");
111
112 /***********************************************************************
113  *              InterlockedExchange (KERNEL32.@)
114  */
115 /* LONG WINAPI InterlockedExchange( PLONG dest, LONG val ); */
116 __ASM_GLOBAL_FUNC(InterlockedExchange,
117                   "movl 8(%esp),%eax\n\t"
118                   "movl 4(%esp),%edx\n\t"
119                   "lock; xchgl %eax,(%edx)\n\t"
120                   "ret $8");
121
122 /***********************************************************************
123  *              InterlockedExchangeAdd (KERNEL32.@)
124  */
125 /* LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ); */
126 __ASM_GLOBAL_FUNC(InterlockedExchangeAdd,
127                   "movl 8(%esp),%eax\n\t"
128                   "movl 4(%esp),%edx\n\t"
129                   "lock; xaddl %eax,(%edx)\n\t"
130                   "ret $8");
131
132 /***********************************************************************
133  *              InterlockedIncrement (KERNEL32.@)
134  */
135 /* LONG WINAPI InterlockedIncrement( PLONG dest ); */
136 __ASM_GLOBAL_FUNC(InterlockedIncrement,
137                   "movl 4(%esp),%edx\n\t"
138                   "movl $1,%eax\n\t"
139                   "lock; xaddl %eax,(%edx)\n\t"
140                   "incl %eax\n\t"
141                   "ret $4");
142
143 /***********************************************************************
144  *              InterlockedDecrement (KERNEL32.@)
145  */
146 __ASM_GLOBAL_FUNC(InterlockedDecrement,
147                   "movl 4(%esp),%edx\n\t"
148                   "movl $-1,%eax\n\t"
149                   "lock; xaddl %eax,(%edx)\n\t"
150                   "decl %eax\n\t"
151                   "ret $4");
152
153 #else  /* __i386__ */
154
155 /***********************************************************************
156  *              InterlockedCompareExchange (KERNEL32.@)
157  */
158 LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare )
159 {
160     return interlocked_cmpxchg( dest, xchg, compare );
161 }
162
163 /***********************************************************************
164  *              InterlockedExchange (KERNEL32.@)
165  */
166 LONG WINAPI InterlockedExchange( PLONG dest, LONG val )
167 {
168     return interlocked_xchg( dest, val );
169 }
170
171 /***********************************************************************
172  *              InterlockedExchangeAdd (KERNEL32.@)
173  */
174 LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr )
175 {
176     return interlocked_xchg_add( dest, incr );
177 }
178
179 /***********************************************************************
180  *              InterlockedIncrement (KERNEL32.@)
181  */
182 LONG WINAPI InterlockedIncrement( PLONG dest )
183 {
184     return interlocked_xchg_add( dest, 1 ) + 1;
185 }
186
187 /***********************************************************************
188  *              InterlockedDecrement (KERNEL32.@)
189  */
190 LONG WINAPI InterlockedDecrement( PLONG dest )
191 {
192     return interlocked_xchg_add( dest, -1 ) - 1;
193 }
194
195 #endif  /* __i386__ */