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:
parent
a6044094db
commit
bdc3aab501
17
eshi/mutex.c
17
eshi/mutex.c
|
@ -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, ...)
|
||||
{
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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, ...);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
38
lib/mutex.c
38
lib/mutex.c
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue