blob: 2984d0d4fbec70ee9578fe4062b66649934497c4 [file] [log] [blame]
Austin Schuh745610d2015-09-06 18:19:50 -07001// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
2// Copyright 2009 Google Inc. All Rights Reserved.
3// Author: Nabeel Mian (nabeelmian@google.com)
4// Chris Demetriou (cgd@google.com)
5//
6// Use of this source code is governed by a BSD-style license that can
7// be found in the LICENSE file.
8//
9//
10// This file contains the unit tests for profile-handler.h interface.
11//
12// It is linked into three separate unit tests:
13// profile-handler_unittest tests basic functionality
14// profile-handler_disable_test tests that the profiler
15// is disabled with --install_signal_handlers=false
16// profile-handler_conflict_test tests that the profiler
17// is disabled when a SIGPROF handler is registered before InitGoogle.
18
19#include "config.h"
20#include "profile-handler.h"
21
22#include <assert.h>
23#include <pthread.h>
24#include <sys/time.h>
25#include <time.h>
26#include "base/logging.h"
27#include "base/simple_mutex.h"
28
29// Some helpful macros for the test class
30#define TEST_F(cls, fn) void cls :: fn()
31
32// Do we expect the profiler to be enabled?
33DEFINE_bool(test_profiler_enabled, true,
34 "expect profiler to be enabled during tests");
35
36// Should we look at the kernel signal handler settings during the test?
37// Not if we're in conflict_test, because we can't distinguish its nop
38// handler from the real one.
39DEFINE_bool(test_profiler_signal_handler, true,
40 "check profiler signal handler during tests");
41
42namespace {
43
44// TODO(csilvers): error-checking on the pthreads routines
45class Thread {
46 public:
47 Thread() : joinable_(false) { }
48 virtual ~Thread() { }
49 void SetJoinable(bool value) { joinable_ = value; }
50 void Start() {
51 pthread_attr_t attr;
52 pthread_attr_init(&attr);
53 pthread_attr_setdetachstate(&attr, joinable_ ? PTHREAD_CREATE_JOINABLE
54 : PTHREAD_CREATE_DETACHED);
55 pthread_create(&thread_, &attr, &DoRun, this);
56 pthread_attr_destroy(&attr);
57 }
58 void Join() {
59 assert(joinable_);
60 pthread_join(thread_, NULL);
61 }
62 virtual void Run() = 0;
63 private:
64 static void* DoRun(void* cls) {
65 ProfileHandlerRegisterThread();
66 reinterpret_cast<Thread*>(cls)->Run();
67 return NULL;
68 }
69 pthread_t thread_;
70 bool joinable_;
71};
72
73// Sleep interval in nano secs. ITIMER_PROF goes off only afer the specified CPU
74// time is consumed. Under heavy load this process may no get scheduled in a
75// timely fashion. Therefore, give enough time (20x of ProfileHandle timer
76// interval 10ms (100Hz)) for this process to accumulate enought CPU time to get
77// a profile tick.
78int kSleepInterval = 200000000;
79
80// Sleep interval in nano secs. To ensure that if the timer has expired it is
81// reset.
82int kTimerResetInterval = 5000000;
83
84// Whether each thread has separate timers.
85static bool linux_per_thread_timers_mode_ = false;
86static bool timer_separate_ = false;
87static int timer_type_ = ITIMER_PROF;
88static int signal_number_ = SIGPROF;
89
90// Delays processing by the specified number of nano seconds. 'delay_ns'
91// must be less than the number of nano seconds in a second (1000000000).
92void Delay(int delay_ns) {
93 static const int kNumNSecInSecond = 1000000000;
94 EXPECT_LT(delay_ns, kNumNSecInSecond);
95 struct timespec delay = { 0, delay_ns };
96 nanosleep(&delay, 0);
97}
98
99// Checks whether the profile timer is enabled for the current thread.
100bool IsTimerEnabled() {
101 itimerval current_timer;
102 EXPECT_EQ(0, getitimer(timer_type_, &current_timer));
103 if ((current_timer.it_value.tv_sec == 0) &&
104 (current_timer.it_value.tv_usec != 0)) {
105 // May be the timer has expired. Sleep for a bit and check again.
106 Delay(kTimerResetInterval);
107 EXPECT_EQ(0, getitimer(timer_type_, &current_timer));
108 }
109 return (current_timer.it_value.tv_sec != 0 ||
110 current_timer.it_value.tv_usec != 0);
111}
112
113class VirtualTimerGetterThread : public Thread {
114 public:
115 VirtualTimerGetterThread() {
116 memset(&virtual_timer_, 0, sizeof virtual_timer_);
117 }
118 struct itimerval virtual_timer_;
119
120 private:
121 void Run() {
122 CHECK_EQ(0, getitimer(ITIMER_VIRTUAL, &virtual_timer_));
123 }
124};
125
126// This function checks whether the timers are shared between thread. This
127// function spawns a thread, so use it carefully when testing thread-dependent
128// behaviour.
129static bool threads_have_separate_timers() {
130 struct itimerval new_timer_val;
131
132 // Enable the virtual timer in the current thread.
133 memset(&new_timer_val, 0, sizeof new_timer_val);
134 new_timer_val.it_value.tv_sec = 1000000; // seconds
135 CHECK_EQ(0, setitimer(ITIMER_VIRTUAL, &new_timer_val, NULL));
136
137 // Spawn a thread, get the virtual timer's value there.
138 VirtualTimerGetterThread thread;
139 thread.SetJoinable(true);
140 thread.Start();
141 thread.Join();
142
143 // Disable timer here.
144 memset(&new_timer_val, 0, sizeof new_timer_val);
145 CHECK_EQ(0, setitimer(ITIMER_VIRTUAL, &new_timer_val, NULL));
146
147 bool target_timer_enabled = (thread.virtual_timer_.it_value.tv_sec != 0 ||
148 thread.virtual_timer_.it_value.tv_usec != 0);
149 if (!target_timer_enabled) {
150 LOG(INFO, "threads have separate timers");
151 return true;
152 } else {
153 LOG(INFO, "threads have shared timers");
154 return false;
155 }
156}
157
158// Dummy worker thread to accumulate cpu time.
159class BusyThread : public Thread {
160 public:
161 BusyThread() : stop_work_(false) {
162 }
163
164 // Setter/Getters
165 bool stop_work() {
166 MutexLock lock(&mu_);
167 return stop_work_;
168 }
169 void set_stop_work(bool stop_work) {
170 MutexLock lock(&mu_);
171 stop_work_ = stop_work;
172 }
173
174 private:
175 // Protects stop_work_ below.
176 Mutex mu_;
177 // Whether to stop work?
178 bool stop_work_;
179
180 // Do work until asked to stop.
181 void Run() {
182 while (!stop_work()) {
183 }
184 // If timers are separate, check that timer is enabled for this thread.
185 EXPECT_TRUE(linux_per_thread_timers_mode_ || !timer_separate_ || IsTimerEnabled());
186 }
187};
188
189class NullThread : public Thread {
190 private:
191 void Run() {
192 // If timers are separate, check that timer is enabled for this thread.
193 EXPECT_TRUE(linux_per_thread_timers_mode_ || !timer_separate_ || IsTimerEnabled());
194 }
195};
196
197// Signal handler which tracks the profile timer ticks.
198static void TickCounter(int sig, siginfo_t* sig_info, void *vuc,
199 void* tick_counter) {
200 int* counter = static_cast<int*>(tick_counter);
201 ++(*counter);
202}
203
204// This class tests the profile-handler.h interface.
205class ProfileHandlerTest {
206 protected:
207
208 // Determines whether threads have separate timers.
209 static void SetUpTestCase() {
210 timer_type_ = (getenv("CPUPROFILE_REALTIME") ? ITIMER_REAL : ITIMER_PROF);
211 signal_number_ = (getenv("CPUPROFILE_REALTIME") ? SIGALRM : SIGPROF);
212
213 timer_separate_ = threads_have_separate_timers();
214#if HAVE_LINUX_SIGEV_THREAD_ID
215 linux_per_thread_timers_mode_ = (getenv("CPUPROFILE_PER_THREAD_TIMERS") != NULL);
216 const char *signal_number = getenv("CPUPROFILE_TIMER_SIGNAL");
217 if (signal_number) {
218 signal_number_ = strtol(signal_number, NULL, 0);
219 linux_per_thread_timers_mode_ = true;
220 }
221#endif
222 Delay(kTimerResetInterval);
223 }
224
225 // Sets up the profile timers and SIGPROF/SIGALRM handler in a known state.
226 // It does the following:
227 // 1. Unregisters all the callbacks, stops the timer (if shared) and
228 // clears out timer_sharing state in the ProfileHandler. This clears
229 // out any state left behind by the previous test or during module
230 // initialization when the test program was started.
231 // 2. Spawns two threads which will be registered with the ProfileHandler.
232 // At this time ProfileHandler knows if the timers are shared.
233 // 3. Starts a busy worker thread to accumulate CPU usage.
234 virtual void SetUp() {
235 // Reset the state of ProfileHandler between each test. This unregisters
236 // all callbacks, stops timer (if shared) and clears timer sharing state.
237 ProfileHandlerReset();
238 EXPECT_EQ(0, GetCallbackCount());
239 VerifyDisabled();
240 // ProfileHandler requires at least two threads to be registerd to determine
241 // whether timers are shared.
242 RegisterThread();
243 RegisterThread();
244 // Now that two threads are started, verify that the signal handler is
245 // disabled and the timers are correctly enabled/disabled.
246 VerifyDisabled();
247 // Start worker to accumulate cpu usage.
248 StartWorker();
249 }
250
251 virtual void TearDown() {
252 ProfileHandlerReset();
253 // Stops the worker thread.
254 StopWorker();
255 }
256
257 // Starts a no-op thread that gets registered with the ProfileHandler. Waits
258 // for the thread to stop.
259 void RegisterThread() {
260 NullThread t;
261 t.SetJoinable(true);
262 t.Start();
263 t.Join();
264 }
265
266 // Starts a busy worker thread to accumulate cpu time. There should be only
267 // one busy worker running. This is required for the case where there are
268 // separate timers for each thread.
269 void StartWorker() {
270 busy_worker_ = new BusyThread();
271 busy_worker_->SetJoinable(true);
272 busy_worker_->Start();
273 // Wait for worker to start up and register with the ProfileHandler.
274 // TODO(nabeelmian) This may not work under very heavy load.
275 Delay(kSleepInterval);
276 }
277
278 // Stops the worker thread.
279 void StopWorker() {
280 busy_worker_->set_stop_work(true);
281 busy_worker_->Join();
282 delete busy_worker_;
283 }
284
285 // Checks whether SIGPROF/SIGALRM signal handler is enabled.
286 bool IsSignalEnabled() {
287 struct sigaction sa;
288 CHECK_EQ(sigaction(signal_number_, NULL, &sa), 0);
289 return ((sa.sa_handler == SIG_IGN) || (sa.sa_handler == SIG_DFL)) ?
290 false : true;
291 }
292
293 // Gets the number of callbacks registered with the ProfileHandler.
294 uint32 GetCallbackCount() {
295 ProfileHandlerState state;
296 ProfileHandlerGetState(&state);
297 return state.callback_count;
298 }
299
300 // Gets the current ProfileHandler interrupt count.
301 uint64 GetInterruptCount() {
302 ProfileHandlerState state;
303 ProfileHandlerGetState(&state);
304 return state.interrupts;
305 }
306
307 // Verifies that a callback is correctly registered and receiving
308 // profile ticks.
309 void VerifyRegistration(const int& tick_counter) {
310 // Check the callback count.
311 EXPECT_GT(GetCallbackCount(), 0);
312 // Check that the profile timer is enabled.
313 EXPECT_EQ(FLAGS_test_profiler_enabled, linux_per_thread_timers_mode_ || IsTimerEnabled());
314 // Check that the signal handler is enabled.
315 if (FLAGS_test_profiler_signal_handler) {
316 EXPECT_EQ(FLAGS_test_profiler_enabled, IsSignalEnabled());
317 }
318 uint64 interrupts_before = GetInterruptCount();
319 // Sleep for a bit and check that tick counter is making progress.
320 int old_tick_count = tick_counter;
321 Delay(kSleepInterval);
322 int new_tick_count = tick_counter;
323 uint64 interrupts_after = GetInterruptCount();
324 if (FLAGS_test_profiler_enabled) {
325 EXPECT_GT(new_tick_count, old_tick_count);
326 EXPECT_GT(interrupts_after, interrupts_before);
327 } else {
328 EXPECT_EQ(new_tick_count, old_tick_count);
329 EXPECT_EQ(interrupts_after, interrupts_before);
330 }
331 }
332
333 // Verifies that a callback is not receiving profile ticks.
334 void VerifyUnregistration(const int& tick_counter) {
335 // Sleep for a bit and check that tick counter is not making progress.
336 int old_tick_count = tick_counter;
337 Delay(kSleepInterval);
338 int new_tick_count = tick_counter;
339 EXPECT_EQ(old_tick_count, new_tick_count);
340 // If no callbacks, signal handler and shared timer should be disabled.
341 if (GetCallbackCount() == 0) {
342 if (FLAGS_test_profiler_signal_handler) {
343 EXPECT_FALSE(IsSignalEnabled());
344 }
345 if (!linux_per_thread_timers_mode_) {
346 if (timer_separate_) {
347 EXPECT_TRUE(IsTimerEnabled());
348 } else {
349 EXPECT_FALSE(IsTimerEnabled());
350 }
351 }
352 }
353 }
354
355 // Verifies that the SIGPROF/SIGALRM interrupt handler is disabled and the
356 // timer, if shared, is disabled. Expects the worker to be running.
357 void VerifyDisabled() {
358 // Check that the signal handler is disabled.
359 if (FLAGS_test_profiler_signal_handler) {
360 EXPECT_FALSE(IsSignalEnabled());
361 }
362 // Check that the callback count is 0.
363 EXPECT_EQ(0, GetCallbackCount());
364 // Check that the timer is disabled if shared, enabled otherwise.
365 if (!linux_per_thread_timers_mode_) {
366 if (timer_separate_) {
367 EXPECT_TRUE(IsTimerEnabled());
368 } else {
369 EXPECT_FALSE(IsTimerEnabled());
370 }
371 }
372 // Verify that the ProfileHandler is not accumulating profile ticks.
373 uint64 interrupts_before = GetInterruptCount();
374 Delay(kSleepInterval);
375 uint64 interrupts_after = GetInterruptCount();
376 EXPECT_EQ(interrupts_before, interrupts_after);
377 }
378
379 // Registers a callback and waits for kTimerResetInterval for timers to get
380 // reset.
381 ProfileHandlerToken* RegisterCallback(void* callback_arg) {
382 ProfileHandlerToken* token = ProfileHandlerRegisterCallback(
383 TickCounter, callback_arg);
384 Delay(kTimerResetInterval);
385 return token;
386 }
387
388 // Unregisters a callback and waits for kTimerResetInterval for timers to get
389 // reset.
390 void UnregisterCallback(ProfileHandlerToken* token) {
391 ProfileHandlerUnregisterCallback(token);
392 Delay(kTimerResetInterval);
393 }
394
395 // Busy worker thread to accumulate cpu usage.
396 BusyThread* busy_worker_;
397
398 private:
399 // The tests to run
400 void RegisterUnregisterCallback();
401 void MultipleCallbacks();
402 void Reset();
403 void RegisterCallbackBeforeThread();
404
405 public:
406#define RUN(test) do { \
407 printf("Running %s\n", #test); \
408 ProfileHandlerTest pht; \
409 pht.SetUp(); \
410 pht.test(); \
411 pht.TearDown(); \
412} while (0)
413
414 static int RUN_ALL_TESTS() {
415 SetUpTestCase();
416 RUN(RegisterUnregisterCallback);
417 RUN(MultipleCallbacks);
418 RUN(Reset);
419 RUN(RegisterCallbackBeforeThread);
420 printf("Done\n");
421 return 0;
422 }
423};
424
425// Verifies ProfileHandlerRegisterCallback and
426// ProfileHandlerUnregisterCallback.
427TEST_F(ProfileHandlerTest, RegisterUnregisterCallback) {
428 int tick_count = 0;
429 ProfileHandlerToken* token = RegisterCallback(&tick_count);
430 VerifyRegistration(tick_count);
431 UnregisterCallback(token);
432 VerifyUnregistration(tick_count);
433}
434
435// Verifies that multiple callbacks can be registered.
436TEST_F(ProfileHandlerTest, MultipleCallbacks) {
437 // Register first callback.
438 int first_tick_count;
439 ProfileHandlerToken* token1 = RegisterCallback(&first_tick_count);
440 // Check that callback was registered correctly.
441 VerifyRegistration(first_tick_count);
442 EXPECT_EQ(1, GetCallbackCount());
443
444 // Register second callback.
445 int second_tick_count;
446 ProfileHandlerToken* token2 = RegisterCallback(&second_tick_count);
447 // Check that callback was registered correctly.
448 VerifyRegistration(second_tick_count);
449 EXPECT_EQ(2, GetCallbackCount());
450
451 // Unregister first callback.
452 UnregisterCallback(token1);
453 VerifyUnregistration(first_tick_count);
454 EXPECT_EQ(1, GetCallbackCount());
455 // Verify that second callback is still registered.
456 VerifyRegistration(second_tick_count);
457
458 // Unregister second callback.
459 UnregisterCallback(token2);
460 VerifyUnregistration(second_tick_count);
461 EXPECT_EQ(0, GetCallbackCount());
462
463 // Verify that the signal handler and timers are correctly disabled.
464 VerifyDisabled();
465}
466
467// Verifies ProfileHandlerReset
468TEST_F(ProfileHandlerTest, Reset) {
469 // Verify that the profile timer interrupt is disabled.
470 VerifyDisabled();
471 int first_tick_count;
472 RegisterCallback(&first_tick_count);
473 VerifyRegistration(first_tick_count);
474 EXPECT_EQ(1, GetCallbackCount());
475
476 // Register second callback.
477 int second_tick_count;
478 RegisterCallback(&second_tick_count);
479 VerifyRegistration(second_tick_count);
480 EXPECT_EQ(2, GetCallbackCount());
481
482 // Reset the profile handler and verify that callback were correctly
483 // unregistered and timer/signal are disabled.
484 ProfileHandlerReset();
485 VerifyUnregistration(first_tick_count);
486 VerifyUnregistration(second_tick_count);
487 VerifyDisabled();
488}
489
490// Verifies that ProfileHandler correctly handles a case where a callback was
491// registered before the second thread started.
492TEST_F(ProfileHandlerTest, RegisterCallbackBeforeThread) {
493 // Stop the worker.
494 StopWorker();
495 // Unregister all existing callbacks, stop the timer (if shared), disable
496 // the signal handler and reset the timer sharing state in the Profile
497 // Handler.
498 ProfileHandlerReset();
499 EXPECT_EQ(0, GetCallbackCount());
500 VerifyDisabled();
501
502 // Start the worker. At this time ProfileHandler doesn't know if timers are
503 // shared as only one thread has registered so far.
504 StartWorker();
505 // Register a callback and check that profile ticks are being delivered.
506 int tick_count;
507 RegisterCallback(&tick_count);
508 EXPECT_EQ(1, GetCallbackCount());
509 VerifyRegistration(tick_count);
510
511 // Register a second thread and verify that timer and signal handler are
512 // correctly enabled.
513 RegisterThread();
514 EXPECT_EQ(1, GetCallbackCount());
515 EXPECT_EQ(FLAGS_test_profiler_enabled, linux_per_thread_timers_mode_ || IsTimerEnabled());
516 if (FLAGS_test_profiler_signal_handler) {
517 EXPECT_EQ(FLAGS_test_profiler_enabled, IsSignalEnabled());
518 }
519}
520
521} // namespace
522
523int main(int argc, char** argv) {
524 return ProfileHandlerTest::RUN_ALL_TESTS();
525}