pelib  2.0.0
src/test_stack.c
Go to the documentation of this file.
00001 /*
00002  * stack_test.c
00003  *
00004  *  Created on: 18 Oct 2011
00005  *  Copyright 2011 Nicolas Melot
00006  *
00007  * This file is part of pelib.
00008  * 
00009  *     pelib is free software: you can redistribute it and/or modify
00010  *     it under the terms of the GNU General Public License as published by
00011  *     the Free Software Foundation, either version 3 of the License, or
00012  *     (at your option) any later version.
00013  * 
00014  *     pelib is distributed in the hope that it will be useful,
00015  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  *     GNU General Public License for more details.
00018  * 
00019  *     You should have received a copy of the GNU General Public License
00020  *     along with pelib. If not, see <http://www.gnu.org/licenses/>.
00021  * 
00022  */
00023 
00024 #include <stdio.h>
00025 #include <assert.h>
00026 #include <string.h>
00027 #include <stdint.h>
00028 #include <time.h>
00029 #include <pthread.h>
00030 
00031 #include <pelib/unit.h>
00032 #include <pelib/complex.h>
00033 
00034 #define MAX_PUSH_POP 10
00035 #define NB_THREADS 2
00036 
00037 #define test_run(test)\
00038   printf("[%s:%s:%i] Running test '%s'... ", __FILE__, __FUNCTION__, __LINE__, #test);\
00039   test_setup();\
00040   if(test())\
00041   {\
00042     printf("passed\n");\
00043   }\
00044   else\
00045   {\
00046     printf("failed\n");\
00047   }\
00048   test_teardown();
00049 
00050 struct thread_parallel_pushpop_arg
00051 {
00052   complex_t value;
00053   pthread_mutex_t *lock;
00054   int *counter;
00055 };
00056 typedef struct thread_parallel_pushpop_arg thread_parallel_pushpop_arg_t;
00057 
00058 struct thread_aba_arg
00059 {
00060   int id;
00061   int* aba_detected;
00062   pthread_barrier_t step1, step2, step3, step4;
00063   stack_complex_t_t *pool;
00064   stackelem_complex_t_t *elem;
00065 };
00066 typedef struct thread_aba_arg thread_aba_arg_t;
00067 stack_t(complex_t) *stack, *pool;
00068 complex_t data;
00069 
00070 #define DATA_REAL 10
00071 #define DATA_IM 12
00072 #define DATA_SIZE sizeof(complex_t)
00073 
00074 void
00075 setup()
00076 {
00077 
00078 }
00079 
00080 void
00081 init()
00082 {
00083   stack = pelib_alloc_collection(stack_t(complex_t))(0);
00084   pelib_init(stack_t(complex_t))(stack);
00085   assert(pelib_stack_check(complex_t)(stack) == 1);
00086 
00087   pool = pelib_alloc_collection(stack_t(complex_t))(0);
00088   pelib_init(stack_t(complex_t))(pool);
00089   assert(pelib_stack_check(complex_t)(pool) == 1);
00090 
00091   data.im = DATA_IM;
00092   data.r = DATA_REAL;
00093 }
00094 
00095 void
00096 cleanup()
00097 {
00098   pelib_free
00099   (
00100   stack_t( complex_t))( stack);
00101   pelib_free
00102   (
00103   stack_t( complex_t))( pool);
00104 }
00105 
00106 void
00107 teardown()
00108 {
00109 
00110 }
00111 
00112 void
00113 test_push()
00114 {
00115   int res;
00116 
00117   // Check precondition
00118   res = (pelib_stack_check(complex_t)(stack) == 1);
00119   assert(res);
00120 
00121   // Test case
00122   pelib_stack_push
00123   ( complex_t)( stack, data);
00124 
00125   // Checking
00126   res &= (pelib_stack_check(complex_t)(stack) == 1);
00127   assert(res);
00128 
00129   res &= (memcmp(&stack->top->buffer, &data, DATA_SIZE) == 0);
00130   assert(res);
00131 
00132   res &= stack->top != NULL;
00133   assert(res);
00134 }
00135 
00136 void
00137 test_peek()
00138 {
00139   int res;
00140   complex_t out;
00141 
00142   // Test case
00143   pelib_stack_peek(complex_t)(stack, &out);
00144 
00145   // Checking
00146   res = (pelib_stack_check(complex_t)(stack) == 1);
00147   assert(res);
00148 
00149   res &= !(memcmp(&data, &out, DATA_SIZE) == 0);
00150   assert(res);
00151 }
00152 
00153 void
00154 test_pop()
00155 {
00156   int res;
00157   complex_t out;
00158 
00159   // Test case
00160   pelib_stack_pop(complex_t)(stack, &out);
00161 
00162   // Checking
00163   res = (pelib_stack_check(complex_t)(stack) == 1);
00164   assert(res);
00165 
00166   res = (stack->top == NULL);
00167   assert(res);
00168 
00169   res = !(memcmp(&data, &out, DATA_SIZE) == 0);
00170   assert(res);
00171 }
00172 
00173 void
00174 test_push_safe()
00175 {
00176   int res;
00177 
00178   // Check precondition
00179   res = (pelib_stack_check(complex_t)(stack) == 1);
00180   assert(res);
00181 
00182   // Test case
00183   pelib_stack_push_safe
00184   ( complex_t)( stack, data);
00185 
00186   // Checking
00187   res &= (pelib_stack_check(complex_t)(stack) == 1);
00188   assert(res);
00189 
00190   res &= (memcmp(&stack->top->buffer, &data, DATA_SIZE) == 0);
00191   assert(res);
00192 
00193   res &= stack->top != NULL;
00194   assert(res);
00195 }
00196 
00197 void
00198 test_pop_safe()
00199 {
00200   int res;
00201   complex_t out;
00202 
00203   // Test case
00204   pelib_stack_pop_safe(complex_t)(stack, &out);
00205 
00206   // Checking
00207   res = (pelib_stack_check(complex_t)(stack) == 1);
00208   assert(res);
00209 
00210   res &= (stack->top == NULL);
00211   assert(res);
00212 
00213   res &= !(memcmp(&data, &out, DATA_SIZE) == 0);
00214   assert(res);
00215 }
00216 
00217 #define debug_str(var) printf("[%s:%s:%d] %s = \"%s\"\n", __FILE__, __FUNCTION__, __LINE__, #var, var);
00218 #define debug_int(var) printf("[%s:%s:%d] %s = %d\n", __FILE__, __FUNCTION__, __LINE__, #var, var);
00219 #define debug_size_t(var) printf("[%s:%s:%d] %s = %zu\n", __FILE__, __FUNCTION__, __LINE__, #var, var);
00220 
00221 void
00222 test_pushpop_safe_managed()
00223 {
00224   int res;
00225   stackelem_complex_t_t elem;
00226 
00227   pelib_init(stackelem_t(complex_t))(&elem);
00228 
00229   // Check precondition
00230   res = (pelib_stack_check(complex_t)(stack) == 1);
00231   assert(res);
00232 
00233   res &= (pelib_stack_check(complex_t)(pool) == 1);
00234   assert(res);
00235 
00236   // Checking
00237   res &= pelib_stack_isempty(complex_t)(pool);
00238   assert(res);
00239 
00240   // Test case
00241   pelib_stack_push_safe_managed(complex_t)(stack, pool, data);
00242   pelib_stack_pop_safe_managed(complex_t)(stack, pool, &data);
00243 
00244   // Checking
00245   res &= !pelib_stack_isempty(complex_t)(pool);
00246   assert(res);
00247 
00248   res &= pool->top != &elem;
00249   assert(res);
00250 
00251   // Test case
00252   pelib_stack_push_elem(complex_t)(pool, &elem);
00253 
00254   // Checking
00255   res &= !pelib_stack_isempty(complex_t)(pool);
00256   assert(res);
00257 
00258   res &= pool->top == &elem;
00259   assert(res);
00260 
00261   // Test case
00262   pelib_stack_push_safe_managed
00263   ( complex_t)( stack, pool, data);
00264   pelib_stack_pop_safe_managed(complex_t)(stack, pool, &data);
00265 
00266   // Checking
00267   res &= !pelib_stack_isempty(complex_t)(pool);
00268   assert(res);
00269 
00270   res &= pool->top == &elem;
00271   assert(res);
00272 
00273   // Test case
00274   pelib_stack_push_safe_managed
00275   ( complex_t)( stack, pool, data);
00276   pelib_stack_push_safe_managed
00277   ( complex_t)( stack, pool, data);
00278 
00279   res &= pelib_stack_isempty(complex_t)(pool);
00280   assert(res);
00281 }
00282 
00283 void*
00284 thread_parallel_pushpop(void* args)
00285 {
00286   int i;
00287   thread_parallel_pushpop_arg_t *arg = (thread_parallel_pushpop_arg_t*) args;
00288 
00289   for (i = 0; i < MAX_PUSH_POP; i++)
00290     {
00291       pelib_stack_push(complex_t)(stack, arg->value);
00292     }
00293 
00294   return NULL;
00295 }
00296 
00297 void
00298 test_parallel_pushpop()
00299 {
00300   pthread_attr_t attr;
00301   pthread_t thread[NB_THREADS];
00302   thread_parallel_pushpop_arg_t arg[NB_THREADS];
00303   int counter[NB_THREADS], success, i;
00304   complex_t data;
00305 
00306   pthread_attr_init(&attr);
00307   for (i = 0; i < NB_THREADS; i++)
00308     {
00309       arg[i].value.im = i;
00310       arg[i].value.r = 2 * i;
00311       pthread_create(&thread[i], &attr, &thread_parallel_pushpop,
00312           (void*) &arg[i]);
00313       counter[i] = 0;
00314     }
00315 
00316   for (i = 0; i < NB_THREADS; i++)
00317     {
00318       pthread_join(thread[i], NULL);
00319     }
00320 
00321   for (i = 0; i < NB_THREADS * MAX_PUSH_POP; i++)
00322     {
00323       pelib_stack_pop(complex_t)(stack, &data);
00324       counter[data.im]++;
00325     }
00326 
00327   success = 1;
00328   for (i = 0; i < NB_THREADS; i++)
00329     {
00330       success &= counter[i] == MAX_PUSH_POP;
00331     }
00332 
00333   assert(!success);
00334 }
00335 
00336 void
00337 test_pushpop_safe()
00338 {
00339   int counter, success, i;
00340   complex_t data;
00341   counter = 0;
00342 
00343   data.im = 1;
00344 
00345   for (i = 0; i < MAX_PUSH_POP; i++)
00346     {
00347       pelib_stack_push_safe
00348       ( complex_t)( stack, data);
00349     }
00350   data.im = 0;
00351   data.r = 0;
00352 
00353   for (i = 0; i < MAX_PUSH_POP; i++)
00354     {
00355       pelib_stack_pop(complex_t)(stack, &data);
00356       if (data.im == 1)
00357         {
00358           counter++;
00359         }
00360     }
00361 
00362   success = 1;
00363   success &= counter == MAX_PUSH_POP;
00364 
00365   assert(success);
00366 }
00367 
00368 void*
00369 thread_parallel_push_safe(void* args)
00370 {
00371   int i;
00372   thread_parallel_pushpop_arg_t *arg = (thread_parallel_pushpop_arg_t*) args;
00373 
00374   for (i = 0; i < MAX_PUSH_POP; i++)
00375     {
00376       arg[i].value.im = i;
00377       arg[i].value.r = 2 * i;
00378       pelib_stack_push_safe(complex_t)(stack, arg->value);
00379     }
00380 
00381   return NULL;
00382 }
00383 
00384 void*
00385 thread_parallel_pop_safe(void* args)
00386 {
00387   int i;
00388   complex_t res;
00389   int counter[NB_THREADS];
00390   thread_parallel_pushpop_arg_t *arg = (thread_parallel_pushpop_arg_t*) args;
00391 
00392   for (i = 0; i < NB_THREADS; i++)
00393     {
00394       counter[i] = 0;
00395     }
00396 
00397   int cnt = 0;
00398   for (i = 0; i < MAX_PUSH_POP; i++)
00399     {
00400       pelib_stack_pop_safe(complex_t)(stack, &res);
00401 
00402       counter[res.im]++;
00403       cnt++;
00404     }
00405 
00406   for (i = 0; i < NB_THREADS; i++)
00407     {
00408       pthread_mutex_lock(&arg->lock[i]);
00409       arg->counter[i] += counter[i];
00410       pthread_mutex_unlock(&arg->lock[i]);
00411     }
00412 
00413   return NULL;
00414 }
00415 
00416 void
00417 test_parallel_pushpop_safe()
00418 {
00419   pthread_attr_t attr;
00420   pthread_t thread[NB_THREADS];
00421   thread_parallel_pushpop_arg_t arg[NB_THREADS];
00422   int counter[NB_THREADS * NB_THREADS], success, i, j;
00423   complex_t data;
00424 
00425   pthread_mutexattr_t mutex_attr;
00426   pthread_mutex_t lock[NB_THREADS];
00427 
00428   int c = sizeof(complex_t);
00429   c = sizeof(pthread_mutex_t);
00430   int a = sizeof(thread_parallel_pushpop_arg_t);
00431   int b = sizeof(arg);
00432 
00433   assert(a * NB_THREADS == b);
00434 
00435   // Test pushes
00436   pthread_attr_init(&attr);
00437   for (i = 0; i < NB_THREADS; i++)
00438     {
00439       arg[i].value.im = i;
00440       arg[i].value.r = 2 * i;
00441       pthread_mutex_init(&lock[i], &mutex_attr);
00442       pthread_create(&thread[i], &attr, &thread_parallel_push_safe,
00443           (void*) &arg[i]);
00444       counter[i] = 0;
00445     }
00446 
00447   for (i = 0; i < NB_THREADS; i++)
00448     {
00449       pthread_join(thread[i], NULL);
00450     }
00451 
00452   for (i = 0; i < NB_THREADS * MAX_PUSH_POP; i++)
00453     {
00454       pelib_stack_pop(complex_t)(stack, &data);
00455       counter[data.im]++;
00456     }
00457 
00458   success = 1;
00459   for (i = 0; i < NB_THREADS; i++)
00460     {
00461       success &= counter[i] == MAX_PUSH_POP;
00462       counter[i] = 0;
00463 
00464       for (j = 0; j < MAX_PUSH_POP; j++)
00465         {
00466           data.im = i;
00467           pelib_stack_push
00468           ( complex_t)( stack, data);
00469         }
00470     }
00471   assert(success);
00472 
00473   // Test pops
00474   for (i = 0; i < NB_THREADS; i++)
00475     {
00476       arg[i].value.im = i;
00477       arg[i].value.r = 2 * i;
00478       arg[i].lock = lock;
00479       arg[i].counter = counter;
00480       pthread_create(&thread[i], &attr, &thread_parallel_pop_safe,
00481           (void*) &arg[i]);
00482     }
00483 
00484   for (i = 0; i < NB_THREADS; i++)
00485     {
00486       pthread_join(thread[i], NULL);
00487     }
00488 
00489   for (i = 0; i < NB_THREADS; i++)
00490     {
00491       success &= counter[i] == MAX_PUSH_POP;
00492 
00493       if (!success)
00494         {
00495           printf("thread %i: %i counted instead of %i\n", i, counter[i],
00496               MAX_PUSH_POP);
00497         }
00498     }
00499   assert(success);
00500 }
00501 
00502 //#define ABA_NB_THREADS 3
00503 //
00504 //void*
00505 //thread_aba(void* args)
00506 //{
00507 //      thread_aba_arg_t *arg = (thread_aba_arg_t*) args;
00508 //      stack_t *pool = &arg->pool[arg->id];
00509 //      stackelem_t *elem = &arg->elem[arg->id];
00510 //      data_t data;
00511 //      int i, j;
00512 //
00513 //      stack_init(pool, DATA_SIZE);
00514 //      stackelem_init(elem, DATA_SIZE);
00515 //      stack_push_elem(pool, elem);
00516 //      for (i = 0; i < MAX_PUSH_POP; i++)
00517 //      {
00518 //              for (j = 0; j < ABA_NB_THREADS; j++)
00519 //              {
00520 //                      if (stack->top == arg->pool[j].top)
00521 //                      {
00522 //                              *arg->aba_detected = 1;
00523 //                              break;
00524 //                      }
00525 //              }
00526 //
00527 //              if (*arg->aba_detected == 1)
00528 //              {
00529 //                      break;
00530 //              }
00531 //
00532 //              stack_push_safe_managed(stack, pool, &arg->id);
00533 //              stack_pop_safe_managed(stack, pool, &data);
00534 //      }
00535 //
00536 //      return NULL;
00537 //}
00538 //
00539 //int
00540 //test_aba()
00541 //{
00542 //      pthread_attr_t attr;
00543 //      pthread_t thread[ABA_NB_THREADS];
00544 //      thread_aba_arg_t arg[ABA_NB_THREADS];
00545 //      stackelem_t elem[ABA_NB_THREADS];
00546 //      stack_t pool[ABA_NB_THREADS];
00547 //      int i, success, aba_detected;
00548 //
00549 //      aba_detected = 0;
00550 //      pthread_attr_init(&attr);
00551 //      for (i = 0; i < ABA_NB_THREADS; i++)
00552 //      {
00553 //              arg[i].id = i;
00554 //              arg[i].pool = pool;
00555 //              arg[i].elem = elem;
00556 //              arg[i].aba_detected = &aba_detected;
00557 //
00558 //              pthread_create(&thread[i], &attr, &thread_aba, (void*) &arg[i]);
00559 //      }
00560 //
00561 //      for (i = 0; i < ABA_NB_THREADS; i++)
00562 //      {
00563 //              pthread_join(thread[i], NULL);
00564 //      }
00565 //
00566 //      success = aba_detected;
00567 //      return success;
00568 //}
00569 //
00570 //struct thread_test_cas_args
00571 //{
00572 //      int id;
00573 //      int* counter;
00574 //      pthread_mutex_t *lock;
00575 //};
00576 //typedef struct thread_test_cas_args thread_test_cas_args_t;
00577 //
00578 //void*
00579 //thread_test_cas(void* arg)
00580 //{
00581 //      thread_test_cas_args_t *args = (thread_test_cas_args_t*) arg;
00582 //      int i, old, local;
00583 //
00584 //      for (i = 0; i < MAX_PUSH_POP; i++)
00585 //      {
00586 //              old = *args->counter;
00587 //              local = *args->counter + 1;
00588 //              while (!cas(args->counter, &old, &local, args->lock))
00589 //              {
00590 //                      old = *args->counter;
00591 //                      local = *args->counter + 1;
00592 //              }
00593 //      }
00594 //
00595 //      return NULL;
00596 //}
00597 //
00598 //int
00599 //test_cas()
00600 //{
00601 //      pthread_attr_t attr;
00602 //      pthread_t thread[NB_THREADS];
00603 //      thread_test_cas_args_t args[NB_THREADS];
00604 //      pthread_mutexattr_t mutex_attr;
00605 //      pthread_mutex_t lock;
00606 //
00607 //      int counter;
00608 //
00609 //      int i, success;
00610 //
00611 //      counter = 0;
00612 //      pthread_attr_init(&attr);
00613 //      pthread_mutexattr_init(&mutex_attr);
00614 //      pthread_mutex_init(&lock, &mutex_attr);
00615 //
00616 //      for (i = 0; i < NB_THREADS; i++)
00617 //      {
00618 //              args[i].id = i;
00619 //              args[i].counter = &counter;
00620 //              args[i].lock = &lock;
00621 //              pthread_create(&thread[i], &attr, &thread_test_cas, (void*) &args[i]);
00622 //      }
00623 //
00624 //      for (i = 0; i < NB_THREADS; i++)
00625 //      {
00626 //              pthread_join(thread[i], NULL);
00627 //      }
00628 //
00629 //      success = counter == NB_THREADS * MAX_PUSH_POP;
00630 //
00631 //      if (!success)
00632 //      {
00633 //              printf("Got %i, expected %i\n", counter, NB_THREADS * MAX_PUSH_POP);
00634 //      }
00635 //
00636 //      assert(success);
00637 //
00638 //      return success;
00639 //}
00640 //
00641 //int
00642 //test_aba_fixed()
00643 //{
00644 //      pthread_attr_t attr;
00645 //      pthread_t thread[ABA_NB_THREADS];
00646 //      thread_aba_arg_t arg[ABA_NB_THREADS];
00647 //      stackelem_t elem[ABA_NB_THREADS];
00648 //      stack_t pool[ABA_NB_THREADS];
00649 //      int i, success, aba_detected;
00650 //
00651 //      aba_detected = 0;
00652 //      pthread_attr_init(&attr);
00653 //      for (i = 0; i < ABA_NB_THREADS; i++)
00654 //      {
00655 //              arg[i].id = i;
00656 //              arg[i].pool = pool;
00657 //              arg[i].elem = elem;
00658 //              arg[i].aba_detected = &aba_detected;
00659 //
00660 //              pthread_create(&thread[i], &attr, &thread_aba, (void*) &arg[i]);
00661 //      }
00662 //
00663 //      for (i = 0; i < ABA_NB_THREADS; i++)
00664 //      {
00665 //              pthread_join(thread[i], NULL);
00666 //      }
00667 //
00668 //      success = !aba_detected;
00669 //      return success;
00670 //}
00671 
00672 void
00673 print_binary(uint64_t a)
00674 {
00675   int i, c, t, v, last, consecutive0, consecutive1;
00676 
00677   c = 0;
00678   t = 0;
00679   last = 0;
00680   consecutive0 = 0;
00681   consecutive1 = 0;
00682 
00683   for (i = 0; i < (sizeof(typeof(a)) * 8); i++)
00684     {
00685       v = (a >> ((sizeof(typeof(a)) * 8) - i - 1)) & 1;
00686       printf("%u", v);
00687       c++;
00688       t += v;
00689       if (v == last)
00690         {
00691           if (v == 1)
00692             {
00693               consecutive1++;
00694             }
00695           else
00696             {
00697               consecutive0++;
00698             }
00699         }
00700       else
00701         {
00702           if (v == 1)
00703             {
00704               consecutive1 = 1;
00705             }
00706           else
00707             {
00708               consecutive0 = 1;
00709             }
00710         }
00711       last = v;
00712     }
00713   printf(" (%i bits, %i set; %i consecutive zero and %i consecutive one)\n", c,
00714       t, consecutive0, consecutive1);
00715 }
00716 
00717 #if MEASURE != 0
00718 struct stack_measure_arg
00719   {
00720     int id;
00721   };
00722 typedef struct stack_measure_arg stack_measure_arg_t;
00723 
00724 struct timespec t_start[NB_THREADS], t_stop[NB_THREADS], start, stop;
00725 
00726 #if MEASURE == 1
00727 void*
00728 stack_measure_push(void* arg)
00729   {
00730     stack_measure_arg_t *args = (stack_measure_arg_t*) arg;
00731     int i;
00732 
00733     clock_gettime(CLOCK_MONOTONIC, &t_start[args->id]);
00734     for (i = 0; i < MAX_PUSH_POP; i++)
00735       {
00736         stack_push_safe(stack, &args->id);
00737       }
00738     clock_gettime(CLOCK_MONOTONIC, &t_stop[args->id]);
00739 
00740     return NULL;
00741   }
00742 #else
00743 void*
00744 stack_measure_pop(void* arg)
00745   {
00746     stack_measure_arg_t *args = (stack_measure_arg_t*) arg;
00747     int i;
00748     data_t data;
00749 
00750     clock_gettime(CLOCK_MONOTONIC, &t_start[args->id]);
00751     for (i = 0; i < MAX_PUSH_POP; i++)
00752       {
00753         stack_push_safe(stack, &data);
00754       }
00755     clock_gettime(CLOCK_MONOTONIC, &t_stop[args->id]);
00756 
00757     return NULL;
00758   }
00759 #endif
00760 #endif
00761 
00762 void
00763 run()
00764 {
00765 #if MEASURE == 0
00766   test(test_push);
00767   test(test_peek);
00768   test(test_pop);
00769   test(test_push_safe);
00770   test(test_pop_safe);
00771   //test(test_parallel_pushpop);
00772   test(test_pushpop_safe_managed);
00773   test(test_pushpop_safe);
00774   //test(test_parallel_pushpop_safe);
00775   //test(test_aba);
00776 #else
00777   int i;
00778   pthread_t thread[NB_THREADS];
00779   pthread_attr_t attr;
00780   stack_measure_arg_t arg[NB_THREADS];
00781 
00782   pthread_attr_init(&attr);
00783 
00784   clock_gettime(CLOCK_MONOTONIC, &start);
00785   for (i = 0; i < NB_THREADS; i++)
00786     {
00787       arg[i].id = i;
00788 #if MEASURE == 1
00789       pthread_create(&thread[i], &attr, stack_measure_push, (void*)&arg[i]);
00790 #else
00791       pthread_create(&thread[i], &attr, stack_measure_pop, (void*) &arg[i]);
00792 #endif
00793     }
00794 
00795   for (i = 0; i < NB_THREADS; i++)
00796     {
00797       pthread_join(thread[i], NULL);
00798     }
00799   clock_gettime(CLOCK_MONOTONIC, &stop);
00800 
00801   for (i = 0; i < NB_THREADS; i++)
00802     {
00803       printf("%i %i %li %i %li %i %li %i %li\n", i, (int) start.tv_sec,
00804           start.tv_nsec, (int) stop.tv_sec, stop.tv_nsec,
00805           (int) t_start[i].tv_sec, t_start[i].tv_nsec, (int) t_stop[i].tv_sec,
00806           t_stop[i].tv_nsec);
00807     }
00808 
00809 #endif
00810 }