Module: xenomai-forge Branch: next Commit: c17e9ea73d4f38db8f66f5c73b13cfe0bd404b18 URL: http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=c17e9ea73d4f38db8f66f5c73b13cfe0bd404b18
Author: Philippe Gerum <r...@xenomai.org> Date: Wed Feb 19 19:06:22 2014 +0100 cobalt/posix/event: introduce sc_cobalt_event_inquire syscall --- include/cobalt/uapi/event.h | 6 +++ include/cobalt/uapi/syscall.h | 3 +- kernel/cobalt/posix/event.c | 85 +++++++++++++++++++++++++++++++++++++++++ kernel/cobalt/posix/event.h | 5 +++ kernel/cobalt/posix/syscall.c | 1 + 5 files changed, 99 insertions(+), 1 deletion(-) diff --git a/include/cobalt/uapi/event.h b/include/cobalt/uapi/event.h index 0db215e..ddb6ec4 100644 --- a/include/cobalt/uapi/event.h +++ b/include/cobalt/uapi/event.h @@ -45,6 +45,12 @@ struct cobalt_event_shadow { int flags; }; +struct cobalt_event_info { + unsigned long value; + int flags; + int nrwait; +}; + typedef struct cobalt_event_shadow cobalt_event_t; #endif /* !_COBALT_UAPI_EVENT_H */ diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h index f1549f7..eb7e38c 100644 --- a/include/cobalt/uapi/syscall.h +++ b/include/cobalt/uapi/syscall.h @@ -79,7 +79,8 @@ #define sc_cobalt_sigpending 56 #define sc_cobalt_kill 57 #define sc_cobalt_sem_inquire 58 -/* 59-60 unimplemented */ +#define sc_cobalt_event_inquire 59 +/* 60 unimplemented */ #define sc_cobalt_mutexattr_init 61 #define sc_cobalt_mutexattr_destroy 62 #define sc_cobalt_mutexattr_gettype 63 diff --git a/kernel/cobalt/posix/event.c b/kernel/cobalt/posix/event.c index 2f5a28ef..57d10f0 100644 --- a/kernel/cobalt/posix/event.c +++ b/kernel/cobalt/posix/event.c @@ -287,6 +287,91 @@ out: return ret; } +int cobalt_event_inquire(struct cobalt_event_shadow __user *u_event, + struct cobalt_event_info __user *u_info, + pid_t __user *u_waitlist, + size_t waitsz) +{ + int nrpend, nrwait = 0, nrpids, ret = 0; + unsigned long pstamp, nstamp = 0; + struct cobalt_event_info info; + struct cobalt_event *event; + pid_t *t = NULL, fbuf[16]; + struct xnthread *thread; + xnhandle_t handle; + spl_t s; + + handle = cobalt_get_handle_from_user(&u_event->handle); + + nrpids = waitsz / sizeof(pid_t); + + xnlock_get_irqsave(&nklock, s); + + for (;;) { + pstamp = nstamp; + event = xnregistry_lookup(handle, &nstamp); + if (event == NULL || event->magic != COBALT_EVENT_MAGIC) { + xnlock_put_irqrestore(&nklock, s); + return -EINVAL; + } + /* + * Allocate memory to return the wait list without + * holding any lock, then revalidate the handle. + */ + if (t == NULL) { + nrpend = 0; + if (!xnsynch_pended_p(&event->synch)) + break; + xnsynch_for_each_sleeper(thread, &event->synch) + nrpend++; + if (u_waitlist == NULL) + break; + xnlock_put_irqrestore(&nklock, s); + if (nrpids > nrpend) + nrpids = nrpend; + if (nrpend <= ARRAY_SIZE(fbuf)) + t = fbuf; /* Use fast buffer. */ + else { + t = xnmalloc(nrpend * sizeof(pid_t)); + if (t == NULL) + return -ENOMEM; + } + xnlock_get_irqsave(&nklock, s); + } else if (pstamp == nstamp) + break; + else { + xnlock_put_irqrestore(&nklock, s); + if (t != fbuf) + xnfree(t); + t = NULL; + xnlock_get_irqsave(&nklock, s); + } + } + + info.flags = event->flags; + info.value = event->value; + info.nrwait = nrpend; + + if (xnsynch_pended_p(&event->synch) && u_waitlist != NULL) { + xnsynch_for_each_sleeper(thread, &event->synch) { + if (nrwait >= nrpids) + break; + t[nrwait++] = xnthread_host_pid(thread); + } + } + + xnlock_put_irqrestore(&nklock, s); + + ret = __xn_safe_copy_to_user(u_info, &info, sizeof(info)); + if (ret == 0 && nrwait > 0) + ret = __xn_safe_copy_to_user(u_waitlist, t, nrwait * sizeof(pid_t)); + + if (t && t != fbuf) + xnfree(t); + + return ret ?: nrwait; +} + void cobalt_eventq_cleanup(struct cobalt_kqueues *q) { struct cobalt_event *event, *tmp; diff --git a/kernel/cobalt/posix/event.h b/kernel/cobalt/posix/event.h index f13dd34..e4db082 100644 --- a/kernel/cobalt/posix/event.h +++ b/kernel/cobalt/posix/event.h @@ -49,6 +49,11 @@ int cobalt_event_sync(struct cobalt_event_shadow __user *u_evtsh); int cobalt_event_destroy(struct cobalt_event_shadow __user *u_evtsh); +int cobalt_event_inquire(struct cobalt_event_shadow __user *u_event, + struct cobalt_event_info __user *u_info, + pid_t __user *u_waitlist, + size_t waitsz); + void cobalt_eventq_cleanup(struct cobalt_kqueues *q); void cobalt_event_pkg_init(void); diff --git a/kernel/cobalt/posix/syscall.c b/kernel/cobalt/posix/syscall.c index 5914469..37c8083 100644 --- a/kernel/cobalt/posix/syscall.c +++ b/kernel/cobalt/posix/syscall.c @@ -168,6 +168,7 @@ static struct xnsyscall cobalt_syscalls[] = { SKINCALL_DEF(sc_cobalt_event_destroy, cobalt_event_destroy, any), SKINCALL_DEF(sc_cobalt_event_wait, cobalt_event_wait, primary), SKINCALL_DEF(sc_cobalt_event_sync, cobalt_event_sync, any), + SKINCALL_DEF(sc_cobalt_event_inquire, cobalt_event_inquire, any), SKINCALL_DEF(sc_cobalt_sched_setconfig_np, cobalt_sched_setconfig_np, any), SKINCALL_DEF(sc_cobalt_sched_getconfig_np, cobalt_sched_getconfig_np, any), }; _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git