Prep for fixups to tpool.
LDAP_F( void )
ldap_pvt_thread_exit LDAP_P(( void *retval ));
+LDAP_F( int )
+ldap_pvt_thread_detach LDAP_P(( ldap_pvt_thread_t thread ));
+
LDAP_F( int )
ldap_pvt_thread_join LDAP_P(( ldap_pvt_thread_t thread, void **status ));
ldap_pvt_thread_cond_wait;
ldap_pvt_thread_create;
ldap_pvt_thread_destroy;
+ ldap_pvt_thread_detach;
ldap_pvt_thread_exit;
ldap_pvt_thread_get_concurrency;
ldap_pvt_thread_initialize;
#define ldap_pvt_thread_set_concurrency ldap_int_thread_set_concurrency
#define ldap_pvt_thread_create ldap_int_thread_create
#define ldap_pvt_thread_exit ldap_int_thread_exit
+#define ldap_pvt_thread_detach ldap_int_thread_detach
#define ldap_pvt_thread_join ldap_int_thread_join
#define ldap_pvt_thread_kill ldap_int_thread_kill
#define ldap_pvt_thread_yield ldap_int_thread_yield
#ifdef LDAP_THREAD_DEBUG_WRAP /* see ldap_pvt_thread.h */
#define ldap_pvt_thread_pool_t ldap_int_thread_pool_t
#endif
-#define ldap_pvt_thread_pool_init ldap_int_thread_pool_init
+#define ldap_pvt_thread_pool_init_q ldap_int_thread_pool_init_q
#define ldap_pvt_thread_pool_submit ldap_int_thread_pool_submit
#define ldap_pvt_thread_pool_maxthreads ldap_int_thread_pool_maxthreads
#define ldap_pvt_thread_pool_backload ldap_int_thread_pool_backload
#undef ldap_pvt_thread_set_concurrency
#undef ldap_pvt_thread_create
#undef ldap_pvt_thread_exit
+#undef ldap_pvt_thread_detach
#undef ldap_pvt_thread_join
#undef ldap_pvt_thread_kill
#undef ldap_pvt_thread_yield
#undef ldap_pvt_thread_rdwr_active
/* LDAP_THREAD_POOL_IMPLEMENTATION: */
#undef ldap_pvt_thread_pool_t
-#undef ldap_pvt_thread_pool_init
+#undef ldap_pvt_thread_pool_init_q
#undef ldap_pvt_thread_pool_submit
#undef ldap_pvt_thread_pool_maxthreads
#undef ldap_pvt_thread_pool_backload
#define init_thread_info() {}
#define with_thread_info_lock(statements) { statements; }
#define thread_info_detached(t) 0
+#define thread_info_set_detach(t) 0
#define add_thread_info(msg, thr, det) ((void) 0)
#define remove_thread_info(tinfo, msg) ((void) 0)
#define get_thread_info(thread, msg) NULL
}
#define thread_info_detached(t) ((t)->detached)
+#define thread_info_set_detach(t) (t)->detached = 1
static void
add_thread_info(
return rc;
}
+int
+ldap_pvt_thread_detach( ldap_pvt_thread_t thread )
+{
+ int rc;
+ ldap_debug_thread_t *t = NULL;
+ ERROR_IF( !threading_enabled, "ldap_pvt_thread_detach" );
+ if( tracethreads ) {
+ char buf[40], buf2[40];
+ fprintf( stderr, "== thr_debug: Detaching thread %s in thread %s ==\n",
+ thread_name( buf, sizeof(buf), thread ),
+ thread_name( buf2, sizeof(buf2), ldap_pvt_thread_self() ) );
+ }
+ if( threadID )
+ with_thread_info_lock( {
+ t = get_thread_info( thread, "ldap_pvt_thread_detach" );
+ ERROR_IF( thread_info_detached( t ), "ldap_pvt_thread_detach" );
+ } );
+ rc = ldap_int_thread_detach( thread );
+ if( rc ) {
+ ERROR( rc, "ldap_pvt_thread_detach" );
+ } else {
+ if( threadID )
+ with_thread_info_lock(
+ thread_info_set_detach( t ) );
+ adjust_count( Idx_unjoined_thread, -1 );
+ }
+ return rc;
+}
+
int
ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return )
{
#ifdef LDAP_THREAD_POOL_IMPLEMENTATION
int
-ldap_pvt_thread_pool_init(
+ldap_pvt_thread_pool_init_q(
ldap_pvt_thread_pool_t *tpool,
int max_threads,
- int max_pending )
+ int max_pending,
+ int num_queues )
{
int rc;
if( !options_done )
get_options();
ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_init" );
- rc = ldap_int_thread_pool_init( tpool, max_threads, max_pending );
+ rc = ldap_int_thread_pool_init_q( tpool, max_threads, max_pending, num_queues );
if( rc ) {
- ERROR( rc, "ldap_pvt_thread_pool_init" );
+ ERROR( rc, "ldap_pvt_thread_pool_init_q" );
} else {
adjust_count( Idx_tpool, +1 );
}
static ldap_int_thread_s tids[NT_MAX_THREADS];
static int ntids;
+static ldap_pvt_thread_mutex_t tid_mutex;
/* mingw compiler very sensitive about getting prototypes right */
typedef unsigned __stdcall thrfunc_t(void *);
int
ldap_int_thread_initialize( void )
{
+ ldap_pvt_thread_mutex_init( &tid_mutex );
return 0;
}
int
ldap_int_thread_destroy( void )
{
+ ldap_pvt_thread_mutex_destroy( &tid_mutex );
return 0;
}
if ( thd ) {
*thread = (ldap_pvt_thread_t) tid;
+ ldap_pvt_thread_mutex_lock( &tid_mutex );
tids[ntids].tid = tid;
tids[ntids].thd = thd;
ntids++;
+ ldap_pvt_thread_mutex_unlock( &tid_mutex );
rc = 0;
}
return rc;
void
ldap_pvt_thread_exit( void *retval )
{
- _endthread( );
+ _endthreadex( (unsigned int)retval );
}
-int
-ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return )
+static int
+ldap_pvt_thread_pop( ldap_pvt_thread_t thread, HANDLE *thd )
{
- DWORD status;
- int i;
+ int i, rc = -1;
- for (i=0; i<ntids; i++) {
+ ldap_pvt_thread_mutex_lock( &tid_mutex );
+ for ( i=0; i<ntids; i++ ) {
if ( tids[i].tid == thread )
break;
}
- if ( i > ntids ) return -1;
+ if ( i<ntids ) {
+ *thd = tids[i].thd;
+ for (; i<ntids; i++) {
+ tids[i] = tids[i+1];
+ }
+ ntids--;
+ rc = 0;
+ }
+ ldap_pvt_thread_mutex_unlock( &tid_mutex );
+ return rc;
+}
+
+int
+ldap_pvt_thread_detach( ldap_pvt_thread_t thread )
+{
+ HANDLE thd;
+ int rc = ldap_pvt_thread_pop( thread, &thd );
- status = WaitForSingleObject( tids[i].thd, INFINITE );
- for (; i<ntids; i++) {
- tids[i] = tids[i+1];
+ if ( !rc )
+ CloseHandle( thd );
+ return rc;
+}
+
+int
+ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return )
+{
+ HANDLE thd;
+ int rc = ldap_pvt_thread_pop( thread, &thd );
+
+ if ( !rc ) {
+ DWORD status = WaitForSingleObject( thd, INFINITE );
+ if ( thread_return ) {
+ DWORD exitcode;
+ GetExitCodeThread( thd, &exitcode );
+ *thread_return = (void *)exitcode;
+ }
+ CloseHandle( thd );
+ rc = status == WAIT_FAILED ? -1 : 0;
}
- ntids--;
- return status == WAIT_FAILED ? -1 : 0;
+ return rc;
}
int
pthread_exit( retval );
}
+int
+ldap_pvt_thread_detach( ldap_pvt_thread_t thread )
+{
+ return ERRVAL( pthread_detach( thread ));
+}
+
int
ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return )
{
int
ldap_int_thread_destroy( void )
{
+ pth_attr_destroy(joined_attr);
pth_attr_destroy(detach_attr);
pth_kill();
return 0;
pth_exit( retval );
}
+int
+ldap_pvt_thread_detach( ldap_pvt_thread_t thread )
+{
+ pth_attr_t attr = pth_attr_of( thread );
+ if ( attr ) {
+ pth_attr_set( attr, PTH_ATTR_JOINABLE, FALSE );
+ pth_attr_destroy( attr );
+ }
+ return attr == NULL ? errno : 0;
+}
+
int ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return )
{
return pth_join( thread, thread_return ) ? 0 : errno;
void
ldap_pvt_thread_exit( void *retval )
{
- thr_exit( NULL );
+ thr_exit( retval );
+}
+
+int
+ldap_pvt_thread_detach( ldap_pvt_thread_t thread )
+{
+ /* there is no way to change the detach state of an existing thread
+ * so if it was created joinable, someone must clean it up with
+ * thr_join otherwise its thread ID is leaked.
+ */
+ return 0;
}
int ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return )