123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338 |
- /* thr_debug.c - wrapper around the chosen thread wrapper, for debugging. */
- /* $OpenLDAP$ */
- /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2005-2022 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
- /*
- * This package provides several types of thread operation debugging:
- *
- * - Check the results of operations on threads, mutexes, condition
- * variables and read/write locks. Also check some thread pool
- * operations, but not those for which failure can happen in normal
- * slapd operation.
- *
- * - Wrap those types except threads and pools in structs with state
- * information, and check that on all operations:
- *
- * + Check that the resources are initialized and are only used at
- * their original address (i.e. not realloced or copied).
- *
- * + Check the owner (thread ID) on mutex operations.
- *
- * + Optionally allocate a reference to a byte of dummy memory.
- * This lets malloc debuggers see some incorrect use as memory
- * leaks, access to freed memory, etc.
- *
- * - Print an error message and by default abort() upon errors.
- *
- * - Print a count of leaked thread resources after cleanup.
- *
- * Compile-time (./configure) setup: Macros defined in CPPFLAGS.
- *
- * LDAP_THREAD_DEBUG or LDAP_THREAD_DEBUG=2
- * Enables debugging, but value & 2 turns off type wrapping.
- *
- * LDAP_UINTPTR_T=integer type to hold pointers, preferably unsigned.
- * Used by dummy memory option "scramble". Default = unsigned long.
- *
- * LDAP_DEBUG_THREAD_NONE = initializer for a "no thread" thread ID.
- *
- * In addition, you may need to set up an implementation-specific way
- * to enable whatever error checking your thread library provides.
- * Currently only implemented for Posix threads (pthreads), where
- * you may need to define LDAP_INT_THREAD_MUTEXATTR. The default
- * is PTHREAD_MUTEX_ERRORCHECK, or PTHREAD_MUTEX_ERRORCHECK_NP for
- * Linux threads. See pthread_mutexattr_settype(3).
- *
- * Run-time configuration:
- *
- * Memory debugging tools:
- * Tools that report uninitialized memory accesses should disable
- * such warnings about the function debug_already_initialized().
- * Alternatively, include "noreinit" (below) in $LDAP_THREAD_DEBUG.
- *
- * Environment variable $LDAP_THREAD_DEBUG:
- * The variable may contain a comma- or space-separated option list.
- * Options:
- * off - Disable this package. (It still slows things down).
- * tracethreads - Report create/join/exit/kill of threads.
- * noabort - Do not abort() on errors.
- * noerror - Do not report errors. Implies noabort.
- * nocount - Do not report counts of unreleased resources.
- * nosync - Disable tests that use synchronization and thus
- * clearly affect thread scheduling:
- * Implies nocount, and cancels threadID if that is set.
- * Note that if you turn on tracethreads or malloc
- * debugging, these also use library calls which may
- * affect thread scheduling (fprintf and malloc).
- * The following options do not apply if type wrapping is disabled:
- * nomem - Do not check memory operations.
- * Implies noreinit,noalloc.
- * noreinit - Do not catch reinitialization of existing resources.
- * (That test accesses uninitialized memory).
- * threadID - Trace thread IDs. Currently mostly useless.
- * Malloc debugging -- allocate dummy memory for initialized
- * resources, so malloc debuggers will report them as memory leaks:
- * noalloc - Default. Do not allocate dummy memory.
- * alloc - Store a pointer to dummy memory. However, leak
- * detectors might not catch unreleased resources in
- * global variables.
- * scramble - Store bitwise complement of dummy memory pointer.
- * That never escapes memory leak detectors -
- * but detection while the program is running will
- * report active resources as leaks. Do not
- * use this if a garbage collector is in use:-)
- * adjptr - Point to end of dummy memory.
- * Purify reports these as "potential leaks" (PLK).
- * I have not checked other malloc debuggers.
- */
- #include "portable.h"
- #if defined( LDAP_THREAD_DEBUG )
- #include <stdio.h>
- #include <ac/errno.h>
- #include <ac/stdlib.h>
- #include <ac/string.h>
- #include "ldap_pvt_thread.h" /* Get the thread interface */
- #define LDAP_THREAD_IMPLEMENTATION
- #define LDAP_THREAD_DEBUG_IMPLEMENTATION
- #define LDAP_THREAD_RDWR_IMPLEMENTATION
- #define LDAP_THREAD_POOL_IMPLEMENTATION
- #include "ldap_thr_debug.h" /* Get the underlying implementation */
- #ifndef LDAP_THREAD_DEBUG_WRAP
- #undef LDAP_THREAD_DEBUG_THREAD_ID
- #elif !defined LDAP_THREAD_DEBUG_THREAD_ID
- #define LDAP_THREAD_DEBUG_THREAD_ID 1
- #endif
- /* Use native malloc - the OpenLDAP wrappers may defeat malloc debuggers */
- #undef malloc
- #undef calloc
- #undef realloc
- #undef free
- /* Options from environment variable $LDAP_THREAD_DEBUG */
- enum { Count_no = 0, Count_yes, Count_reported, Count_reported_more };
- static int count = Count_yes;
- #ifdef LDAP_THREAD_DEBUG_WRAP
- enum { Wrap_noalloc, Wrap_alloc, Wrap_scramble, Wrap_adjptr };
- static int wraptype = Wrap_noalloc, wrap_offset, unwrap_offset;
- static int nomem, noreinit;
- #endif
- #if LDAP_THREAD_DEBUG_THREAD_ID +0
- static int threadID;
- #else
- enum { threadID = 0 };
- #endif
- static int nodebug, noabort, noerror, nosync, tracethreads;
- static int wrap_threads;
- static int options_done;
- /* ldap_pvt_thread_initialize() called, ldap_pvt_thread_destroy() not called */
- static int threading_enabled;
- /* Resource counts */
- enum {
- Idx_unexited_thread, Idx_unjoined_thread, Idx_locked_mutex,
- Idx_mutex, Idx_cond, Idx_rdwr, Idx_tpool, Idx_max
- };
- static int resource_counts[Idx_max];
- static const char *const resource_names[] = {
- "unexited threads", "unjoined threads", "locked mutexes",
- "mutexes", "conds", "rdwrs", "thread pools"
- };
- static ldap_int_thread_mutex_t resource_mutexes[Idx_max];
- /* Hide pointers from malloc debuggers. */
- #define SCRAMBLE(ptr) (~(LDAP_UINTPTR_T) (ptr))
- #define UNSCRAMBLE_usagep(num) ((ldap_debug_usage_info_t *) ~(num))
- #define UNSCRAMBLE_dummyp(num) ((unsigned char *) ~(num))
- #define WARN(var, msg) (warn (__FILE__, __LINE__, (msg), #var, (var)))
- #define WARN_IF(rc, msg) {if (rc) warn (__FILE__, __LINE__, (msg), #rc, (rc));}
- #define ERROR(var, msg) { \
- if (!noerror) { \
- errmsg(__FILE__, __LINE__, (msg), #var, (var)); \
- if( !noabort ) abort(); \
- } \
- }
- #define ERROR_IF(rc, msg) { \
- if (!noerror) { \
- int rc_ = (rc); \
- if (rc_) { \
- errmsg(__FILE__, __LINE__, (msg), #rc, rc_); \
- if( !noabort ) abort(); \
- } \
- } \
- }
- #ifdef LDAP_THREAD_DEBUG_WRAP
- #define MEMERROR_IF(rc, msg, mem_act) { \
- if (!noerror) { \
- int rc_ = (rc); \
- if (rc_) { \
- errmsg(__FILE__, __LINE__, (msg), #rc, rc_); \
- if( wraptype != Wrap_noalloc ) { mem_act; } \
- if( !noabort ) abort(); \
- } \
- } \
- }
- #endif /* LDAP_THREAD_DEBUG_WRAP */
- #if 0
- static void
- warn( const char *file, int line, const char *msg, const char *var, int val )
- {
- fprintf( stderr,
- (strpbrk( var, "!=" )
- ? "%s:%d: %s warning: %s\n"
- : "%s:%d: %s warning: %s is %d\n"),
- file, line, msg, var, val );
- }
- #endif
- static void
- errmsg( const char *file, int line, const char *msg, const char *var, int val )
- {
- fprintf( stderr,
- (strpbrk( var, "!=" )
- ? "%s:%d: %s error: %s\n"
- : "%s:%d: %s error: %s is %d\n"),
- file, line, msg, var, val );
- }
- static void
- count_resource_leaks( void )
- {
- int i, j;
- char errbuf[200];
- if( count == Count_yes ) {
- count = Count_reported;
- #if 0 /* Could break if there are still threads after atexit */
- for( i = j = 0; i < Idx_max; i++ )
- j |= ldap_int_thread_mutex_destroy( &resource_mutexes[i] );
- WARN_IF( j, "ldap_debug_thread_destroy:mutexes" );
- #endif
- for( i = j = 0; i < Idx_max; i++ )
- if( resource_counts[i] )
- j += sprintf( errbuf + j, ", %d %s",
- resource_counts[i], resource_names[i] );
- if( j )
- fprintf( stderr, "== thr_debug: Leaked%s. ==\n", errbuf + 1 );
- }
- }
- static void
- get_options( void )
- {
- static const struct option_info_s {
- const char *name;
- int *var, val;
- } option_info[] = {
- { "off", &nodebug, 1 },
- { "noabort", &noabort, 1 },
- { "noerror", &noerror, 1 },
- { "nocount", &count, Count_no },
- { "nosync", &nosync, 1 },
- #if LDAP_THREAD_DEBUG_THREAD_ID +0
- { "threadID", &threadID, 1 },
- #endif
- #ifdef LDAP_THREAD_DEBUG_WRAP
- { "nomem", &nomem, 1 },
- { "noreinit", &noreinit, 1 },
- { "noalloc", &wraptype, Wrap_noalloc },
- { "alloc", &wraptype, Wrap_alloc },
- { "adjptr", &wraptype, Wrap_adjptr },
- { "scramble", &wraptype, Wrap_scramble },
- #endif
- { "tracethreads", &tracethreads, 1 },
- { NULL, NULL, 0 }
- };
- const char *s = getenv( "LDAP_THREAD_DEBUG" );
- if( s != NULL ) {
- while( *(s += strspn( s, ", \t\r\n" )) != '\0' ) {
- size_t optlen = strcspn( s, ", \t\r\n" );
- const struct option_info_s *oi = option_info;
- while( oi->name &&
- (strncasecmp( oi->name, s, optlen ) || oi->name[optlen]) )
- oi++;
- if( oi->name )
- *oi->var = oi->val;
- else
- fprintf( stderr,
- "== thr_debug: Unknown $%s option '%.*s' ==\n",
- "LDAP_THREAD_DEBUG", (int) optlen, s );
- s += optlen;
- }
- }
- if( nodebug ) {
- tracethreads = 0;
- nosync = noerror = 1;
- }
- if( nosync )
- count = Count_no;
- if( noerror )
- noabort = 1;
- #if LDAP_THREAD_DEBUG_THREAD_ID +0
- if( nosync )
- threadID = 0;
- #endif
- #ifdef LDAP_THREAD_DEBUG_WRAP
- if( noerror )
- nomem = 1;
- if( !nomem ) {
- static const ldap_debug_usage_info_t usage;
- if( sizeof(LDAP_UINTPTR_T) < sizeof(unsigned char *)
- || sizeof(LDAP_UINTPTR_T) < sizeof(ldap_debug_usage_info_t *)
- || UNSCRAMBLE_usagep( SCRAMBLE( &usage ) ) != &usage
- || UNSCRAMBLE_dummyp( SCRAMBLE( (unsigned char *) 0 ) ) )
- {
- fputs( "== thr_debug: Memory checks unsupported, "
- "adding nomem to $LDAP_THREAD_DEBUG ==\n", stderr );
- nomem = 1;
- }
- }
- if( nomem ) {
- noreinit = 1;
- wraptype = Wrap_noalloc;
- }
- unwrap_offset = -(wrap_offset = (wraptype == Wrap_adjptr));
- #endif
- wrap_threads = (tracethreads || threadID || count);
- options_done = 1;
- }
- #ifndef LDAP_THREAD_DEBUG_WRAP
- #define WRAPPED(ptr) (ptr)
- #define GET_OWNER(ptr) 0
- #define SET_OWNER(ptr, thread) ((void) 0)
- #define RESET_OWNER(ptr) ((void) 0)
- #define ASSERT_OWNER(ptr, msg) ((void) 0)
- #define ASSERT_NO_OWNER(ptr, msg) ((void) 0)
- #define init_usage(ptr, msg) ((void) 0)
- #define check_usage(ptr, msg) ((void) 0)
- #define destroy_usage(ptr) ((void) 0)
- #else /* LDAP_THREAD_DEBUG_WRAP */
- /* Specialize this if the initializer is not appropriate. */
- /* The ASSERT_NO_OWNER() definition may also need an override. */
- #ifndef LDAP_DEBUG_THREAD_NONE
- #define LDAP_DEBUG_THREAD_NONE { -1 } /* "no thread" ldap_int_thread_t value */
- #endif
- static const ldap_int_thread_t ldap_debug_thread_none = LDAP_DEBUG_THREAD_NONE;
- #define THREAD_MUTEX_OWNER(mutex) \
- ldap_int_thread_equal( (mutex)->owner, ldap_int_thread_self() )
- void
- ldap_debug_thread_assert_mutex_owner(
- const char *file,
- int line,
- const char *msg,
- ldap_pvt_thread_mutex_t *mutex )
- {
- if( !(noerror || THREAD_MUTEX_OWNER( mutex )) ) {
- errmsg( file, line, msg, "ASSERT_MUTEX_OWNER", 0 );
- if( !noabort ) abort();
- }
- }
- #define WRAPPED(ptr) (&(ptr)->wrapped)
- #define GET_OWNER(ptr) ((ptr)->owner)
- #define SET_OWNER(ptr, thread) ((ptr)->owner = (thread))
- #define RESET_OWNER(ptr) ((ptr)->owner = ldap_debug_thread_none)
- #define ASSERT_OWNER(ptr, msg) ERROR_IF( !THREAD_MUTEX_OWNER( ptr ), msg )
- #ifndef ASSERT_NO_OWNER
- #define ASSERT_NO_OWNER(ptr, msg) ERROR_IF( \
- !ldap_int_thread_equal( (ptr)->owner, ldap_debug_thread_none ), msg )
- #endif
- /* Try to provoke memory access error (for malloc debuggers) */
- #define PEEK(mem) {if (-*(volatile const unsigned char *)(mem)) debug_noop();}
- static void debug_noop( void );
- static int debug_already_initialized( const ldap_debug_usage_info_t *usage );
- /* Name used for clearer error message */
- #define IS_COPY_OR_MOVED(usage) ((usage)->self != SCRAMBLE( usage ))
- #define DUMMY_ADDR(usage) \
- (wraptype == Wrap_scramble \
- ? UNSCRAMBLE_dummyp( (usage)->mem.num ) \
- : (usage)->mem.ptr + unwrap_offset)
- /* Mark resource as initialized */
- static void
- init_usage( ldap_debug_usage_info_t *usage, const char *msg )
- {
- if( !options_done )
- get_options();
- if( !nomem ) {
- if( !noreinit ) {
- MEMERROR_IF( debug_already_initialized( usage ), msg, {
- /* Provoke malloc debuggers */
- unsigned char *dummy = DUMMY_ADDR( usage );
- PEEK( dummy );
- free( dummy );
- free( dummy );
- } );
- }
- if( wraptype != Wrap_noalloc ) {
- unsigned char *dummy = malloc( 1 );
- assert( dummy != NULL );
- if( wraptype == Wrap_scramble ) {
- usage->mem.num = SCRAMBLE( dummy );
- /* Verify that ptr<->integer casts work on this host */
- assert( UNSCRAMBLE_dummyp( usage->mem.num ) == dummy );
- } else {
- usage->mem.ptr = dummy + wrap_offset;
- }
- }
- } else {
- /* Unused, but set for readability in debugger */
- usage->mem.ptr = NULL;
- }
- usage->self = SCRAMBLE( usage ); /* If nomem, only for debugger */
- usage->magic = ldap_debug_magic;
- usage->state = ldap_debug_state_inited;
- }
- /* Check that resource is initialized and not copied/realloced */
- static void
- check_usage( const ldap_debug_usage_info_t *usage, const char *msg )
- {
- enum { Is_destroyed = 1 }; /* Name used for clearer error message */
- if( usage->magic != ldap_debug_magic ) {
- ERROR( usage->magic, msg );
- return;
- }
- switch( usage->state ) {
- case ldap_debug_state_destroyed:
- MEMERROR_IF( Is_destroyed, msg, {
- PEEK( DUMMY_ADDR( usage ) );
- } );
- break;
- default:
- ERROR( usage->state, msg );
- break;
- case ldap_debug_state_inited:
- if( !nomem ) {
- MEMERROR_IF( IS_COPY_OR_MOVED( usage ), msg, {
- PEEK( DUMMY_ADDR( usage ) );
- PEEK( UNSCRAMBLE_usagep( usage->self ) );
- } );
- }
- break;
- }
- }
- /* Mark resource as destroyed. */
- /* Does not check for errors, call check_usage()/init_usage() first. */
- static void
- destroy_usage( ldap_debug_usage_info_t *usage )
- {
- if( usage->state == ldap_debug_state_inited ) {
- if( wraptype != Wrap_noalloc ) {
- free( DUMMY_ADDR( usage ) );
- /* Do not reset the DUMMY_ADDR, leave it for malloc debuggers
- * in case the resource is used after it is freed. */
- }
- usage->state = ldap_debug_state_destroyed;
- }
- }
- /* Define these after they are used, so they are hopefully not inlined */
- static void
- debug_noop( void )
- {
- }
- /*
- * Valid programs access uninitialized memory here unless "noreinit".
- *
- * Returns true if the resource is initialized and not copied/realloced.
- */
- LDAP_GCCATTR((noinline))
- static int
- debug_already_initialized( const ldap_debug_usage_info_t *usage )
- {
- /*
- * 'ret' keeps the Valgrind warning "Conditional jump or move
- * depends on uninitialised value(s)" _inside_ this function.
- */
- volatile int ret = 0;
- if( usage->state == ldap_debug_state_inited )
- if( !IS_COPY_OR_MOVED( usage ) )
- if( usage->magic == ldap_debug_magic )
- ret = 1;
- return ret;
- }
- #endif /* LDAP_THREAD_DEBUG_WRAP */
- #if !(LDAP_THREAD_DEBUG_THREAD_ID +0)
- typedef void ldap_debug_thread_t;
- #define init_thread_info() {}
- #define with_thread_info_lock(statements) { statements; }
- #define thread_info_detached(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
- #else /* LDAP_THREAD_DEBUG_THREAD_ID */
- /*
- * Thread ID tracking. Currently achieves little.
- * Should be either expanded or deleted.
- */
- /*
- * Array of threads. Used instead of making ldap_pvt_thread_t a wrapper
- * around ldap_int_thread_t, which would slow down ldap_pvt_thread_self().
- */
- typedef struct {
- ldap_pvt_thread_t wrapped;
- ldap_debug_usage_info_t usage;
- int detached;
- int idx;
- } ldap_debug_thread_t;
- static ldap_debug_thread_t **thread_info;
- static unsigned int thread_info_size, thread_info_used;
- static ldap_int_thread_mutex_t thread_info_mutex;
- #define init_thread_info() { \
- if( threadID ) { \
- int mutex_init_rc = ldap_int_thread_mutex_init( &thread_info_mutex ); \
- assert( mutex_init_rc == 0 ); \
- } \
- }
- #define with_thread_info_lock(statements) { \
- int rc_wtl_ = ldap_int_thread_mutex_lock( &thread_info_mutex ); \
- assert( rc_wtl_ == 0 ); \
- { statements; } \
- rc_wtl_ = ldap_int_thread_mutex_unlock( &thread_info_mutex ); \
- assert( rc_wtl_ == 0 ); \
- }
- #define thread_info_detached(t) ((t)->detached)
- static void
- add_thread_info(
- const char *msg,
- const ldap_pvt_thread_t *thread,
- int detached )
- {
- ldap_debug_thread_t *t;
- if( thread_info_used >= thread_info_size ) {
- unsigned int more = thread_info_size + 8;
- unsigned int new_size = thread_info_size + more;
- t = calloc( more, sizeof(ldap_debug_thread_t) );
- assert( t != NULL );
- thread_info = realloc( thread_info, new_size * sizeof(*thread_info) );
- assert( thread_info != NULL );
- do {
- t->idx = thread_info_size;
- thread_info[thread_info_size++] = t++;
- } while( thread_info_size < new_size );
- }
- t = thread_info[thread_info_used];
- init_usage( &t->usage, msg );
- t->wrapped = *thread;
- t->detached = detached;
- thread_info_used++;
- }
- static void
- remove_thread_info( ldap_debug_thread_t *t, const char *msg )
- {
- ldap_debug_thread_t *last;
- int idx;
- check_usage( &t->usage, msg );
- destroy_usage( &t->usage );
- idx = t->idx;
- assert( thread_info[idx] == t );
- last = thread_info[--thread_info_used];
- assert( last->idx == thread_info_used );
- (thread_info[idx] = last)->idx = idx;
- (thread_info[thread_info_used] = t )->idx = thread_info_used;
- }
- static ldap_debug_thread_t *
- get_thread_info( ldap_pvt_thread_t thread, const char *msg )
- {
- unsigned int i;
- ldap_debug_thread_t *t;
- for( i = 0; i < thread_info_used; i++ ) {
- if( ldap_pvt_thread_equal( thread, thread_info[i]->wrapped ) )
- break;
- }
- ERROR_IF( i == thread_info_used, msg );
- t = thread_info[i];
- check_usage( &t->usage, msg );
- return t;
- }
- #endif /* LDAP_THREAD_DEBUG_THREAD_ID */
- static char *
- thread_name( char *buf, int bufsize, ldap_pvt_thread_t thread )
- {
- int i;
- --bufsize;
- if( bufsize > 2*sizeof(thread) )
- bufsize = 2*sizeof(thread);
- for( i = 0; i < bufsize; i += 2 )
- snprintf( buf+i, 3, "%02x", ((unsigned char *)&thread)[i/2] );
- return buf;
- }
- /* Add <adjust> (+/-1) to resource count <which> unless "nocount". */
- static void
- adjust_count( int which, int adjust )
- {
- int rc;
- switch( count ) {
- case Count_no:
- break;
- case Count_yes:
- rc = ldap_int_thread_mutex_lock( &resource_mutexes[which] );
- assert( rc == 0 );
- resource_counts[which] += adjust;
- rc = ldap_int_thread_mutex_unlock( &resource_mutexes[which] );
- assert( rc == 0 );
- break;
- case Count_reported:
- fputs( "== thr_debug: More thread activity after exit ==\n", stderr );
- count = Count_reported_more;
- /* FALL THROUGH */
- case Count_reported_more:
- /* Not used, but result might be inspected with debugger */
- /* (Hopefully threading is disabled by now...) */
- resource_counts[which] += adjust;
- break;
- }
- }
- /* Wrappers for LDAP_THREAD_IMPLEMENTATION: */
- /* Used instead of ldap_int_thread_initialize by ldap_pvt_thread_initialize */
- int
- ldap_debug_thread_initialize( void )
- {
- int i, rc, rc2;
- if( !options_done )
- get_options();
- ERROR_IF( threading_enabled, "ldap_debug_thread_initialize" );
- threading_enabled = 1;
- rc = ldap_int_thread_initialize();
- if( rc ) {
- ERROR( rc, "ldap_debug_thread_initialize:threads" );
- threading_enabled = 0;
- } else {
- init_thread_info();
- if( count != Count_no ) {
- for( i = rc2 = 0; i < Idx_max; i++ )
- rc2 |= ldap_int_thread_mutex_init( &resource_mutexes[i] );
- assert( rc2 == 0 );
- /* FIXME: Only for static libldap as in init.c? If so, why? */
- atexit( count_resource_leaks );
- }
- }
- return rc;
- }
- /* Used instead of ldap_int_thread_destroy by ldap_pvt_thread_destroy */
- int
- ldap_debug_thread_destroy( void )
- {
- int rc;
- ERROR_IF( !threading_enabled, "ldap_debug_thread_destroy" );
- /* sleep(1) -- need to wait for thread pool to finish? */
- rc = ldap_int_thread_destroy();
- if( rc ) {
- ERROR( rc, "ldap_debug_thread_destroy:threads" );
- } else {
- threading_enabled = 0;
- }
- return rc;
- }
- int
- ldap_pvt_thread_set_concurrency( int n )
- {
- int rc;
- ERROR_IF( !threading_enabled, "ldap_pvt_thread_set_concurrency" );
- rc = ldap_int_thread_set_concurrency( n );
- ERROR_IF( rc, "ldap_pvt_thread_set_concurrency" );
- return rc;
- }
- int
- ldap_pvt_thread_get_concurrency( void )
- {
- int rc;
- ERROR_IF( !threading_enabled, "ldap_pvt_thread_get_concurrency" );
- rc = ldap_int_thread_get_concurrency();
- ERROR_IF( rc, "ldap_pvt_thread_get_concurrency" );
- return rc;
- }
- unsigned int
- ldap_pvt_thread_sleep( unsigned int interval )
- {
- int rc;
- ERROR_IF( !threading_enabled, "ldap_pvt_thread_sleep" );
- rc = ldap_int_thread_sleep( interval );
- ERROR_IF( rc, "ldap_pvt_thread_sleep" );
- return 0;
- }
- static void
- thread_exiting( const char *how, const char *msg )
- {
- ldap_pvt_thread_t thread;
- #if 0 /* Detached threads may exit after ldap_debug_thread_destroy(). */
- ERROR_IF( !threading_enabled, msg );
- #endif
- thread = ldap_pvt_thread_self();
- if( tracethreads ) {
- char buf[40];
- fprintf( stderr, "== thr_debug: %s thread %s ==\n",
- how, thread_name( buf, sizeof(buf), thread ) );
- }
- if( threadID ) {
- with_thread_info_lock({
- ldap_debug_thread_t *t = get_thread_info( thread, msg );
- if( thread_info_detached( t ) )
- remove_thread_info( t, msg );
- });
- }
- adjust_count( Idx_unexited_thread, -1 );
- }
- void
- ldap_pvt_thread_exit( void *retval )
- {
- thread_exiting( "Exiting", "ldap_pvt_thread_exit" );
- ldap_int_thread_exit( retval );
- }
- typedef struct {
- void *(*start_routine)( void * );
- void *arg;
- } ldap_debug_thread_call_t;
- static void *
- ldap_debug_thread_wrapper( void *arg )
- {
- void *ret;
- ldap_debug_thread_call_t call = *(ldap_debug_thread_call_t *)arg;
- free( arg );
- ret = call.start_routine( call.arg );
- thread_exiting( "Returning from", "ldap_debug_thread_wrapper" );
- return ret;
- }
- int
- ldap_pvt_thread_create(
- ldap_pvt_thread_t *thread,
- int detach,
- void *(*start_routine)( void * ),
- void *arg )
- {
- int rc;
- if( !options_done )
- get_options();
- ERROR_IF( !threading_enabled, "ldap_pvt_thread_create" );
- if( wrap_threads ) {
- ldap_debug_thread_call_t *call = malloc(
- sizeof( ldap_debug_thread_call_t ) );
- assert( call != NULL );
- call->start_routine = start_routine;
- call->arg = arg;
- start_routine = ldap_debug_thread_wrapper;
- arg = call;
- }
- if( threadID ) {
- with_thread_info_lock({
- rc = ldap_int_thread_create( thread, detach, start_routine, arg );
- if( rc == 0 )
- add_thread_info( "ldap_pvt_thread_create", thread, detach );
- });
- } else {
- rc = ldap_int_thread_create( thread, detach, start_routine, arg );
- }
- if( rc ) {
- ERROR( rc, "ldap_pvt_thread_create" );
- if( wrap_threads )
- free( arg );
- } else {
- if( tracethreads ) {
- char buf[40], buf2[40];
- fprintf( stderr,
- "== thr_debug: Created thread %s%s from thread %s ==\n",
- thread_name( buf, sizeof(buf), *thread ),
- detach ? " (detached)" : "",
- thread_name( buf2, sizeof(buf2), ldap_pvt_thread_self() ) );
- }
- adjust_count( Idx_unexited_thread, +1 );
- if( !detach )
- adjust_count( Idx_unjoined_thread, +1 );
- }
- return rc;
- }
- int
- ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return )
- {
- int rc;
- ldap_debug_thread_t *t = NULL;
- ERROR_IF( !threading_enabled, "ldap_pvt_thread_join" );
- if( tracethreads ) {
- char buf[40], buf2[40];
- fprintf( stderr, "== thr_debug: Joining 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_join" );
- ERROR_IF( thread_info_detached( t ), "ldap_pvt_thread_join" );
- } );
- rc = ldap_int_thread_join( thread, thread_return );
- if( rc ) {
- ERROR( rc, "ldap_pvt_thread_join" );
- } else {
- if( threadID )
- with_thread_info_lock(
- remove_thread_info( t, "ldap_pvt_thread_join" ) );
- adjust_count( Idx_unjoined_thread, -1 );
- }
- return rc;
- }
- int
- ldap_pvt_thread_kill( ldap_pvt_thread_t thread, int signo )
- {
- int rc;
- ERROR_IF( !threading_enabled, "ldap_pvt_thread_kill" );
- if( tracethreads ) {
- char buf[40], buf2[40];
- fprintf( stderr,
- "== thr_debug: Killing thread %s (sig %i) from thread %s ==\n",
- thread_name( buf, sizeof(buf), thread ), signo,
- thread_name( buf2, sizeof(buf2), ldap_pvt_thread_self() ) );
- }
- rc = ldap_int_thread_kill( thread, signo );
- ERROR_IF( rc, "ldap_pvt_thread_kill" );
- return rc;
- }
- int
- ldap_pvt_thread_yield( void )
- {
- int rc;
- ERROR_IF( !threading_enabled, "ldap_pvt_thread_yield" );
- rc = ldap_int_thread_yield();
- ERROR_IF( rc, "ldap_pvt_thread_yield" );
- return rc;
- }
- ldap_pvt_thread_t
- ldap_pvt_thread_self( void )
- {
- #if 0 /* Function is used by ch_free() via slap_sl_contxt() in slapd */
- ERROR_IF( !threading_enabled, "ldap_pvt_thread_self" );
- #endif
- return ldap_int_thread_self();
- }
- int
- ldap_pvt_thread_cond_init( ldap_pvt_thread_cond_t *cond )
- {
- int rc;
- init_usage( &cond->usage, "ldap_pvt_thread_cond_init" );
- rc = ldap_int_thread_cond_init( WRAPPED( cond ) );
- if( rc ) {
- ERROR( rc, "ldap_pvt_thread_cond_init" );
- destroy_usage( &cond->usage );
- } else {
- adjust_count( Idx_cond, +1 );
- }
- return rc;
- }
- int
- ldap_pvt_thread_cond_destroy( ldap_pvt_thread_cond_t *cond )
- {
- int rc;
- check_usage( &cond->usage, "ldap_pvt_thread_cond_destroy" );
- rc = ldap_int_thread_cond_destroy( WRAPPED( cond ) );
- if( rc ) {
- ERROR( rc, "ldap_pvt_thread_cond_destroy" );
- } else {
- destroy_usage( &cond->usage );
- adjust_count( Idx_cond, -1 );
- }
- return rc;
- }
- int
- ldap_pvt_thread_cond_signal( ldap_pvt_thread_cond_t *cond )
- {
- int rc;
- check_usage( &cond->usage, "ldap_pvt_thread_cond_signal" );
- rc = ldap_int_thread_cond_signal( WRAPPED( cond ) );
- ERROR_IF( rc, "ldap_pvt_thread_cond_signal" );
- return rc;
- }
- int
- ldap_pvt_thread_cond_broadcast( ldap_pvt_thread_cond_t *cond )
- {
- int rc;
- check_usage( &cond->usage, "ldap_pvt_thread_cond_broadcast" );
- rc = ldap_int_thread_cond_broadcast( WRAPPED( cond ) );
- ERROR_IF( rc, "ldap_pvt_thread_cond_broadcast" );
- return rc;
- }
- int
- ldap_pvt_thread_cond_wait(
- ldap_pvt_thread_cond_t *cond,
- ldap_pvt_thread_mutex_t *mutex )
- {
- int rc;
- ldap_int_thread_t owner;
- check_usage( &cond->usage, "ldap_pvt_thread_cond_wait:cond" );
- check_usage( &mutex->usage, "ldap_pvt_thread_cond_wait:mutex" );
- adjust_count( Idx_locked_mutex, -1 );
- owner = GET_OWNER( mutex );
- ASSERT_OWNER( mutex, "ldap_pvt_thread_cond_wait" );
- RESET_OWNER( mutex );
- rc = ldap_int_thread_cond_wait( WRAPPED( cond ), WRAPPED( mutex ) );
- ASSERT_NO_OWNER( mutex, "ldap_pvt_thread_cond_wait" );
- SET_OWNER( mutex, rc ? owner : ldap_int_thread_self() );
- adjust_count( Idx_locked_mutex, +1 );
- ERROR_IF( rc, "ldap_pvt_thread_cond_wait" );
- return rc;
- }
- int
- ldap_pvt_thread_mutex_recursive_init( ldap_pvt_thread_mutex_t *mutex )
- {
- int rc;
- init_usage( &mutex->usage, "ldap_pvt_thread_mutex_recursive_init" );
- rc = ldap_int_thread_mutex_recursive_init( WRAPPED( mutex ) );
- if( rc ) {
- ERROR( rc, "ldap_pvt_thread_mutex_recursive_init" );
- destroy_usage( &mutex->usage );
- } else {
- RESET_OWNER( mutex );
- adjust_count( Idx_mutex, +1 );
- }
- return rc;
- }
- int
- ldap_pvt_thread_mutex_init( ldap_pvt_thread_mutex_t *mutex )
- {
- int rc;
- init_usage( &mutex->usage, "ldap_pvt_thread_mutex_init" );
- rc = ldap_int_thread_mutex_init( WRAPPED( mutex ) );
- if( rc ) {
- ERROR( rc, "ldap_pvt_thread_mutex_init" );
- destroy_usage( &mutex->usage );
- } else {
- RESET_OWNER( mutex );
- adjust_count( Idx_mutex, +1 );
- }
- return rc;
- }
- int
- ldap_pvt_thread_mutex_destroy( ldap_pvt_thread_mutex_t *mutex )
- {
- int rc;
- check_usage( &mutex->usage, "ldap_pvt_thread_mutex_destroy" );
- ASSERT_NO_OWNER( mutex, "ldap_pvt_thread_mutex_destroy" );
- rc = ldap_int_thread_mutex_destroy( WRAPPED( mutex ) );
- if( rc ) {
- ERROR( rc, "ldap_pvt_thread_mutex_destroy" );
- } else {
- destroy_usage( &mutex->usage );
- RESET_OWNER( mutex );
- adjust_count( Idx_mutex, -1 );
- }
- return rc;
- }
- int
- ldap_pvt_thread_mutex_lock( ldap_pvt_thread_mutex_t *mutex )
- {
- int rc;
- check_usage( &mutex->usage, "ldap_pvt_thread_mutex_lock" );
- rc = ldap_int_thread_mutex_lock( WRAPPED( mutex ) );
- if( rc ) {
- ERROR_IF( rc, "ldap_pvt_thread_mutex_lock" );
- } else {
- ASSERT_NO_OWNER( mutex, "ldap_pvt_thread_mutex_lock" );
- SET_OWNER( mutex, ldap_int_thread_self() );
- adjust_count( Idx_locked_mutex, +1 );
- }
- return rc;
- }
- int
- ldap_pvt_thread_mutex_trylock( ldap_pvt_thread_mutex_t *mutex )
- {
- int rc;
- check_usage( &mutex->usage, "ldap_pvt_thread_mutex_trylock" );
- rc = ldap_int_thread_mutex_trylock( WRAPPED( mutex ) );
- if( rc == 0 ) {
- ASSERT_NO_OWNER( mutex, "ldap_pvt_thread_mutex_trylock" );
- SET_OWNER( mutex, ldap_int_thread_self() );
- adjust_count( Idx_locked_mutex, +1 );
- }
- return rc;
- }
- int
- ldap_pvt_thread_mutex_unlock( ldap_pvt_thread_mutex_t *mutex )
- {
- int rc;
- check_usage( &mutex->usage, "ldap_pvt_thread_mutex_unlock" );
- ASSERT_OWNER( mutex, "ldap_pvt_thread_mutex_unlock" );
- RESET_OWNER( mutex ); /* Breaks if this thread did not own the mutex */
- rc = ldap_int_thread_mutex_unlock( WRAPPED( mutex ) );
- if( rc ) {
- ERROR_IF( rc, "ldap_pvt_thread_mutex_unlock" );
- } else {
- adjust_count( Idx_locked_mutex, -1 );
- }
- return rc;
- }
- /* Wrappers for LDAP_THREAD_RDWR_IMPLEMENTATION: */
- int
- ldap_pvt_thread_rdwr_init( ldap_pvt_thread_rdwr_t *rwlock )
- {
- int rc;
- init_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_init" );
- rc = ldap_int_thread_rdwr_init( WRAPPED( rwlock ) );
- if( rc ) {
- ERROR( rc, "ldap_pvt_thread_rdwr_init" );
- destroy_usage( &rwlock->usage );
- } else {
- adjust_count( Idx_rdwr, +1 );
- }
- return rc;
- }
- int
- ldap_pvt_thread_rdwr_destroy( ldap_pvt_thread_rdwr_t *rwlock )
- {
- int rc;
- check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_destroy" );
- rc = ldap_int_thread_rdwr_destroy( WRAPPED( rwlock ) );
- if( rc ) {
- ERROR( rc, "ldap_pvt_thread_rdwr_destroy" );
- } else {
- destroy_usage( &rwlock->usage );
- adjust_count( Idx_rdwr, -1 );
- }
- return rc;
- }
- int
- ldap_pvt_thread_rdwr_rlock( ldap_pvt_thread_rdwr_t *rwlock )
- {
- int rc;
- check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_rlock" );
- rc = ldap_int_thread_rdwr_rlock( WRAPPED( rwlock ) );
- ERROR_IF( rc, "ldap_pvt_thread_rdwr_rlock" );
- return rc;
- }
- int
- ldap_pvt_thread_rdwr_rtrylock( ldap_pvt_thread_rdwr_t *rwlock )
- {
- check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_rtrylock" );
- return ldap_int_thread_rdwr_rtrylock( WRAPPED( rwlock ) );
- }
- int
- ldap_pvt_thread_rdwr_runlock( ldap_pvt_thread_rdwr_t *rwlock )
- {
- int rc;
- check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_runlock" );
- rc = ldap_int_thread_rdwr_runlock( WRAPPED( rwlock ) );
- ERROR_IF( rc, "ldap_pvt_thread_rdwr_runlock" );
- return rc;
- }
- int
- ldap_pvt_thread_rdwr_wlock( ldap_pvt_thread_rdwr_t *rwlock )
- {
- int rc;
- check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_wlock" );
- rc = ldap_int_thread_rdwr_wlock( WRAPPED( rwlock ) );
- ERROR_IF( rc, "ldap_pvt_thread_rdwr_wlock" );
- return rc;
- }
- int
- ldap_pvt_thread_rdwr_wtrylock( ldap_pvt_thread_rdwr_t *rwlock )
- {
- check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_wtrylock" );
- return ldap_int_thread_rdwr_wtrylock( WRAPPED( rwlock ) );
- }
- int
- ldap_pvt_thread_rdwr_wunlock( ldap_pvt_thread_rdwr_t *rwlock )
- {
- int rc;
- check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_wunlock" );
- rc = ldap_int_thread_rdwr_wunlock( WRAPPED( rwlock ) );
- ERROR_IF( rc, "ldap_pvt_thread_rdwr_wunlock" );
- return rc;
- }
- #if defined(LDAP_RDWR_DEBUG) && !defined(LDAP_THREAD_HAVE_RDWR)
- int
- ldap_pvt_thread_rdwr_readers( ldap_pvt_thread_rdwr_t *rwlock )
- {
- check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_readers" );
- return ldap_int_thread_rdwr_readers( WRAPPED( rwlock ) );
- }
- int
- ldap_pvt_thread_rdwr_writers( ldap_pvt_thread_rdwr_t *rwlock )
- {
- check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_writers" );
- return ldap_int_thread_rdwr_writers( WRAPPED( rwlock ) );
- }
- int
- ldap_pvt_thread_rdwr_active( ldap_pvt_thread_rdwr_t *rwlock )
- {
- check_usage( &rwlock->usage, "ldap_pvt_thread_rdwr_active" );
- return ldap_int_thread_rdwr_active( WRAPPED( rwlock ) );
- }
- #endif /* LDAP_RDWR_DEBUG && !LDAP_THREAD_HAVE_RDWR */
- /* Some wrappers for LDAP_THREAD_POOL_IMPLEMENTATION: */
- #ifdef LDAP_THREAD_POOL_IMPLEMENTATION
- int
- ldap_pvt_thread_pool_init(
- ldap_pvt_thread_pool_t *tpool,
- int max_threads,
- int max_pending )
- {
- 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 );
- if( rc ) {
- ERROR( rc, "ldap_pvt_thread_pool_init" );
- } else {
- adjust_count( Idx_tpool, +1 );
- }
- return rc;
- }
- int
- ldap_pvt_thread_pool_submit(
- ldap_pvt_thread_pool_t *tpool,
- ldap_pvt_thread_start_t *start_routine, void *arg )
- {
- int rc, has_pool;
- ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_submit" );
- has_pool = (tpool && *tpool);
- rc = ldap_int_thread_pool_submit( tpool, start_routine, arg );
- if( has_pool )
- ERROR_IF( rc, "ldap_pvt_thread_pool_submit" );
- return rc;
- }
- int
- ldap_pvt_thread_pool_maxthreads(
- ldap_pvt_thread_pool_t *tpool,
- int max_threads )
- {
- ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_maxthreads" );
- return ldap_int_thread_pool_maxthreads( tpool, max_threads );
- }
- int
- ldap_pvt_thread_pool_backload( ldap_pvt_thread_pool_t *tpool )
- {
- ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_backload" );
- return ldap_int_thread_pool_backload( tpool );
- }
- int
- ldap_pvt_thread_pool_destroy( ldap_pvt_thread_pool_t *tpool, int run_pending )
- {
- int rc, has_pool;
- ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_destroy" );
- has_pool = (tpool && *tpool);
- rc = ldap_int_thread_pool_destroy( tpool, run_pending );
- if( has_pool ) {
- if( rc ) {
- ERROR( rc, "ldap_pvt_thread_pool_destroy" );
- } else {
- adjust_count( Idx_tpool, -1 );
- }
- }
- return rc;
- }
- int
- ldap_pvt_thread_pool_close( ldap_pvt_thread_pool_t *tpool, int run_pending )
- {
- int rc, has_pool;
- ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_close" );
- has_pool = (tpool && *tpool);
- rc = ldap_int_thread_pool_close( tpool, run_pending );
- if( has_pool && rc ) {
- ERROR( rc, "ldap_pvt_thread_pool_close" );
- }
- return rc;
- }
- int
- ldap_pvt_thread_pool_free( ldap_pvt_thread_pool_t *tpool )
- {
- int rc, has_pool;
- ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_free" );
- has_pool = (tpool && *tpool);
- rc = ldap_int_thread_pool_free( tpool );
- if( has_pool ) {
- if( rc ) {
- ERROR( rc, "ldap_pvt_thread_pool_free" );
- } else {
- adjust_count( Idx_tpool, -1 );
- }
- }
- return rc;
- }
- int
- ldap_pvt_thread_pool_pause( ldap_pvt_thread_pool_t *tpool )
- {
- ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_pause" );
- return ldap_int_thread_pool_pause( tpool );
- }
- int
- ldap_pvt_thread_pool_resume( ldap_pvt_thread_pool_t *tpool )
- {
- ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_resume" );
- return ldap_int_thread_pool_resume( tpool );
- }
- int
- ldap_pvt_thread_pool_getkey(
- void *xctx,
- void *key,
- void **data,
- ldap_pvt_thread_pool_keyfree_t **kfree )
- {
- #if 0 /* Function is used by ch_free() via slap_sl_contxt() in slapd */
- ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_getkey" );
- #endif
- return ldap_int_thread_pool_getkey( xctx, key, data, kfree );
- }
- int
- ldap_pvt_thread_pool_setkey(
- void *xctx,
- void *key,
- void *data,
- ldap_pvt_thread_pool_keyfree_t *kfree,
- void **olddatap,
- ldap_pvt_thread_pool_keyfree_t **oldkfreep )
- {
- int rc;
- ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_setkey" );
- rc = ldap_int_thread_pool_setkey(
- xctx, key, data, kfree, olddatap, oldkfreep );
- ERROR_IF( rc, "ldap_pvt_thread_pool_setkey" );
- return rc;
- }
- void
- ldap_pvt_thread_pool_purgekey( void *key )
- {
- ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_purgekey" );
- ldap_int_thread_pool_purgekey( key );
- }
- void *
- ldap_pvt_thread_pool_context( void )
- {
- #if 0 /* Function is used by ch_free() via slap_sl_contxt() in slapd */
- ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_context" );
- #endif
- return ldap_int_thread_pool_context();
- }
- void
- ldap_pvt_thread_pool_context_reset( void *vctx )
- {
- ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_context_reset" );
- ldap_int_thread_pool_context_reset( vctx );
- }
- #endif /* LDAP_THREAD_POOL_IMPLEMENTATION */
- #endif /* LDAP_THREAD_DEBUG */
|