Add pthread spinlock support.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@10775 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/helgrind/hg_main.c b/helgrind/hg_main.c
index e620262..e5ba438 100644
--- a/helgrind/hg_main.c
+++ b/helgrind/hg_main.c
@@ -2003,6 +2003,79 @@
 }
 
 
+/* ------------------------------------------------------- */
+/* -------------- events to do with mutexes -------------- */
+/* ------------------------------------------------------- */
+
+/* All a bit of a kludge.  Pretend we're really dealing with ordinary
+   pthread_mutex_t's instead, for the most part. */
+
+static void evh__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_PRE( ThreadId tid, 
+                                                     void* slock )
+{
+   Thread* thr;
+   Lock*   lk;
+   /* In glibc's kludgey world, we're either initialising or unlocking
+      it.  Since this is the pre-routine, if it is locked, unlock it
+      and take a dependence edge.  Otherwise, do nothing. */
+
+   if (SHOW_EVENTS >= 1)
+      VG_(printf)("evh__hg_PTHREAD_SPIN_INIT_OR_UNLOCK_PRE"
+                  "(ctid=%d, slock=%p)\n", 
+                  (Int)tid, (void*)slock );
+
+   thr = map_threads_maybe_lookup( tid );
+   /* cannot fail - Thread* must already exist */;
+   tl_assert( HG_(is_sane_Thread)(thr) );
+
+   lk = map_locks_maybe_lookup( (Addr)slock );
+   if (lk && lk->heldBy) {
+      /* it's held.  So do the normal pre-unlock actions, as copied
+         from evh__HG_PTHREAD_MUTEX_UNLOCK_PRE.  This stupidly
+         duplicates the map_locks_maybe_lookup. */
+      evhH__pre_thread_releases_lock( thr, (Addr)slock,
+                                           False/*!isRDWR*/ );
+   }
+}
+
+static void evh__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_POST( ThreadId tid, 
+                                                      void* slock )
+{
+   Lock* lk;
+   /* More kludgery.  If the lock has never been seen before, do
+      actions as per evh__HG_PTHREAD_MUTEX_INIT_POST.  Else do
+      nothing. */
+
+   if (SHOW_EVENTS >= 1)
+      VG_(printf)("evh__hg_PTHREAD_SPIN_INIT_OR_UNLOCK_POST"
+                  "(ctid=%d, slock=%p)\n", 
+                  (Int)tid, (void*)slock );
+
+   lk = map_locks_maybe_lookup( (Addr)slock );
+   if (!lk) {
+      map_locks_lookup_or_create( LK_nonRec, (Addr)slock, tid );
+   }
+}
+
+static void evh__HG_PTHREAD_SPIN_LOCK_PRE( ThreadId tid, 
+                                           void* slock, Word isTryLock )
+{
+   evh__HG_PTHREAD_MUTEX_LOCK_PRE( tid, slock, isTryLock );
+}
+
+static void evh__HG_PTHREAD_SPIN_LOCK_POST( ThreadId tid, 
+                                            void* slock )
+{
+   evh__HG_PTHREAD_MUTEX_LOCK_POST( tid, slock );
+}
+
+static void evh__HG_PTHREAD_SPIN_DESTROY_PRE( ThreadId tid, 
+                                              void* slock )
+{
+   evh__HG_PTHREAD_MUTEX_DESTROY_PRE( tid, slock );
+}
+
+
 /* ----------------------------------------------------- */
 /* --------------- events to do with CVs --------------- */
 /* ----------------------------------------------------- */
@@ -4144,6 +4217,31 @@
          evh__HG_PTHREAD_BARRIER_DESTROY_PRE( tid, (void*)args[1] );
          break;
 
+      case _VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_PRE:
+         /* pth_spinlock_t* */
+         evh__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_PRE( tid, (void*)args[1] );
+         break;
+
+      case _VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_POST:
+         /* pth_spinlock_t* */
+         evh__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_POST( tid, (void*)args[1] );
+         break;
+
+      case _VG_USERREQ__HG_PTHREAD_SPIN_LOCK_PRE:
+         /* pth_spinlock_t*, Word */
+         evh__HG_PTHREAD_SPIN_LOCK_PRE( tid, (void*)args[1], args[2] );
+         break;
+
+      case _VG_USERREQ__HG_PTHREAD_SPIN_LOCK_POST:
+         /* pth_spinlock_t* */
+         evh__HG_PTHREAD_SPIN_LOCK_POST( tid, (void*)args[1] );
+         break;
+
+      case _VG_USERREQ__HG_PTHREAD_SPIN_DESTROY_PRE:
+         /* pth_spinlock_t* */
+         evh__HG_PTHREAD_SPIN_DESTROY_PRE( tid, (void*)args[1] );
+         break;
+
       default:
          /* Unhandled Helgrind client request! */
          tl_assert2(0, "unhandled Helgrind client request 0x%lx",