Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(794)

Side by Side Diff: base/task_scheduler/scheduler_lock_unittest.cc

Issue 1706123002: TaskScheduler [2/9] Scheduler Lock (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: thread_local -> thread_local_storage ( Bug http://crbug.com/588824) Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium 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 "base/task_scheduler/scheduler_lock.h"
6
7 #include <stdlib.h>
8
9 #include "base/compiler_specific.h"
10 #include "base/macros.h"
11 #include "base/rand_util.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "base/threading/platform_thread.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace base {
17 namespace internal {
18
19 // Adapted from base::Lock's BasicLockTestThread to make sure
20 // Acquire()/Release() don't crash.
21 class BasicLockTestThread : public PlatformThread::Delegate {
22 public:
23 explicit BasicLockTestThread(SchedulerLock* lock)
24 : lock_(lock),
25 acquired_(0) {}
26
27 void ThreadMain() override {
28 for (int i = 0; i < 10; i++) {
29 lock_->Acquire();
30 acquired_++;
31 lock_->Release();
32 }
33 for (int i = 0; i < 10; i++) {
34 lock_->Acquire();
35 acquired_++;
36 PlatformThread::Sleep(TimeDelta::FromMilliseconds(base::RandInt(0, 19)));
37 lock_->Release();
38 }
39 }
40
41 int acquired() const { return acquired_; }
42
43 private:
44 SchedulerLock* const lock_;
45 int acquired_;
46
47 DISALLOW_COPY_AND_ASSIGN(BasicLockTestThread);
48 };
49
50 class BasicLockAcquireAndWaitThread : public PlatformThread::Delegate {
51 public:
52 explicit BasicLockAcquireAndWaitThread(SchedulerLock* lock)
53 : lock_(lock),
54 lock_acquire_event_(false, false),
55 main_thread_continue_event_(false, false) {}
56
57 void ThreadMain() override {
58 lock_->Acquire();
59 lock_acquire_event_.Signal();
60 main_thread_continue_event_.Wait();
61 lock_->Release();
62 }
63
64 void WaitForLockAcquisition() {
65 lock_acquire_event_.Wait();
66 }
67
68 void ContinueMain() {
69 main_thread_continue_event_.Signal();
70 }
71
72 private:
73 SchedulerLock* const lock_;
74 WaitableEvent lock_acquire_event_;
75 WaitableEvent main_thread_continue_event_;
76
77 DISALLOW_COPY_AND_ASSIGN(BasicLockAcquireAndWaitThread);
78 };
79
80 TEST(TaskSchedulerLock, Basic) {
81 SchedulerLock lock;
82 BasicLockTestThread thread(&lock);
83 PlatformThreadHandle handle;
84
85 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
86
87 int acquired = 0;
88 for (int i = 0; i < 5; i++) {
89 lock.Acquire();
90 acquired++;
91 lock.Release();
92 }
93 for (int i = 0; i < 10; i++) {
94 lock.Acquire();
95 acquired++;
96 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
97 lock.Release();
98 }
99 for (int i = 0; i < 5; i++) {
100 lock.Acquire();
101 acquired++;
102 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
103 lock.Release();
104 }
105
106 PlatformThread::Join(handle);
107
108 EXPECT_EQ(acquired, 20);
109 EXPECT_EQ(thread.acquired(), 20);
110 }
111
112 TEST(TaskSchedulerLock, AcquirePredecessor) {
113 SchedulerLock predecessor;
114 SchedulerLock lock(&predecessor);
115 predecessor.Acquire();
116 lock.Acquire();
117 lock.Release();
118 predecessor.Release();
119 }
120
121 TEST(TaskSchedulerLock, AcquirePredecessorWrongOrder) {
122 SchedulerLock predecessor;
123 SchedulerLock lock(&predecessor);
124 EXPECT_DEBUG_DEATH({
125 lock.Acquire();
126 predecessor.Acquire();
127 }, "");
128 }
129
130 TEST(TaskSchedulerLock, AcquireNonPredecessor) {
131 SchedulerLock lock1;
132 SchedulerLock lock2;
133 EXPECT_DEBUG_DEATH({
134 lock1.Acquire();
135 lock2.Acquire();
136 }, "");
137 }
138
139 TEST(TaskSchedulerLock, AcquireMultipleLocksInOrder) {
140 SchedulerLock lock1;
141 SchedulerLock lock2(&lock1);
142 SchedulerLock lock3(&lock2);
143 lock1.Acquire();
144 lock2.Acquire();
145 lock3.Acquire();
146 lock3.Release();
147 lock2.Release();
148 lock1.Release();
149 }
150
151 TEST(TaskSchedulerLock, AcquireMultipleLocksInTheMiddleOfAChain) {
152 SchedulerLock lock1;
153 SchedulerLock lock2(&lock1);
154 SchedulerLock lock3(&lock2);
155 lock2.Acquire();
156 lock3.Acquire();
157 lock3.Release();
158 lock2.Release();
159 }
160
161 TEST(TaskSchedulerLock, AcquireMultipleLocksNoTransitivity) {
162 SchedulerLock lock1;
163 SchedulerLock lock2(&lock1);
164 SchedulerLock lock3(&lock2);
165 EXPECT_DEBUG_DEATH({
166 lock1.Acquire();
167 lock3.Acquire();
168 }, "");
169 }
170
171 TEST(TaskSchedulerLock, AcquireLocksDifferentThreadsSafely) {
172 SchedulerLock lock1;
173 SchedulerLock lock2;
174 BasicLockAcquireAndWaitThread thread(&lock1);
175 PlatformThreadHandle handle;
176 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
177
178 lock2.Acquire();
179 thread.WaitForLockAcquisition();
180 thread.ContinueMain();
181 PlatformThread::Join(handle);
182 lock2.Release();
183 }
184
185 TEST(TaskSchedulerLock,
186 AcquireLocksWithPredecessorDifferentThreadsSafelyPredecessorFirst) {
187 // A lock and its predecessor may be safely acquired on different threads.
188 // This Thread Other Thread
189 // predecessor.Acquire()
190 // lock.Acquire()
191 // predecessor.Release()
192 // lock.Release()
193 SchedulerLock predecessor;
194 SchedulerLock lock(&predecessor);
195 predecessor.Acquire();
196 BasicLockAcquireAndWaitThread thread(&lock);
197 PlatformThreadHandle handle;
198 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
199 thread.WaitForLockAcquisition();
200 predecessor.Release();
201 thread.ContinueMain();
202 PlatformThread::Join(handle);
203 }
204
205 TEST(TaskSchedulerLock,
206 AcquireLocksWithPredecessorDifferentThreadsSafelyPredecessorLast) {
207 // A lock and its predecessor may be safely acquired on different threads.
208 // This Thread Other Thread
209 // lock.Acquire()
210 // predecessor.Acquire()
211 // lock.Release()
212 // predecessor.Release()
213 SchedulerLock predecessor;
214 SchedulerLock lock(&predecessor);
215 lock.Acquire();
216 BasicLockAcquireAndWaitThread thread(&predecessor);
217 PlatformThreadHandle handle;
218 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
219 thread.WaitForLockAcquisition();
220 lock.Release();
221 thread.ContinueMain();
222 PlatformThread::Join(handle);
223 }
224
225 TEST(TaskSchedulerLock, SelfReferentialLock) {
226 struct SelfReferentialLock {
227 SelfReferentialLock() : lock(&lock) {}
228
229 SchedulerLock lock;
230 };
231
232 EXPECT_DEBUG_DEATH({ SelfReferentialLock lock; }, "");
233 }
234
235 TEST(TaskSchedulerLock, PredecessorCycle) {
236 struct LockCycle {
237 LockCycle() : lock1(&lock2), lock2(&lock1) {}
238
239 SchedulerLock lock1;
240 SchedulerLock lock2;
241 };
242
243 EXPECT_DEBUG_DEATH({ LockCycle cycle; }, "");
244 }
245
246 TEST(TaskSchedulerLock, PredecessorLongerCycle) {
247 struct LockCycle {
248 LockCycle()
249 : lock1(&lock5),
250 lock2(&lock1),
251 lock3(&lock2),
252 lock4(&lock3),
253 lock5(&lock4) {}
254
255 SchedulerLock lock1;
256 SchedulerLock lock2;
257 SchedulerLock lock3;
258 SchedulerLock lock4;
259 SchedulerLock lock5;
260 };
261
262 EXPECT_DEBUG_DEATH({ LockCycle cycle; }, "");
263 }
264
265 } // namespace internal
266 } // base
OLDNEW
« base/task_scheduler/scheduler_lock_impl.cc ('K') | « base/task_scheduler/scheduler_lock_impl.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698