]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Implement pthread_mutex_timedlock. This resolves bug 78422.
authorTom Hughes <tom@compton.nu>
Sun, 17 Oct 2004 15:00:20 +0000 (15:00 +0000)
committerTom Hughes <tom@compton.nu>
Sun, 17 Oct 2004 15:00:20 +0000 (15:00 +0000)
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2780

coregrind/core.h
coregrind/vg_libpthread.c
coregrind/vg_libpthread_unimp.c
coregrind/vg_scheduler.c

index 89d93a8925ac7407bdab3a82a5cce5d8ea58410f..666eb2299b4d2161c9a8908271913d51e384da48 100644 (file)
@@ -509,8 +509,9 @@ extern Bool  VG_(is_empty_arena) ( ArenaId aid );
 /* Set/get detach state for this thread. */
 #define VG_USERREQ__SET_OR_GET_DETACH       0x3009
 
-#define VG_USERREQ__PTHREAD_GET_THREADID    0x300B
-#define VG_USERREQ__PTHREAD_MUTEX_LOCK      0x300C
+#define VG_USERREQ__PTHREAD_GET_THREADID    0x300A
+#define VG_USERREQ__PTHREAD_MUTEX_LOCK      0x300B
+#define VG_USERREQ__PTHREAD_MUTEX_TIMEDLOCK 0x300C
 #define VG_USERREQ__PTHREAD_MUTEX_TRYLOCK   0x300D
 #define VG_USERREQ__PTHREAD_MUTEX_UNLOCK    0x300E
 #define VG_USERREQ__PTHREAD_COND_WAIT       0x300F
index b16038055fe67e26aa79643dd31dee12f39b2122..df06d9cd5b605f66efcb5f194e7bdc67254c7ee4 100644 (file)
@@ -1347,6 +1347,41 @@ int __pthread_mutex_lock(pthread_mutex_t *mutex)
 }
 
 
