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