You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2013/11/28 19:07:21 UTC

svn commit: r1546421 - /subversion/trunk/subversion/tests/svn_test_main.c

Author: stefan2
Date: Thu Nov 28 18:07:21 2013
New Revision: 1546421

URL: http://svn.apache.org/r1546421
Log:
Replace the thread-pool in our test main by a set of explicitly created
and terminated threads.  The job queue is a simple atomic counter.
Once at it, give every thread its separate, non-synchronizing memory pool.

* subversion/tests/svn_test_main.c
  (HAVE_THREADPOOLS): Drop macro.
  (test_params_t): This is now a singleton structure used as thread input
                   as well as for tracking test progress.
  (test_thread): Create your own root pool.  Grab test numbers and
                 execute tests until the test array has been exhausted.
  (do_tests_concurrently): Simply init the params, start N threads and
                           wait for them to finish.
  (main): Adapt to macro being dropped.

Modified:
    subversion/trunk/subversion/tests/svn_test_main.c

Modified: subversion/trunk/subversion/tests/svn_test_main.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/svn_test_main.c?rev=1546421&r1=1546420&r2=1546421&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/svn_test_main.c (original)
+++ subversion/trunk/subversion/tests/svn_test_main.c Thu Nov 28 18:07:21 2013
@@ -52,11 +52,8 @@
 
 #include "svn_private_config.h"
 
-#if APR_HAS_THREADS && APR_VERSION_AT_LEAST(1,3,0)
-#  include <apr_thread_pool.h>
-#  define HAVE_THREADPOOLS 1
-#else
-#  define HAVE_THREADPOOLS 0
+#if APR_HAS_THREADS
+#  include <apr_thread_proc.h>
 #endif
 
 /* Some Subversion test programs may want to parse options in the
@@ -420,7 +417,7 @@ do_test_num(const char *progname,
   return skip_cleanup;
 }
 
-#if HAVE_THREADPOOLS
+#if APR_HAS_THREADS
 
 /* Per-test parameters used by test_thread */
 typedef struct test_params_t
@@ -428,21 +425,17 @@ typedef struct test_params_t
   /* Name of the application */
   const char *progname;
 
-  /* Number / index of the test to execute */
-  int test_num;
+  /* Total number of tests to execute */
+  svn_atomic_t test_count;
 
   /* Global test options as provided by main() */
   svn_test_opts_t *opts;
 
-  /* Thread-safe parent pool for the test-specific pool.  We expect the
-     test thread to create a sub-pool and destroy it after test completion. */
-  apr_pool_t *pool;
-
   /* Reference to the global failure flag.  Set this if any test failed. */
-  svn_atomic_t *got_error;
+  svn_atomic_t got_error;
 
-  /* Reference to the global completed test counter. */
-  svn_atomic_t *run_count;
+  /* Test to execute next. */
+  svn_atomic_t test_num;
 } test_params_t;
 
 /* Thread function similar to do_test_num() but with fewer options.  We do
@@ -456,36 +449,43 @@ test_thread(apr_thread_t *tid, void *dat
   const struct svn_test_descriptor_t *desc;
   svn_boolean_t run_this_test; /* This test's mode matches DESC->MODE. */
   test_params_t *params = data;
+  svn_atomic_t test_num;
 
-  apr_pool_t *test_pool = svn_pool_create(params->pool);
+  apr_pool_t *pool
+    = apr_allocator_owner_get(svn_pool_create_allocator(FALSE));
 
-  desc = &test_funcs[params->test_num];
-  skip = desc->mode == svn_test_skip;
-  xfail = desc->mode == svn_test_xfail;
-  wimp = xfail && desc->wip;
-  run_this_test = mode_filter == svn_test_all || mode_filter == desc->mode;
+  for (test_num = svn_atomic_inc(&params->test_num);
+       test_num <= params->test_count;
+       test_num = svn_atomic_inc(&params->test_num))
+    {
+      svn_pool_clear(pool);
+
+      desc = &test_funcs[test_num];
+      skip = desc->mode == svn_test_skip;
+      xfail = desc->mode == svn_test_xfail;
+      wimp = xfail && desc->wip;
+      run_this_test = mode_filter == svn_test_all
+                   || mode_filter == desc->mode;
 
-  /* Do test */
-  if (skip || !run_this_test)
-    ; /* pass */
-  else if (desc->func2)
-    err = (*desc->func2)(test_pool);
-  else
-    err = (*desc->func_opts)(params->opts, test_pool);
+      /* Do test */
+      if (skip || !run_this_test)
+        ; /* pass */
+      else if (desc->func2)
+        err = (*desc->func2)(pool);
+      else
+        err = (*desc->func_opts)(params->opts, pool);
 
-  /* Write results to console */
-  svn_error_clear(svn_mutex__lock(log_mutex));
-  if (log_results(params->progname, params->test_num, FALSE, run_this_test,
-                  skip, xfail, wimp, err, desc->msg, desc))
-    svn_atomic_set(params->got_error, TRUE);
-  svn_error_clear(svn_mutex__unlock(log_mutex, NULL));
+      /* Write results to console */
+      svn_error_clear(svn_mutex__lock(log_mutex));
+      if (log_results(params->progname, test_num, FALSE, run_this_test,
+                      skip, xfail, wimp, err, desc->msg, desc))
+        svn_atomic_set(&params->got_error, TRUE);
+      svn_error_clear(svn_mutex__unlock(log_mutex, NULL));
+    }
 
   /* release all test memory */
