LCOV - code coverage report
Current view: directory - tests/unittests/shared/platform - atomic_ops_test.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 67 50 74.6 %
Date: 2012-02-16 Functions: 0 0 -

       1                 : /* Copyright (c) 2011 The Native Client Authors. All rights reserved.
       2                 :  * Use of this source code is governed by a BSD-style license that can be
       3                 :  * found in the LICENSE file.
       4                 :  */
       5                 : 
       6                 : #include <stdio.h>
       7                 : #include "native_client/src/include/atomic_ops.h"
       8                 : #include "native_client/src/shared/platform/nacl_threads.h"
       9                 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
      10                 : #include "native_client/src/shared/platform/nacl_sync.h"
      11                 : 
      12                 : #define THREAD_STACK_SIZE  (128*1024)
      13                 : 
      14                 : int32_t gIncrementsPerThread = 1000;
      15                 : int32_t gNumThreads;
      16                 : 
      17                 : struct NaClMutex gMutex;
      18                 : 
      19                 : 
      20                 : /* For atomic counter test */
      21                 : Atomic32 gCounter = 0;
      22                 : 
      23              56 : static void IncrementTest() {
      24                 :   /* Increment the counter, gIncrementsPerThread times,
      25                 :    * with the values 1...gIncrementsPerThread
      26                 :    */
      27                 :   Atomic32 i;
      28           24249 :   for (i=1; i <= gIncrementsPerThread; i++) {
      29           24224 :     AtomicIncrement(&gCounter, i);
      30                 :   }
      31              25 : }
      32                 : 
      33               0 : static void DecrementTest() {
      34                 :   /* Decrement the counter gIncrementsPerThread times,
      35                 :    * with the values 1...gIncrementsPerThread-1
      36                 :    */
      37                 :   Atomic32 i;
      38           23896 :   for (i=1; i < gIncrementsPerThread; i++) {
      39           23871 :     AtomicIncrement(&gCounter, -i);
      40                 :   }
      41              25 : }
      42                 : 
      43                 : /* Atomic exchange test
      44                 :  * Each thread exchanges gExchange for its tid.
      45                 :  * It takes the returned value and adds it to gExchangeSum.
      46                 :  * When finished, gExchangeSum + gExchange will contain
      47                 :  * 1 + ... + gNumThreads
      48                 :  */
      49                 : Atomic32 gExchange = 0;
      50                 : Atomic32 gExchangeSum = 0;
      51                 : 
      52              25 : static void ExchangeTest(int32_t tid) {
      53                 :   Atomic32 i;
      54              25 :   i = AtomicExchange(&gExchange, tid);
      55              25 :   if (i == tid) {
      56               0 :     fprintf(stderr,
      57                 :             "Error: AtomicExchange returned the new value instead of old.\n");
      58               0 :     exit(EXIT_FAILURE);
      59                 :   }
      60              25 :   AtomicIncrement(&gExchangeSum, i);
      61              25 : }
      62                 : 
      63                 : /* Atomic compare and swap test
      64                 :    Each thread spins until gSwap == tid, and
      65                 :    then exchanges it for tid + 1
      66                 : */
      67                 : Atomic32 gSwap = 1;
      68         1624898 : static void CompareAndSwapTest(int32_t tid) {
      69         1624898 :   while (CompareAndSwap(&gSwap, tid, tid+1) != tid);
      70              25 : }
      71                 : 
      72              25 : void WINAPI ThreadMain(void *state) {
      73              25 :   int32_t tid = (int32_t) (intptr_t) state;
      74                 : 
      75                 :   /* Wait for the signal to begin */
      76              25 :   NaClXMutexLock(&gMutex);
      77              25 :   NaClXMutexUnlock(&gMutex);
      78                 : 
      79                 :   /* Swap the order to shake things up a bit */
      80              25 :   if (tid % 2 == 0) {
      81              12 :     IncrementTest();
      82              12 :     DecrementTest();
      83                 :   } else {
      84              13 :     DecrementTest();
      85              13 :     IncrementTest();
      86                 :   }
      87                 : 
      88              25 :   ExchangeTest(tid);
      89                 : 
      90              25 :   CompareAndSwapTest(tid);
      91              25 : }
      92                 : 
      93               1 : int main(int argc, const char *argv[]) {
      94                 :   struct NaClThread *threads;
      95                 :   int rv;
      96                 :   int32_t tid;
      97                 :   int32_t tmp;
      98                 : 
      99               1 :   if (argc != 2) {
     100               0 :     fprintf(stderr, "Usage: %s <NumThreads>\n", argv[0]);
     101               0 :     exit(EXIT_FAILURE);
     102                 :   }
     103                 : 
     104               1 :   gNumThreads = strtol(argv[1], NULL, 10);
     105                 : 
     106               1 :   threads = (struct NaClThread*)malloc(gNumThreads*sizeof(struct NaClThread));
     107               1 :   if (threads == NULL) {
     108               0 :     fprintf(stderr, "malloc returned NULL\n");
     109               0 :     exit(EXIT_FAILURE);
     110                 :   }
     111                 : 
     112               1 :   if (!NaClMutexCtor(&gMutex)) {
     113               0 :     fprintf(stderr, "NaClMutexCtor failed\n");
     114               0 :     exit(EXIT_FAILURE);
     115                 :   }
     116                 : 
     117               1 :   NaClXMutexLock(&gMutex);
     118                 : 
     119              26 :   for (tid = 1; tid <= gNumThreads; ++tid) {
     120              25 :     fprintf(stderr, "Creating thread %d\n", (int)tid);
     121                 : 
     122              25 :     rv = NaClThreadCreateJoinable(&threads[tid-1],
     123                 :                                   ThreadMain,
     124                 :                                   (void*) (intptr_t) tid,
     125                 :                                   THREAD_STACK_SIZE);
     126              25 :     if (!rv) {
     127               0 :       fprintf(stderr, "NaClThreadCtor failed\n");
     128               0 :       exit(EXIT_FAILURE);
     129                 :     }
     130                 :   }
     131                 : 
     132               1 :   NaClXMutexUnlock(&gMutex);
     133                 : 
     134              26 :   for (tid = 1; tid <= gNumThreads; ++tid) {
     135              25 :     NaClThreadJoin(&threads[tid-1]);
     136                 :   }
     137                 : 
     138                 :   /* Check the results */
     139               1 :   tmp = gIncrementsPerThread * gNumThreads;
     140               1 :   if (gCounter != tmp) {
     141               0 :     fprintf(stderr, "ERROR: gCounter is wrong. Expected %d, got %d\n",
     142                 :            (int)tmp, (int)gCounter);
     143               0 :     exit(EXIT_FAILURE);
     144                 :   }
     145                 : 
     146               1 :   tmp = gNumThreads*(gNumThreads+1)/2;
     147               1 :   if (gExchange + gExchangeSum != tmp) {
     148               0 :     fprintf(stderr,
     149                 :             "ERROR: gExchange+gExchangeSum is wrong. Expected %d, got %d\n",
     150                 :             (int)tmp, (int)(gExchange + gExchangeSum));
     151               0 :     exit(EXIT_FAILURE);
     152                 :   }
     153                 : 
     154               1 :   if (gSwap != gNumThreads+1) {
     155               0 :     fprintf(stderr, "ERROR: gSwap is wrong. Expected %d, got %d\n",
     156                 :             (int)(gNumThreads+1), (int)gSwap);
     157               0 :     exit(EXIT_FAILURE);
     158                 :   }
     159                 : 
     160               1 :   fprintf(stderr, "PASSED\n");
     161               1 :   NaClMutexDtor(&gMutex);
     162               1 :   free(threads);
     163               1 :   return 0;
     164                 : }

Generated by: LCOV version 1.7