#include "mm-internal.h"
#include "evthread-internal.h"
+static pthread_mutexattr_t attr_default;
static pthread_mutexattr_t attr_recursive;
static void *
evthread_posix_lock_alloc(unsigned locktype)
{
- pthread_mutexattr_t *attr = NULL;
+ pthread_mutexattr_t *attr = &attr_default;
pthread_mutex_t *lock = mm_malloc(sizeof(pthread_mutex_t));
if (!lock)
return NULL;
}
int
-evthread_use_pthreads(void)
+evthread_use_pthreads_with_flags(int flags)
{
struct evthread_lock_callbacks cbs = {
EVTHREAD_LOCK_API_VERSION,
evthread_posix_cond_signal,
evthread_posix_cond_wait
};
+
+ if (pthread_mutexattr_init(&attr_default))
+ return -1;
+
/* Set ourselves up to get recursive locks. */
if (pthread_mutexattr_init(&attr_recursive))
return -1;
if (pthread_mutexattr_settype(&attr_recursive, PTHREAD_MUTEX_RECURSIVE))
return -1;
+ if (flags & EVTHREAD_PTHREAD_PRIO_INHERIT) {
+ /* Set up priority inheritance */
+ if (pthread_mutexattr_setprotocol(&attr_default, PTHREAD_PRIO_INHERIT))
+ return -1;
+ if (pthread_mutexattr_setprotocol(&attr_recursive, PTHREAD_PRIO_INHERIT))
+ return -1;
+ }
+
evthread_set_lock_callbacks(&cbs);
evthread_set_condition_callbacks(&cond_cbs);
evthread_set_id_callback(evthread_posix_get_id);
return 0;
}
+
+int
+evthread_use_pthreads(void)
+{
+ return evthread_use_pthreads_with_flags(0);
+}
@return 0 on success, -1 on failure. */
EVENT2_EXPORT_SYMBOL
int evthread_use_pthreads(void);
+
+/* Enables posix mutex priority inheritance. */
+#define EVTHREAD_PTHREAD_PRIO_INHERIT 0x01
+
+/**
+ * Sets up Libevent for use with Pthreads locking and thread ID functions.
+ * Use evthred_use_pthreads_with_flags() to use Pthreads locking, taking the
+ * specified flags under consideration.
+ *
+ * @param flags the flags to apply when setting up Pthreads locking. @see EVTHREAD_PTHREAD_*
+ * @return 0 on success, -1 on failure.
+ **/
+EVENT2_EXPORT_SYMBOL
+int evthread_use_pthreads_with_flags(int flags);
+
/** Defined if Libevent was built with support for evthread_use_pthreads() */
#define EVTHREAD_USE_PTHREADS_IMPLEMENTED 1
#define TT_ENABLE_IOCP_FLAG (TT_FIRST_USER_FLAG<<6)
#define TT_ENABLE_IOCP (TT_ENABLE_IOCP_FLAG|TT_NEED_THREADS)
#define TT_ENABLE_DEBUG_MODE (TT_ENABLE_IOCP_FLAG<<7)
+#define TT_ENABLE_PRIORITY_INHERITANCE (TT_ENABLE_IOCP_FLAG<<8)
/* All the flags that a legacy test needs. */
#define TT_ISOLATED TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE
evutil_socket_t spair[2] = { -1, -1 };
struct basic_test_data *data = NULL;
+#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED)
+ int evthread_flags = 0;
+ if (testcase->flags & TT_ENABLE_PRIORITY_INHERITANCE)
+ evthread_flags |= EVTHREAD_PTHREAD_PRIO_INHERIT;
+#endif
+
#ifndef _WIN32
if (testcase->flags & TT_ENABLE_IOCP_FLAG)
return (void*)TT_SKIP;
if (!(testcase->flags & TT_FORK))
return NULL;
#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED)
- if (evthread_use_pthreads())
+ if (evthread_use_pthreads_with_flags(evthread_flags))
exit(1);
#elif defined(EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED)
if (evthread_use_windows_threads())
#ifndef _WIN32
{ "forking", thread_basic, TT_FORK|TT_NEED_THREADS|TT_NEED_BASE,
&basic_setup, (char*)"forking" },
+ { "priority_inheritance", thread_basic,
+ TT_FORK|TT_NEED_THREADS|TT_NEED_BASE|TT_ENABLE_PRIORITY_INHERITANCE,
+ &basic_setup, (char*)"priority_inheritance" },
#endif
TEST(conditions_simple, TT_RETRIABLE),
{ "deferred_cb_skew", thread_deferred_cb_skew,