lib/mutex: introduce compact creation calls

Normal (i.e. non-recursive) mutexes timed on the monotonic clock are
the most common form of locks used by applications. Allow people to
write more compact code by providing creation calls and static
initializers aimed at building these directly:

- evl_new_mutex(), EVL_MUTEX_INITIALIZER() for PI locks timed on the
  monotonic clock.

- evl_new_mutex_any() and EVL_MUTEX_ANY_INITIALIZER() for building any
  supported type of lock (normal/recursive), specifying the protocol
  (PI/PP) and the base clock.
This commit is contained in:
Philippe Gerum 2019-08-18 19:20:21 +02:00
parent a6044094db
commit bdc3aab501
15 changed files with 62 additions and 97 deletions

View File

@ -55,7 +55,13 @@ static int create_mutex(struct evl_mutex *mutex, int type,
protocol = PTHREAD_PRIO_PROTECT;
pthread_mutexattr_setprioceiling(&attr, ceiling);
}
pthread_mutexattr_setprotocol(&attr, protocol);
ret = pthread_mutexattr_setprotocol(&attr, protocol);
if (ret) {
pthread_mutexattr_destroy(&attr);
close(fd);
return -ret;
}
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE);
ret = pthread_mutex_init(&mutex->active.mutex, &attr);
pthread_mutexattr_destroy(&attr);
@ -70,14 +76,7 @@ static int create_mutex(struct evl_mutex *mutex, int type,
return 0;
}
int evl_new_mutex(struct evl_mutex *mutex, int type,
int clockfd, const char *fmt, ...)
{
return create_mutex(mutex, type, clockfd, 0) ?:
mutex->active.fd;
}
int evl_new_mutex_ceiling(struct evl_mutex *mutex, int type,
int evl_new_mutex_any(struct evl_mutex *mutex, int type,
int clockfd, unsigned int ceiling,
const char *fmt, ...)
{

View File

@ -34,17 +34,7 @@ struct evl_mutex {
};
};
#define EVL_MUTEX_INITIALIZER(__name, __clockfd, __type) { \
.magic = __MUTEX_UNINIT_MAGIC, \
.uninit = { \
.name = (__name), \
.clockfd = (__clockfd), \
.ceiling = 0, \
.type = (__type), \
} \
}
#define EVL_MUTEX_CEILING_INITIALIZER(__name, __clockfd, __ceiling, __type) { \
#define EVL_MUTEX_ANY_INITIALIZER(__type, __name, __clockfd, __ceiling) { \
.magic = __MUTEX_UNINIT_MAGIC, \
.uninit = { \
.name = (__name), \
@ -54,17 +44,22 @@ struct evl_mutex {
} \
}
#define EVL_MUTEX_INITIALIZER(__name) \
EVL_MUTEX_ANY_INITIALIZER(EVL_MUTEX_NORMAL, __name, \
EVL_CLOCK_MONOTONIC, 0)
#ifdef __cplusplus
extern "C" {
#endif
int evl_new_mutex(struct evl_mutex *mutex, int type,
int clockfd, const char *fmt, ...);
int evl_new_mutex_ceiling(struct evl_mutex *mutex, int type,
int evl_new_mutex_any(struct evl_mutex *mutex, int type,
int clockfd, unsigned int ceiling,
const char *fmt, ...);
#define evl_new_mutex(__mutex, __fmt, __args...) \
evl_new_mutex_any(__mutex, EVL_MUTEX_NORMAL, \
EVL_CLOCK_MONOTONIC, 0, __fmt, ##__args)
int evl_lock_mutex(struct evl_mutex *mutex);
int evl_timedlock_mutex(struct evl_mutex *mutex,

View File

@ -34,29 +34,15 @@ struct evl_mutex {
int clockfd;
unsigned int ceiling;
int monitor : 2,
protocol : 4,
type : 1;
} uninit;
};
};
#define EVL_MUTEX_INITIALIZER(__type, __name, __clockfd) { \
#define EVL_MUTEX_ANY_INITIALIZER(__type, __name, __clockfd, __ceiling) { \
.magic = __MUTEX_UNINIT_MAGIC, \
.uninit = { \
.monitor = EVL_MONITOR_GATE, \
.protocol = EVL_GATE_PI, \
.type = (__type), \
.name = (__name), \
.clockfd = (__clockfd), \
.ceiling = 0, \
} \
}
#define EVL_MUTEX_CEILING_INITIALIZER(__type, __name, __clockfd, __ceiling) { \
.magic = __MUTEX_UNINIT_MAGIC, \
.uninit = { \
.monitor = EVL_MONITOR_GATE, \
.protocol = EVL_GATE_PP, \
.type = (__type), \
.name = (__name), \
.clockfd = (__clockfd), \
@ -64,17 +50,22 @@ struct evl_mutex {
} \
}
#define EVL_MUTEX_INITIALIZER(__name) \
EVL_MUTEX_ANY_INITIALIZER(EVL_MUTEX_NORMAL, __name, \
EVL_CLOCK_MONOTONIC, 0)
#ifdef __cplusplus
extern "C" {
#endif
int evl_new_mutex(struct evl_mutex *mutex, int type,
int clockfd, const char *fmt, ...);
int evl_new_mutex_ceiling(struct evl_mutex *mutex, int type,
int evl_new_mutex_any(struct evl_mutex *mutex, int type,
int clockfd, unsigned int ceiling,
const char *fmt, ...);
#define evl_new_mutex(__mutex, __fmt, __args...) \
evl_new_mutex_any(__mutex, EVL_MUTEX_NORMAL, \
EVL_CLOCK_MONOTONIC, 0, __fmt, ##__args)
int evl_open_mutex(struct evl_mutex *mutex,
const char *fmt, ...);

View File

@ -1249,8 +1249,7 @@ int evl_init_heap(struct evl_heap *heap, void *mem, size_t size)
list_init(&heap->extents);
ret = evl_new_mutex(&heap->lock, EVL_MUTEX_NORMAL,
EVL_CLOCK_MONOTONIC, "heap:%.3d",
ret = evl_new_mutex(&heap->lock, "heap:%.3d",
atomic_add_return(&heap_serial, 1));
if (ret < 0)
return ret;

View File

@ -54,7 +54,7 @@ static int init_mutex_vargs(struct evl_mutex *mutex,
*/
if (protocol == EVL_GATE_PP) {
ret = sched_get_priority_max(SCHED_FIFO);
if (ret < 0 || ceiling > ret)
if (ret < 0 || ceiling == 0 || ceiling > ret)
return -EINVAL;
}
@ -83,12 +83,12 @@ static int init_mutex_vargs(struct evl_mutex *mutex,
return efd;
}
static int init_mutex(struct evl_mutex *mutex,
int type, int protocol, int clockfd,
unsigned int ceiling, const char *fmt, ...)
static int init_mutex_static(struct evl_mutex *mutex,
int type, int clockfd, unsigned int ceiling,
const char *fmt, ...)
{
int efd, protocol = ceiling ? EVL_GATE_PP : EVL_GATE_PI;
va_list ap;
int efd;
va_start(ap, fmt);
efd = init_mutex_vargs(mutex, type, protocol, clockfd,
@ -133,29 +133,16 @@ fail:
return ret;
}
int evl_new_mutex(struct evl_mutex *mutex, int type,
int clockfd, const char *fmt, ...)
{
va_list ap;
int efd;
va_start(ap, fmt);
efd = init_mutex_vargs(mutex, type, EVL_GATE_PI,
clockfd, 0, fmt, ap);
va_end(ap);
return efd;
}
int evl_new_mutex_ceiling(struct evl_mutex *mutex, int type,
int evl_new_mutex_any(struct evl_mutex *mutex, int type,
int clockfd, unsigned int ceiling,
const char *fmt, ...)
{
int efd, protocol;
va_list ap;
int efd;
protocol = ceiling ? EVL_GATE_PP : EVL_GATE_PI;
va_start(ap, fmt);
efd = init_mutex_vargs(mutex, type, EVL_GATE_PP,
efd = init_mutex_vargs(mutex, type, protocol,
clockfd, ceiling, fmt, ap);
va_end(ap);
@ -210,9 +197,8 @@ static int try_lock(struct evl_mutex *mutex)
if (mutex->magic == __MUTEX_UNINIT_MAGIC &&
mutex->uninit.monitor == EVL_MONITOR_GATE) {
ret = init_mutex(mutex,
ret = init_mutex_static(mutex,
mutex->uninit.type,
mutex->uninit.protocol,
mutex->uninit.clockfd,
mutex->uninit.ceiling,
mutex->uninit.name);
@ -379,7 +365,7 @@ int evl_set_mutex_ceiling(struct evl_mutex *mutex,
if (mutex->magic == __MUTEX_UNINIT_MAGIC) {
if (mutex->uninit.monitor != EVL_MONITOR_GATE ||
mutex->uninit.protocol != EVL_GATE_PP)
mutex->uninit.ceiling == 0)
return -EINVAL;
mutex->uninit.ceiling = ceiling;
return 0;
@ -400,7 +386,7 @@ int evl_get_mutex_ceiling(struct evl_mutex *mutex)
{
if (mutex->magic == __MUTEX_UNINIT_MAGIC) {
if (mutex->uninit.monitor != EVL_MONITOR_GATE ||
mutex->uninit.protocol != EVL_GATE_PP)
mutex->uninit.ceiling == 0)
return -EINVAL;
return mutex->uninit.ceiling;

View File

@ -111,8 +111,7 @@ int main(int argc, char *argv[])
__Tcall_assert(evfd, evl_new_event(&c.event, EVL_CLOCK_MONOTONIC, name));
name = get_unique_name(EVL_MONITOR_DEV, 3);
__Tcall_assert(mfd, evl_new_mutex(&c.lock, EVL_MUTEX_NORMAL,
EVL_CLOCK_MONOTONIC, name));
__Tcall_assert(mfd, evl_new_mutex(&c.lock, name));
new_thread(&receiver, SCHED_FIFO, LOW_PRIO, event_receiver, &c);

View File

@ -72,8 +72,7 @@ int main(int argc, char *argv[])
__Tcall_assert(tfd, evl_attach_self("monitor-pi:%d", getpid()));
name = get_unique_name(EVL_MONITOR_DEV, 0);
__Tcall_assert(gfd, evl_new_mutex(&c.lock, EVL_MUTEX_NORMAL,
EVL_CLOCK_MONOTONIC, name));
__Tcall_assert(gfd, evl_new_mutex(&c.lock, name));
name = get_unique_name(EVL_MONITOR_DEV, 1);
__Tcall_assert(sfd, evl_new_sem(&c.sem, EVL_CLOCK_MONOTONIC, 0, name));

View File

@ -43,9 +43,8 @@ int main(int argc, char *argv[])
__Tcall_assert(tfd, evl_attach_self("monitor-pp-dynamic:%d", getpid()));
name = get_unique_name(EVL_MONITOR_DEV, 0);
__Tcall_assert(gfd, evl_new_mutex_ceiling(&lock, EVL_MUTEX_NORMAL,
EVL_CLOCK_MONOTONIC,
LOW_PRIO, name));
__Tcall_assert(gfd, evl_new_mutex_any(&lock, EVL_MUTEX_NORMAL,
EVL_CLOCK_MONOTONIC, LOW_PRIO, name));
__Tcall_assert(ret, evl_lock_mutex(&lock));
/* Commit PP boost, no priority change expected. */
__Tcall_assert(ret, evl_udelay(1000));

View File

@ -43,7 +43,7 @@ int main(int argc, char *argv[])
__Tcall_assert(tfd, evl_attach_self("monitor-pp-lower:%d", getpid()));
name = get_unique_name(EVL_MONITOR_DEV, 0);
__Tcall_assert(gfd, evl_new_mutex_ceiling(&lock, EVL_MUTEX_NORMAL,
__Tcall_assert(gfd, evl_new_mutex_any(&lock, EVL_MUTEX_NORMAL,
EVL_CLOCK_MONOTONIC, LOW_PRIO, name));
__Tcall_assert(ret, evl_lock_mutex(&lock));
/* Commit PP, no priority change expected. */

View File

@ -44,11 +44,11 @@ int main(int argc, char *argv[])
__Tcall_assert(tfd, evl_attach_self("monitor-pp-nested:%d", getpid()));
name = get_unique_name(EVL_MONITOR_DEV, 0);
__Tcall_assert(gfd, evl_new_mutex_ceiling(&lock_medium, EVL_MUTEX_NORMAL,
__Tcall_assert(gfd, evl_new_mutex_any(&lock_medium, EVL_MUTEX_NORMAL,
EVL_CLOCK_MONOTONIC, MEDIUM_PRIO, name));
name = get_unique_name(EVL_MONITOR_DEV, 1);
__Tcall_assert(gfd, evl_new_mutex_ceiling(&lock_high, EVL_MUTEX_NORMAL,
__Tcall_assert(gfd, evl_new_mutex_any(&lock_high, EVL_MUTEX_NORMAL,
EVL_CLOCK_MONOTONIC, HIGH_PRIO, name));
__Tcall_assert(ret, evl_lock_mutex(&lock_medium));

View File

@ -74,11 +74,10 @@ int main(int argc, char *argv[])
__Tcall_assert(tfd, evl_attach_self("monitor-pp-pi:%d", getpid()));
name = get_unique_name(EVL_MONITOR_DEV, 0);
__Tcall_assert(gfd, evl_new_mutex(&c.lock, EVL_MUTEX_NORMAL,
EVL_CLOCK_MONOTONIC, name));
__Tcall_assert(gfd, evl_new_mutex(&c.lock, name));
name = get_unique_name(EVL_MONITOR_DEV, 1);
__Tcall_assert(gfd, evl_new_mutex_ceiling(&lock_pp, EVL_MUTEX_NORMAL,
__Tcall_assert(gfd, evl_new_mutex_any(&lock_pp, EVL_MUTEX_NORMAL,
EVL_CLOCK_MONOTONIC, MEDIUM_PRIO, name));
name = get_unique_name(EVL_MONITOR_DEV, 2);

View File

@ -43,7 +43,7 @@ int main(int argc, char *argv[])
__Tcall_assert(tfd, evl_attach_self("monitor-pp-raise:%d", getpid()));
name = get_unique_name(EVL_MONITOR_DEV, 0);
__Tcall_assert(gfd, evl_new_mutex_ceiling(&lock, EVL_MUTEX_NORMAL,
__Tcall_assert(gfd, evl_new_mutex_any(&lock, EVL_MUTEX_NORMAL,
EVL_CLOCK_MONOTONIC, HIGH_PRIO, name));
__Tcall_assert(ret, evl_lock_mutex(&lock));

View File

@ -43,7 +43,7 @@ int main(int argc, char *argv[])
__Tcall_assert(tfd, evl_attach_self("monitor-pp-tryenter:%d", getpid()));
name = get_unique_name(EVL_MONITOR_DEV, 0);
__Tcall_assert(gfd, evl_new_mutex_ceiling(&lock, EVL_MUTEX_NORMAL,
__Tcall_assert(gfd, evl_new_mutex_any(&lock, EVL_MUTEX_NORMAL,
EVL_CLOCK_MONOTONIC, HIGH_PRIO, name));
/* Taking the fast locking path requires running OOB. */

View File

@ -43,7 +43,7 @@ int main(int argc, char *argv[])
__Tcall_assert(ret, evl_set_schedattr(tfd, &attrs));
name = get_unique_name(EVL_MONITOR_DEV, 0);
__Tcall_assert(gfd, evl_new_mutex_ceiling(&lock, EVL_MUTEX_NORMAL,
__Tcall_assert(gfd, evl_new_mutex_any(&lock, EVL_MUTEX_NORMAL,
EVL_CLOCK_MONOTONIC, HIGH_PRIO, name));
__Tcall_assert(ret, evl_lock_mutex(&lock));

View File

@ -60,8 +60,7 @@ static void test_steal(bool do_steal)
char *name;
name = get_unique_name(EVL_MONITOR_DEV, 0);
__Tcall_assert(gfd, evl_new_mutex(&c.lock, EVL_MUTEX_NORMAL,
EVL_CLOCK_MONOTONIC, name));
__Tcall_assert(gfd, evl_new_mutex(&c.lock, name));
name = get_unique_name(EVL_MONITOR_DEV, 1);
__Tcall_assert(sfd, evl_new_sem(&c.start, EVL_CLOCK_MONOTONIC, 0, name));