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

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: CR Feedback 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, AcquireNonPredecessor) {
122 SchedulerLock lock1;
123 SchedulerLock lock2;
124 EXPECT_DEBUG_DEATH({
125 lock1.Acquire();
126 lock2.Acquire();
127 }, "");
128 }
129
130 TEST(TaskSchedulerLock, AcquireMultipleLocksInOrder) {
131 SchedulerLock lock1;
132 SchedulerLock lock2(&lock1);
133 SchedulerLock lock3(&lock2);
134 lock1.Acquire();
135 lock2.Acquire();
136 lock3.Acquire();
137 lock3.Release();
138 lock2.Release();
139 lock1.Release();
140 }
141
142 TEST(TaskSchedulerLock, AcquireMultipleLocksInTheMiddleOfAChain) {
143 SchedulerLock lock1;
144 SchedulerLock lock2(&lock1);
145 SchedulerLock lock3(&lock2);
146 lock2.Acquire();
147 lock3.Acquire();
148 lock3.Release();
149 lock2.Release();
150 }
151
152 TEST(TaskSchedulerLock, AcquireMultipleLocksNoTransitivity) {
153 SchedulerLock lock1;
154 SchedulerLock lock2(&lock1);
155 SchedulerLock lock3(&lock2);
156 EXPECT_DEBUG_DEATH({
157 lock1.Acquire();
158 lock3.Acquire();
159 }, "");
160 }
161
162 TEST(TaskSchedulerLock, AcquireLocksDifferentThreadsSafely) {
163 SchedulerLock lock1;
164 SchedulerLock lock2;
165 BasicLockAcquireAndWaitThread thread(&lock1);
166 PlatformThreadHandle handle;
167 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
168
169 lock2.Acquire();
170 thread.WaitForLockAcquisition();
171 thread.ContinueMain();
172 PlatformThread::Join(handle);
173 lock2.Release();
174 }
gab 2016/02/19 22:05:24 What is this now testing that the next two tests a
robliao 2016/02/19 23:51:12 This tests the absence of any predecessor relation
175
176 TEST(TaskSchedulerLock,
177 AcquireLocksWithPredecessorDifferentThreadsSafely1PredecessorFirst) {
178 // A lock and its predecessor may be safely acquired on different threads.
179 // This Thread Other Thread
180 // predecessor.Acquire()
181 // lock.Acquire()
182 // predecessor.Release()
183 // lock.Release()
184 SchedulerLock predecessor;
185 SchedulerLock lock(&predecessor);
186 predecessor.Acquire();
187 BasicLockAcquireAndWaitThread thread(&lock);
188 PlatformThreadHandle handle;
189 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
190 thread.WaitForLockAcquisition();
191 predecessor.Release();
192 thread.ContinueMain();
193 PlatformThread::Join(handle);
194 }
195
196 TEST(TaskSchedulerLock,
197 AcquireLocksWithPredecessorDifferentThreadsSafely1PredecessorLast) {
198 // A lock and its predecessor may be safely acquired on different threads.
199 // This Thread Other Thread
200 // lock.Acquire()
201 // predecessor.Acquire()
202 // lock.Release()
203 // predecessor.Release()
204 SchedulerLock predecessor;
205 SchedulerLock lock(&predecessor);
206 lock.Acquire();
207 BasicLockAcquireAndWaitThread thread(&predecessor);
208 PlatformThreadHandle handle;
209 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
210 thread.WaitForLockAcquisition();
211 lock.Release();
212 thread.ContinueMain();
213 PlatformThread::Join(handle);
214 }
215
216 TEST(TaskSchedulerLock, SelfReferentialLock) {
217 struct SelfReferentialLock {
218 SelfReferentialLock() : lock(&lock) {}
219
220 SchedulerLock lock;
221 };
222
223 EXPECT_DEBUG_DEATH({ SelfReferentialLock lock; }, "");
224 }
225
226 TEST(TaskSchedulerLock, PredecessorCycle) {
227 struct LockCycle {
228 LockCycle() : lock1(&lock2), lock2(&lock1) {}
229
230 SchedulerLock lock1;
231 SchedulerLock lock2;
232 };
233
234 EXPECT_DEBUG_DEATH({ LockCycle cycle; }, "");
235 }
236
237 TEST(TaskSchedulerLock, PredecessorLongerCycle) {
238 struct LockCycle {
239 LockCycle()
240 : lock1(&lock5),
241 lock2(&lock1),
242 lock3(&lock2),
243 lock4(&lock3),
244 lock5(&lock4) {}
245
246 SchedulerLock lock1;
247 SchedulerLock lock2;
248 SchedulerLock lock3;
249 SchedulerLock lock4;
250 SchedulerLock lock5;
251 };
252
253 EXPECT_DEBUG_DEATH({ LockCycle cycle; }, "");
254 }
255
256 } // namespace internal
257 } // base
OLDNEW
« base/task_scheduler/scheduler_lock_impl.h ('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