]> git.sur5r.net Git - openldap/blobdiff - libraries/libldap_r/thr_debug.c
Restore pre-C99 preprocessor support (since rev 1.165)
[openldap] / libraries / libldap_r / thr_debug.c
index 142f9db23315dcb55d42e6883bcab058e2343bd0..2d271252bc871766955f9065688462c956bfbad4 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2005-2006 The OpenLDAP Foundation.
+ * Copyright 2005-2007 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -57,7 +57,7 @@
  *
  * Run-time configuration:
  *
- *  Setup of memory debugging tools:
+ *  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.
@@ -141,6 +141,7 @@ static int threadID;
 enum { threadID = 0 };
 #endif
 static int nodebug, noabort, noerror, nosync, tracethreads;
+static int wrap_threads;
 static int options_done;
 
 
@@ -273,19 +274,16 @@ get_options( void )
        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;
-                       for( oi = option_info; oi->name; oi++ ) {
-                               if( strncasecmp( oi->name, s, optlen ) == 0 ) {
-                                       if( oi->name && oi->name[optlen] == '\0' ) {
-                                               *oi->var = oi->val;
-                                       } else {
-                                               fprintf( stderr,
-                                                       "== thr_debug: Unknown $%s option '%.*s' ==\n",
-                                                       "LDAP_THREAD_DEBUG", (int) optlen, s );
-                                       }
-                                       break;
-                               }
-                       }
+                       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;
                }
        }
@@ -322,6 +320,7 @@ get_options( void )
        }
        unwrap_offset = -(wrap_offset = (wraptype == Wrap_adjptr));
 #endif
+       wrap_threads = (tracethreads || threadID || count);
        options_done = 1;
 }
 
@@ -381,9 +380,8 @@ ldap_debug_thread_assert_mutex_owner(
 static void debug_noop( void );
 static int debug_already_initialized( const ldap_debug_usage_info_t *usage );
 
-/* Names used to give clearer error messages */
+/* Name used for clearer error message */
 #define IS_COPY_OR_MOVED(usage) ((usage)->self != SCRAMBLE( usage ))
-enum { Is_destroyed = 1 };
 
 #define DUMMY_ADDR(usage) \
        (wraptype == Wrap_scramble \
@@ -406,18 +404,22 @@ init_usage( ldap_debug_usage_info_t *usage, const char *msg )
                                free( dummy );
                        } );
                }
-               usage->self = SCRAMBLE( usage );
                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;
 }
@@ -426,6 +428,8 @@ init_usage( ldap_debug_usage_info_t *usage, const char *msg )
 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;
@@ -472,14 +476,24 @@ debug_noop( void )
 {
 }
 
-/* Return true if the resource is initialized and not copied/realloced. */
-/* Valid programs access uninitialized memory here unless "noreinit".   */
+/*
+ * Valid programs access uninitialized memory here unless "noreinit".
+ *
+ * Returns true if the resource is initialized and not copied/realloced.
+ */
 static int
 debug_already_initialized( const ldap_debug_usage_info_t *usage )
 {
-       return (usage->state == ldap_debug_state_inited &&
-               !IS_COPY_OR_MOVED( usage ) &&
-               usage->magic == ldap_debug_magic);
+       /*
+        * '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 */
@@ -487,7 +501,7 @@ debug_already_initialized( const ldap_debug_usage_info_t *usage )
 
 #if !(LDAP_THREAD_DEBUG_THREAD_ID +0)
 
-typedef int ldap_debug_thread_t;
+typedef void ldap_debug_thread_t;
 #define init_thread_info()     {}
 #define with_thread_info_lock(statements) { statements; }
 #define thread_info_detached(t)        0
@@ -575,13 +589,13 @@ remove_thread_info( ldap_debug_thread_t *t, const char *msg )
                (thread_info[thread_info_used] = t   )->idx = thread_info_used;
 }
 
-ldap_debug_thread_t *
-get_thread_info( ldap_pvt_thread_t *thread, const char *msg )
+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 ) )
+               if( ldap_pvt_thread_equal( thread, thread_info[i]->wrapped ) )
                        break;
        }
        ERROR_IF( i == thread_info_used, msg );
@@ -620,6 +634,7 @@ adjust_count( int which, int adjust )
                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;
@@ -707,6 +722,52 @@ ldap_pvt_thread_sleep( unsigned int interval )
        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,
@@ -718,6 +779,15 @@ ldap_pvt_thread_create(
        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 );
@@ -729,6 +799,8 @@ ldap_pvt_thread_create(
        }
        if( rc ) {
                ERROR( rc, "ldap_pvt_thread_create" );
+               if( wrap_threads )
+                       free( arg );
        } else {
                if( tracethreads ) {
                        char buf[40], buf2[40];
@@ -745,29 +817,6 @@ ldap_pvt_thread_create(
        return rc;
 }
 
-void
-ldap_pvt_thread_exit( void *retval )
-{
-       ldap_pvt_thread_t thread;
-       ERROR_IF( !threading_enabled, "ldap_pvt_thread_exit" );
-       thread = ldap_pvt_thread_self();
-       if( tracethreads ) {
-               char buf[40];
-               fprintf( stderr, "== thr_debug: Exiting thread %s ==\n",
-                       thread_name( buf, sizeof(buf), thread ) );
-       }
-       if( threadID ) {
-               with_thread_info_lock({
-                       ldap_debug_thread_t *t = get_thread_info(
-                               &thread, "ldap_pvt_thread_exit" );
-                       if( thread_info_detached( t ) )
-                               remove_thread_info( t, "ldap_pvt_thread_exit" );
-               });
-       }
-       adjust_count( Idx_unexited_thread, -1 );
-       ldap_int_thread_exit( retval );
-}
-
 int
 ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return )
 {
@@ -782,7 +831,7 @@ ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return )
        }
        if( threadID )
                with_thread_info_lock( {
-                       t = get_thread_info( &thread, "ldap_pvt_thread_join" );
+                       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 );
@@ -1125,7 +1174,7 @@ ldap_pvt_thread_pool_submit(
 {
        int rc, has_pool;
        ERROR_IF( !threading_enabled, "ldap_pvt_thread_pool_submit" );
-       has_pool = (tpool != NULL && *tpool != NULL);
+       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" );
@@ -1153,7 +1202,7 @@ 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 != NULL && *tpool != NULL);
+       has_pool = (tpool && *tpool);
        rc = ldap_int_thread_pool_destroy( tpool, run_pending );
        if( has_pool ) {
                if( rc ) {