|
From: Tom H. <th...@cy...> - 2004-10-17 15:00:24
|
CVS commit by thughes:
Implement pthread_mutex_timedlock. This resolves bug 78422.
M +3 -2 core.h 1.37
M +36 -0 vg_libpthread.c 1.168
M +1 -1 vg_libpthread_unimp.c 1.49
M +49 -6 vg_scheduler.c 1.190
--- valgrind/coregrind/core.h #1.36:1.37
@@ -510,6 +510,7 @@ extern Bool VG_(is_empty_arena) ( Arena
#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
--- valgrind/coregrind/vg_libpthread.c #1.167:1.168
@@ -1348,4 +1348,39 @@ int __pthread_mutex_lock(pthread_mutex_t
+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)
{
@@ -3377,4 +3412,5 @@ int __libc_allocate_rtsig (int high)
------------------------------------------------------------------ */
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)
--- valgrind/coregrind/vg_libpthread_unimp.c #1.48:1.49
@@ -137,5 +137,5 @@ void pthread_getcpuclockid ( void ) { u
//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"); }
--- valgrind/coregrind/vg_scheduler.c #1.189:1.190
@@ -97,4 +97,5 @@ static Addr __libc_freeres_wrapper;
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 );
@@ -668,4 +669,8 @@ void idle ( void )
break;
+ case VgTs_WaitMX:
+ do_pthread_mutex_timedlock_TIMEOUT(tst->tid);
+ break;
+
case VgTs_WaitCV:
do_pthread_cond_timedwait_TIMEOUT(tst->tid);
@@ -767,4 +772,6 @@ VgSchedReturnCode do_scheduler ( Int* ex
if (VG_(threads)[tid_next].status == VgTs_Sleeping
|| VG_(threads)[tid_next].status == VgTs_WaitSys
+ || (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))
@@ -1886,4 +1893,27 @@ void do__apply_in_new_thread ( ThreadId
/* 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 )
@@ -1933,5 +1963,6 @@ 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];
@@ -1940,4 +1971,7 @@ void do_pthread_mutex_lock( ThreadId tid
: "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 );
@@ -1986,5 +2020,5 @@ 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) {
@@ -2015,4 +2049,7 @@ 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) {
@@ -2911,9 +2948,13 @@ void do_client_request ( ThreadId tid, U
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;
@@ -3219,4 +3260,5 @@ 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
@@ -3243,5 +3285,6 @@ void scheduler_sanity ( void )
/* 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) {
|