LCOV - code coverage report
Current view: top level - test/cctest - test-atomicops.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 122 122 100.0 %
Date: 2017-10-20 Functions: 22 22 100.0 %

          Line data    Source code
       1             : // Copyright 2014 the V8 project authors. All rights reserved.
       2             : // Redistribution and use in source and binary forms, with or without
       3             : // modification, are permitted provided that the following conditions are
       4             : // met:
       5             : //
       6             : //     * Redistributions of source code must retain the above copyright
       7             : //       notice, this list of conditions and the following disclaimer.
       8             : //     * Redistributions in binary form must reproduce the above
       9             : //       copyright notice, this list of conditions and the following
      10             : //       disclaimer in the documentation and/or other materials provided
      11             : //       with the distribution.
      12             : //     * Neither the name of Google Inc. nor the names of its
      13             : //       contributors may be used to endorse or promote products derived
      14             : //       from this software without specific prior written permission.
      15             : //
      16             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      17             : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      18             : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      19             : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      20             : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      21             : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      22             : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      23             : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      24             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      25             : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      26             : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      27             : 
      28             : #include "src/v8.h"
      29             : 
      30             : #include "src/base/atomicops.h"
      31             : #include "test/cctest/cctest.h"
      32             : 
      33             : namespace v8 {
      34             : namespace base {
      35             : 
      36             : #define CHECK_EQU(v1, v2) \
      37             :   CHECK_EQ(static_cast<int64_t>(v1), static_cast<int64_t>(v2))
      38             : 
      39             : #define NUM_BITS(T) (sizeof(T) * 8)
      40             : 
      41             : 
      42             : template <class AtomicType>
      43          12 : static void TestAtomicIncrement() {
      44             :   // For now, we just test the single-threaded execution.
      45             : 
      46             :   // Use a guard value to make sure that Relaxed_AtomicIncrement doesn't
      47             :   // go outside the expected address bounds.  This is to test that the
      48             :   // 32-bit Relaxed_AtomicIncrement doesn't do the wrong thing on 64-bit
      49             :   // machines.
      50             :   struct {
      51             :     AtomicType prev_word;
      52             :     AtomicType count;
      53             :     AtomicType next_word;
      54             :   } s;
      55             : 
      56             :   AtomicType prev_word_value, next_word_value;
      57             :   memset(&prev_word_value, 0xFF, sizeof(AtomicType));
      58             :   memset(&next_word_value, 0xEE, sizeof(AtomicType));
      59             : 
      60          12 :   s.prev_word = prev_word_value;
      61          12 :   s.count = 0;
      62          12 :   s.next_word = next_word_value;
      63             : 
      64          12 :   CHECK_EQU(Relaxed_AtomicIncrement(&s.count, 1), 1);
      65          12 :   CHECK_EQU(s.count, 1);
      66          12 :   CHECK_EQU(s.prev_word, prev_word_value);
      67          12 :   CHECK_EQU(s.next_word, next_word_value);
      68             : 
      69          12 :   CHECK_EQU(Relaxed_AtomicIncrement(&s.count, 2), 3);
      70          12 :   CHECK_EQU(s.count, 3);
      71          12 :   CHECK_EQU(s.prev_word, prev_word_value);
      72          12 :   CHECK_EQU(s.next_word, next_word_value);
      73             : 
      74          12 :   CHECK_EQU(Relaxed_AtomicIncrement(&s.count, 3), 6);
      75          12 :   CHECK_EQU(s.count, 6);
      76          12 :   CHECK_EQU(s.prev_word, prev_word_value);
      77          12 :   CHECK_EQU(s.next_word, next_word_value);
      78             : 
      79          12 :   CHECK_EQU(Relaxed_AtomicIncrement(&s.count, -3), 3);
      80          12 :   CHECK_EQU(s.count, 3);
      81          12 :   CHECK_EQU(s.prev_word, prev_word_value);
      82          12 :   CHECK_EQU(s.next_word, next_word_value);
      83             : 
      84          12 :   CHECK_EQU(Relaxed_AtomicIncrement(&s.count, -2), 1);
      85          12 :   CHECK_EQU(s.count, 1);
      86          12 :   CHECK_EQU(s.prev_word, prev_word_value);
      87          12 :   CHECK_EQU(s.next_word, next_word_value);
      88             : 
      89          12 :   CHECK_EQU(Relaxed_AtomicIncrement(&s.count, -1), 0);
      90          12 :   CHECK_EQU(s.count, 0);
      91          12 :   CHECK_EQU(s.prev_word, prev_word_value);
      92          12 :   CHECK_EQU(s.next_word, next_word_value);
      93             : 
      94          12 :   CHECK_EQU(Relaxed_AtomicIncrement(&s.count, -1), -1);
      95          12 :   CHECK_EQU(s.count, -1);
      96          12 :   CHECK_EQU(s.prev_word, prev_word_value);
      97          12 :   CHECK_EQU(s.next_word, next_word_value);
      98             : 
      99          12 :   CHECK_EQU(Relaxed_AtomicIncrement(&s.count, -4), -5);
     100          12 :   CHECK_EQU(s.count, -5);
     101          12 :   CHECK_EQU(s.prev_word, prev_word_value);
     102          12 :   CHECK_EQU(s.next_word, next_word_value);
     103             : 
     104          12 :   CHECK_EQU(Relaxed_AtomicIncrement(&s.count, 5), 0);
     105          12 :   CHECK_EQU(s.count, 0);
     106          12 :   CHECK_EQU(s.prev_word, prev_word_value);
     107          12 :   CHECK_EQU(s.next_word, next_word_value);
     108          12 : }
     109             : 
     110             : 
     111             : template <class AtomicType>
     112          12 : static void TestCompareAndSwap() {
     113          12 :   AtomicType value = 0;
     114             :   AtomicType prev = Relaxed_CompareAndSwap(&value, 0, 1);
     115          12 :   CHECK_EQU(1, value);
     116          12 :   CHECK_EQU(0, prev);
     117             : 
     118             :   // Use a test value that has non-zero bits in both halves, for testing
     119             :   // the 64-bit implementation on 32-bit platforms.
     120             :   const AtomicType k_test_val =
     121             :       (static_cast<AtomicType>(1) << (NUM_BITS(AtomicType) - 2)) + 11;
     122          12 :   value = k_test_val;
     123             :   prev = Relaxed_CompareAndSwap(&value, 0, 5);
     124          12 :   CHECK_EQU(k_test_val, value);
     125          12 :   CHECK_EQU(k_test_val, prev);
     126             : 
     127          12 :   value = k_test_val;
     128             :   prev = Relaxed_CompareAndSwap(&value, k_test_val, 5);
     129          12 :   CHECK_EQU(5, value);
     130          12 :   CHECK_EQU(k_test_val, prev);
     131          12 : }
     132             : 
     133             : 
     134             : template <class AtomicType>
     135          12 : static void TestAtomicExchange() {
     136          12 :   AtomicType value = 0;
     137             :   AtomicType new_value = Relaxed_AtomicExchange(&value, 1);
     138          12 :   CHECK_EQU(1, value);
     139          12 :   CHECK_EQU(0, new_value);
     140             : 
     141             :   // Use a test value that has non-zero bits in both halves, for testing
     142             :   // the 64-bit implementation on 32-bit platforms.
     143             :   const AtomicType k_test_val =
     144             :       (static_cast<AtomicType>(1) << (NUM_BITS(AtomicType) - 2)) + 11;
     145          12 :   value = k_test_val;
     146             :   new_value = Relaxed_AtomicExchange(&value, k_test_val);
     147          12 :   CHECK_EQU(k_test_val, value);
     148          12 :   CHECK_EQU(k_test_val, new_value);
     149             : 
     150          12 :   value = k_test_val;
     151             :   new_value = Relaxed_AtomicExchange(&value, 5);
     152          12 :   CHECK_EQU(5, value);
     153          12 :   CHECK_EQU(k_test_val, new_value);
     154          12 : }
     155             : 
     156             : 
     157             : template <class AtomicType>
     158          12 : static void TestAtomicIncrementBounds() {
     159             :   // Test at 32-bit boundary for 64-bit atomic type.
     160             :   AtomicType test_val = static_cast<AtomicType>(1)
     161             :                         << (NUM_BITS(AtomicType) / 2);
     162          12 :   AtomicType value = test_val - 1;
     163             :   AtomicType new_value = Relaxed_AtomicIncrement(&value, 1);
     164          12 :   CHECK_EQU(test_val, value);
     165          12 :   CHECK_EQU(value, new_value);
     166             : 
     167             :   Relaxed_AtomicIncrement(&value, -1);
     168          12 :   CHECK_EQU(test_val - 1, value);
     169          12 : }
     170             : 
     171             : 
     172             : // Return an AtomicType with the value 0xa5a5a5..
     173             : template <class AtomicType>
     174             : static AtomicType TestFillValue() {
     175             :   AtomicType val = 0;
     176             :   memset(&val, 0xa5, sizeof(AtomicType));
     177             :   return val;
     178             : }
     179             : 
     180             : 
     181             : // This is a simple sanity check to ensure that values are correct.
     182             : // Not testing atomicity.
     183             : template <class AtomicType>
     184          12 : static void TestStore() {
     185             :   const AtomicType kVal1 = TestFillValue<AtomicType>();
     186             :   const AtomicType kVal2 = static_cast<AtomicType>(-1);
     187             : 
     188             :   AtomicType value;
     189             : 
     190             :   Relaxed_Store(&value, kVal1);
     191          12 :   CHECK_EQU(kVal1, value);
     192             :   Relaxed_Store(&value, kVal2);
     193          12 :   CHECK_EQU(kVal2, value);
     194             : 
     195             :   Release_Store(&value, kVal1);
     196          12 :   CHECK_EQU(kVal1, value);
     197             :   Release_Store(&value, kVal2);
     198          12 :   CHECK_EQU(kVal2, value);
     199          12 : }
     200             : 
     201             : 
     202             : // Merge this test with TestStore as soon as we have Atomic8 acquire
     203             : // and release stores.
     204           6 : static void TestStoreAtomic8() {
     205             :   const Atomic8 kVal1 = TestFillValue<Atomic8>();
     206             :   const Atomic8 kVal2 = static_cast<Atomic8>(-1);
     207             : 
     208             :   Atomic8 value;
     209             : 
     210             :   Relaxed_Store(&value, kVal1);
     211           6 :   CHECK_EQU(kVal1, value);
     212             :   Relaxed_Store(&value, kVal2);
     213           6 :   CHECK_EQU(kVal2, value);
     214           6 : }
     215             : 
     216             : 
     217             : // This is a simple sanity check to ensure that values are correct.
     218             : // Not testing atomicity.
     219             : template <class AtomicType>
     220          12 : static void TestLoad() {
     221             :   const AtomicType kVal1 = TestFillValue<AtomicType>();
     222             :   const AtomicType kVal2 = static_cast<AtomicType>(-1);
     223             : 
     224             :   AtomicType value;
     225             : 
     226          12 :   value = kVal1;
     227          12 :   CHECK_EQU(kVal1, Relaxed_Load(&value));
     228          12 :   value = kVal2;
     229          12 :   CHECK_EQU(kVal2, Relaxed_Load(&value));
     230             : 
     231          12 :   value = kVal1;
     232          12 :   CHECK_EQU(kVal1, Acquire_Load(&value));
     233          12 :   value = kVal2;
     234          12 :   CHECK_EQU(kVal2, Acquire_Load(&value));
     235          12 : }
     236             : 
     237             : 
     238             : // Merge this test with TestLoad as soon as we have Atomic8 acquire
     239             : // and release loads.
     240           6 : static void TestLoadAtomic8() {
     241             :   const Atomic8 kVal1 = TestFillValue<Atomic8>();
     242             :   const Atomic8 kVal2 = static_cast<Atomic8>(-1);
     243             : 
     244             :   Atomic8 value;
     245             : 
     246           6 :   value = kVal1;
     247           6 :   CHECK_EQU(kVal1, Relaxed_Load(&value));
     248           6 :   value = kVal2;
     249           6 :   CHECK_EQU(kVal2, Relaxed_Load(&value));
     250           6 : }
     251             : 
     252             : 
     253       23724 : TEST(AtomicIncrement) {
     254           6 :   TestAtomicIncrement<Atomic32>();
     255           6 :   TestAtomicIncrement<AtomicWord>();
     256           6 : }
     257             : 
     258             : 
     259       23724 : TEST(CompareAndSwap) {
     260           6 :   TestCompareAndSwap<Atomic32>();
     261           6 :   TestCompareAndSwap<AtomicWord>();
     262           6 : }
     263             : 
     264             : 
     265       23724 : TEST(AtomicExchange) {
     266           6 :   TestAtomicExchange<Atomic32>();
     267           6 :   TestAtomicExchange<AtomicWord>();
     268           6 : }
     269             : 
     270             : 
     271       23724 : TEST(AtomicIncrementBounds) {
     272           6 :   TestAtomicIncrementBounds<Atomic32>();
     273           6 :   TestAtomicIncrementBounds<AtomicWord>();
     274           6 : }
     275             : 
     276             : 
     277       23724 : TEST(Store) {
     278           6 :   TestStoreAtomic8();
     279           6 :   TestStore<Atomic32>();
     280           6 :   TestStore<AtomicWord>();
     281           6 : }
     282             : 
     283             : 
     284       23724 : TEST(Load) {
     285           6 :   TestLoadAtomic8();
     286           6 :   TestLoad<Atomic32>();
     287           6 :   TestLoad<AtomicWord>();
     288           6 : }
     289             : 
     290             : }  // namespace base
     291       71154 : }  // namespace v8

Generated by: LCOV version 1.10