2  * Copyright (C) 2015 Apple Inc. All rights reserved. 
   4  * Redistribution and use in source and binary forms, with or without 
   5  * modification, are permitted provided that the following conditions 
   7  * 1. Redistributions of source code must retain the above copyright 
   8  *    notice, this list of conditions and the following disclaimer. 
   9  * 2. Redistributions in binary form must reproduce the above copyright 
  10  *    notice, this list of conditions and the following disclaimer in the 
  11  *    documentation and/or other materials provided with the distribution. 
  13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 
  14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
  15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 
  17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
  19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
  20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
  21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
  23  * THE POSSIBILITY OF SUCH DAMAGE. 
  27 #include "CompareAndSwapTest.h" 
  30 #include <wtf/Atomics.h> 
  31 #include <wtf/Threading.h> 
  35     Bitmap() { clearAll(); } 
  37     inline void clearAll(); 
  38     inline bool concurrentTestAndSet(size_t n
); 
  39     inline size_t numBits() const { return words 
* wordSize
; } 
  42     static const size_t Size 
= 4096*10; 
  44     static const unsigned wordSize 
= sizeof(uint8_t) * 8; 
  45     static const unsigned words 
= (Size 
+ wordSize 
- 1) / wordSize
; 
  46     static const uint8_t one 
= 1; 
  51 inline void Bitmap::clearAll() 
  53     memset(&bits
, 0, sizeof(bits
)); 
  56 inline bool Bitmap::concurrentTestAndSet(size_t n
) 
  58     uint8_t mask 
= one 
<< (n 
% wordSize
); 
  59     size_t index 
= n 
/ wordSize
; 
  60     uint8_t* wordPtr 
= &bits
[index
]; 
  66     } while (!WTF::weakCompareAndSwap(wordPtr
, oldValue
, oldValue 
| mask
)); 
  76 static void setBitThreadFunc(void* p
) 
  78     Data
* data 
= reinterpret_cast<Data
*>(p
); 
  79     Bitmap
* bitmap 
= data
->bitmap
; 
  80     size_t numBits 
= bitmap
->numBits(); 
  82     // The computed start index here is heuristic that seems to maximize (anecdotally) 
  83     // the chance for the CAS issue to manifest. 
  84     size_t start 
= (numBits 
* (data
->numThreads 
- data
->id
)) / data
->numThreads
; 
  86     printf("   started Thread %d\n", data
->id
); 
  87     for (size_t i 
= start
; i 
< numBits
; i
++) 
  88         while (!bitmap
->concurrentTestAndSet(i
)) { } 
  89     for (size_t i 
= 0; i 
< start
; i
++) 
  90         while (!bitmap
->concurrentTestAndSet(i
)) { } 
  92     printf("   finished Thread %d\n", data
->id
); 
  95 void testCompareAndSwap() 
  98     const int numThreads 
= 5; 
  99     ThreadIdentifier threadIDs
[numThreads
]; 
 100     Data data
[numThreads
]; 
 102     WTF::initializeThreading(); 
 104     printf("Starting %d threads for CompareAndSwap test.  Test should complete without hanging.\n", numThreads
); 
 105     for (int i 
= 0; i 
< numThreads
; i
++) { 
 106         data
[i
].bitmap 
= &bitmap
; 
 108         data
[i
].numThreads 
= numThreads
; 
 109         std::function
<void()> threadFunc 
= std::bind(setBitThreadFunc
, &data
[i
]); 
 110         threadIDs
[i
] = createThread("setBitThreadFunc", threadFunc
); 
 113     printf("Waiting for %d threads to join\n", numThreads
); 
 114     for (int i 
= 0; i 
< numThreads
; i
++) 
 115         waitForThreadCompletion(threadIDs
[i
]); 
 117     printf("PASS: CompareAndSwap test completed without a hang\n");