]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
FreeBSD DRD and Helgrind: add sem_clockwait_np wrappers
authorPaul Floyd <pjfloyd@wanadoo.fr>
Sun, 31 Mar 2024 16:04:04 +0000 (18:04 +0200)
committerPaul Floyd <pjfloyd@wanadoo.fr>
Sun, 31 Mar 2024 16:04:04 +0000 (18:04 +0200)
Helgrind wrapper was complicated because sem_wait calls
sem_clockwait_np.

14 files changed:
.gitignore
configure.ac
drd/drd_pthread_intercepts.c
drd/tests/Makefile.am
drd/tests/sem_clockwait_np.stderr.exp [new file with mode: 0644]
drd/tests/sem_clockwait_np.stdout.exp [new file with mode: 0644]
drd/tests/sem_clockwait_np.vgtest [new file with mode: 0644]
helgrind/hg_intercepts.c
helgrind/hg_main.c
helgrind/tests/Makefile.am
helgrind/tests/sem_clockwait_np.c [new file with mode: 0644]
helgrind/tests/sem_clockwait_np.stderr.exp [new file with mode: 0644]
helgrind/tests/sem_clockwait_np.stdout.exp [new file with mode: 0644]
helgrind/tests/sem_clockwait_np.vgtest [new file with mode: 0644]

index 347be07dee1adff7915e4cbc40e176de3a6c3e57..abc693c825e1b8d089d293d72a401b4680ad6e56 100644 (file)
 /helgrind/tests/pth_mempcpy_false_races
 /helgrind/tests/rwlock_race
 /helgrind/tests/rwlock_test
+/helgrind/tests/sem_clockwait_np
 /helgrind/tests/sem_timedwait
 /helgrind/tests/shmem_abits
 /helgrind/tests/stackteardown
index e7bfe41854ae33ce2d348f7cc67ff915efca8e72..21ec7a07f17e2c82696c807b27e6ffe9abd93e04 100755 (executable)
@@ -4972,7 +4972,8 @@ AC_CHECK_FUNCS([     \
         free_aligned_sized \
         wcpncpy      \
         wcsxfrm      \
-        sem_timedwait
+        sem_timedwait \
+        sem_clockwait_np
         ])
 
 # AC_CHECK_LIB adds any library found to the variable LIBS, and links these
@@ -5018,6 +5019,8 @@ AM_CONDITIONAL([HAVE_WCSXFRM],
                [test x$ac_cv_func_wcsxfrm = xyes])
 AM_CONDITIONAL([HAVE_SEM_TIMEDWAIT],
                [test x$ac_cv_func_sem_timedwait = xyes])
+AM_CONDITIONAL([HAVE_SEM_CLOCKWAIT_NP],
+               [test x$ac_cv_func_sem_clockwait_np = xyes])
 
 if test x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX \
      -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX \
index f3077d626304acd32fc9b60eefb566c5f97d25b3..a4000b467ce4abee9c91272a01de7a5fdc318fdc 100644 (file)
@@ -1636,6 +1636,28 @@ PTH_FUNCS(int, semaZureltimedwait, sem_timedwait_intercept,
           (sem, timeout));
 #endif /* VGO_solaris */
 
