1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright (c) 2009 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <stdio.h>
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <stdlib.h>
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <algorithm>   // for min()
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/atomicops.h"
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h"
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "testing/gtest/include/gtest/gtest.h"
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Number of bits in a size_t.
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const int kSizeBits = 8 * sizeof(size_t);
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The maximum size of a size_t.
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const size_t kMaxSize = ~static_cast<size_t>(0);
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Maximum positive size of a size_t if it were signed.
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const size_t kMaxSignedSize = ((size_t(1) << (kSizeBits-1)) - 1);
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// An allocation size which is not too big to be reasonable.
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const size_t kNotTooBig = 100000;
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// An allocation size which is just too big.
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const size_t kTooBig = ~static_cast<size_t>(0);
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace {
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing std::min;
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Fill a buffer of the specified size with a predetermined pattern
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void Fill(unsigned char* buffer, int n) {
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < n; i++) {
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    buffer[i] = (i & 0xff);
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Check that the specified buffer has the predetermined pattern
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// generated by Fill()
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic bool Valid(unsigned char* buffer, int n) {
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < n; i++) {
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (buffer[i] != (i & 0xff)) {
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Check that a buffer is completely zeroed.
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic bool IsZeroed(unsigned char* buffer, int n) {
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < n; i++) {
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (buffer[i] != 0) {
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Check alignment
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void CheckAlignment(void* p, int align) {
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(0, reinterpret_cast<uintptr_t>(p) & (align-1));
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Return the next interesting size/delta to check.  Returns -1 if no more.
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int NextSize(int size) {
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (size < 100)
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return size+1;
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (size < 100000) {
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Find next power of two
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int power = 1;
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    while (power < size)
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      power <<= 1;
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Yield (power-1, power, power+1)
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (size < power-1)
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return power-1;
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (size == power-1)
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return power;
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    assert(size == power);
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return power+1;
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return -1;
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define GG_ULONGLONG(x)  static_cast<uint64>(x)
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class AtomicType>
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void TestAtomicIncrement() {
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // For now, we just test single threaded execution
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // use a guard value to make sure the NoBarrier_AtomicIncrement doesn't go
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // outside the expected address bounds.  This is in particular to
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // test that some future change to the asm code doesn't cause the
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // 32-bit NoBarrier_AtomicIncrement to do the wrong thing on 64-bit machines.
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  struct {
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    AtomicType prev_word;
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    AtomicType count;
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    AtomicType next_word;
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } s;
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AtomicType prev_word_value, next_word_value;
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memset(&prev_word_value, 0xFF, sizeof(AtomicType));
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memset(&next_word_value, 0xEE, sizeof(AtomicType));
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  s.prev_word = prev_word_value;
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  s.count = 0;
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  s.next_word = next_word_value;
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 1), 1);
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.count, 1);
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.prev_word, prev_word_value);
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.next_word, next_word_value);
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 2), 3);
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.count, 3);
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.prev_word, prev_word_value);
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.next_word, next_word_value);
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 3), 6);
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.count, 6);
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.prev_word, prev_word_value);
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.next_word, next_word_value);
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -3), 3);
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.count, 3);
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.prev_word, prev_word_value);
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.next_word, next_word_value);
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -2), 1);
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.count, 1);
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.prev_word, prev_word_value);
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.next_word, next_word_value);
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -1), 0);
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.count, 0);
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.prev_word, prev_word_value);
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.next_word, next_word_value);
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -1), -1);
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.count, -1);
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.prev_word, prev_word_value);
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.next_word, next_word_value);
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -4), -5);
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.count, -5);
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.prev_word, prev_word_value);
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.next_word, next_word_value);
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 5), 0);
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.count, 0);
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.prev_word, prev_word_value);
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(s.next_word, next_word_value);
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define NUM_BITS(T) (sizeof(T) * 8)
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class AtomicType>
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void TestCompareAndSwap() {
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AtomicType value = 0;
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AtomicType prev = base::subtle::NoBarrier_CompareAndSwap(&value, 0, 1);
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(1, value);
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(0, prev);
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Use test value that has non-zero bits in both halves, more for testing
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // 64-bit implementation on 32-bit platforms.
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const AtomicType k_test_val = (GG_ULONGLONG(1) <<
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                 (NUM_BITS(AtomicType) - 2)) + 11;
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  value = k_test_val;
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  prev = base::subtle::NoBarrier_CompareAndSwap(&value, 0, 5);
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(k_test_val, value);
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(k_test_val, prev);
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  value = k_test_val;
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  prev = base::subtle::NoBarrier_CompareAndSwap(&value, k_test_val, 5);
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(5, value);
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(k_test_val, prev);
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class AtomicType>
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void TestAtomicExchange() {
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AtomicType value = 0;
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AtomicType new_value = base::subtle::NoBarrier_AtomicExchange(&value, 1);
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(1, value);
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(0, new_value);
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Use test value that has non-zero bits in both halves, more for testing
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // 64-bit implementation on 32-bit platforms.
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const AtomicType k_test_val = (GG_ULONGLONG(1) <<
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                 (NUM_BITS(AtomicType) - 2)) + 11;
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  value = k_test_val;
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  new_value = base::subtle::NoBarrier_AtomicExchange(&value, k_test_val);
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(k_test_val, value);
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(k_test_val, new_value);
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  value = k_test_val;
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  new_value = base::subtle::NoBarrier_AtomicExchange(&value, 5);
200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(5, value);
201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(k_test_val, new_value);
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class AtomicType>
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void TestAtomicIncrementBounds() {
207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Test increment at the half-width boundary of the atomic type.
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // It is primarily for testing at the 32-bit boundary for 64-bit atomic type.
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AtomicType test_val = GG_ULONGLONG(1) << (NUM_BITS(AtomicType) / 2);
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AtomicType value = test_val - 1;
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AtomicType new_value = base::subtle::NoBarrier_AtomicIncrement(&value, 1);
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(test_val, value);
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(value, new_value);
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  base::subtle::NoBarrier_AtomicIncrement(&value, -1);
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(test_val - 1, value);
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This is a simple sanity check that values are correct. Not testing
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// atomicity
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class AtomicType>
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void TestStore() {
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const AtomicType kVal1 = static_cast<AtomicType>(0xa5a5a5a5a5a5a5a5LL);
224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const AtomicType kVal2 = static_cast<AtomicType>(-1);
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AtomicType value;
227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  base::subtle::NoBarrier_Store(&value, kVal1);
229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(kVal1, value);
230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  base::subtle::NoBarrier_Store(&value, kVal2);
231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(kVal2, value);
232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  base::subtle::Acquire_Store(&value, kVal1);
234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(kVal1, value);
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  base::subtle::Acquire_Store(&value, kVal2);
236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(kVal2, value);
237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  base::subtle::Release_Store(&value, kVal1);
239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(kVal1, value);
240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  base::subtle::Release_Store(&value, kVal2);
241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(kVal2, value);
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This is a simple sanity check that values are correct. Not testing
245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// atomicity
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class AtomicType>
247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void TestLoad() {
248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const AtomicType kVal1 = static_cast<AtomicType>(0xa5a5a5a5a5a5a5a5LL);
249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const AtomicType kVal2 = static_cast<AtomicType>(-1);
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AtomicType value;
252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  value = kVal1;
254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(kVal1, base::subtle::NoBarrier_Load(&value));
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  value = kVal2;
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(kVal2, base::subtle::NoBarrier_Load(&value));
257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  value = kVal1;
259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(kVal1, base::subtle::Acquire_Load(&value));
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  value = kVal2;
261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(kVal2, base::subtle::Acquire_Load(&value));
262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  value = kVal1;
264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(kVal1, base::subtle::Release_Load(&value));
265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  value = kVal2;
266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(kVal2, base::subtle::Release_Load(&value));
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class AtomicType>
270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void TestAtomicOps() {
271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestCompareAndSwap<AtomicType>();
272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestAtomicExchange<AtomicType>();
273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestAtomicIncrementBounds<AtomicType>();
274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestStore<AtomicType>();
275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestLoad<AtomicType>();
276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void TestCalloc(size_t n, size_t s, bool ok) {
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char* p = reinterpret_cast<char*>(calloc(n, s));
280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!ok) {
281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(NULL, p) << "calloc(n, s) should not succeed";
282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_NE(reinterpret_cast<void*>(NULL), p) <<
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        "calloc(n, s) should succeed";
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (int i = 0; i < n*s; i++) {
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EXPECT_EQ('\0', p[i]);
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    free(p);
289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// A global test counter for number of times the NewHandler is called.
294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int news_handled = 0;
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void TestNewHandler() {
296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ++news_handled;
297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  throw std::bad_alloc();
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Because we compile without exceptions, we expect these will not throw.
301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void TestOneNewWithoutExceptions(void* (*func)(size_t),
302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                        bool should_throw) {
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // success test
304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  try {
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    void* ptr = (*func)(kNotTooBig);
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_NE(reinterpret_cast<void*>(NULL), ptr) <<
307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        "allocation should not have failed.";
308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } catch(...) {
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(0, 1) << "allocation threw unexpected exception.";
310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // failure test
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  try {
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    void* rv = (*func)(kTooBig);
315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(NULL, rv);
31672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    EXPECT_FALSE(should_throw) << "allocation should have thrown.";
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } catch(...) {
31872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    EXPECT_TRUE(should_throw) << "allocation threw unexpected exception.";
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void TestNothrowNew(void* (*func)(size_t)) {
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  news_handled = 0;
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // test without new_handler:
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::new_handler saved_handler = std::set_new_handler(0);
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestOneNewWithoutExceptions(func, false);
328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // test with new_handler:
330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::set_new_handler(TestNewHandler);
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestOneNewWithoutExceptions(func, true);
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(news_handled, 1) << "nothrow new_handler was not called.";
333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::set_new_handler(saved_handler);
334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace
337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//-----------------------------------------------------------------------------
339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(Atomics, AtomicIncrementWord) {
341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestAtomicIncrement<AtomicWord>();
342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(Atomics, AtomicIncrement32) {
345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestAtomicIncrement<Atomic32>();
346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(Atomics, AtomicOpsWord) {
349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestAtomicIncrement<AtomicWord>();
350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(Atomics, AtomicOps32) {
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestAtomicIncrement<Atomic32>();
354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(Allocators, Malloc) {
357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Try allocating data with a bunch of alignments and sizes
358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int size = 1; size < 1048576; size *= 2) {
359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    unsigned char* ptr = reinterpret_cast<unsigned char*>(malloc(size));
360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CheckAlignment(ptr, 2);  // Should be 2 byte aligned
361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Fill(ptr, size);
36272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    EXPECT_TRUE(Valid(ptr, size));
363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    free(ptr);
364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(Allocators, Calloc) {
368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestCalloc(0, 0, true);
369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestCalloc(0, 1, true);
370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestCalloc(1, 1, true);
371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestCalloc(1<<10, 0, true);
372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestCalloc(1<<20, 0, true);
373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestCalloc(0, 1<<10, true);
374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestCalloc(0, 1<<20, true);
375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestCalloc(1<<20, 2, true);
376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestCalloc(2, 1<<20, true);
377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestCalloc(1000, 1000, true);
378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestCalloc(kMaxSize, 2, false);
380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestCalloc(2, kMaxSize, false);
381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestCalloc(kMaxSize, kMaxSize, false);
382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestCalloc(kMaxSignedSize, 3, false);
384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestCalloc(3, kMaxSignedSize, false);
385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestCalloc(kMaxSignedSize, kMaxSignedSize, false);
386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(Allocators, New) {
389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestNothrowNew(&::operator new);
390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestNothrowNew(&::operator new[]);
391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This makes sure that reallocing a small number of bytes in either
394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// direction doesn't cause us to allocate new memory.
395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(Allocators, Realloc1) {
396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int start_sizes[] = { 100, 1000, 10000, 100000 };
397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int deltas[] = { 1, -2, 4, -8, 16, -32, 64, -128 };
398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int s = 0; s < sizeof(start_sizes)/sizeof(*start_sizes); ++s) {
400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    void* p = malloc(start_sizes[s]);
401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CHECK(p);
402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // The larger the start-size, the larger the non-reallocing delta.
403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (int d = 0; d < s*2; ++d) {
404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      void* new_p = realloc(p, start_sizes[s] + deltas[d]);
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CHECK_EQ(p, new_p);  // realloc should not allocate new memory
406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Test again, but this time reallocing smaller first.
408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (int d = 0; d < s*2; ++d) {
409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      void* new_p = realloc(p, start_sizes[s] - deltas[d]);
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CHECK_EQ(p, new_p);  // realloc should not allocate new memory
411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    free(p);
413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(Allocators, Realloc2) {
417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int src_size = 0; src_size >= 0; src_size = NextSize(src_size)) {
418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (int dst_size = 0; dst_size >= 0; dst_size = NextSize(dst_size)) {
419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      unsigned char* src = reinterpret_cast<unsigned char*>(malloc(src_size));
420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      Fill(src, src_size);
421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      unsigned char* dst =
422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          reinterpret_cast<unsigned char*>(realloc(src, dst_size));
42372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      EXPECT_TRUE(Valid(dst, min(src_size, dst_size)));
424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      Fill(dst, dst_size);
42572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      EXPECT_TRUE(Valid(dst, dst_size));
426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (dst != NULL) free(dst);
427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Now make sure realloc works correctly even when we overflow the
431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // packed cache, so some entries are evicted from the cache.
432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The cache has 2^12 entries, keyed by page number.
433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const int kNumEntries = 1 << 14;
434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int** p = reinterpret_cast<int**>(malloc(sizeof(*p) * kNumEntries));
435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int sum = 0;
436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < kNumEntries; i++) {
437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // no page size is likely to be bigger than 8192?
438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    p[i] = reinterpret_cast<int*>(malloc(8192));
439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    p[i][1000] = i;              // use memory deep in the heart of p
440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < kNumEntries; i++) {
442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    p[i] = reinterpret_cast<int*>(realloc(p[i], 9000));
443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < kNumEntries; i++) {
445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    sum += p[i][1000];
446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    free(p[i]);
447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(kNumEntries/2 * (kNumEntries - 1), sum);  // assume kNE is even
449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  free(p);
450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(Allocators, ReallocZero) {
453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Test that realloc to zero does not return NULL.
454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int size = 0; size >= 0; size = NextSize(size)) {
455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    char* ptr = reinterpret_cast<char*>(malloc(size));
456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_NE(static_cast<char*>(NULL), ptr);
457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ptr = reinterpret_cast<char*>(realloc(ptr, 0));
458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_NE(static_cast<char*>(NULL), ptr);
459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (ptr)
460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      free(ptr);
461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef WIN32
465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Test recalloc
466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(Allocators, Recalloc) {
467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int src_size = 0; src_size >= 0; src_size = NextSize(src_size)) {
468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (int dst_size = 0; dst_size >= 0; dst_size = NextSize(dst_size)) {
469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      unsigned char* src =
470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          reinterpret_cast<unsigned char*>(_recalloc(NULL, 1, src_size));
47172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      EXPECT_TRUE(IsZeroed(src, src_size));
472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      Fill(src, src_size);
473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      unsigned char* dst =
474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          reinterpret_cast<unsigned char*>(_recalloc(src, 1, dst_size));
47572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      EXPECT_TRUE(Valid(dst, min(src_size, dst_size)));
476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      Fill(dst, dst_size);
47772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      EXPECT_TRUE(Valid(dst, dst_size));
478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (dst != NULL)
479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        free(dst);
480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint main(int argc, char** argv) {
487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  testing::InitGoogleTest(&argc, argv);
488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return RUN_ALL_TESTS();
489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
490