+int __pthread_mutex_timedlock(pthread_mutex_t *mutex,
+                              const struct  timespec *abstime )
+{
+   int res;
+   unsigned int ms_now, ms_end;
+   struct  timeval timeval_now;
+   unsigned long long int ull_ms_now_after_1970;
+   unsigned long long int ull_ms_end_after_1970;
+   vg_pthread_mutex_t* vg_mutex;
+   CONVERT(mutex, mutex, vg_mutex);
+   
+   VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */,
+                           VG_USERREQ__READ_MILLISECOND_TIMER,
+                           0, 0, 0, 0);
+   my_assert(ms_now != 0xFFFFFFFF);
+   res = gettimeofday(&timeval_now, NULL);
+   my_assert(res == 0);
+
+   ull_ms_now_after_1970 
+      = 1000ULL * ((unsigned long long int)(timeval_now.tv_sec))
+        + ((unsigned long long int)(timeval_now.tv_usec / 1000));
+   ull_ms_end_after_1970
+      = 1000ULL * ((unsigned long long int)(abstime->tv_sec))
+        + ((unsigned long long int)(abstime->tv_nsec / 1000000));
+   if (ull_ms_end_after_1970 < ull_ms_now_after_1970)
+      ull_ms_end_after_1970 = ull_ms_now_after_1970;
+   ms_end 
+      = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
+   VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
+                           VG_USERREQ__PTHREAD_MUTEX_TIMEDLOCK,
+                           vg_mutex, ms_end, 0, 0);
+   return res;
+}
+
+
 int __pthread_mutex_trylock(pthread_mutex_t *mutex)
 {
    int res;
@@ -3376,6 +3411,7 @@ int __libc_allocate_rtsig (int high)
    B'stard.
    ------------------------------------------------------------------ */
 strong_alias(__pthread_mutex_lock, pthread_mutex_lock)
+strong_alias(__pthread_mutex_timedlock, pthread_mutex_timedlock)
 strong_alias(__pthread_mutex_trylock, pthread_mutex_trylock)
 strong_alias(__pthread_mutex_unlock, pthread_mutex_unlock)
 strong_alias(__pthread_mutexattr_init, pthread_mutexattr_init)
index a5fb0b3d83eedcb1413f11dbd46af6dad9ccd983..f40c57d9cff2616efbb1eea04f43b07af6d82f58 100644 (file)
@@ -136,7 +136,7 @@ void pthread_getcpuclockid ( void )  { unimp("pthread_getcpuclockid"); }
 //void pthread_mutex_destroy ( void )  { unimp("pthread_mutex_destroy"); }
 //void pthread_mutex_init ( void )  { unimp("pthread_mutex_init"); }
 //void pthread_mutex_lock ( void )  { unimp("pthread_mutex_lock"); }
-void pthread_mutex_timedlock ( void )  { unimp("pthread_mutex_timedlock"); }
+//void pthread_mutex_timedlock ( void )  { unimp("pthread_mutex_timedlock"); }
 //void pthread_mutex_trylock ( void )  { unimp("pthread_mutex_trylock"); }
 //void pthread_mutex_unlock ( void )  { unimp("pthread_mutex_unlock"); }
 //void pthread_mutexattr_destroy ( void )  { unimp("pthread_mutexattr_destroy"); }
index 5ce5bb3aa5263a88dceb455e7e77e6000caf327e..66d638f127c38e8307a4e9ad5ed3bd4d9aca59be 100644 (file)
@@ -96,6 +96,7 @@ static Addr __libc_freeres_wrapper;
 /* Forwards */
 static void do_client_request ( ThreadId tid, UInt* args );
 static void scheduler_sanity ( void );
+static void do_pthread_mutex_timedlock_TIMEOUT ( ThreadId tid );
 static void do_pthread_cond_timedwait_TIMEOUT ( ThreadId tid );
 static void maybe_rendezvous_joiners_and_joinees ( void );
 
@@ -667,6 +668,10 @@ void idle ( void )
               tst->status = VgTs_Runnable;
               break;
 
+           case VgTs_WaitMX:
+              do_pthread_mutex_timedlock_TIMEOUT(tst->tid);
+              break;
+
            case VgTs_WaitCV:
               do_pthread_cond_timedwait_TIMEOUT(tst->tid);
               break;
@@ -766,7 +771,9 @@ VgSchedReturnCode do_scheduler ( Int* exitcode, ThreadId* last_run_tid )
             if (tid_next >= VG_N_THREADS) tid_next = 1;
             if (VG_(threads)[tid_next].status == VgTs_Sleeping
                 || VG_(threads)[tid_next].status == VgTs_WaitSys
-                || (VG_(threads)[tid_next].status == VgTs_WaitCV 
+                || (VG_(threads)[tid_next].status == VgTs_WaitMX
+                    && VG_(threads)[tid_next].awaken_at != 0xFFFFFFFF)
+                || (VG_(threads)[tid_next].status == VgTs_WaitCV
                     && VG_(threads)[tid_next].awaken_at != 0xFFFFFFFF))
                n_in_bounded_wait ++;
            if (VG_(threads)[tid_next].status != VgTs_Empty)
@@ -1884,6 +1891,29 @@ void do__apply_in_new_thread ( ThreadId parent_tid,
 */
 
 /* Helper fns ... */
+static 
+void do_pthread_mutex_timedlock_TIMEOUT ( ThreadId tid )
+{
+   Char             msg_buf[100];
+   vg_pthread_mutex_t* mx;
+
+   vg_assert(VG_(is_valid_tid)(tid) 
+             && VG_(threads)[tid].status == VgTs_WaitMX
+             && VG_(threads)[tid].awaken_at != 0xFFFFFFFF);
+   mx = VG_(threads)[tid].associated_mx;
+   vg_assert(mx != NULL);
+
+   VG_(threads)[tid].status        = VgTs_Runnable;
+   SET_PTHREQ_RETVAL(tid, ETIMEDOUT);  /* pthread_mutex_lock return value */
+   VG_(threads)[tid].associated_mx = NULL;
+
+   if (VG_(clo_trace_pthread_level) >= 1) {
+      VG_(sprintf)(msg_buf, "pthread_mutex_timedlock  mx %p: TIMEOUT", mx);
+      print_pthread_event(tid, msg_buf);
+   }
+}
+
+
 static
 void release_one_thread_waiting_on_mutex ( vg_pthread_mutex_t* mutex, 
                                            Char* caller )
@@ -1932,13 +1962,17 @@ void release_one_thread_waiting_on_mutex ( vg_pthread_mutex_t* mutex,
 static
 void do_pthread_mutex_lock( ThreadId tid, 
                             Bool is_trylock, 
-                            vg_pthread_mutex_t* mutex )
+                            vg_pthread_mutex_t* mutex,
+                            UInt ms_end )
 {
    Char  msg_buf[100];
    Char* caller
       = is_trylock ? "pthread_mutex_trylock"
                    : "pthread_mutex_lock   ";
 
+   /* If ms_end == 0xFFFFFFFF, wait forever (no timeout).  Otherwise,
+      ms_end is the ending millisecond. */
+
    if (VG_(clo_trace_pthread_level) >= 2) {
       VG_(sprintf)(msg_buf, "%s    mx %p ...", caller, mutex );
       print_pthread_event(tid, msg_buf);
@@ -1985,7 +2019,7 @@ void do_pthread_mutex_lock( ThreadId tid,
       }         
 
       /* Someone has it already. */
-      if ((ThreadId)mutex->__vg_m_owner == tid) {
+      if ((ThreadId)mutex->__vg_m_owner == tid && ms_end == 0xFFFFFFFF) {
          /* It's locked -- by me! */
          if (mutex->__vg_m_kind == PTHREAD_MUTEX_RECURSIVE_NP) {
             /* return 0 (success). */
@@ -2014,6 +2048,9 @@ void do_pthread_mutex_lock( ThreadId tid,
 
             VG_(threads)[tid].status        = VgTs_WaitMX;
             VG_(threads)[tid].associated_mx = mutex;
+            VG_(threads)[tid].awaken_at     = ms_end;
+            if (ms_end != 0xFFFFFFFF)
+               add_timeout(tid, ms_end);
             SET_PTHREQ_RETVAL(tid, 0); /* pth_mx_lock success value */
             if (VG_(clo_trace_pthread_level) >= 1) {
                VG_(sprintf)(msg_buf, "%s    mx %p: BLOCK", 
@@ -2910,11 +2947,15 @@ void do_client_request ( ThreadId tid, UInt* arg )
       /* Some of these may make thread tid non-runnable, but the
          scheduler checks for that on return from this function. */
       case VG_USERREQ__PTHREAD_MUTEX_LOCK:
-         do_pthread_mutex_lock( tid, False, (void *)(arg[1]) );
+         do_pthread_mutex_lock( tid, False, (void *)(arg[1]), 0xFFFFFFFF );
+         break;
+
+      case VG_USERREQ__PTHREAD_MUTEX_TIMEDLOCK:
+         do_pthread_mutex_lock( tid, False, (void *)(arg[1]), arg[2] );
          break;
 
       case VG_USERREQ__PTHREAD_MUTEX_TRYLOCK:
-         do_pthread_mutex_lock( tid, True, (void *)(arg[1]) );
+         do_pthread_mutex_lock( tid, True, (void *)(arg[1]), 0xFFFFFFFF );
          break;
 
       case VG_USERREQ__PTHREAD_MUTEX_UNLOCK:
@@ -3218,6 +3259,7 @@ void scheduler_sanity ( void )
       */
       vg_assert(VG_(threads)[top->tid].awaken_at != top->time ||
                VG_(threads)[top->tid].status == VgTs_Sleeping ||
+               VG_(threads)[top->tid].status == VgTs_WaitMX ||
                VG_(threads)[top->tid].status == VgTs_WaitCV);
 #endif
 
@@ -3242,7 +3284,8 @@ void scheduler_sanity ( void )
          /* 1 */ vg_assert(mx != NULL);
         /* 2 */ vg_assert(mx->__vg_m_count > 0);
          /* 3 */ vg_assert(VG_(is_valid_tid)((ThreadId)mx->__vg_m_owner));
-         /* 4 */ vg_assert((UInt)i != (ThreadId)mx->__vg_m_owner); 
+         /* 4 */ vg_assert((UInt)i != (ThreadId)mx->__vg_m_owner ||
+                           VG_(threads)[i].awaken_at != 0xFFFFFFFF); 
       } else 
       if (VG_(threads)[i].status == VgTs_WaitCV) {
          vg_assert(cv != NULL);