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

Reply via email to