Skip to content

Commit f76456b

Browse files
author
Andre Pereira Azevedo Pinto
committed
Add support for priority inheritance
Add support for posix mutex priority inheritance. This is important to avoid priority inversion in systems running with threads with different priorities. Signed-off-by: Andre Azevedo <[email protected]>
1 parent 8f13c17 commit f76456b

File tree

5 files changed

+47
-3
lines changed

5 files changed

+47
-3
lines changed

evthread_pthread.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,13 @@ struct event_base;
3939
#include "mm-internal.h"
4040
#include "evthread-internal.h"
4141

42+
static pthread_mutexattr_t attr_default;
4243
static pthread_mutexattr_t attr_recursive;
4344

4445
static void *
4546
evthread_posix_lock_alloc(unsigned locktype)
4647
{
47-
pthread_mutexattr_t *attr = NULL;
48+
pthread_mutexattr_t *attr = &attr_default;
4849
pthread_mutex_t *lock = mm_malloc(sizeof(pthread_mutex_t));
4950
if (!lock)
5051
return NULL;
@@ -161,7 +162,7 @@ evthread_posix_cond_wait(void *cond_, void *lock_, const struct timeval *tv)
161162
}
162163

163164
int
164-
evthread_use_pthreads(void)
165+
evthread_use_pthreads_with_flags(int flags)
165166
{
166167
struct evthread_lock_callbacks cbs = {
167168
EVTHREAD_LOCK_API_VERSION,
@@ -178,14 +179,32 @@ evthread_use_pthreads(void)
178179
evthread_posix_cond_signal,
179180
evthread_posix_cond_wait
180181
};
182+
183+
if (pthread_mutexattr_init(&attr_default))
184+
return -1;
185+
181186
/* Set ourselves up to get recursive locks. */
182187
if (pthread_mutexattr_init(&attr_recursive))
183188
return -1;
184189
if (pthread_mutexattr_settype(&attr_recursive, PTHREAD_MUTEX_RECURSIVE))
185190
return -1;
186191

192+
if (flags & EVTHREAD_PTHREAD_PRIO_INHERIT) {
193+
/* Set up priority inheritance */
194+
if (pthread_mutexattr_setprotocol(&attr_default, PTHREAD_PRIO_INHERIT))
195+
return -1;
196+
if (pthread_mutexattr_setprotocol(&attr_recursive, PTHREAD_PRIO_INHERIT))
197+
return -1;
198+
}
199+
187200
evthread_set_lock_callbacks(&cbs);
188201
evthread_set_condition_callbacks(&cond_cbs);
189202
evthread_set_id_callback(evthread_posix_get_id);
190203
return 0;
191204
}
205+
206+
int
207+
evthread_use_pthreads(void)
208+
{
209+
return evthread_use_pthreads_with_flags(0);
210+
}

include/event2/thread.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,21 @@ int evthread_use_windows_threads(void);
212212
@return 0 on success, -1 on failure. */
213213
EVENT2_EXPORT_SYMBOL
214214
int evthread_use_pthreads(void);
215+
216+
/* Enables posix mutex priority inheritance. */
217+
#define EVTHREAD_PTHREAD_PRIO_INHERIT 0x01
218+
219+
/**
220+
* Sets up Libevent for use with Pthreads locking and thread ID functions.
221+
* Use evthred_use_pthreads_with_flags() to use Pthreads locking, taking the
222+
* specified flags under consideration.
223+
*
224+
* @param flags the flags to apply when setting up Pthreads locking. @see EVTHREAD_PTHREAD_*
225+
* @return 0 on success, -1 on failure.
226+
**/
227+
EVENT2_EXPORT_SYMBOL
228+
int evthread_use_pthreads_with_flags(int flags);
229+
215230
/** Defined if Libevent was built with support for evthread_use_pthreads() */
216231
#define EVTHREAD_USE_PTHREADS_IMPLEMENTED 1
217232

test/regress.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ extern int libevent_tests_running_in_debug_mode;
9797
#define TT_ENABLE_IOCP_FLAG (TT_FIRST_USER_FLAG<<6)
9898
#define TT_ENABLE_IOCP (TT_ENABLE_IOCP_FLAG|TT_NEED_THREADS)
9999
#define TT_ENABLE_DEBUG_MODE (TT_ENABLE_IOCP_FLAG<<7)
100+
#define TT_ENABLE_PRIORITY_INHERITANCE (TT_ENABLE_IOCP_FLAG<<8)
100101

101102
/* All the flags that a legacy test needs. */
102103
#define TT_ISOLATED TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE

test/regress_main.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,12 @@ basic_test_setup(const struct testcase_t *testcase)
193193
evutil_socket_t spair[2] = { -1, -1 };
194194
struct basic_test_data *data = NULL;
195195

196+
#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED)
197+
int evthread_flags = 0;
198+
if (testcase->flags & TT_ENABLE_PRIORITY_INHERITANCE)
199+
evthread_flags |= EVTHREAD_PTHREAD_PRIO_INHERIT;
200+
#endif
201+
196202
#ifndef _WIN32
197203
if (testcase->flags & TT_ENABLE_IOCP_FLAG)
198204
return (void*)TT_SKIP;
@@ -208,7 +214,7 @@ basic_test_setup(const struct testcase_t *testcase)
208214
if (!(testcase->flags & TT_FORK))
209215
return NULL;
210216
#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED)
211-
if (evthread_use_pthreads())
217+
if (evthread_use_pthreads_with_flags(evthread_flags))
212218
exit(1);
213219
#elif defined(EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED)
214220
if (evthread_use_windows_threads())

test/regress_thread.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,9 @@ struct testcase_t thread_testcases[] = {
574574
#ifndef _WIN32
575575
{ "forking", thread_basic, TT_FORK|TT_NEED_THREADS|TT_NEED_BASE,
576576
&basic_setup, (char*)"forking" },
577+
{ "priority_inheritance", thread_basic,
578+
TT_FORK|TT_NEED_THREADS|TT_NEED_BASE|TT_ENABLE_PRIORITY_INHERITANCE,
579+
&basic_setup, (char*)"priority_inheritance" },
577580
#endif
578581
TEST(conditions_simple, TT_RETRIABLE),
579582
{ "deferred_cb_skew", thread_deferred_cb_skew,

0 commit comments

Comments
 (0)