/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
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
[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 \
(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;
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 \
--- /dev/null
+prereq: test -e ../../helgrind/tests/sem_clockwait_np
+vgopts: -q
+prog: ../../helgrind/tests/sem_clockwait_np
// 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)
{
#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
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;
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;
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;
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 \
check_PROGRAMS += getaddrinfo
endif
+if HAVE_SEM_CLOCKWAIT_NP
+check_PROGRAMS += sem_clockwait_np
+endif
+
if HAVE_SEM_TIMEDWAIT
check_PROGRAMS += sem_timedwait
endif
--- /dev/null
+// 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);
+}
--- /dev/null
+prereq: test -e ./sem_clockwait_np
+vgopts: -q
+prog: sem_clockwait_np