LCOV - code coverage report
Current view: directory - src/shared/platform - nacl_semaphore_test.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 92 67 72.8 %
Date: 2014-09-25 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2011 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : #include <stdio.h>
       8                 : 
       9                 : #include "native_client/src/include/portability.h"
      10                 : #include "native_client/src/include/nacl_macros.h"
      11                 : 
      12                 : #include "native_client/src/shared/platform/nacl_semaphore.h"
      13                 : 
      14                 : #include "native_client/src/shared/platform/nacl_sync.h"
      15                 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
      16                 : #include "native_client/src/shared/platform/nacl_threads.h"
      17                 : #include "native_client/src/shared/platform/nacl_time.h"
      18                 : #include "native_client/src/shared/platform/platform_init.h"
      19                 : 
      20                 : #include "native_client/src/trusted/service_runtime/include/sys/time.h"
      21                 : 
      22                 : #define STACK_SIZE_BYTES        (4 * 4096)
      23                 : #define NUM_TRIES_SUFFICIENT    (5)
      24                 : 
      25               1 : void ThreadSleepMs(uint64_t msec) {
      26                 :   struct nacl_abi_timespec nap_duration;
      27                 : 
      28               1 :   nap_duration.tv_sec = (nacl_abi_time_t) (msec / 1000);
      29               1 :   nap_duration.tv_nsec = (long) (msec % 1000);
      30               1 :   NaClNanosleep(&nap_duration, (struct nacl_abi_timespec *) NULL);
      31               1 : }
      32                 : 
      33               1 : void PauseSpinningThread(void) {
      34               1 :   ThreadSleepMs(10);
      35               1 : }
      36                 : 
      37                 : size_t gNumTriesSufficient = NUM_TRIES_SUFFICIENT;
      38                 : struct NaClSemaphore gSem;
      39                 : struct NaClMutex gMu;
      40                 : struct NaClCondVar gCv;
      41                 : size_t gNumThreadsDone = 0;
      42                 : size_t gNumThreadsTried = 0;
      43                 : int gFailure = 0;
      44                 : 
      45               1 : void WINAPI ThreadMain(void *personality) {
      46               1 :   int       thread_num = (int) (uintptr_t) personality;
      47                 :   uint64_t  sleep_count;
      48               1 :   int       got_sem = 0;
      49               1 :   int       failed = 0;
      50                 : 
      51               1 :   for (sleep_count = 0; sleep_count < gNumTriesSufficient; ++sleep_count) {
      52                 :     /* the sem_trywait should not succeed the first time through */
      53               1 :     if (NACL_SYNC_BUSY != NaClSemTryWait(&gSem)) {
      54               1 :       got_sem = 1;
      55               1 :       break;
      56                 :     }
      57               1 :     if (0 == sleep_count) {
      58               1 :       NaClXMutexLock(&gMu);
      59               1 :       ++gNumThreadsTried;
      60               1 :       NaClXCondVarSignal(&gCv);
      61               1 :       NaClXMutexUnlock(&gMu);
      62                 :     }
      63               1 :     PauseSpinningThread();
      64               1 :   }
      65                 : 
      66               1 :   if (got_sem) {
      67                 :     printf("Thread %d: NaClSemTryWait succeeded at %"NACL_PRId64"\n",
      68                 :            thread_num,
      69               1 :            sleep_count);
      70               1 :   } else {
      71                 :     /* gNumThreadsTried == sleep_count */
      72               0 :     printf("Thread %d: NaClSemWait\n", thread_num);
      73               0 :     if (NACL_SYNC_OK != NaClSemWait(&gSem)) {
      74               0 :       printf("FAILED\n");
      75               0 :       printf("NaClSemWait failed!?!\n");
      76               0 :       failed = 1;
      77                 :     }
      78                 :   }
      79                 : 
      80               1 :   if (0 == sleep_count) {
      81               0 :     printf("FAILED\n");
      82               0 :     printf("Thread %d never actually waited at NaClSemTryWait\n", thread_num);
      83               0 :     failed = 1;
      84               0 :   } else {
      85               1 :     printf("OK -- thread %d\n", thread_num);
      86                 :   }
      87                 : 
      88               1 :   NaClXMutexLock(&gMu);
      89               1 :   gFailure += failed;
      90               1 :   ++gNumThreadsDone;
      91               1 :   NaClXCondVarSignal(&gCv);
      92               1 :   NaClXMutexUnlock(&gMu);
      93               1 : }
      94                 : 
      95               1 : int main(int ac, char **av) {
      96               1 :   int exit_status = -1;
      97                 :   int opt;
      98               1 :   size_t num_threads = 16;
      99                 :   size_t n;
     100                 :   struct NaClThread thr;
     101                 : 
     102               1 :   while (EOF != (opt = getopt(ac, av, "n:s:t:"))) {
     103               0 :     switch (opt) {
     104                 :       case 'n':
     105               0 :         num_threads = strtoul(optarg, (char **) NULL, 0);
     106               0 :         break;
     107                 :       case 't':
     108               0 :         gNumTriesSufficient = strtoul(optarg, (char **) NULL, 0);
     109               0 :         break;
     110                 :       default:
     111                 :         fprintf(stderr,
     112                 :                 "Usage: nacl_semaphore_test [args]\n"
     113                 :                 "  -n n   number of threads used to test semaphore\n"
     114               0 :                 "  -t n   number of TryWait operations before blocking Try\n");
     115               0 :         goto cleanup0;
     116                 :     }
     117               0 :   }
     118                 : 
     119               1 :   NaClPlatformInit();
     120                 : 
     121               1 :   if (!NaClSemCtor(&gSem, 0)) {
     122               0 :     fprintf(stderr, "nacl_semaphore_test: NaClSemCtor failed!\n");
     123               0 :     goto cleanup1;
     124                 :   }
     125               1 :   if (!NaClMutexCtor(&gMu)) {
     126               0 :     fprintf(stderr, "nacl_semaphore_test: NaClMutexCtor failed!\n");
     127               0 :     goto cleanup2;
     128                 :   }
     129               1 :   if (!NaClCondVarCtor(&gCv)) {
     130               0 :     fprintf(stderr, "nacl_semaphore_test: NaClCondVarCtor failed!\n");
     131               0 :     goto cleanup3;
     132                 :   }
     133                 : 
     134               1 :   for (n = 0; n < num_threads; ++n) {
     135                 :     if (!NaClThreadCtor(&thr, ThreadMain, (void *) (uintptr_t) n,
     136               1 :                         STACK_SIZE_BYTES)) {
     137                 :       fprintf(stderr,
     138                 :               "nacl_semaphore_test: could not create thread %"NACL_PRIdS"\n",
     139               0 :               n);
     140               0 :       goto cleanup4;  /* osx leak semaphore otherwise */
     141                 :     }
     142               1 :   }
     143                 : 
     144               1 :   NaClXMutexLock(&gMu);
     145               1 :   while (gNumThreadsTried != num_threads) {
     146               1 :     NaClXCondVarWait(&gCv, &gMu);
     147               1 :   }
     148               1 :   NaClXMutexUnlock(&gMu);
     149                 : 
     150               1 :   for (n = 0; n < num_threads; ++n) {
     151               1 :     NaClSemPost(&gSem);  /* let a thread go */
     152               1 :   }
     153                 : 
     154               1 :   NaClXMutexLock(&gMu);
     155               1 :   while (gNumThreadsDone != num_threads) {
     156               1 :     NaClXCondVarWait(&gCv, &gMu);
     157               1 :   }
     158               1 :   exit_status = gFailure;
     159               1 :   NaClXMutexUnlock(&gMu);
     160                 : 
     161               1 :   if (0 == exit_status) {
     162               1 :     printf("SUCCESS\n");
     163                 :   }
     164                 :  cleanup4:
     165                 :   /* single exit with (ah hem) simulation of RAII via cleanup sled */
     166               1 :   NaClCondVarDtor(&gCv);
     167                 :  cleanup3:
     168               1 :   NaClMutexDtor(&gMu);
     169                 :  cleanup2:
     170               1 :   NaClSemDtor(&gSem);
     171                 :  cleanup1:
     172               1 :   NaClPlatformFini();
     173                 :  cleanup0:
     174               1 :   return exit_status;
     175               1 : }

Generated by: LCOV version 1.7