lib: talloc: tests - add test_pthread_talloc_passing() testing talloc in a pthread...
authorJeremy Allison <jra@samba.org>
Mon, 16 Mar 2015 19:18:17 +0000 (12:18 -0700)
committerJeremy Allison <jra@samba.org>
Tue, 17 Mar 2015 18:23:29 +0000 (19:23 +0100)
Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Simo <simo@samba.org>
Reviewed-by: "Stefan (metze) Metzmacher" <metze@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Tue Mar 17 19:23:29 CET 2015 on sn-devel-104

lib/talloc/testsuite.c
lib/talloc/wscript

index eb3e13d5af08347a33cb8d2b30e643d332dda442..6d0fe94479e3b80326e4159ad94f035d20dc0db1 100644 (file)
 #include "system/time.h"
 #include <talloc.h>
 
+#ifdef HAVE_PTHREAD
+#include <pthread.h>
+#endif
+
 #include "talloc_testsuite.h"
 
 static struct timeval timeval_current(void)
@@ -1701,6 +1705,151 @@ static bool test_memlimit(void)
        return true;
 }
 
+#ifdef HAVE_PTHREAD
+
+#define NUM_THREADS 100
+
+/* Sync variables. */
+static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t condvar = PTHREAD_COND_INITIALIZER;
+static void *intermediate_ptr;
+
+/* Subthread. */
+static void *thread_fn(void *arg)
+{
+       int ret;
+       const char *ctx_name = (const char *)arg;
+       void *sub_ctx = NULL;
+       /*
+        * Do stuff that creates a new talloc hierarchy in
+        * this thread.
+        */
+       void *top_ctx = talloc_named_const(NULL, 0, "top");
+       if (top_ctx == NULL) {
+               return NULL;
+       }
+       sub_ctx = talloc_named_const(top_ctx, 100, ctx_name);
+       if (sub_ctx == NULL) {
+               return NULL;
+       }
+
+       /*
+        * Now transfer a pointer from our hierarchy
+        * onto the intermediate ptr.
+        */
+       ret = pthread_mutex_lock(&mtx);
+       if (ret != 0) {
+               talloc_free(top_ctx);
+               return NULL;
+       }
+       /* Wait for intermediate_ptr to be free. */
+       while (intermediate_ptr != NULL) {
+               ret = pthread_cond_wait(&condvar, &mtx);
+               if (ret != 0) {
+                       talloc_free(top_ctx);
+                       return NULL;
+               }
+       }
+
+       /* and move our memory onto it from our toplevel hierarchy. */
+       intermediate_ptr = talloc_move(NULL, &sub_ctx);
+
+       /* Tell the main thread it's ready for pickup. */
+       pthread_cond_broadcast(&condvar);
+       pthread_mutex_unlock(&mtx);
+
+       talloc_free(top_ctx);
+       return NULL;
+}
+
+/* Main thread. */
+static bool test_pthread_talloc_passing(void)
+{
+       int i;
+       int ret;
+       char str_array[NUM_THREADS][20];
+       pthread_t thread_id;
+       void *mem_ctx;
+
+       /*
+        * Important ! Null tracking breaks threaded talloc.
+        * It *must* be turned off.
+        */
+       talloc_disable_null_tracking();
+
+       printf("test: pthread_talloc_passing\n# PTHREAD TALLOC PASSING\n");
+
+       /* Main thread toplevel context. */
+       mem_ctx = talloc_named_const(NULL, 0, "toplevel");
+       if (mem_ctx == NULL) {
+               printf("failed to create toplevel context\n");
+               return false;
+       }
+
+       /*
+        * Spin off NUM_THREADS threads.
+        * They will use their own toplevel contexts.
+        */
+       for (i = 0; i < NUM_THREADS; i++) {
+               (void)snprintf(str_array[i],
+                               20,
+                               "thread:%d",
+                               i);
+               if (str_array[i] == NULL) {
+                       printf("snprintf %d failed\n", i);
+                       return false;
+               }
+               ret = pthread_create(&thread_id,
+                               NULL,
+                               thread_fn,
+                               str_array[i]);
+               if (ret != 0) {
+                       printf("failed to create thread %d (%d)\n", i, ret);
+                       return false;
+               }
+       }
+
+       printf("Created %d threads\n", NUM_THREADS);
+
+       /* Now wait for NUM_THREADS transfers of the talloc'ed memory. */
+       for (i = 0; i < NUM_THREADS; i++) {
+               ret = pthread_mutex_lock(&mtx);
+               if (ret != 0) {
+                       printf("pthread_mutex_lock %d failed (%d)\n", i, ret);
+                       talloc_free(mem_ctx);
+                       return false;
+               }
+
+               /* Wait for intermediate_ptr to have our data. */
+               while (intermediate_ptr == NULL) {
+                       ret = pthread_cond_wait(&condvar, &mtx);
+                       if (ret != 0) {
+                               printf("pthread_cond_wait %d failed (%d)\n", i,
+                                       ret);
+                               talloc_free(mem_ctx);
+                               return false;
+                       }
+               }
+
+               /* and move it onto our toplevel hierarchy. */
+               (void)talloc_move(mem_ctx, &intermediate_ptr);
+
+               /* Tell the sub-threads we're ready for another. */
+               pthread_cond_broadcast(&condvar);
+               pthread_mutex_unlock(&mtx);
+       }
+
+       CHECK_SIZE("pthread_talloc_passing", mem_ctx, NUM_THREADS * 100);
+#if 1
+       /* Dump the hierarchy. */
+       talloc_report(mem_ctx, stdout);
+#endif
+       talloc_free(mem_ctx);
+       printf("success: pthread_talloc_passing\n");
+       return true;
+}
+#endif
+
 static void test_reset(void)
 {
        talloc_set_log_fn(test_log_stdout);
@@ -1771,6 +1920,10 @@ bool torture_local_talloc(struct torture_context *tctx)
        ret &= test_free_children();
        test_reset();
        ret &= test_memlimit();
+#ifdef HAVE_PTHREAD
+       test_reset();
+       ret &= test_pthread_talloc_passing();
+#endif
 
 
        if (ret) {
index 97c52c3e3eda948baa7391ce09c7c1373a65824d..9efc895b5589744a71390f48ee5e5b8f9aa866c8 100644 (file)
@@ -89,9 +89,13 @@ def build(bld):
                           public_headers=[],
                           enabled=bld.env.TALLOC_COMPAT1)
 
+        testsuite_deps = 'talloc'
+        if bld.CONFIG_SET('HAVE_PTHREAD'):
+            testsuite_deps += ' pthread'
+
         bld.SAMBA_BINARY('talloc_testsuite',
                          'testsuite_main.c testsuite.c',
-                         deps='talloc',
+                         testsuite_deps,
                          install=False)
 
     else: