1 /* thr_nt.c - wrapper around NT threads */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 *
5 * Copyright 1998-2021 The OpenLDAP Foundation.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
10 * Public License.
11 *
12 * A copy of this license is available in file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
15 */
16
17 #include "portable.h"
18
19 #if defined( HAVE_NT_THREADS )
20
21 #define _WIN32_WINNT 0x0400
22 #include <windows.h>
23 #include <process.h>
24
25 #include "ldap_pvt_thread.h" /* Get the thread interface */
26 #define LDAP_THREAD_IMPLEMENTATION
27 #include "ldap_thr_debug.h" /* May rename the symbols defined below */
28
29 typedef struct ldap_int_thread_s {
30 long tid;
31 HANDLE thd;
32 } ldap_int_thread_s;
33
34 #ifndef NT_MAX_THREADS
35 #define NT_MAX_THREADS 1024
36 #endif
37
38 static ldap_int_thread_s tids[NT_MAX_THREADS];
39 static int ntids;
40
41
42 /* mingw compiler very sensitive about getting prototypes right */
43 typedef unsigned __stdcall thrfunc_t(void *);
44
45 int
ldap_int_thread_initialize(void)46 ldap_int_thread_initialize( void )
47 {
48 return 0;
49 }
50
51 int
ldap_int_thread_destroy(void)52 ldap_int_thread_destroy( void )
53 {
54 return 0;
55 }
56
57 int
ldap_int_mutex_firstcreate(ldap_int_thread_mutex_t * mutex)58 ldap_int_mutex_firstcreate( ldap_int_thread_mutex_t *mutex )
59 {
60 if ( *mutex == NULL ) {
61 HANDLE p = CreateMutex( NULL, 0, NULL );
62 if ( InterlockedCompareExchangePointer((PVOID*)mutex, (PVOID)p, NULL) != NULL)
63 CloseHandle( p );
64 }
65 return 0;
66 }
67
68 int
ldap_pvt_thread_create(ldap_pvt_thread_t * thread,int detach,void * (* start_routine)(void *),void * arg)69 ldap_pvt_thread_create( ldap_pvt_thread_t * thread,
70 int detach,
71 void *(*start_routine)( void *),
72 void *arg)
73 {
74 unsigned tid;
75 HANDLE thd;
76 int rc = -1;
77
78 thd = (HANDLE) _beginthreadex(NULL, LDAP_PVT_THREAD_STACK_SIZE, (thrfunc_t *) start_routine,
79 arg, 0, &tid);
80
81 if ( thd ) {
82 *thread = (ldap_pvt_thread_t) tid;
83 tids[ntids].tid = tid;
84 tids[ntids].thd = thd;
85 ntids++;
86 rc = 0;
87 }
88 return rc;
89 }
90
91 void
ldap_pvt_thread_exit(void * retval)92 ldap_pvt_thread_exit( void *retval )
93 {
94 _endthread( );
95 }
96
97 int
ldap_pvt_thread_join(ldap_pvt_thread_t thread,void ** thread_return)98 ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return )
99 {
100 DWORD status;
101 int i;
102
103 for (i=0; i<ntids; i++) {
104 if ( tids[i].tid == thread )
105 break;
106 }
107 if ( i > ntids ) return -1;
108
109 status = WaitForSingleObject( tids[i].thd, INFINITE );
110 for (; i<ntids; i++) {
111 tids[i] = tids[i+1];
112 }
113 ntids--;
114 return status == WAIT_FAILED ? -1 : 0;
115 }
116
117 int
ldap_pvt_thread_kill(ldap_pvt_thread_t thread,int signo)118 ldap_pvt_thread_kill( ldap_pvt_thread_t thread, int signo )
119 {
120 return 0;
121 }
122
123 int
ldap_pvt_thread_yield(void)124 ldap_pvt_thread_yield( void )
125 {
126 Sleep( 0 );
127 return 0;
128 }
129
130 int
ldap_pvt_thread_cond_init(ldap_pvt_thread_cond_t * cond)131 ldap_pvt_thread_cond_init( ldap_pvt_thread_cond_t *cond )
132 {
133 *cond = CreateEvent( NULL, FALSE, FALSE, NULL );
134 return( 0 );
135 }
136
137 int
ldap_pvt_thread_cond_destroy(ldap_pvt_thread_cond_t * cv)138 ldap_pvt_thread_cond_destroy( ldap_pvt_thread_cond_t *cv )
139 {
140 CloseHandle( *cv );
141 return( 0 );
142 }
143
144 int
ldap_pvt_thread_cond_signal(ldap_pvt_thread_cond_t * cond)145 ldap_pvt_thread_cond_signal( ldap_pvt_thread_cond_t *cond )
146 {
147 SetEvent( *cond );
148 return( 0 );
149 }
150
151 int
ldap_pvt_thread_cond_wait(ldap_pvt_thread_cond_t * cond,ldap_pvt_thread_mutex_t * mutex)152 ldap_pvt_thread_cond_wait( ldap_pvt_thread_cond_t *cond,
153 ldap_pvt_thread_mutex_t *mutex )
154 {
155 SignalObjectAndWait( *mutex, *cond, INFINITE, FALSE );
156 WaitForSingleObject( *mutex, INFINITE );
157 return( 0 );
158 }
159
160 int
ldap_pvt_thread_cond_broadcast(ldap_pvt_thread_cond_t * cond)161 ldap_pvt_thread_cond_broadcast( ldap_pvt_thread_cond_t *cond )
162 {
163 while ( WaitForSingleObject( *cond, 0 ) == WAIT_TIMEOUT )
164 SetEvent( *cond );
165 return( 0 );
166 }
167
168 int
ldap_pvt_thread_mutex_init(ldap_pvt_thread_mutex_t * mutex)169 ldap_pvt_thread_mutex_init( ldap_pvt_thread_mutex_t *mutex )
170 {
171 *mutex = CreateMutex( NULL, 0, NULL );
172 return ( 0 );
173 }
174
175 int
ldap_pvt_thread_mutex_recursive_init(ldap_pvt_thread_mutex_t * mutex)176 ldap_pvt_thread_mutex_recursive_init( ldap_pvt_thread_mutex_t *mutex )
177 {
178 /* All NT mutexes are recursive */
179 return ldap_pvt_thread_mutex_init( mutex );
180 }
181
182 int
ldap_pvt_thread_mutex_destroy(ldap_pvt_thread_mutex_t * mutex)183 ldap_pvt_thread_mutex_destroy( ldap_pvt_thread_mutex_t *mutex )
184 {
185 CloseHandle( *mutex );
186 return ( 0 );
187 }
188
189 int
ldap_pvt_thread_mutex_lock(ldap_pvt_thread_mutex_t * mutex)190 ldap_pvt_thread_mutex_lock( ldap_pvt_thread_mutex_t *mutex )
191 {
192 DWORD status;
193 status = WaitForSingleObject( *mutex, INFINITE );
194 return status == WAIT_FAILED ? -1 : 0;
195 }
196
197 int
ldap_pvt_thread_mutex_unlock(ldap_pvt_thread_mutex_t * mutex)198 ldap_pvt_thread_mutex_unlock( ldap_pvt_thread_mutex_t *mutex )
199 {
200 ReleaseMutex( *mutex );
201 return ( 0 );
202 }
203
204 int
ldap_pvt_thread_mutex_trylock(ldap_pvt_thread_mutex_t * mp)205 ldap_pvt_thread_mutex_trylock( ldap_pvt_thread_mutex_t *mp )
206 {
207 DWORD status;
208 status = WaitForSingleObject( *mp, 0 );
209 return status == WAIT_FAILED || status == WAIT_TIMEOUT
210 ? -1 : 0;
211 }
212
213 ldap_pvt_thread_t
ldap_pvt_thread_self(void)214 ldap_pvt_thread_self( void )
215 {
216 return GetCurrentThreadId();
217 }
218
219 int
ldap_pvt_thread_key_create(ldap_pvt_thread_key_t * keyp)220 ldap_pvt_thread_key_create( ldap_pvt_thread_key_t *keyp )
221 {
222 DWORD key = TlsAlloc();
223 if ( key != TLS_OUT_OF_INDEXES ) {
224 *keyp = key;
225 return 0;
226 } else {
227 return -1;
228 }
229 }
230
231 int
ldap_pvt_thread_key_destroy(ldap_pvt_thread_key_t key)232 ldap_pvt_thread_key_destroy( ldap_pvt_thread_key_t key )
233 {
234 /* TlsFree returns 0 on failure */
235 return( TlsFree( key ) == 0 );
236 }
237
238 int
ldap_pvt_thread_key_setdata(ldap_pvt_thread_key_t key,void * data)239 ldap_pvt_thread_key_setdata( ldap_pvt_thread_key_t key, void *data )
240 {
241 return ( TlsSetValue( key, data ) == 0 );
242 }
243
244 int
ldap_pvt_thread_key_getdata(ldap_pvt_thread_key_t key,void ** data)245 ldap_pvt_thread_key_getdata( ldap_pvt_thread_key_t key, void **data )
246 {
247 void *ptr = TlsGetValue( key );
248 *data = ptr;
249 return( ptr ? GetLastError() : 0 );
250 }
251
252 #endif
253