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