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

Reply via email to