From 979b854b551b61ca623c2224ca8a367962a23bc0 Mon Sep 17 00:00:00 2001 From: Martin Brabham Date: Mon, 22 Apr 2019 09:33:25 -0700 Subject: [PATCH] Revert "Revert "DO NOT MERGE: osi: Offload mutex pointer to local scope"" This reverts commit f964b3c6817d0a400886bd103e5294bb929b7c3b. Bug: 117997080 Test: atest net_test_bluetooth --- osi/src/alarm.cc | 16 +++++++++++----- osi/test/alarm_test.cc | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/osi/src/alarm.cc b/osi/src/alarm.cc index ea075dbc1..bc1eee54b 100644 --- a/osi/src/alarm.cc +++ b/osi/src/alarm.cc @@ -91,7 +91,7 @@ struct alarm_t { // potentially long-running callback is executing. |alarm_cancel| uses this // mutex to provide a guarantee to its caller that the callback will not be // in progress when it returns. - std::recursive_mutex* callback_mutex; + std::shared_ptr callback_mutex; uint64_t creation_time_ms; uint64_t period_ms; uint64_t deadline_ms; @@ -174,7 +174,8 @@ static alarm_t* alarm_new_internal(const char* name, bool is_periodic) { alarm_t* ret = static_cast(osi_calloc(sizeof(alarm_t))); - ret->callback_mutex = new std::recursive_mutex; + std::shared_ptr ptr(new std::recursive_mutex()); + ret->callback_mutex = ptr; ret->is_periodic = is_periodic; ret->stats.name = osi_strdup(name); @@ -191,7 +192,7 @@ void alarm_free(alarm_t* alarm) { if (!alarm) return; alarm_cancel(alarm); - delete alarm->callback_mutex; + osi_free((void*)alarm->stats.name); alarm->closure.~CancelableClosureInStruct(); osi_free(alarm); @@ -245,13 +246,15 @@ void alarm_cancel(alarm_t* alarm) { CHECK(alarms != NULL); if (!alarm) return; + std::shared_ptr local_mutex_ref; { std::lock_guard lock(alarms_mutex); + local_mutex_ref = alarm->callback_mutex; alarm_cancel_internal(alarm); } // If the callback for |alarm| is in progress, wait here until it completes. - std::lock_guard lock(*alarm->callback_mutex); + std::lock_guard lock(*local_mutex_ref); } // Internal implementation of canceling an alarm. @@ -583,7 +586,10 @@ static void alarm_ready_generic(alarm_t* alarm, alarm->queue = NULL; } - std::lock_guard cb_lock(*alarm->callback_mutex); + // Increment the reference count of the mutex so it doesn't get freed + // before the callback gets finished executing. + std::shared_ptr local_mutex_ref = alarm->callback_mutex; + std::lock_guard cb_lock(*local_mutex_ref); lock.unlock(); // Update the statistics diff --git a/osi/test/alarm_test.cc b/osi/test/alarm_test.cc index 20fd7d67e..dad54ef4e 100644 --- a/osi/test/alarm_test.cc +++ b/osi/test/alarm_test.cc @@ -344,3 +344,17 @@ TEST_F(AlarmTest, test_callback_free_race) { } alarm_cleanup(); } + +static void remove_cb(void* data) { + alarm_free((alarm_t*)data); + semaphore_post(semaphore); +} + +TEST_F(AlarmTest, test_delete_during_callback) { + for (int i = 0; i < 1000; ++i) { + alarm_t* alarm = alarm_new("alarm_test.test_delete_during_callback"); + alarm_set(alarm, 0, remove_cb, alarm); + semaphore_wait(semaphore); + } + alarm_cleanup(); +} -- 2.11.0