]> git.openfabrics.org - ~shefty/rdma-win.git/commitdiff
complib/user: fix timer race conditions
authorSean Hefty <sean.hefty@intel.com>
Thu, 24 Jun 2010 18:40:25 +0000 (11:40 -0700)
committerSean Hefty <sean.hefty@intel.com>
Thu, 24 Jun 2010 18:40:25 +0000 (11:40 -0700)
Signed-off-by: Sean Hefty <sean.hefty@intel.com>
trunk/core/complib/user/cl_timer.c
trunk/inc/user/complib/cl_timer_osd.h

index 4f2ce0fcbc67c5766b92d563cbc9fc6cd94f13ee..e2d581aab46998cbf38cc3f6825a32fddff5fdef 100644 (file)
 #include "complib/cl_timer.h"\r
 \r
 \r
+static HANDLE\r
+__clear_timer_handle(\r
+       IN      cl_timer_t* const p_timer )\r
+{\r
+       HANDLE timer;\r
+\r
+       EnterCriticalSection( &p_timer->lock );\r
+       timer = p_timer->h_timer;\r
+       p_timer->h_timer = NULL;\r
+       LeaveCriticalSection( &p_timer->lock );\r
+\r
+       return timer;\r
+}\r
+\r
 static void CALLBACK\r
 __timer_callback( \r
        IN cl_timer_t* const p_timer,\r
        IN BOOLEAN timer_signalled )\r
 {\r
-       /* timer_signalled is always TRUE, and has no value. */\r
-       CL_ASSERT( timer_signalled );\r
-       UNUSED_PARAM( timer_signalled );\r
+       UNUSED_PARAMETER( timer_signalled );\r
 \r
-       p_timer->timeout_time = 0;\r
-       p_timer->thread_id = GetCurrentThreadId();\r
+       if( !__clear_timer_handle( p_timer ))\r
+               return;\r
 \r
+       EnterCriticalSection( &p_timer->cb_lock );\r
        (p_timer->pfn_callback)( (void*)p_timer->context );\r
-\r
-       p_timer->thread_id = 0;\r
+       LeaveCriticalSection( &p_timer->cb_lock );\r
 }\r
 \r
 \r
@@ -56,9 +68,7 @@ void
 cl_timer_construct(\r
        IN      cl_timer_t* const       p_timer )\r
 {\r
-       p_timer->h_timer = NULL;\r
-       p_timer->timeout_time = 0;\r
-       p_timer->thread_id = 0;\r
+       memset(p_timer, 0, sizeof *p_timer);\r
 }\r
 \r
 \r
@@ -76,6 +86,12 @@ cl_timer_init(
 \r
        p_timer->pfn_callback = pfn_callback;\r
        p_timer->context = context;\r
+       p_timer->h_timer_queue = CreateTimerQueue();\r
+       if( !p_timer->h_timer_queue )\r
+               return CL_ERROR;\r
+\r
+       InitializeCriticalSection( &p_timer->lock );\r
+       InitializeCriticalSection( &p_timer->cb_lock );\r
        return( CL_SUCCESS );\r
 }\r
 \r
