LCOV - code coverage report
Current view: top level - src/tools/race - race.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 0 67 0.0 %
Date: 2019-09-12 12:28:41 Functions: 0 2 0.0 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  */
       8             : 
       9             : #include <kdb.h>
      10             : #include <kdbhelper.h>
      11             : #include <kdbmacros.h>
      12             : 
      13             : #include <fcntl.h>
      14             : #include <pthread.h>
      15             : #include <stdio.h>
      16             : #include <stdlib.h>
      17             : #include <sys/mman.h>
      18             : #include <sys/stat.h>
      19             : #include <sys/wait.h>
      20             : #include <unistd.h>
      21             : 
      22             : pthread_barrier_t * bar;
      23             : 
      24           0 : void * writer (void * pV_data ELEKTRA_UNUSED)
      25             : {
      26           0 :         Key * parent = keyNew ("user/test/race", KEY_END);
      27           0 :         KDB * h = kdbOpen (parent);
      28             :         char buffer[4096];
      29           0 :         unsigned long tid = (unsigned long) pthread_self ();
      30           0 :         int pid = getpid ();
      31           0 :         sprintf (buffer, "user/test/race/keys/%d/%lu", pid, tid);
      32           0 :         KeySet * ks = ksNew (20, KS_END);
      33             : 
      34           0 :         int retg = kdbGet (h, ks, parent);
      35           0 :         ksAppendKey (ks, keyNew (buffer, KEY_VALUE, "a value", KEY_END));
      36             : 
      37           0 :         pthread_barrier_wait (bar);
      38           0 :         int rets = kdbSet (h, ks, parent);
      39             : 
      40           0 :         if (rets != -1)
      41             :         {
      42           0 :                 int retg2 = kdbGet (h, ks, parent);
      43           0 :                 printf ("I (%d/%lu) won the race! Got return values from first get %d,"
      44             :                         " from set %d, from second get %d\n",
      45             :                         pid, tid, retg, rets, retg2);
      46           0 :                 ksRewind (ks);
      47             :                 /*
      48             :                 Key * c;
      49             :                 while ((c = ksNext(ks)))
      50             :                 {
      51             :                         printf ("Got key: %s - %s\n",
      52             :                                 keyName(c), keyString(c));
      53             :                 }
      54             :                 */
      55             :         }
      56             :         else
      57             :         {
      58           0 :                 printf ("I (%d/%lu) lost the race! Got %d and from set %d\n", pid, tid, retg, rets);
      59             :         }
      60             : 
      61           0 :         ksDel (ks);
      62           0 :         kdbClose (h, parent);
      63           0 :         keyDel (parent);
      64             : 
      65             :         // pthread_exit (NULL);
      66           0 :         return 0;
      67             : }
      68             : 
      69           0 : int main (int argc, char ** argv)
      70             : {
      71           0 :         if (argc != 4)
      72             :         {
      73           0 :                 printf ("Usage %s <procs> <threads> <barriers>\n", argv[0]);
      74           0 :                 printf ("This program tests race condition in Elektra\n");
      75           0 :                 printf ("If you set barriers procs*threads, all threads will\n");
      76           0 :                 printf ("start kdbSet() at roughly the same time\n");
      77           0 :                 return 1;
      78             :         }
      79             : 
      80             :         // on error (0) is safe
      81           0 :         int num_procs = atoi (argv[1]);
      82           0 :         int num_threads = atoi (argv[2]);
      83           0 :         int num_barriers = atoi (argv[3]);
      84             : 
      85           0 :         if (num_barriers > num_procs * num_threads)
      86             :         {
      87             :                 return 1;
      88             :         }
      89             : 
      90             :         pthread_barrierattr_t attr;
      91           0 :         if (pthread_barrierattr_init (&attr) != 0)
      92             :         {
      93             :                 return 2;
      94             :         }
      95             : 
      96           0 :         if (pthread_barrierattr_setpshared (&attr, PTHREAD_PROCESS_SHARED) != 0)
      97             :         {
      98             :                 return 3;
      99             :         }
     100             : 
     101           0 :         char shm_name[] = "shm_name_elektra_test_race";
     102           0 :         shm_unlink (shm_name); // may fail
     103             : 
     104           0 :         int shm_fd = shm_open (shm_name, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
     105             : 
     106           0 :         if (shm_fd == -1)
     107             :         {
     108             :                 return 6;
     109             :         }
     110             : 
     111           0 :         if (ftruncate (shm_fd, sizeof (pthread_barrier_t)) != 0)
     112             :         {
     113             :                 return 7;
     114             :         }
     115             : 
     116           0 :         bar = mmap (NULL, sizeof (pthread_barrier_t), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
     117             : 
     118           0 :         if (bar == MAP_FAILED)
     119             :         {
     120           0 :                 shm_unlink (shm_name);
     121           0 :                 return 8;
     122             :         }
     123             : 
     124           0 :         if (pthread_barrier_init (bar, &attr, num_barriers) != 0)
     125             :         {
     126             :                 return 10;
     127             :         }
     128             : 
     129           0 :         if (pthread_barrierattr_destroy (&attr) != 0)
     130             :         {
     131             :                 return 11;
     132             :         }
     133             : 
     134             : 
     135             :         int i;
     136           0 :         for (i = 0; i < num_procs; i++)
     137             :         {
     138           0 :                 int pid = fork ();
     139             : 
     140           0 :                 if (pid == -1)
     141             :                 {
     142             :                         // fork not successful
     143             :                         return 12;
     144             :                 }
     145           0 :                 else if (pid == 0)
     146             :                 {
     147             :                         // child
     148           0 :                         pthread_t * pwriter = elektraMalloc (num_threads * sizeof (pthread_t));
     149           0 :                         if (!pwriter) return 13;
     150           0 :                         for (i = 0; i < num_threads; i++)
     151           0 :                                 if (pthread_create (&pwriter[i], NULL, writer, (void *) 0) != 0) return 14;
     152           0 :                         for (i = 0; i < num_threads; i++)
     153           0 :                                 pthread_join (pwriter[i], NULL);
     154           0 :                         elektraFree (pwriter);
     155           0 :                         return 0;
     156             :                 }
     157             :         }
     158             : 
     159           0 :         int status = 0;
     160           0 :         int sumexitstatus = 0;
     161           0 :         for (i = 0; i < num_procs; i++)
     162             :         {
     163           0 :                 wait (&status);
     164           0 :                 int exitstatus = WEXITSTATUS (status);
     165             : 
     166           0 :                 if (exitstatus)
     167             :                 {
     168           0 :                         sumexitstatus = 100 + exitstatus;
     169             :                 }
     170             :         }
     171             : 
     172             : 
     173           0 :         if (pthread_barrier_destroy (bar) != 0)
     174             :         {
     175             :                 return 40;
     176             :         }
     177             : 
     178           0 :         if ((shm_unlink (shm_name)) != 0)
     179             :         {
     180             :                 return 41;
     181             :         }
     182             : 
     183           0 :         printf ("Test run finished\n");
     184           0 :         return sumexitstatus;
     185             : }

Generated by: LCOV version 1.13