"Fossies" - the Fresh Open Source Software Archive

Member "apr-1.7.0/test/testlock.c" (12 Dec 2017, 12131 Bytes) of package /linux/www/apr-1.7.0.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "testlock.c": 1.6.5_vs_1.7.0.

    1 /* Licensed to the Apache Software Foundation (ASF) under one or more
    2  * contributor license agreements.  See the NOTICE file distributed with
    3  * this work for additional information regarding copyright ownership.
    4  * The ASF licenses this file to You under the Apache License, Version 2.0
    5  * (the "License"); you may not use this file except in compliance with
    6  * the License.  You may obtain a copy of the License at
    7  *
    8  *     http://www.apache.org/licenses/LICENSE-2.0
    9  *
   10  * Unless required by applicable law or agreed to in writing, software
   11  * distributed under the License is distributed on an "AS IS" BASIS,
   12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13  * See the License for the specific language governing permissions and
   14  * limitations under the License.
   15  */
   16 
   17 #include "apr_thread_proc.h"
   18 #include "apr_file_io.h"
   19 #include "apr_thread_mutex.h"
   20 #include "apr_thread_rwlock.h"
   21 #include "apr_thread_cond.h"
   22 #include "apr_errno.h"
   23 #include "apr_general.h"
   24 #include "apr_getopt.h"
   25 #include "testutil.h"
   26 
   27 #if APR_HAS_THREADS
   28 
   29 #define MAX_ITER 40000
   30 #define MAX_COUNTER 100000
   31 #define MAX_RETRY 5
   32 
   33 static void *APR_THREAD_FUNC thread_rwlock_func(apr_thread_t *thd, void *data);
   34 static void *APR_THREAD_FUNC thread_mutex_function(apr_thread_t *thd, void *data);
   35 static void *APR_THREAD_FUNC thread_cond_producer(apr_thread_t *thd, void *data);
   36 static void *APR_THREAD_FUNC thread_cond_consumer(apr_thread_t *thd, void *data);
   37 
   38 static apr_thread_mutex_t *thread_mutex;
   39 static apr_thread_rwlock_t *rwlock;
   40 static int i = 0, x = 0;
   41 
   42 static int buff[MAX_COUNTER];
   43 
   44 struct {
   45     apr_thread_mutex_t *mutex;
   46     int                nput;
   47     int                nval;
   48 } put;
   49 
   50 struct {
   51     apr_thread_mutex_t *mutex;
   52     apr_thread_cond_t  *cond;
   53     int                nready;
   54 } nready;
   55 
   56 static apr_thread_mutex_t *timeout_mutex;
   57 static apr_thread_cond_t *timeout_cond;
   58 
   59 static void *APR_THREAD_FUNC thread_rwlock_func(apr_thread_t *thd, void *data)
   60 {
   61     int exitLoop = 1;
   62 
   63     while (1)
   64     {
   65         apr_thread_rwlock_rdlock(rwlock);
   66         if (i == MAX_ITER)
   67             exitLoop = 0;
   68         apr_thread_rwlock_unlock(rwlock);
   69 
   70         if (!exitLoop)
   71             break;
   72 
   73         apr_thread_rwlock_wrlock(rwlock);
   74         if (i != MAX_ITER)
   75         {
   76             i++;
   77             x++;
   78         }
   79         apr_thread_rwlock_unlock(rwlock);
   80     }
   81     return NULL;
   82 } 
   83 
   84 static void *APR_THREAD_FUNC thread_mutex_function(apr_thread_t *thd, void *data)
   85 {
   86     int exitLoop = 1;
   87 
   88     /* slight delay to allow things to settle */
   89     apr_sleep (1);
   90     
   91     while (1)
   92     {
   93         if (data) {
   94             apr_thread_mutex_timedlock(thread_mutex, *(apr_interval_time_t *)data);
   95         }
   96         else {
   97             apr_thread_mutex_lock(thread_mutex);
   98         }
   99         if (i == MAX_ITER)
  100             exitLoop = 0;
  101         else 
  102         {
  103             i++;
  104             x++;
  105         }
  106         apr_thread_mutex_unlock(thread_mutex);
  107 
  108         if (!exitLoop)
  109             break;
  110     }
  111     return NULL;
  112 } 
  113 
  114 static void *APR_THREAD_FUNC thread_cond_producer(apr_thread_t *thd, void *data)
  115 {
  116     for (;;) {
  117         apr_thread_mutex_lock(put.mutex);
  118         if (put.nput >= MAX_COUNTER) {
  119             apr_thread_mutex_unlock(put.mutex);
  120             return NULL;
  121         }
  122         buff[put.nput] = put.nval;
  123         put.nput++;
  124         put.nval++;
  125         apr_thread_mutex_unlock(put.mutex);
  126 
  127         apr_thread_mutex_lock(nready.mutex);
  128         if (nready.nready == 0)
  129             apr_thread_cond_signal(nready.cond);
  130         nready.nready++;
  131         apr_thread_mutex_unlock(nready.mutex);
  132 
  133         *((int *) data) += 1;
  134     }
  135 
  136     return NULL;
  137 }
  138 
  139 static void *APR_THREAD_FUNC thread_cond_consumer(apr_thread_t *thd, void *data)
  140 {
  141     int i;
  142 
  143     for (i = 0; i < MAX_COUNTER; i++) {
  144         apr_thread_mutex_lock(nready.mutex);
  145         while (nready.nready == 0)
  146             apr_thread_cond_wait(nready.cond, nready.mutex);
  147         nready.nready--;
  148         apr_thread_mutex_unlock(nready.mutex);
  149 
  150         if (buff[i] != i)
  151             printf("buff[%d] = %d\n", i, buff[i]);
  152     }
  153 
  154     return NULL;
  155 }
  156 
  157 static void test_thread_mutex(abts_case *tc, void *data)
  158 {
  159     apr_thread_t *t1, *t2, *t3, *t4;
  160     apr_status_t s1, s2, s3, s4;
  161 
  162     s1 = apr_thread_mutex_create(&thread_mutex, APR_THREAD_MUTEX_DEFAULT, p);
  163     ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
  164     ABTS_PTR_NOTNULL(tc, thread_mutex);
  165 
  166     i = 0;
  167     x = 0;
  168 
  169     s1 = apr_thread_create(&t1, NULL, thread_mutex_function, NULL, p);
  170     ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
  171     s2 = apr_thread_create(&t2, NULL, thread_mutex_function, NULL, p);
  172     ABTS_INT_EQUAL(tc, APR_SUCCESS, s2);
  173     s3 = apr_thread_create(&t3, NULL, thread_mutex_function, NULL, p);
  174     ABTS_INT_EQUAL(tc, APR_SUCCESS, s3);
  175     s4 = apr_thread_create(&t4, NULL, thread_mutex_function, NULL, p);
  176     ABTS_INT_EQUAL(tc, APR_SUCCESS, s4);
  177 
  178     apr_thread_join(&s1, t1);
  179     apr_thread_join(&s2, t2);
  180     apr_thread_join(&s3, t3);
  181     apr_thread_join(&s4, t4);
  182 
  183     ABTS_INT_EQUAL(tc, MAX_ITER, x);
  184 }
  185 
  186 #if APR_HAS_TIMEDLOCKS
  187 static void test_thread_timedmutex(abts_case *tc, void *data)
  188 {
  189     apr_thread_t *t1, *t2, *t3, *t4;
  190     apr_status_t s1, s2, s3, s4;
  191     apr_interval_time_t timeout;
  192 
  193     s1 = apr_thread_mutex_create(&thread_mutex, APR_THREAD_MUTEX_TIMED, p);
  194     ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
  195     ABTS_PTR_NOTNULL(tc, thread_mutex);
  196 
  197     i = 0;
  198     x = 0;
  199 
  200     timeout = apr_time_from_sec(5);
  201 
  202     s1 = apr_thread_create(&t1, NULL, thread_mutex_function, &timeout, p);
  203     ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
  204     s2 = apr_thread_create(&t2, NULL, thread_mutex_function, &timeout, p);
  205     ABTS_INT_EQUAL(tc, APR_SUCCESS, s2);
  206     s3 = apr_thread_create(&t3, NULL, thread_mutex_function, &timeout, p);
  207     ABTS_INT_EQUAL(tc, APR_SUCCESS, s3);
  208     s4 = apr_thread_create(&t4, NULL, thread_mutex_function, &timeout, p);
  209     ABTS_INT_EQUAL(tc, APR_SUCCESS, s4);
  210 
  211     apr_thread_join(&s1, t1);
  212     apr_thread_join(&s2, t2);
  213     apr_thread_join(&s3, t3);
  214     apr_thread_join(&s4, t4);
  215 
  216     ABTS_INT_EQUAL(tc, MAX_ITER, x);
  217 }
  218 #endif
  219 
  220 static void test_thread_rwlock(abts_case *tc, void *data)
  221 {
  222     apr_thread_t *t1, *t2, *t3, *t4;
  223     apr_status_t s1, s2, s3, s4;
  224 
  225     s1 = apr_thread_rwlock_create(&rwlock, p);
  226     if (s1 == APR_ENOTIMPL) {
  227         ABTS_NOT_IMPL(tc, "rwlocks not implemented");
  228         return;
  229     }
  230     APR_ASSERT_SUCCESS(tc, "rwlock_create", s1);
  231     ABTS_PTR_NOTNULL(tc, rwlock);
  232 
  233     i = 0;
  234     x = 0;
  235 
  236     s1 = apr_thread_create(&t1, NULL, thread_rwlock_func, NULL, p);
  237     APR_ASSERT_SUCCESS(tc, "create thread 1", s1);
  238     s2 = apr_thread_create(&t2, NULL, thread_rwlock_func, NULL, p);
  239     APR_ASSERT_SUCCESS(tc, "create thread 2", s2);
  240     s3 = apr_thread_create(&t3, NULL, thread_rwlock_func, NULL, p);
  241     APR_ASSERT_SUCCESS(tc, "create thread 3", s3);
  242     s4 = apr_thread_create(&t4, NULL, thread_rwlock_func, NULL, p);
  243     APR_ASSERT_SUCCESS(tc, "create thread 4", s4);
  244 
  245     apr_thread_join(&s1, t1);
  246     apr_thread_join(&s2, t2);
  247     apr_thread_join(&s3, t3);
  248     apr_thread_join(&s4, t4);
  249 
  250     ABTS_INT_EQUAL(tc, MAX_ITER, x);
  251 
  252     apr_thread_rwlock_destroy(rwlock);
  253 }
  254 
  255 static void test_cond(abts_case *tc, void *data)
  256 {
  257     apr_thread_t *p1, *p2, *p3, *p4, *c1;
  258     apr_status_t s0, s1, s2, s3, s4;
  259     int count1, count2, count3, count4;
  260     int sum;
  261     
  262     APR_ASSERT_SUCCESS(tc, "create put mutex",
  263                        apr_thread_mutex_create(&put.mutex, 
  264                                                APR_THREAD_MUTEX_DEFAULT, p));
  265     ABTS_PTR_NOTNULL(tc, put.mutex);
  266 
  267     APR_ASSERT_SUCCESS(tc, "create nready mutex",
  268                        apr_thread_mutex_create(&nready.mutex, 
  269                                                APR_THREAD_MUTEX_DEFAULT, p));
  270     ABTS_PTR_NOTNULL(tc, nready.mutex);
  271 
  272     APR_ASSERT_SUCCESS(tc, "create condvar",
  273                        apr_thread_cond_create(&nready.cond, p));
  274     ABTS_PTR_NOTNULL(tc, nready.cond);
  275 
  276     count1 = count2 = count3 = count4 = 0;
  277     put.nput = put.nval = 0;
  278     nready.nready = 0;
  279     i = 0;
  280     x = 0;
  281 
  282     s0 = apr_thread_create(&p1, NULL, thread_cond_producer, &count1, p);
  283     ABTS_INT_EQUAL(tc, APR_SUCCESS, s0);
  284     s1 = apr_thread_create(&p2, NULL, thread_cond_producer, &count2, p);
  285     ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
  286     s2 = apr_thread_create(&p3, NULL, thread_cond_producer, &count3, p);
  287     ABTS_INT_EQUAL(tc, APR_SUCCESS, s2);
  288     s3 = apr_thread_create(&p4, NULL, thread_cond_producer, &count4, p);
  289     ABTS_INT_EQUAL(tc, APR_SUCCESS, s3);
  290     s4 = apr_thread_create(&c1, NULL, thread_cond_consumer, NULL, p);
  291     ABTS_INT_EQUAL(tc, APR_SUCCESS, s4);
  292 
  293     apr_thread_join(&s0, p1);
  294     apr_thread_join(&s1, p2);
  295     apr_thread_join(&s2, p3);
  296     apr_thread_join(&s3, p4);
  297     apr_thread_join(&s4, c1);
  298 
  299     APR_ASSERT_SUCCESS(tc, "destroy condvar", 
  300                        apr_thread_cond_destroy(nready.cond));
  301 
  302     sum = count1 + count2 + count3 + count4;
  303     /*
  304     printf("count1 = %d count2 = %d count3 = %d count4 = %d\n",
  305             count1, count2, count3, count4);
  306     */
  307     ABTS_INT_EQUAL(tc, MAX_COUNTER, sum);
  308 }
  309 
  310 static void test_timeoutcond(abts_case *tc, void *data)
  311 {
  312     apr_status_t s;
  313     apr_interval_time_t timeout;
  314     apr_time_t begin, end;
  315     int i;
  316 
  317     s = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_DEFAULT, p);
  318     ABTS_INT_EQUAL(tc, APR_SUCCESS, s);
  319     ABTS_PTR_NOTNULL(tc, timeout_mutex);
  320 
  321     s = apr_thread_cond_create(&timeout_cond, p);
  322     ABTS_INT_EQUAL(tc, APR_SUCCESS, s);
  323     ABTS_PTR_NOTNULL(tc, timeout_cond);
  324 
  325     timeout = apr_time_from_sec(5);
  326 
  327     for (i = 0; i < MAX_RETRY; i++) {
  328         apr_thread_mutex_lock(timeout_mutex);
  329 
  330         begin = apr_time_now();
  331         s = apr_thread_cond_timedwait(timeout_cond, timeout_mutex, timeout);
  332         end = apr_time_now();
  333         apr_thread_mutex_unlock(timeout_mutex);
  334         
  335         if (s != APR_SUCCESS && !APR_STATUS_IS_TIMEUP(s)) {
  336             continue;
  337         }
  338         ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(s));
  339         ABTS_ASSERT(tc, "Timer returned too late", end - begin - timeout < 500000);
  340         break;
  341     }
  342     ABTS_ASSERT(tc, "Too many retries", i < MAX_RETRY);
  343     APR_ASSERT_SUCCESS(tc, "Unable to destroy the conditional",
  344                        apr_thread_cond_destroy(timeout_cond));
  345 }
  346 
  347 #if APR_HAS_TIMEDLOCKS
  348 static void test_timeoutmutex(abts_case *tc, void *data)
  349 {
  350     apr_status_t s;
  351     apr_interval_time_t timeout;
  352     apr_time_t begin, end;
  353     int i;
  354 
  355     s = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_TIMED, p);
  356     ABTS_INT_EQUAL(tc, APR_SUCCESS, s);
  357     ABTS_PTR_NOTNULL(tc, timeout_mutex);
  358 
  359     timeout = apr_time_from_sec(5);
  360 
  361     ABTS_INT_EQUAL(tc, 0, apr_thread_mutex_lock(timeout_mutex));
  362     for (i = 0; i < MAX_RETRY; i++) {
  363         begin = apr_time_now();
  364         s = apr_thread_mutex_timedlock(timeout_mutex, timeout);
  365         end = apr_time_now();
  366 
  367         if (s != APR_SUCCESS && !APR_STATUS_IS_TIMEUP(s)) {
  368             continue;
  369         }
  370         ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(s));
  371         ABTS_ASSERT(tc, "Timer returned too late", end - begin - timeout < 1000000);
  372         break;
  373     }
  374     ABTS_ASSERT(tc, "Too many retries", i < MAX_RETRY);
  375     ABTS_INT_EQUAL(tc, 0, apr_thread_mutex_unlock(timeout_mutex));
  376     APR_ASSERT_SUCCESS(tc, "Unable to destroy the mutex",
  377                        apr_thread_mutex_destroy(timeout_mutex));
  378 }
  379 #endif
  380 
  381 #endif /* !APR_HAS_THREADS */
  382 
  383 #if !APR_HAS_THREADS
  384 static void threads_not_impl(abts_case *tc, void *data)
  385 {
  386     ABTS_NOT_IMPL(tc, "Threads not implemented on this platform");
  387 }
  388 #endif
  389 
  390 
  391 abts_suite *testlock(abts_suite *suite)
  392 {
  393     suite = ADD_SUITE(suite)
  394 
  395 #if !APR_HAS_THREADS
  396     abts_run_test(suite, threads_not_impl, NULL);
  397 #else
  398     abts_run_test(suite, test_thread_mutex, NULL);
  399 #if APR_HAS_TIMEDLOCKS
  400     abts_run_test(suite, test_thread_timedmutex, NULL);
  401 #endif
  402     abts_run_test(suite, test_thread_rwlock, NULL);
  403     abts_run_test(suite, test_cond, NULL);
  404     abts_run_test(suite, test_timeoutcond, NULL);
  405 #if APR_HAS_TIMEDLOCKS
  406     abts_run_test(suite, test_timeoutmutex, NULL);
  407 #endif
  408 #endif
  409 
  410     return suite;
  411 }
  412