15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>   // for min()
8c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/atomicops.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Number of bits in a size_t.
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kSizeBits = 8 * sizeof(size_t);
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The maximum size of a size_t.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const size_t kMaxSize = ~static_cast<size_t>(0);
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Maximum positive size of a size_t if it were signed.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const size_t kMaxSignedSize = ((size_t(1) << (kSizeBits-1)) - 1);
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An allocation size which is not too big to be reasonable.
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const size_t kNotTooBig = 100000;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An allocation size which is just too big.
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const size_t kTooBig = ~static_cast<size_t>(0);
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::min;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Fill a buffer of the specified size with a predetermined pattern
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void Fill(unsigned char* buffer, int n) {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < n; i++) {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer[i] = (i & 0xff);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Check that the specified buffer has the predetermined pattern
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// generated by Fill()
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool Valid(unsigned char* buffer, int n) {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < n; i++) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (buffer[i] != (i & 0xff)) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Check that a buffer is completely zeroed.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool IsZeroed(unsigned char* buffer, int n) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < n; i++) {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (buffer[i] != 0) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Check alignment
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void CheckAlignment(void* p, int align) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, reinterpret_cast<uintptr_t>(p) & (align-1));
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Return the next interesting size/delta to check.  Returns -1 if no more.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int NextSize(int size) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (size < 100)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return size+1;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (size < 100000) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Find next power of two
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int power = 1;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (power < size)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      power <<= 1;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Yield (power-1, power, power+1)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size < power-1)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return power-1;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size == power-1)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return power;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert(size == power);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return power+1;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class AtomicType>
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestAtomicIncrement() {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For now, we just test single threaded execution
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // use a guard value to make sure the NoBarrier_AtomicIncrement doesn't go
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // outside the expected address bounds.  This is in particular to
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // test that some future change to the asm code doesn't cause the
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 32-bit NoBarrier_AtomicIncrement to do the wrong thing on 64-bit machines.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AtomicType prev_word;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AtomicType count;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AtomicType next_word;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } s;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AtomicType prev_word_value, next_word_value;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&prev_word_value, 0xFF, sizeof(AtomicType));
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&next_word_value, 0xEE, sizeof(AtomicType));
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s.prev_word = prev_word_value;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s.count = 0;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s.next_word = next_word_value;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 1), 1);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.count, 1);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.prev_word, prev_word_value);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.next_word, next_word_value);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 2), 3);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.count, 3);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.prev_word, prev_word_value);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.next_word, next_word_value);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 3), 6);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.count, 6);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.prev_word, prev_word_value);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.next_word, next_word_value);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -3), 3);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.count, 3);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.prev_word, prev_word_value);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.next_word, next_word_value);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -2), 1);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.count, 1);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.prev_word, prev_word_value);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.next_word, next_word_value);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -1), 0);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.count, 0);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.prev_word, prev_word_value);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.next_word, next_word_value);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -1), -1);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.count, -1);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.prev_word, prev_word_value);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.next_word, next_word_value);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -4), -5);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.count, -5);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.prev_word, prev_word_value);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.next_word, next_word_value);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 5), 0);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.count, 0);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.prev_word, prev_word_value);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(s.next_word, next_word_value);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NUM_BITS(T) (sizeof(T) * 8)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class AtomicType>
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestCompareAndSwap() {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AtomicType value = 0;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AtomicType prev = base::subtle::NoBarrier_CompareAndSwap(&value, 0, 1);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, value);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, prev);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use test value that has non-zero bits in both halves, more for testing
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 64-bit implementation on 32-bit platforms.
166c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const AtomicType k_test_val = (static_cast<uint64_t>(1) <<
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 (NUM_BITS(AtomicType) - 2)) + 11;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value = k_test_val;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prev = base::subtle::NoBarrier_CompareAndSwap(&value, 0, 5);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(k_test_val, value);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(k_test_val, prev);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value = k_test_val;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prev = base::subtle::NoBarrier_CompareAndSwap(&value, k_test_val, 5);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(5, value);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(k_test_val, prev);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class AtomicType>
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestAtomicExchange() {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AtomicType value = 0;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AtomicType new_value = base::subtle::NoBarrier_AtomicExchange(&value, 1);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, value);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, new_value);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use test value that has non-zero bits in both halves, more for testing
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 64-bit implementation on 32-bit platforms.
189c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const AtomicType k_test_val = (static_cast<uint64_t>(1) <<
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 (NUM_BITS(AtomicType) - 2)) + 11;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value = k_test_val;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  new_value = base::subtle::NoBarrier_AtomicExchange(&value, k_test_val);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(k_test_val, value);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(k_test_val, new_value);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value = k_test_val;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  new_value = base::subtle::NoBarrier_AtomicExchange(&value, 5);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(5, value);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(k_test_val, new_value);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class AtomicType>
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestAtomicIncrementBounds() {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test increment at the half-width boundary of the atomic type.
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It is primarily for testing at the 32-bit boundary for 64-bit atomic type.
207c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  AtomicType test_val = static_cast<uint64_t>(1) << (NUM_BITS(AtomicType) / 2);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AtomicType value = test_val - 1;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AtomicType new_value = base::subtle::NoBarrier_AtomicIncrement(&value, 1);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(test_val, value);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(value, new_value);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::subtle::NoBarrier_AtomicIncrement(&value, -1);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(test_val - 1, value);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is a simple sanity check that values are correct. Not testing
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// atomicity
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class AtomicType>
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestStore() {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const AtomicType kVal1 = static_cast<AtomicType>(0xa5a5a5a5a5a5a5a5LL);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const AtomicType kVal2 = static_cast<AtomicType>(-1);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AtomicType value;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::subtle::NoBarrier_Store(&value, kVal1);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kVal1, value);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::subtle::NoBarrier_Store(&value, kVal2);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kVal2, value);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::subtle::Acquire_Store(&value, kVal1);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kVal1, value);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::subtle::Acquire_Store(&value, kVal2);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kVal2, value);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::subtle::Release_Store(&value, kVal1);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kVal1, value);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::subtle::Release_Store(&value, kVal2);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kVal2, value);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is a simple sanity check that values are correct. Not testing
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// atomicity
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class AtomicType>
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestLoad() {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const AtomicType kVal1 = static_cast<AtomicType>(0xa5a5a5a5a5a5a5a5LL);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const AtomicType kVal2 = static_cast<AtomicType>(-1);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AtomicType value;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value = kVal1;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kVal1, base::subtle::NoBarrier_Load(&value));
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value = kVal2;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kVal2, base::subtle::NoBarrier_Load(&value));
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value = kVal1;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kVal1, base::subtle::Acquire_Load(&value));
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value = kVal2;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kVal2, base::subtle::Acquire_Load(&value));
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value = kVal1;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kVal1, base::subtle::Release_Load(&value));
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value = kVal2;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kVal2, base::subtle::Release_Load(&value));
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class AtomicType>
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestAtomicOps() {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompareAndSwap<AtomicType>();
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestAtomicExchange<AtomicType>();
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestAtomicIncrementBounds<AtomicType>();
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestStore<AtomicType>();
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestLoad<AtomicType>();
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestCalloc(size_t n, size_t s, bool ok) {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* p = reinterpret_cast<char*>(calloc(n, s));
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ok) {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(NULL, p) << "calloc(n, s) should not succeed";
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_NE(reinterpret_cast<void*>(NULL), p) <<
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "calloc(n, s) should succeed";
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < n*s; i++) {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ('\0', p[i]);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free(p);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// MSVC C4530 complains about exception handler usage when exceptions are
2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// disabled.  Temporarily disable that warning so we can test that they are, in
2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// fact, disabled.
2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_WIN)
2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#pragma warning(push)
2955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#pragma warning(disable: 4530)
2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A global test counter for number of times the NewHandler is called.
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int news_handled = 0;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestNewHandler() {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++news_handled;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  throw std::bad_alloc();
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Because we compile without exceptions, we expect these will not throw.
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestOneNewWithoutExceptions(void* (*func)(size_t),
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        bool should_throw) {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // success test
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  try {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* ptr = (*func)(kNotTooBig);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_NE(reinterpret_cast<void*>(NULL), ptr) <<
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "allocation should not have failed.";
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } catch(...) {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0, 1) << "allocation threw unexpected exception.";
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // failure test
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  try {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* rv = (*func)(kTooBig);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(NULL, rv);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(should_throw) << "allocation should have thrown.";
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } catch(...) {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(should_throw) << "allocation threw unexpected exception.";
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestNothrowNew(void* (*func)(size_t)) {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  news_handled = 0;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // test without new_handler:
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::new_handler saved_handler = std::set_new_handler(0);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestOneNewWithoutExceptions(func, false);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // test with new_handler:
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set_new_handler(TestNewHandler);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestOneNewWithoutExceptions(func, true);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(news_handled, 1) << "nothrow new_handler was not called.";
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set_new_handler(saved_handler);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_WIN)
3425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#pragma warning(pop)
3435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
3445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(Atomics, AtomicIncrementWord) {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestAtomicIncrement<AtomicWord>();
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(Atomics, AtomicIncrement32) {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestAtomicIncrement<Atomic32>();
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(Atomics, AtomicOpsWord) {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestAtomicIncrement<AtomicWord>();
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(Atomics, AtomicOps32) {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestAtomicIncrement<Atomic32>();
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(Allocators, Malloc) {
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Try allocating data with a bunch of alignments and sizes
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int size = 1; size < 1048576; size *= 2) {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned char* ptr = reinterpret_cast<unsigned char*>(malloc(size));
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CheckAlignment(ptr, 2);  // Should be 2 byte aligned
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Fill(ptr, size);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(Valid(ptr, size));
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free(ptr);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(Allocators, Calloc) {
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCalloc(0, 0, true);
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCalloc(0, 1, true);
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCalloc(1, 1, true);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCalloc(1<<10, 0, true);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCalloc(1<<20, 0, true);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCalloc(0, 1<<10, true);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCalloc(0, 1<<20, true);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCalloc(1<<20, 2, true);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCalloc(2, 1<<20, true);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCalloc(1000, 1000, true);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCalloc(kMaxSize, 2, false);
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCalloc(2, kMaxSize, false);
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCalloc(kMaxSize, kMaxSize, false);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCalloc(kMaxSignedSize, 3, false);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCalloc(3, kMaxSignedSize, false);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCalloc(kMaxSignedSize, kMaxSignedSize, false);
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(Allocators, New) {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestNothrowNew(&::operator new);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestNothrowNew(&::operator new[]);
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This makes sure that reallocing a small number of bytes in either
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// direction doesn't cause us to allocate new memory.
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(Allocators, Realloc1) {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int start_sizes[] = { 100, 1000, 10000, 100000 };
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int deltas[] = { 1, -2, 4, -8, 16, -32, 64, -128 };
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int s = 0; s < sizeof(start_sizes)/sizeof(*start_sizes); ++s) {
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* p = malloc(start_sizes[s]);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(p);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The larger the start-size, the larger the non-reallocing delta.
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int d = 0; d < s*2; ++d) {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      void* new_p = realloc(p, start_sizes[s] + deltas[d]);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(p, new_p);  // realloc should not allocate new memory
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Test again, but this time reallocing smaller first.
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int d = 0; d < s*2; ++d) {
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      void* new_p = realloc(p, start_sizes[s] - deltas[d]);
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(p, new_p);  // realloc should not allocate new memory
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free(p);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(Allocators, Realloc2) {
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int src_size = 0; src_size >= 0; src_size = NextSize(src_size)) {
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int dst_size = 0; dst_size >= 0; dst_size = NextSize(dst_size)) {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned char* src = reinterpret_cast<unsigned char*>(malloc(src_size));
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Fill(src, src_size);
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned char* dst =
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reinterpret_cast<unsigned char*>(realloc(src, dst_size));
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(Valid(dst, min(src_size, dst_size)));
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Fill(dst, dst_size);
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(Valid(dst, dst_size));
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (dst != NULL) free(dst);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now make sure realloc works correctly even when we overflow the
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // packed cache, so some entries are evicted from the cache.
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The cache has 2^12 entries, keyed by page number.
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kNumEntries = 1 << 14;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int** p = reinterpret_cast<int**>(malloc(sizeof(*p) * kNumEntries));
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int sum = 0;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kNumEntries; i++) {
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // no page size is likely to be bigger than 8192?
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p[i] = reinterpret_cast<int*>(malloc(8192));
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p[i][1000] = i;              // use memory deep in the heart of p
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kNumEntries; i++) {
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p[i] = reinterpret_cast<int*>(realloc(p[i], 9000));
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kNumEntries; i++) {
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sum += p[i][1000];
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free(p[i]);
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kNumEntries/2 * (kNumEntries - 1), sum);  // assume kNE is even
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  free(p);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(Allocators, ReallocZero) {
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test that realloc to zero does not return NULL.
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int size = 0; size >= 0; size = NextSize(size)) {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char* ptr = reinterpret_cast<char*>(malloc(size));
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_NE(static_cast<char*>(NULL), ptr);
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ptr = reinterpret_cast<char*>(realloc(ptr, 0));
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_NE(static_cast<char*>(NULL), ptr);
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ptr)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      free(ptr);
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WIN32
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test recalloc
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(Allocators, Recalloc) {
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int src_size = 0; src_size >= 0; src_size = NextSize(src_size)) {
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int dst_size = 0; dst_size >= 0; dst_size = NextSize(dst_size)) {
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned char* src =
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reinterpret_cast<unsigned char*>(_recalloc(NULL, 1, src_size));
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(IsZeroed(src, src_size));
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Fill(src, src_size);
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned char* dst =
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reinterpret_cast<unsigned char*>(_recalloc(src, 1, dst_size));
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(Valid(dst, min(src_size, dst_size)));
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Fill(dst, dst_size);
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(Valid(dst, dst_size));
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (dst != NULL)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        free(dst);
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test windows specific _aligned_malloc() and _aligned_free() methods.
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(Allocators, AlignedMalloc) {
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Try allocating data with a bunch of alignments and sizes
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kTestAlignments[] = {8, 16, 256, 4096, 8192, 16384};
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int size = 1; size > 0; size = NextSize(size)) {
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < ARRAYSIZE(kTestAlignments); ++i) {
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned char* ptr = static_cast<unsigned char*>(
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          _aligned_malloc(size, kTestAlignments[i]));
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckAlignment(ptr, kTestAlignments[i]);
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Fill(ptr, size);
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(Valid(ptr, size));
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Make a second allocation of the same size and alignment to prevent
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // allocators from passing this test by accident.  Per jar, tcmalloc
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // provides allocations for new (never before seen) sizes out of a thread
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // local heap of a given "size class."  Each time the test requests a new
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // size, it will usually get the first element of a span, which is a
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // 4K aligned allocation.
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned char* ptr2 = static_cast<unsigned char*>(
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          _aligned_malloc(size, kTestAlignments[i]));
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckAlignment(ptr2, kTestAlignments[i]);
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Fill(ptr2, size);
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(Valid(ptr2, size));
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Should never happen, but sanity check just in case.
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_NE(ptr, ptr2);
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      _aligned_free(ptr);
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      _aligned_free(ptr2);
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int main(int argc, char** argv) {
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  testing::InitGoogleTest(&argc, argv);
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return RUN_ALL_TESTS();
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
532