-  svn_pool_destroy(test_pool);
+  svn_pool_destroy(pool);
 
-  /* one more test completed */
-  svn_atomic_inc(params->run_count);
-    
   return NULL;
 }
 
@@ -502,56 +502,48 @@ do_tests_concurrently(const char *progna
                       svn_test_opts_t *opts,
                       apr_pool_t *pool)
 {
-  apr_thread_pool_t *threads;
   apr_status_t status;
-  svn_atomic_t got_error = FALSE;
   int i;
-  svn_atomic_t run_count = 0;
-
-  /* Create the thread pool. */
-  status = apr_thread_pool_create(&threads, max_threads, max_threads, pool);
-  if (status)
-    {
-      printf("apr_thread_pool_create() failed.\n");
-      return TRUE;
-    }
-
-  /* Don't queue requests unless we reached the worker thread limit. */
-  apr_thread_pool_threshold_set(threads, 0);
-
-  /* Generate one task per test and queue them in the thread pool. */
-  for (i = 1; i <= array_size; i++)
-    {
-      test_params_t *params = apr_pcalloc(pool, sizeof(*params));
-      params->got_error = &got_error;
-      params->opts = opts;
-      params->pool = pool;
-      params->progname = progname;
-      params->test_num = i;
-      params->run_count = &run_count;
+  apr_thread_t **threads;
 
-      apr_thread_pool_push(threads, test_thread, params, 0, NULL);
+  test_params_t params;
+  params.got_error = FALSE;
+  params.opts = opts;
+  params.progname = progname;
+  params.test_num = 1;
+  params.test_count = array_size;
+
+  threads = apr_pcalloc(pool, max_threads * sizeof(*threads));
+  for (i = 0; i < max_threads; ++i)
+    {
+      status = apr_thread_create(&threads[i], NULL, test_thread, &params,
+                                 pool);
+      if (status)
+        {
+          printf("creating test thread failed.\n");
+          return TRUE;
+        }
     }
 
   /* Wait for all tasks (tests) to complete.  As it turns out, this is the
      variant with the least run-time overhead to the test threads. */
-  while (   apr_thread_pool_tasks_count(threads)
-         || apr_thread_pool_busy_count(threads))
-    apr_thread_yield();
-  
-  /* For some unknown reason, cleaning POOL (TEST_POOL in main()) does not
-     call the following reliably for all users. */
-  apr_thread_pool_destroy(threads);
-
-  /* Verify that we didn't skip any tasks. */
-  if (run_count != array_size)
+  for (i = 0; i < max_threads; ++i)
     {
-      printf("Parallel test failure: only %d of %d tests executed.\n",
-             (int)run_count, array_size);
-      return TRUE;
+      apr_status_t result;
+      status = apr_thread_join(&result, threads[i]);
+      if (status)
+        {
+          printf("waiting for test thread to finish failed.\n");
+          return TRUE;
+        }
+      if (result)
+        {
+          printf("test thread returned an error.\n");
+          return TRUE;
+        }
     }
-
-  return got_error != FALSE;
+  
+  return params.got_error != FALSE;
 }
 
 #endif
@@ -798,7 +790,7 @@ main(int argc, const char *argv[])
               }
             break;
           }
-#if HAVE_THREADPOOLS
+#if APR_HAS_THREADS
         case parallel_opt:
           parallel = TRUE;
           break;
@@ -888,7 +880,7 @@ main(int argc, const char *argv[])
               svn_pool_clear(cleanup_pool);
             }
         }
-#if HAVE_THREADPOOLS
+#if APR_HAS_THREADS
       else
         {
           got_error = do_tests_concurrently(prog_name, array_size,