xref: /netbsd-src/external/bsd/openldap/dist/libraries/libldap/thr_nt.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
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