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: 2019-04-17 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          10 : 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          10 :   s.prev_word = prev_word_value;
      61          10 :   s.count = 0;
      62          10 :   s.next_word = next_word_value;
      63             : 
      64          10 :   CHECK_EQU(Relaxed_AtomicIncrement(&s.count, 1), 1);
      65          10 :   CHECK_EQU(s.count, 1);
      66          10 :   CHECK_EQU(s.prev_word, prev_word_value);
      67          10 :   CHECK_EQU(s.next_word, next_word_value);
      68             : 
      69          10 :   CHECK_EQU(Relaxed_AtomicIncrement(&s.count, 2), 3);
      70          10 :   CHECK_EQU(s.count, 3);
      71          10 :   CHECK_EQU(s.prev_word, prev_word_value);
      72          10 :   CHECK_EQU(s.next_word, next_word_value);
      73             : 
      74           5 :   CHECK_EQU(Relaxed_AtomicIncrement(&s.count, 3), 6);
      75          10 :   CHECK_EQU(s.count, 6);
      76          10 :   CHECK_EQU(s.prev_word, prev_word_value);
      77          10 :   CHECK_EQU(s.next_word, next_word_value);
      78             : 
      79          10 :   CHECK_EQU(Relaxed_AtomicIncrement(&s.count, -3), 3);
      80          10 :   CHECK_EQU(s.count, 3);
      81          10 :   CHECK_EQU(s.prev_word, prev_word_value);
      82          10 :   CHECK_EQU(s.next_word, next_word_value);
      83             : 
      84          10 :   CHECK_EQU(Relaxed_AtomicIncrement(&s.count, -2), 1);
      85          10 :   CHECK_EQU(s.count, 1);
      86          10 :   CHECK_EQU(s.prev_word, prev_word_value);
      87          10 :   CHECK_EQU(s.next_word, next_word_value);
      88             : 
      89          10 :   CHECK_EQU(Relaxed_AtomicIncrement(&s.count, -1), 0);
      90          10 :   CHECK_EQU(s.count, 0);
      91          10 :   CHECK_EQU(s.prev_word, prev_word_value);
      92          10 :   CHECK_EQU(s.next_word, next_word_value);
      93             : 
      94          10 :   CHECK_EQU(Relaxed_AtomicIncrement(&s.count, -1), -1);
      95          10 :   CHECK_EQU(s.count, -1);
      96          10 :   CHECK_EQU(s.prev_word, prev_word_value);
      97          10 :   CHECK_EQU(s.next_word, next_word_value);
      98             : 
      99          10 :   CHECK_EQU(Relaxed_AtomicIncrement(&s.count, -4), -5);
     100          10 :   CHECK_EQU(s.count, -5);
     101          10 :   CHECK_EQU(s.prev_word, prev_word_value);
     102          10 :   CHECK_EQU(s.next_word, next_word_value);
     103             : 
     104          10 :   CHECK_EQU(Relaxed_AtomicIncrement(&s.count, 5), 0);
     105          10 :   CHECK_EQU(s.count, 0);
     106          10 :   CHECK_EQU(s.prev_word, prev_word_value);
     107          10 :   CHECK_EQU(s.next_word, next_word_value);
     108          10 : }
     109             : 
     110             : 
     111             : template <class AtomicType>
     112          10 : static void TestCompareAndSwap() {
     113          10 :   AtomicType value = 0;
     114             :   AtomicType prev = Relaxed_CompareAndSwap(&value, 0, 1);
     115          10 :   CHECK_EQU(1, value);
     116          10 :   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          10 :   value = k_test_val;
     123             :   prev = Relaxed_CompareAndSwap(&value, 0, 5);
     124          10 :   CHECK_EQU(k_test_val, value);
     125          10 :   CHECK_EQU(k_test_val, prev);
     126             : 
     127          10 :   value = k_test_val;
     128             :   prev = Relaxed_CompareAndSwap(&value, k_test_val, 5);
     129          10 :   CHECK_EQU(5, value);
     130          10 :   CHECK_EQU(k_test_val, prev);
     131          10 : }
     132             : 
     133             : 
     134             : template <class AtomicType>
     135          10 : static void TestAtomicExchange() {
     136          10 :   AtomicType value = 0;
     137             :   AtomicType new_value = Relaxed_AtomicExchange(&value, 1);
     138          10 :   CHECK_EQU(1, value);
     139          10 :   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          10 :   value = k_test_val;
     146             :   new_value = Relaxed_AtomicExchange(&value, k_test_val);
     147           5 :   CHECK_EQU(k_test_val, value);
     148          10 :   CHECK_EQU(k_test_val, new_value);
     149             : 
     150          10 :   value = k_test_val;
     151             :   new_value = Relaxed_AtomicExchange(&value, 5);
     152          10 :   CHECK_EQU(5, value);
     153          10 :   CHECK_EQU(k_test_val, new_value);
     154          10 : }
     155             : 
     156             : 
     157             : template <class AtomicType>
     158          10 : 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          10 :   AtomicType value = test_val - 1;
     163             :   AtomicType new_value = Relaxed_AtomicIncrement(&value, 1);
     164          10 :   CHECK_EQU(test_val, value);
     165          10 :   CHECK_EQU(value, new_value);
     166             : 
     167             :   Relaxed_AtomicIncrement(&value, -1);
     168          10 :   CHECK_EQU(test_val - 1, value);
     169          10 : }
     170             : 
     171             : // Return an AtomicType with the value 0xA5A5A5..
     172             : template <class AtomicType>
     173             : static AtomicType TestFillValue() {
     174             :   AtomicType val = 0;
     175             :   memset(&val, 0xA5, sizeof(AtomicType));
     176             :   return val;
     177             : }
     178             : 
     179             : 
     180             : // This is a simple sanity check to ensure that values are correct.
     181             : // Not testing atomicity.
     182             : template <class AtomicType>
     183          10 : static void TestStore() {
     184             :   const AtomicType kVal1 = TestFillValue<AtomicType>();
     185             :   const AtomicType kVal2 = static_cast<AtomicType>(-1);
     186             : 
     187             :   AtomicType value;
     188             : 
     189             :   Relaxed_Store(&value, kVal1);
     190          10 :   CHECK_EQU(kVal1, value);
     191             :   Relaxed_Store(&value, kVal2);
     192          10 :   CHECK_EQU(kVal2, value);
     193             : 
     194             :   Release_Store(&value, kVal1);
     195          10 :   CHECK_EQU(kVal1, value);
     196             :   Release_Store(&value, kVal2);
     197          10 :   CHECK_EQU(kVal2, value);
     198          10 : }
     199             : 
     200             : 
     201             : // Merge this test with TestStore as soon as we have Atomic8 acquire
     202             : // and release stores.
     203           5 : static void TestStoreAtomic8() {
     204             :   const Atomic8 kVal1 = TestFillValue<Atomic8>();
     205             :   const Atomic8 kVal2 = static_cast<Atomic8>(-1);
     206             : 
     207             :   Atomic8 value;
     208             : 
     209             :   Relaxed_Store(&value, kVal1);
     210           5 :   CHECK_EQU(kVal1, value);
     211             :   Relaxed_Store(&value, kVal2);
     212           5 :   CHECK_EQU(kVal2, value);
     213           5 : }
     214             : 
     215             : 
     216             : // This is a simple sanity check to ensure that values are correct.
     217             : // Not testing atomicity.
     218             : template <class AtomicType>
     219          10 : static void TestLoad() {
     220             :   const AtomicType kVal1 = TestFillValue<AtomicType>();
     221             :   const AtomicType kVal2 = static_cast<AtomicType>(-1);
     222             : 
     223             :   AtomicType value;
     224             : 
     225          10 :   value = kVal1;
     226          10 :   CHECK_EQU(kVal1, Relaxed_Load(&value));
     227          10 :   value = kVal2;
     228          10 :   CHECK_EQU(kVal2, Relaxed_Load(&value));
     229             : 
     230          10 :   value = kVal1;
     231          10 :   CHECK_EQU(kVal1, Acquire_Load(&value));
     232          10 :   value = kVal2;
     233          10 :   CHECK_EQU(kVal2, Acquire_Load(&value));
     234          10 : }
     235             : 
     236             : 
     237             : // Merge this test with TestLoad as soon as we have Atomic8 acquire
     238             : // and release loads.
     239           5 : static void TestLoadAtomic8() {
     240             :   const Atomic8 kVal1 = TestFillValue<Atomic8>();
     241             :   const Atomic8 kVal2 = static_cast<Atomic8>(-1);
     242             : 
     243             :   Atomic8 value;
     244             : 
     245           5 :   value = kVal1;
     246           5 :   CHECK_EQU(kVal1, Relaxed_Load(&value));
     247           5 :   value = kVal2;
     248           5 :   CHECK_EQU(kVal2, Relaxed_Load(&value));
     249           5 : }
     250             : 
     251             : 
     252       26644 : TEST(AtomicIncrement) {
     253           5 :   TestAtomicIncrement<Atomic32>();
     254           5 :   TestAtomicIncrement<AtomicWord>();
     255           5 : }
     256             : 
     257             : 
     258       26644 : TEST(CompareAndSwap) {
     259           5 :   TestCompareAndSwap<Atomic32>();
     260           5 :   TestCompareAndSwap<AtomicWord>();
     261           5 : }
     262             : 
     263             : 
     264       26644 : TEST(AtomicExchange) {
     265           5 :   TestAtomicExchange<Atomic32>();
     266           5 :   TestAtomicExchange<AtomicWord>();
     267           5 : }
     268             : 
     269             : 
     270       26644 : TEST(AtomicIncrementBounds) {
     271           5 :   TestAtomicIncrementBounds<Atomic32>();
     272           5 :   TestAtomicIncrementBounds<AtomicWord>();
     273           5 : }
     274             : 
     275             : 
     276       26644 : TEST(Store) {
     277           5 :   TestStoreAtomic8();
     278           5 :   TestStore<Atomic32>();
     279           5 :   TestStore<AtomicWord>();
     280           5 : }
     281             : 
     282             : 
     283       26644 : TEST(Load) {
     284           5 :   TestLoadAtomic8();
     285           5 :   TestLoad<Atomic32>();
     286           5 :   TestLoad<AtomicWord>();
     287           5 : }
     288             : 
     289             : }  // namespace base
     290       79917 : }  // namespace v8

Generated by: LCOV version 1.10