+#if defined(VGO_freebsd)
+static __always_inline
+   int sem_clockwait_np_intercept(sem_t* sem, clockid_t clock_id, int flags,
+                                  const struct timespec * rqtp, struct timespec * rmtp)
+{
+   int   ret;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ_DRD_PRE_SEM_WAIT,
+                                   sem, 0, 0, 0, 0);
+   CALL_FN_W_5W(ret, fn, sem, clock_id, flags, rqtp, rmtp);
+   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ_DRD_POST_SEM_WAIT,
+                                   sem, ret == 0, 0, 0, 0);
+   return ret;
+}
+
+LIBC_FUNC(int, semZuclockwaitZunp, sem_clockwait_np_intercept,
+          (sem_t* sem, clockid_t clock_id, int flags,
+           const struct timespec * rqtp, struct timespec * rmtp),
+          (sem, clock_id, flags, rqtp, rmtp));
+#endif
+
 static __always_inline int sem_post_intercept(sem_t *sem)
 {
    int   ret;
index 13d94df3b2a95e66b64196af2d669ef7b0aa82b8..e12ab5fb2449a50e9c0c215ff6dc5b0e083786c3 100755 (executable)
@@ -269,6 +269,9 @@ EXTRA_DIST =                                        \
        sem_as_mutex3.stderr.exp-mips32-be          \
        sem_as_mutex3.stderr.exp-mips32-le          \
        sem_as_mutex3.vgtest                        \
+       sem_clockwait_np.stderr.exp                 \
+       sem_clockwait_np.stdout.exp                 \
+       sem_clockwait_np.vgtest                     \
        sem_open.stderr.exp                         \
        sem_open.stderr.exp-mips32-be               \
        sem_open.stderr.exp-mips32-le               \
diff --git a/drd/tests/sem_clockwait_np.stderr.exp b/drd/tests/sem_clockwait_np.stderr.exp
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/drd/tests/sem_clockwait_np.stdout.exp b/drd/tests/sem_clockwait_np.stdout.exp
new file mode 100644 (file)
index 0000000..1264c94
--- /dev/null
@@ -0,0 +1 @@
+Finished!
diff --git a/drd/tests/sem_clockwait_np.vgtest b/drd/tests/sem_clockwait_np.vgtest
new file mode 100644 (file)
index 0000000..9bfa750
--- /dev/null
@@ -0,0 +1,3 @@
+prereq: test -e ../../helgrind/tests/sem_clockwait_np
+vgopts: -q
+prog: ../../helgrind/tests/sem_clockwait_np
index 8f883e6af793119f97699cf6e01e6af08e9443cb..50bbc90b611482db53d97757a5aea836cc465144 100644 (file)
@@ -3263,8 +3263,9 @@ PTH_FUNC(int, semaZutrywait, sem_t *sem) { /* sema_trywait */
 // Solaris: sema_timedwait (sem_timedwait is built on top of sema_timedwait)
 // FreeBSD: sem_timedwait (libc)
 //
-/* trywait: decrement semaphore if non-zero otherwise return error */
 #if !defined(VGO_darwin)
+/* timedwait: decrement semaphore if non-zero otherwise wait for specified
+   time then return an error */
 __attribute__((noinline))
 static int sem_timedwait_WRK(sem_t* sem, const struct timespec* abs_timeout)
 {
@@ -3316,6 +3317,53 @@ PTH_FUNC(int, semaZutimedwait, sem_t *sem, const struct timespec* abs_timeout) {
 #endif
 #endif // not VGO_darwin
 
+//-----------------------------------------------------------
+// glibc:   does not exist
+// darwin:  does not exist
+// Solaris: does not exist
+// FreeBSD: sem_clockwait_np (libc)
+//
+/* clockwait_np: decrement semaphore if non-zero otherwise wait for specified
+   time then return an error with a flag to select the kind of clock and
+   a timespec for the remaining time */
+#if defined (VGO_freebsd)
+__attribute__((noinline))
+static int sem_clockwait_np_WRK(sem_t* sem, clockid_t clock_id, int flags,
+                                const struct timespec * rqtp, struct timespec * rmtp)
+{
+   OrigFn fn;
+   int    ret;
+   VALGRIND_GET_ORIG_FN(fn);
+
+   if (TRACE_SEM_FNS) {
+      fprintf(stderr, "<< sem_clockwait_np(%p, %d, %d, %p, %p) ", sem, clock_id, flags, rqtp, rmtp);
+      fflush(stderr);
+   }
+
+   DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_WAIT_PRE, sem_t*,sem);
+
+   CALL_FN_W_5W(ret, fn, sem, clock_id, flags, rqtp, rmtp);
+
+   DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_WAIT_POST, sem_t*,sem,
+                long, (ret == 0) ? True : False);
+
+   if (ret != 0) {
+      DO_PthAPIerror( "sem_clockwait_np", SEM_ERROR );
+   }
+
+   if (TRACE_SEM_FNS) {
+      fprintf(stderr, " sem_clockwait_np -> %d >>\n", ret);
+      fflush(stderr);
+   }
+
+   return ret;
+}
+
+LIBC_FUNC(int, semZuclockwaitZunp, sem_t* sem, clockid_t clock_id, int flags,
+          const struct timespec * rqtp, struct timespec * rmtp) { /* sem_clockwait_np */
+   return sem_clockwait_np_WRK(sem, clock_id, flags, rqtp, rmtp);
+}
+#endif
 
 //-----------------------------------------------------------
 // glibc:   sem_post
index 3146cc4373a78ff564a279c0df1f27c5a9f6b794..3ac5d6bc8a30721f0c86a0f8d8b4b9f3f5f08f6d 100644 (file)
@@ -715,18 +715,25 @@ static void map_threads_delete ( ThreadId coretid )
 
 static void HG_(thread_enter_synchr)(Thread *thr) {
    tl_assert(thr->synchr_nesting >= 0);
-#if defined(VGO_solaris)
+#if defined(VGO_solaris) || defined(VGO_freebsd)
    thr->synchr_nesting += 1;
 #endif /* VGO_solaris */
 }
 
 static void HG_(thread_leave_synchr)(Thread *thr) {
-#if defined(VGO_solaris)
+#if defined(VGO_solaris) || defined(VGO_freebsd)
    thr->synchr_nesting -= 1;
 #endif /* VGO_solaris */
    tl_assert(thr->synchr_nesting >= 0);
 }
 
+#if defined(VGO_freebsd)
+static Int HG_(get_pthread_synchr_nesting_level)(ThreadId tid) {
+   Thread *thr = map_threads_maybe_lookup(tid);
+   return thr->synchr_nesting;
+}
+#endif
+
 static void HG_(thread_enter_pthread_create)(Thread *thr) {
    tl_assert(thr->pthread_create_nesting_level >= 0);
    thr->pthread_create_nesting_level += 1;
@@ -5373,6 +5380,11 @@ Bool hg_handle_client_request ( ThreadId tid, UWord* args, UWord* ret)
          map_pthread_t_to_Thread_INIT();
          my_thr = map_threads_maybe_lookup( tid );
          tl_assert(my_thr); /* See justification above in SET_MY_PTHREAD_T */
+#if defined(VGO_freebsd)
+         if (HG_(get_pthread_synchr_nesting_level)(tid) >= 1) {
+            break;
+         }
+#endif
          HG_(record_error_PthAPIerror)(
             my_thr, (HChar*)args[1], (UWord)args[2], (HChar*)args[3] );
          break;
@@ -5603,8 +5615,13 @@ Bool hg_handle_client_request ( ThreadId tid, UWord* args, UWord* ret)
          break;
 
       case _VG_USERREQ__HG_POSIX_SEM_WAIT_POST: /* sem_t*, long tookLock */
+#if defined(VGO_freebsd)
+      if (args[2] == True && HG_(get_pthread_synchr_nesting_level)(tid) == 1)
+         evh__HG_POSIX_SEM_WAIT_POST( tid, (void*)args[1] );
+#else
          if (args[2] == True)
             evh__HG_POSIX_SEM_WAIT_POST( tid, (void*)args[1] );
+#endif
          HG_(thread_leave_synchr)(map_threads_maybe_lookup(tid));
          break;
 
index 927e11116c1ee9ae2fa156a62f2f3051b7af251e..0f2a5ef8580d93f1da5ffff9dae936c02b52e881 100755 (executable)
@@ -72,6 +72,8 @@ EXTRA_DIST = \
        pth_spinlock.vgtest pth_spinlock.stdout.exp pth_spinlock.stderr.exp \
        rwlock_race.vgtest rwlock_race.stdout.exp rwlock_race.stderr.exp \
        rwlock_test.vgtest rwlock_test.stdout.exp rwlock_test.stderr.exp \
+       sem_clockwait_np.vgtest sem_clockwait_np.stdout.exp \
+               sem_clockwait_np.stderr.exp \
        sem_timedwait.vgtest sem_timedwait.stdout.exp sem_timedwait.stderr.exp \
        shared_timed_mutex.vgtest shared_timed_mutex.stderr.exp \
        shmem_abits.vgtest shmem_abits.stdout.exp shmem_abits.stderr.exp \
@@ -247,6 +249,10 @@ if HAVE_GETADDRINFO
 check_PROGRAMS += getaddrinfo
 endif
 
+if HAVE_SEM_CLOCKWAIT_NP
+check_PROGRAMS += sem_clockwait_np
+endif
+
 if HAVE_SEM_TIMEDWAIT
 check_PROGRAMS += sem_timedwait
 endif
diff --git a/helgrind/tests/sem_clockwait_np.c b/helgrind/tests/sem_clockwait_np.c
new file mode 100644 (file)
index 0000000..65dbb8d
--- /dev/null
@@ -0,0 +1,36 @@
+// this is a variation of bug484480.c using sem_clockwait_np
+
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+
+static char* result;
+static sem_t sem;
+
+static void* func(void* data)
+{
+   result = "Finished!";
+   sem_post(&sem);
+   return NULL;
+}
+
+int main(void)
+{
+   sem_init(&sem, 0, 0);
+
+   pthread_t tid;
+   pthread_create(&tid, NULL, func, NULL);
+
+   struct timespec ts = {0, 100000};
+   struct timespec ts_remain;
+
+   while (sem_clockwait_np(&sem, CLOCK_REALTIME, 0, &ts, &ts_remain))
+      ; // do nothing but keep retrying
+
+   printf("%s\n", result);
+
+   pthread_join(tid, NULL);
+}
diff --git a/helgrind/tests/sem_clockwait_np.stderr.exp b/helgrind/tests/sem_clockwait_np.stderr.exp
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/helgrind/tests/sem_clockwait_np.stdout.exp b/helgrind/tests/sem_clockwait_np.stdout.exp
new file mode 100644 (file)
index 0000000..1264c94
--- /dev/null
@@ -0,0 +1 @@
+Finished!
diff --git a/helgrind/tests/sem_clockwait_np.vgtest b/helgrind/tests/sem_clockwait_np.vgtest
new file mode 100644 (file)
index 0000000..d66be46
--- /dev/null
@@ -0,0 +1,3 @@
+prereq: test -e ./sem_clockwait_np
+vgopts: -q
+prog: sem_clockwait_np