@@ -86,7 +102,12 @@ cl_timer_destroy(
 {\r
        CL_ASSERT( p_timer );\r
        \r
-       cl_timer_stop( p_timer );\r
+       if( p_timer->h_timer_queue )\r
+       {\r
+               DeleteTimerQueueEx( p_timer->h_timer_queue, INVALID_HANDLE_VALUE );\r
+               DeleteCriticalSection( &p_timer->lock );\r
+               DeleteCriticalSection( &p_timer->cb_lock );\r
+       }\r
 }\r
 \r
 \r
@@ -95,19 +116,7 @@ cl_timer_start(
        IN      cl_timer_t* const       p_timer,\r
        IN      const uint32_t          time_ms )\r
 {\r
-       CL_ASSERT( p_timer );\r
-\r
-       cl_timer_stop( p_timer );\r
-\r
-       p_timer->timeout_time = cl_get_time_stamp() + (((uint64_t)time_ms) * 1000);\r
-\r
-       if( !CreateTimerQueueTimer( &p_timer->h_timer, NULL, __timer_callback,\r
-               p_timer, time_ms, 0, WT_EXECUTEINIOTHREAD ) )\r
-       {\r
-               return( CL_ERROR );\r
-       }\r
-       \r
-       return( CL_SUCCESS );\r
+       return cl_timer_trim( p_timer, time_ms );\r
 }\r
 \r
 \r
@@ -116,19 +125,30 @@ cl_timer_trim(
        IN      cl_timer_t* const       p_timer,\r
        IN      const uint32_t          time_ms )\r
 {\r
-       uint64_t                timeout_time;\r
+       uint64_t        timeout;\r
+       cl_status_t     status = CL_SUCCESS;\r
 \r
        CL_ASSERT( p_timer );\r
        CL_ASSERT( p_timer->pfn_callback );\r
 \r
-       /* Calculate the timeout time in the timer object. */\r
-       timeout_time = cl_get_time_stamp() + (((uint64_t)time_ms) * 1000);\r
-\r
-       /* Only pull in the timeout time. */\r
-       if( p_timer->timeout_time && p_timer->timeout_time < timeout_time )\r
-               return( CL_SUCCESS );\r
+       timeout = cl_get_time_stamp() + (((uint64_t)time_ms) * 1000);\r
 \r
-       return cl_timer_start( p_timer, time_ms );\r
+       EnterCriticalSection( &p_timer->lock );\r
+       if ( !p_timer->h_timer || timeout < p_timer->timeout_time )\r
+       {\r
+               if( p_timer->h_timer )\r
+                       DeleteTimerQueueTimer( p_timer->timer_queue, timer, NULL );\r
+\r
+               p_timer->timeout_time = timeout;\r
+               if( !CreateTimerQueueTimer( &p_timer->h_timer, p_timer->h_timer_queue,\r
+                       __timer_callback, p_timer, time_ms, 0, WT_EXECUTEINIOTHREAD ) )\r
+               {\r
+                       p_timer->h_timer = NULL;\r
+                       status = CL_ERROR;\r
+               }\r
+       }\r
+       LeaveCriticalSection( &p_timer->lock );\r
+       return status;\r
 }\r
 \r
 \r
@@ -136,15 +156,14 @@ void
 cl_timer_stop(\r
        IN      cl_timer_t* const       p_timer )\r
 {\r
+       HANDLE timer;\r
+\r
        CL_ASSERT( p_timer );\r
 \r
-       if( p_timer->h_timer && p_timer->thread_id != GetCurrentThreadId() )\r
-       {\r
-               /* Make sure we block until the timer is cancelled. */\r
-               DeleteTimerQueueTimer( NULL, p_timer->h_timer, INVALID_HANDLE_VALUE );\r
-               p_timer->h_timer = NULL;\r
-       }\r
-       p_timer->timeout_time = 0;\r
+       timer = __clear_timer_handle( p_timer );\r
+\r
+       if( timer )\r
+               DeleteTimerQueueTimer( p_timer->timer_queue, timer, INVALID_HANDLE_VALUE );\r
 }\r
 \r
 \r
index 0a023ba60992bd11b5058f95ab61ba01aad87bdd..370a1755b8a0b556b7c57e76cfd73649d7a8d6d8 100644 (file)
 /* Timer object definition. */\r
 typedef struct _cl_timer\r
 {\r
+       HANDLE                                  h_timer_queue;\r
        HANDLE                                  h_timer;\r
        cl_pfn_timer_callback_t pfn_callback;\r
        const void                              *context;\r
        uint64_t                                timeout_time;\r
-       DWORD                                   thread_id;\r
+       CRITICAL_SECTION                lock;\r
+       CRITICAL_SECTION                cb_lock;\r
 \r
 } cl_timer_t;\r
 \r