Module: sems Branch: 1.4 Commit: 4552965220fb56486f25e46e65dde214dd4f0b46 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sems/?a=commit;h=4552965220fb56486f25e46e65dde214dd4f0b46
Author: Raphael Coeffic <[email protected]> Committer: Raphael Coeffic <[email protected]> Date: Fri Mar 11 23:56:10 2011 +0100 b/f: race condition timers Fixes a race condition that caused a timer to be removed from the wheel before it has been inserted. --- core/sip/wheeltimer.cpp | 49 ++++++++++++++++++++-------------------------- core/sip/wheeltimer.h | 30 ++++++++++++++-------------- 2 files changed, 36 insertions(+), 43 deletions(-) diff --git a/core/sip/wheeltimer.cpp b/core/sip/wheeltimer.cpp index 0fee595..5f3a871 100644 --- a/core/sip/wheeltimer.cpp +++ b/core/sip/wheeltimer.cpp @@ -54,17 +54,17 @@ _wheeltimer::~_wheeltimer() void _wheeltimer::insert_timer(timer* t) { //add new timer to user request list - utimer_add_m.lock(); - utimer_add.push_back(t); - utimer_add_m.unlock(); + reqs_m.lock(); + reqs_backlog.push_back(timer_req(t,true)); + reqs_m.unlock(); } void _wheeltimer::remove_timer(timer* t) { //add timer to remove to user request list - utimer_rem_m.lock(); - utimer_rem.push_back(t); - utimer_rem_m.unlock(); + reqs_m.lock(); + reqs_backlog.push_back(timer_req(t,false)); + reqs_m.unlock(); } void _wheeltimer::run() @@ -144,28 +144,21 @@ void _wheeltimer::turn_wheel() // Update existing timer entries update_wheel(i); - // Check for timer insertion requests - utimer_add_m.lock(); - std::vector<timer*> utimer_add_cp = utimer_add; - utimer_add.clear(); - utimer_add_m.unlock(); - - for (std::vector<timer*>::iterator it= - utimer_add_cp.begin(); it != - utimer_add_cp.end(); it++) { - place_timer(*it); - } - - // Check for timer deletion requests - utimer_rem_m.lock(); - std::vector<timer*> utimer_rem_cp = utimer_rem; - utimer_rem.clear(); - utimer_rem_m.unlock(); - - for (std::vector<timer*>::iterator it= - utimer_rem_cp.begin(); it != - utimer_rem_cp.end(); it++) { - delete_timer(*it); + // Swap the lists for timer insertion/deletion requests + reqs_m.lock(); + reqs_process.swap(reqs_backlog); + reqs_m.unlock(); + + while(!reqs_process.empty()) { + timer_req rq = reqs_process.front(); + reqs_process.pop_front(); + + if(rq.insert) { + place_timer(rq.t); + } + else { + delete_timer(rq.t); + } } //check for expired timer to process diff --git a/core/sip/wheeltimer.h b/core/sip/wheeltimer.h index 6f1087b..879fc37 100644 --- a/core/sip/wheeltimer.h +++ b/core/sip/wheeltimer.h @@ -32,7 +32,7 @@ #include "../AmThread.h" -#include <queue> +#include <deque> #define BITS_PER_WHEEL 8 #define ELMTS_PER_WHEEL (1 << BITS_PER_WHEEL) @@ -88,23 +88,23 @@ public: class _wheeltimer: public AmThread { - //the timer wheel - base_timer wheels[WHEELS][ELMTS_PER_WHEEL]; - - // utimer remove lock - AmMutex utimer_add_m; + struct timer_req { - //list with timer insertions requests - std::vector<timer*> utimer_add; + timer* t; + bool insert; // false -> remove + + timer_req(timer* t, bool insert) + : t(t), insert(insert) + {} + }; - // utimer remove lock - AmMutex utimer_rem_m; - - //list with timer deletions requests - std::vector<timer*> utimer_rem; + //the timer wheel + base_timer wheels[WHEELS][ELMTS_PER_WHEEL]; - //list with expired timers - base_timer utimer_expired; + // request backlog lock (insert/remove) + AmMutex reqs_m; + std::deque<timer_req> reqs_backlog; + std::deque<timer_req> reqs_process; void turn_wheel(); void update_wheel(int wheel); _______________________________________________ Semsdev mailing list [email protected] http://lists.iptel.org/mailman/listinfo/semsdev
