This source file includes following definitions.
- store_newest_sum
- block_sigint
- idle_thread
- sigint_handler
- send_signal
- signal_sending_thread
- mutator_thread
- main
- main
- main
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 
  33 
  34 
  35 
  36 
  37 
  38 
  39 
  40 
  41 
  42 
  43 
  44 #include <config.h>
  45 
  46 
  47 #if 4 < __GNUC__ + (3 <= __GNUC_MINOR__)
  48 # pragma GCC diagnostic ignored "-Wreturn-type"
  49 #endif
  50 
  51 #include "gl_linked_list.h"
  52 
  53 #if SIGNAL_SAFE_LIST
  54 
  55 # if USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS 
  56 
  57 
  58 
  59 
  60 
  61 
  62 
  63 #  include <signal.h>
  64 #  include <stdint.h>
  65 #  include <stdlib.h>
  66 #  include <unistd.h>
  67 #  include <time.h>
  68 
  69 #  include "glthread/thread.h"
  70 #  include "glthread/yield.h"
  71 
  72 #  include "macros.h"
  73 
  74 
  75 
  76 
  77 
  78 
  79 
  80 #  define MY_SIGNAL SIGTERM
  81 
  82 #  define RANDOM(n) (rand () % (n))
  83 #  define RANDOM_OBJECT() ((void *) (uintptr_t) RANDOM (10000))
  84 
  85 
  86 
  87 
  88 static int volatile test;
  89 
  90 
  91 
  92 #  define NUM_RECENT_SUMS (4*1024*1024)
  93 static uintptr_t volatile recent_sums[NUM_RECENT_SUMS];
  94 
  95 
  96 
  97 
  98 static size_t volatile recent_sums_newest_index;
  99 static size_t volatile recent_sums_oldest_index;
 100 
 101 static void
 102 store_newest_sum (uintptr_t sum)
     
 103 {
 104   recent_sums_oldest_index +=
 105     (recent_sums_newest_index - recent_sums_oldest_index) == NUM_RECENT_SUMS;
 106   recent_sums[recent_sums_newest_index % NUM_RECENT_SUMS] = sum;
 107   recent_sums_newest_index++;
 108 }
 109 
 110 static gl_list_t volatile list1;
 111 
 112 static gl_thread_t volatile signal_target;
 113 
 114 
 115 static unsigned int volatile num_mutations;
 116 static unsigned int volatile num_signals_sent;
 117 static unsigned int volatile num_signals_arrived;
 118 
 119 
 120 static void
 121 block_sigint (void)
     
 122 {
 123   sigset_t mask;
 124 
 125   sigemptyset (&mask);
 126   sigaddset (&mask, MY_SIGNAL);
 127   sigprocmask (SIG_BLOCK, &mask, NULL); 
 128 }
 129 
 130 
 131 static void *
 132 idle_thread (void *arg)
     
 133 {
 134   for (;;)
 135     gl_thread_yield ();
 136 
 137   
 138 }
 139 
 140 
 141 
 142 static _GL_ASYNC_SAFE void
 143 sigint_handler (int signo)
     
 144 {
 145   num_signals_arrived++;
 146 
 147   uintptr_t sum = 0;
 148   {
 149     gl_list_iterator_t iter = gl_list_iterator (list1);
 150     const void *elt;
 151 
 152     while (gl_list_iterator_next (&iter, &elt, NULL))
 153       sum += (uintptr_t) elt;
 154     gl_list_iterator_free (&iter);
 155   }
 156 
 157   bool found = false;
 158   if (test != 1)
 159     {
 160       
 161 
 162 
 163 
 164       size_t i;
 165       for (i = recent_sums_newest_index - 1;;)
 166         {
 167           if (sum == recent_sums[i % NUM_RECENT_SUMS]
 168               && i >= recent_sums_oldest_index)
 169             {
 170               found = true;
 171               break;
 172             }
 173           if (i <= recent_sums_oldest_index)
 174             break;
 175           i--;
 176         }
 177     }
 178   else
 179     {
 180       
 181 
 182 
 183       size_t i = recent_sums_newest_index - 1;
 184       found = (sum == recent_sums[i % NUM_RECENT_SUMS]
 185                || (i > recent_sums_oldest_index
 186                    && sum == recent_sums[(i - 1) % NUM_RECENT_SUMS]));
 187     }
 188   if (!found)
 189     {
 190       
 191 
 192 
 193       size_t i = recent_sums_newest_index - 1;
 194       fprintf (stderr, "sum = %lu, expected %lu or older (after %u mutations and %u signals)\n",
 195                (unsigned long) sum,
 196                (unsigned long) recent_sums[i % NUM_RECENT_SUMS],
 197                num_mutations, num_signals_arrived);
 198       fflush (stderr);
 199       abort ();
 200     }
 201 }
 202 
 203 
 204 static void
 205 send_signal (void)
     
 206 {
 207 #if 0
 208   
 209 
 210 
 211   raise (MY_SIGNAL);
 212 #else
 213   
 214 
 215 
 216 
 217 
 218 
 219 
 220   kill (getpid (), MY_SIGNAL);
 221 #endif
 222 }
 223 
 224 
 225 static void *
 226 signal_sending_thread (void *arg)
     
 227 {
 228   if (test != 3)
 229     block_sigint ();
 230 
 231   int repeat;
 232 
 233   for (repeat = 1000; repeat > 0; repeat--)
 234     {
 235       num_signals_sent++; send_signal ();
 236       num_signals_sent++; send_signal ();
 237       num_signals_sent++; send_signal ();
 238       num_signals_sent++; send_signal ();
 239       num_signals_sent++; send_signal ();
 240       {
 241         struct timespec ts;
 242         ts.tv_sec = 0; ts.tv_nsec = 1000000;
 243         nanosleep (&ts, NULL);
 244       }
 245       gl_thread_yield ();
 246     }
 247 
 248   printf ("Sent %u signals. Received %u signals. Done after %u mutations.\n",
 249           num_signals_sent, num_signals_arrived, num_mutations);
 250 
 251   exit (0);
 252 
 253   
 254 }
 255 
 256 
 257 static void *
 258 mutator_thread (void *arg)
     
 259 {
 260   if (test != 1)
 261     block_sigint ();
 262 
 263   gl_list_t list2 = (gl_list_t) arg;
 264 
 265   for (num_mutations = 0; ; num_mutations++)
 266     {
 267       unsigned int operation = RANDOM (2);
 268       switch (operation)
 269         {
 270         case 0: 
 271           {
 272             const void *obj = RANDOM_OBJECT ();
 273             ASSERT (gl_list_nx_add_first (list2, obj) != NULL);
 274             uintptr_t sum_before_current_operation =
 275               recent_sums[(recent_sums_newest_index - 1) % NUM_RECENT_SUMS];
 276             uintptr_t sum_after_current_operation =
 277               sum_before_current_operation + (uintptr_t) obj;
 278             store_newest_sum (sum_after_current_operation);
 279             ASSERT (gl_list_nx_add_first (list1, obj) != NULL);
 280           }
 281           break;
 282         case 1: 
 283           if (gl_list_size (list2) > 0)
 284             {
 285               size_t index = RANDOM (gl_list_size (list2));
 286               const void *obj = gl_list_get_at (list2, index);
 287               ASSERT (gl_list_remove (list2, obj));
 288               uintptr_t sum_before_current_operation =
 289                 recent_sums[(recent_sums_newest_index - 1) % NUM_RECENT_SUMS];
 290               uintptr_t sum_after_current_operation =
 291                 sum_before_current_operation - (uintptr_t) obj;
 292               store_newest_sum (sum_after_current_operation);
 293               ASSERT (gl_list_remove (list1, obj));
 294             }
 295           break;
 296         }
 297     }
 298 
 299   
 300 }
 301 
 302 int
 303 main (int argc, char *argv[])
     
 304 {
 305   test = atoi (argv[1]);
 306 
 307   
 308   if (argc > 2)
 309     srand (atoi (argv[2]));
 310 
 311   gl_list_t list2;
 312   
 313   {
 314     size_t initial_size = RANDOM (50);
 315     const void **contents =
 316       (const void **) malloc (initial_size * sizeof (const void *));
 317     size_t i;
 318 
 319     for (i = 0; i < initial_size; i++)
 320       contents[i] = RANDOM_OBJECT ();
 321 
 322     list1 = gl_list_nx_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
 323     ASSERT (list1 != NULL);
 324     for (i = 0; i < initial_size; i++)
 325       ASSERT (gl_list_nx_add_first (list1, contents[i]) != NULL);
 326 
 327     list2 = gl_list_nx_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
 328     ASSERT (list2 != NULL);
 329     for (i = 0; i < initial_size; i++)
 330       ASSERT (gl_list_nx_add_last (list2, contents[i]) != NULL);
 331 
 332     uintptr_t initial_sum = 0;
 333     for (i = 0; i < initial_size; i++)
 334       initial_sum += (uintptr_t) contents[i];
 335     recent_sums_oldest_index = 0;
 336     recent_sums[0] = initial_sum;
 337     recent_sums_newest_index = 1;
 338   }
 339 
 340   
 341 
 342 
 343   #if 0
 344   signal (MY_SIGNAL, sigint_handler);
 345   #else
 346   {
 347     struct sigaction action;
 348     action.sa_handler = sigint_handler;
 349     action.sa_flags = SA_RESTART | SA_NODEFER;
 350     sigemptyset (&action.sa_mask);
 351     ASSERT (sigaction (MY_SIGNAL, &action, NULL) == 0);
 352   }
 353   #endif
 354 
 355   
 356   switch (test)
 357     {
 358     case 1:
 359       {
 360         signal_target = gl_thread_create (mutator_thread, list2);
 361         signal_sending_thread (NULL);
 362         abort ();
 363       }
 364 
 365     case 2:
 366       {
 367         signal_target = gl_thread_create (idle_thread, NULL);
 368         gl_thread_create (mutator_thread, list2);
 369         signal_sending_thread (NULL);
 370         abort ();
 371       }
 372 
 373     case 3:
 374       {
 375         gl_thread_create (mutator_thread, list2);
 376         signal_target = gl_thread_self (); signal_sending_thread (NULL);
 377         abort ();
 378       }
 379 
 380     default:
 381       ASSERT (false);
 382     }
 383 }
 384 
 385 # else
 386 
 387 #  include <stdio.h>
 388 
 389 int
 390 main ()
     
 391 {
 392   fputs ("Skipping test: POSIX compatible multithreading not enabled\n", stderr);
 393   return 77;
 394 }
 395 
 396 # endif
 397 
 398 #else
 399 
 400 # include <stdio.h>
 401 
 402 int
 403 main ()
     
 404 {
 405   fputs ("Skipping test: signal-safety of linked lists is not enabled\n", stderr);
 406   return 77;
 407 }
 408 
 409 #endif