diff options
author | Christopher Ferris <cferris@google.com> | 2014-10-22 19:43:44 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-10-22 19:43:44 +0000 |
commit | 9b7b0d82eb288f5d36f91c52a7bb91bc916fdcaf (patch) | |
tree | 5acb29690ce77e699285368d11881f5c9c5a75e4 /tests | |
parent | 702ab5b37e77684ee352300d32b078606ee388d0 (diff) | |
parent | 0724132c3263145f2a667f453a199d313a5b3d9f (diff) | |
download | bionic-9b7b0d82eb288f5d36f91c52a7bb91bc916fdcaf.zip bionic-9b7b0d82eb288f5d36f91c52a7bb91bc916fdcaf.tar.gz bionic-9b7b0d82eb288f5d36f91c52a7bb91bc916fdcaf.tar.bz2 |
Merge "Fix race condition in timer disarm/delete." into lmp-mr1-dev
Diffstat (limited to 'tests')
-rw-r--r-- | tests/time_test.cpp | 95 |
1 files changed, 79 insertions, 16 deletions
diff --git a/tests/time_test.cpp b/tests/time_test.cpp index 241c4a0..d637df2 100644 --- a/tests/time_test.cpp +++ b/tests/time_test.cpp @@ -205,22 +205,44 @@ struct Counter { volatile int value; timer_t timer_id; sigevent_t se; + bool timer_valid; - Counter(void (*fn)(sigval_t)) : value(0) { + Counter(void (*fn)(sigval_t)) : value(0), timer_valid(false) { memset(&se, 0, sizeof(se)); se.sigev_notify = SIGEV_THREAD; se.sigev_notify_function = fn; se.sigev_value.sival_ptr = this; + Create(); } void Create() { + ASSERT_FALSE(timer_valid); ASSERT_EQ(0, timer_create(CLOCK_REALTIME, &se, &timer_id)); + timer_valid = true; + } + + void DeleteTimer() { + ASSERT_TRUE(timer_valid); + ASSERT_EQ(0, timer_delete(timer_id)); + timer_valid = false; } ~Counter() { - if (timer_delete(timer_id) != 0) { - abort(); + if (timer_valid) { + DeleteTimer(); + } + } + + void SetTime(time_t value_s, time_t value_ns, time_t interval_s, time_t interval_ns) { + ::SetTime(timer_id, value_s, value_ns, interval_s, interval_ns); + } + + bool ValueUpdated() { + volatile int current_value = value; + time_t start = time(NULL); + while (current_value == value && (time(NULL) - start) < 5) { } + return current_value != value; } static void CountNotifyFunction(sigval_t value) { @@ -233,17 +255,17 @@ struct Counter { ++cd->value; // Setting the initial expiration time to 0 disarms the timer. - SetTime(cd->timer_id, 0, 0, 1, 0); + cd->SetTime(0, 0, 1, 0); } }; TEST(time, timer_settime_0) { Counter counter(Counter::CountAndDisarmNotifyFunction); - counter.Create(); + ASSERT_TRUE(counter.timer_valid); ASSERT_EQ(0, counter.value); - SetTime(counter.timer_id, 0, 1, 1, 0); + counter.SetTime(0, 1, 1, 0); usleep(500000); // The count should just be 1 because we disarmed the timer the first time it fired. @@ -252,15 +274,14 @@ TEST(time, timer_settime_0) { TEST(time, timer_settime_repeats) { Counter counter(Counter::CountNotifyFunction); - counter.Create(); + ASSERT_TRUE(counter.timer_valid); ASSERT_EQ(0, counter.value); - SetTime(counter.timer_id, 0, 1, 0, 10); - usleep(500000); - - // The count should just be > 1 because we let the timer repeat. - ASSERT_GT(counter.value, 1); + counter.SetTime(0, 1, 0, 10); + ASSERT_TRUE(counter.ValueUpdated()); + ASSERT_TRUE(counter.ValueUpdated()); + ASSERT_TRUE(counter.ValueUpdated()); } static int timer_create_NULL_signal_handler_invocation_count = 0; @@ -320,17 +341,17 @@ TEST(time, timer_delete_multiple) { TEST(time, timer_create_multiple) { Counter counter1(Counter::CountNotifyFunction); - counter1.Create(); + ASSERT_TRUE(counter1.timer_valid); Counter counter2(Counter::CountNotifyFunction); - counter2.Create(); + ASSERT_TRUE(counter2.timer_valid); Counter counter3(Counter::CountNotifyFunction); - counter3.Create(); + ASSERT_TRUE(counter3.timer_valid); ASSERT_EQ(0, counter1.value); ASSERT_EQ(0, counter2.value); ASSERT_EQ(0, counter3.value); - SetTime(counter2.timer_id, 0, 1, 0, 0); + counter2.SetTime(0, 1, 0, 0); usleep(500000); EXPECT_EQ(0, counter1.value); @@ -403,3 +424,45 @@ TEST(time, clock_gettime) { ASSERT_EQ(0, ts2.tv_sec); ASSERT_LT(ts2.tv_nsec, 1000000); } + +// Test to verify that disarming a repeatable timer disables the +// callbacks. +TEST(time, timer_disarm_terminates) { + Counter counter(Counter::CountNotifyFunction); + ASSERT_TRUE(counter.timer_valid); + + ASSERT_EQ(0, counter.value); + + counter.SetTime(0, 1, 0, 1); + ASSERT_TRUE(counter.ValueUpdated()); + ASSERT_TRUE(counter.ValueUpdated()); + ASSERT_TRUE(counter.ValueUpdated()); + + counter.SetTime(0, 0, 1, 0); + volatile int value = counter.value; + usleep(500000); + + // Verify the counter has not been incremented. + ASSERT_EQ(value, counter.value); +} + +// Test to verify that deleting a repeatable timer disables the +// callbacks. +TEST(time, timer_delete_terminates) { + Counter counter(Counter::CountNotifyFunction); + ASSERT_TRUE(counter.timer_valid); + + ASSERT_EQ(0, counter.value); + + counter.SetTime(0, 1, 0, 1); + ASSERT_TRUE(counter.ValueUpdated()); + ASSERT_TRUE(counter.ValueUpdated()); + ASSERT_TRUE(counter.ValueUpdated()); + + counter.DeleteTimer(); + volatile int value = counter.value; + usleep(500000); + + // Verify the counter has not been incremented. + ASSERT_EQ(value, counter.value); +} |