Line data Source code
1 : // Copyright 2014 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/base/platform/platform.h"
6 :
7 : #if V8_OS_POSIX
8 : #include <setjmp.h>
9 : #include <signal.h>
10 : #include <unistd.h> // NOLINT
11 : #endif
12 :
13 : #if V8_OS_WIN
14 : #include "src/base/win32-headers.h"
15 : #endif
16 : #include "testing/gtest/include/gtest/gtest.h"
17 :
18 : #if V8_OS_ANDROID
19 : #define DISABLE_ON_ANDROID(Name) DISABLED_##Name
20 : #else
21 : #define DISABLE_ON_ANDROID(Name) Name
22 : #endif
23 :
24 : namespace v8 {
25 : namespace base {
26 :
27 13158 : TEST(OS, GetCurrentProcessId) {
28 : #if V8_OS_POSIX
29 2 : EXPECT_EQ(static_cast<int>(getpid()), OS::GetCurrentProcessId());
30 : #endif
31 :
32 : #if V8_OS_WIN
33 : EXPECT_EQ(static_cast<int>(::GetCurrentProcessId()),
34 : OS::GetCurrentProcessId());
35 : #endif
36 1 : }
37 :
38 :
39 : namespace {
40 :
41 : class ThreadLocalStorageTest : public Thread, public ::testing::Test {
42 : public:
43 2 : ThreadLocalStorageTest() : Thread(Options("ThreadLocalStorageTest")) {
44 33 : for (size_t i = 0; i < arraysize(keys_); ++i) {
45 32 : keys_[i] = Thread::CreateThreadLocalKey();
46 : }
47 1 : }
48 2 : ~ThreadLocalStorageTest() {
49 33 : for (size_t i = 0; i < arraysize(keys_); ++i) {
50 32 : Thread::DeleteThreadLocalKey(keys_[i]);
51 : }
52 1 : }
53 :
54 2 : void Run() final {
55 66 : for (size_t i = 0; i < arraysize(keys_); i++) {
56 128 : CHECK(!Thread::HasThreadLocal(keys_[i]));
57 : }
58 66 : for (size_t i = 0; i < arraysize(keys_); i++) {
59 64 : Thread::SetThreadLocal(keys_[i], GetValue(i));
60 : }
61 64 : for (size_t i = 0; i < arraysize(keys_); i++) {
62 128 : CHECK(Thread::HasThreadLocal(keys_[i]));
63 : }
64 66 : for (size_t i = 0; i < arraysize(keys_); i++) {
65 128 : CHECK_EQ(GetValue(i), Thread::GetThreadLocal(keys_[i]));
66 128 : CHECK_EQ(GetValue(i), Thread::GetExistingThreadLocal(keys_[i]));
67 : }
68 64 : for (size_t i = 0; i < arraysize(keys_); i++) {
69 64 : Thread::SetThreadLocal(keys_[i], GetValue(arraysize(keys_) - i - 1));
70 : }
71 64 : for (size_t i = 0; i < arraysize(keys_); i++) {
72 128 : CHECK(Thread::HasThreadLocal(keys_[i]));
73 : }
74 64 : for (size_t i = 0; i < arraysize(keys_); i++) {
75 128 : CHECK_EQ(GetValue(arraysize(keys_) - i - 1),
76 : Thread::GetThreadLocal(keys_[i]));
77 128 : CHECK_EQ(GetValue(arraysize(keys_) - i - 1),
78 : Thread::GetExistingThreadLocal(keys_[i]));
79 : }
80 2 : }
81 :
82 : private:
83 : static void* GetValue(size_t x) {
84 256 : return bit_cast<void*>(static_cast<uintptr_t>(x + 1));
85 : }
86 :
87 : // Older versions of Android have fewer TLS slots (nominally 64, but the
88 : // system uses "about 5 of them" itself).
89 : Thread::LocalStorageKey keys_[32];
90 : };
91 :
92 : } // namespace
93 :
94 :
95 13158 : TEST_F(ThreadLocalStorageTest, DoTest) {
96 1 : Run();
97 1 : Start();
98 1 : Join();
99 1 : }
100 :
101 : #if V8_OS_POSIX
102 : // TODO(eholk): Add a windows version of these tests
103 :
104 : namespace {
105 :
106 : // These tests make sure the routines to allocate memory do so with the correct
107 : // permissions.
108 : //
109 : // Unfortunately, there is no API to find the protection of a memory address,
110 : // so instead we test permissions by installing a signal handler, probing a
111 : // memory location and recovering from the fault.
112 : //
113 : // We don't test the execution permission because to do so we'd have to
114 : // dynamically generate code and test if we can execute it.
115 :
116 2 : class MemoryAllocationPermissionsTest : public ::testing::Test {
117 2 : static void SignalHandler(int signal, siginfo_t* info, void*) {
118 2 : siglongjmp(continuation_, 1);
119 : }
120 : struct sigaction old_action_;
121 : // On Mac, sometimes we get SIGBUS instead of SIGSEGV.
122 : #if V8_OS_MACOSX
123 : struct sigaction old_bus_action_;
124 : #endif
125 :
126 : protected:
127 1 : virtual void SetUp() {
128 : struct sigaction action;
129 1 : action.sa_sigaction = SignalHandler;
130 1 : sigemptyset(&action.sa_mask);
131 1 : action.sa_flags = SA_SIGINFO;
132 1 : sigaction(SIGSEGV, &action, &old_action_);
133 : #if V8_OS_MACOSX
134 : sigaction(SIGBUS, &action, &old_bus_action_);
135 : #endif
136 1 : }
137 :
138 1 : virtual void TearDown() {
139 : // be a good citizen and restore the old signal handler.
140 1 : sigaction(SIGSEGV, &old_action_, nullptr);
141 : #if V8_OS_MACOSX
142 : sigaction(SIGBUS, &old_bus_action_, nullptr);
143 : #endif
144 1 : }
145 :
146 : public:
147 : static sigjmp_buf continuation_;
148 :
149 : enum class MemoryAction { kRead, kWrite };
150 :
151 6 : void ProbeMemory(volatile int* buffer, MemoryAction action,
152 : bool should_succeed) {
153 : const int save_sigs = 1;
154 6 : if (!sigsetjmp(continuation_, save_sigs)) {
155 4 : switch (action) {
156 : case MemoryAction::kRead: {
157 : // static_cast to remove the reference and force a memory read.
158 2 : USE(static_cast<int>(*buffer));
159 : break;
160 : }
161 : case MemoryAction::kWrite: {
162 2 : *buffer = 0;
163 : break;
164 : }
165 : }
166 4 : if (should_succeed) {
167 8 : SUCCEED();
168 : } else {
169 0 : FAIL();
170 : }
171 : return;
172 : }
173 2 : if (should_succeed) {
174 0 : FAIL();
175 : } else {
176 4 : SUCCEED();
177 : }
178 : }
179 :
180 3 : void TestPermissions(OS::MemoryPermission permission, bool can_read,
181 : bool can_write) {
182 3 : const size_t allocation_size = OS::CommitPageSize();
183 3 : size_t actual = 0;
184 : int* buffer =
185 3 : static_cast<int*>(OS::Allocate(allocation_size, &actual, permission));
186 3 : ProbeMemory(buffer, MemoryAction::kRead, can_read);
187 3 : ProbeMemory(buffer, MemoryAction::kWrite, can_write);
188 3 : OS::Free(buffer, actual);
189 3 : }
190 : };
191 :
192 : sigjmp_buf MemoryAllocationPermissionsTest::continuation_;
193 :
194 13159 : TEST_F(MemoryAllocationPermissionsTest, DoTest) {
195 1 : TestPermissions(OS::MemoryPermission::kNoAccess, false, false);
196 1 : TestPermissions(OS::MemoryPermission::kReadWrite, true, true);
197 1 : TestPermissions(OS::MemoryPermission::kReadWriteExecute, true, true);
198 1 : }
199 :
200 : } // namespace
201 : #endif // V8_OS_POSIX
202 :
203 : } // namespace base
204 7893 : } // namespace v8
|