#include "drd_clientreq.h"
#include "pub_tool_redir.h" /* VG_WRAP_FUNCTION_ZZ() */
+#if defined(VGO_freebsd)
+#include <dlfcn.h>
+#endif
+
#if defined(VGO_solaris)
/*
* Solaris usually provides pthread_* functions on top of Solaris threading
fflush(stdout); \
return pth_func_result; \
}
+#elif defined(VG_WRAP_THREAD_FUNCTION_LIBPTHREAD_ONLY)
+#define PTH_FUNC(ret_ty, zf, implf, argl_decl, argl) \
+ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl; \
+ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl \
+{ return implf argl; }
#elif defined(VG_WRAP_THREAD_FUNCTION_LIBC_ONLY)
#define PTH_FUNC(ret_ty, zf, implf, argl_decl, argl) \
ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBC_SONAME,zf) argl_decl; \
# error "Unknown platform/thread wrapping"
#endif
+#if defined(VGO_freebsd)
+#define LIBC_FUNC(ret_ty, zf, implf, argl_decl, argl) \
+ ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBC_SONAME,zf) argl_decl; \
+ ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBC_SONAME,zf) argl_decl \
+ { return implf argl; }
+#endif
+
/**
* Macro for generating three Valgrind interception functions: one with the
* Z-encoded name zf, one with ZAZa ("@*") appended to the name zf and one
*/
static void DRD_(init)(void)
{
+#if defined(VGO_freebsd)
+ {
+ /*
+ * On FreeBSD, pthead functions are all in libthr.so
+ * However libc.so contains stubs. In this ctor function,
+ * calling DRD_(set_pthread_id)() results in a call to
+ * pthread_self() resolving to the libc.so stub which
+ * returns a junk value for the tid. Subsequent calls
+ * to pthread_create() then also cause calls to
+ * DRD_(set_pthread_id)(), but this time with pthread_self()
+ * resolving to the good libthr.so version (since this is later
+ * and libthr.so has been loaded). That causes an assert
+ * since we expect the tid to either be INVALID_POSIX_THREADID
+ * or the same as the current tid, and the junk value
+ * is neither. So we force loading of libthr.so, which
+ * avoids this junk tid value.
+ */
+ dlclose(dlopen("/lib/libthr.so.3", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE));
+ }
+#endif
+
DRD_(check_threading_library)();
DRD_(set_pthread_id)();
#if defined(VGO_solaris)
return ret;
}
+#if defined(VGO_freebsd)
+LIBC_FUNC(int, semZuinit, sem_init_intercept,
+ (sem_t *sem, int pshared, unsigned int value), (sem, pshared, value));
+#else
PTH_FUNCS(int, semZuinit, sem_init_intercept,
(sem_t *sem, int pshared, unsigned int value), (sem, pshared, value));
+#endif
#if defined(VGO_solaris)
static __always_inline
return ret;
}
+#if defined(VGO_freebsd)
+LIBC_FUNC(int, semZudestroy, sem_destroy_intercept, (sem_t *sem), (sem));
+#else
PTH_FUNCS(int, semZudestroy, sem_destroy_intercept, (sem_t *sem), (sem));
+#endif
+
#if defined(VGO_solaris)
PTH_FUNCS(int, semaZudestroy, sem_destroy_intercept, (sem_t *sem), (sem));
#endif /* VGO_solaris */
return ret;
}
+#if defined(VGO_freebsd)
+LIBC_FUNC(sem_t *, semZuopen, sem_open_intercept,
+ (const char *name, int oflag, mode_t mode, unsigned int value),
+ (name, oflag, mode, value));
+#else
PTH_FUNCS(sem_t *, semZuopen, sem_open_intercept,
(const char *name, int oflag, mode_t mode, unsigned int value),
(name, oflag, mode, value));
+#endif
static __always_inline int sem_close_intercept(sem_t *sem)
{
return ret;
}
+#if defined(VGO_freebsd)
+LIBC_FUNC(int, semZuclose, sem_close_intercept, (sem_t *sem), (sem));
+#else
PTH_FUNCS(int, semZuclose, sem_close_intercept, (sem_t *sem), (sem));
+#endif
static __always_inline int sem_wait_intercept(sem_t *sem)
{
return ret;
}
+#if defined(VGO_freebsd)
+LIBC_FUNC(int, semZuwait, sem_wait_intercept, (sem_t *sem), (sem));
+#else
PTH_FUNCS(int, semZuwait, sem_wait_intercept, (sem_t *sem), (sem));
+#endif
+
#if defined(VGO_solaris)
PTH_FUNCS(int, semaZuwait, sem_wait_intercept, (sem_t *sem), (sem));
#endif /* VGO_solaris */
return ret;
}
+#if defined(VGO_freebsd)
+LIBC_FUNC(int, semZutrywait, sem_trywait_intercept, (sem_t *sem), (sem));
+#else
PTH_FUNCS(int, semZutrywait, sem_trywait_intercept, (sem_t *sem), (sem));
+#endif
#if defined(VGO_solaris)
PTH_FUNCS(int, semaZutrywait, sem_trywait_intercept, (sem_t *sem), (sem));
#endif /* VGO_solaris */
return ret;
}
+#if defined(VGO_freebsd)
+LIBC_FUNC(int, semZutimedwait, sem_timedwait_intercept,
+ (sem_t *sem, const struct timespec *abs_timeout),
+ (sem, abs_timeout));
+#else
PTH_FUNCS(int, semZutimedwait, sem_timedwait_intercept,
(sem_t *sem, const struct timespec *abs_timeout),
(sem, abs_timeout));
+#endif
#if defined(VGO_solaris)
PTH_FUNCS(int, semaZutimedwait, sem_timedwait_intercept,
(sem_t *sem, const struct timespec *timeout),
return ret;
}
+#if defined(VGO_freebsd)
+LIBC_FUNC(int, semZupost, sem_post_intercept, (sem_t *sem), (sem));
+#else
PTH_FUNCS(int, semZupost, sem_post_intercept, (sem_t *sem), (sem));
+#endif
#if defined(VGO_solaris)
PTH_FUNCS(int, semaZupost, sem_post_intercept, (sem_t *sem), (sem));
#endif /* VGO_solaris */