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 51 ldap_int_thread_initialize( void ) 52 { 53 return 0; 54 } 55 56 int 57 ldap_int_thread_destroy( void ) 58 { 59 return 0; 60 } 61 62 int 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 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 97 ldap_pvt_thread_exit( void *retval ) 98 { 99 _endthread( ); 100 } 101 102 int 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 123 ldap_pvt_thread_kill( ldap_pvt_thread_t thread, int signo ) 124 { 125 return 0; 126 } 127 128 int 129 ldap_pvt_thread_yield( void ) 130 { 131 Sleep( 0 ); 132 return 0; 133 } 134 135 int 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 143 ldap_pvt_thread_cond_destroy( ldap_pvt_thread_cond_t *cv ) 144 { 145 CloseHandle( *cv ); 146 return( 0 ); 147 } 148 149 int 150 ldap_pvt_thread_cond_signal( ldap_pvt_thread_cond_t *cond ) 151 { 152 SetEvent( *cond ); 153 return( 0 ); 154 } 155 156 int 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 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 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 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 188 ldap_pvt_thread_mutex_destroy( ldap_pvt_thread_mutex_t *mutex ) 189 { 190 CloseHandle( *mutex ); 191 return ( 0 ); 192 } 193 194 int 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 203 ldap_pvt_thread_mutex_unlock( ldap_pvt_thread_mutex_t *mutex ) 204 { 205 ReleaseMutex( *mutex ); 206 return ( 0 ); 207 } 208 209 int 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 219 ldap_pvt_thread_self( void ) 220 { 221 return GetCurrentThreadId(); 222 } 223 224 int 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 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 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 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