All of lore.kernel.org
 help / color / mirror / Atom feed
* [Xenomai-core] [PATCH 0/5] Support for select v2.
@ 2008-02-02 14:11 Gilles Chanteperdrix
  2008-02-02 14:12 ` [Xenomai-core] [PATCH 1/5] select-like services support to xenomai core Gilles Chanteperdrix
                   ` (5 more replies)
  0 siblings, 6 replies; 15+ messages in thread
From: Gilles Chanteperdrix @ 2008-02-02 14:11 UTC (permalink / raw)
  To: xenomai


Hi,

after some tests, bug fixes and optimizations, here comes a second version of 
the patch-set adding select support to xenomai posix skin.

Regards.

-- 


					    Gilles Chanteperdrix.


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Xenomai-core] [PATCH 1/5] select-like services support to xenomai core.
  2008-02-02 14:11 [Xenomai-core] [PATCH 0/5] Support for select v2 Gilles Chanteperdrix
@ 2008-02-02 14:12 ` Gilles Chanteperdrix
  2008-02-02 14:18   ` [Xenomai-core] [PATCH 5/5] RTDM: check file descriptor owner Gilles Chanteperdrix
  2008-02-02 14:14 ` [Xenomai-core] [PATCH 2/5] select-like services support to rtdm Gilles Chanteperdrix
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 15+ messages in thread
From: Gilles Chanteperdrix @ 2008-02-02 14:12 UTC (permalink / raw)
  To: xenomai

[-- Attachment #1: message body and .signature --]
[-- Type: text/plain, Size: 638 bytes --]


This patch adds select-like services support to xenomai core.

Changes:
- the xnselect function now ignores null fd_sets, which makes it faster in the
common case when several fd_sets are null;
- the timeout is now passed to xnselect as an (xnticks_t, xntmode_t) couple,
  which avoids xnselect to suspend forever the caller when a computed timeout
  happens to be XN_INFINITE.

Stats:
 include/nucleus/select.h |  111 ++++++++++++
 ksrc/nucleus/Makefile    |    4
 ksrc/nucleus/select.c    |  412 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 525 insertions(+), 2 deletions(-)


-- 


					    Gilles Chanteperdrix.

[-- Attachment #2: xeno-select-core.diff --]
[-- Type: text/plain, Size: 16021 bytes --]

--- include/nucleus/select.h	(revision 0)
+++ include/nucleus/select.h	(revision 0)
@@ -0,0 +1,111 @@
+/*!\file select.h
+ * \brief file descriptors events multiplexing header.
+ * \author Gilles Chanteperdrix
+ *
+ * Copyright (C) 2008 Efixo <gilles.chanteperdrix@xenomai.org>
+ *
+ * Xenomai is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * Xenomai is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Xenomai; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * \ingroup select
+ */
+
+#ifndef XNSELECT_H
+#define XNSELECT_H
+
+/*! \addtogroup select
+ *@{*/
+
+#include <nucleus/thread.h>
+
+#define XNSELECT_READ      0
+#define XNSELECT_WRITE     1
+#define XNSELECT_EXCEPT    2
+#define XNSELECT_MAX_TYPES 3
+
+struct xnselector { 
+        xnsynch_t synchbase;
+	struct fds {
+		fd_set expected;
+		fd_set pending;
+	} fds [XNSELECT_MAX_TYPES];
+	xnqueue_t bindings; /* only used by xnselector_destroy */
+};
+
+struct xnselect {
+	xnqueue_t bindings;
+};
+
+struct xnselect_binding {
+	struct xnselector *selector;
+	struct xnselect *fd;
+	unsigned type;
+	unsigned bit_index;
+	xnholder_t link;  /* link in selected fds list. */
+	xnholder_t slink; /* link in selector list */
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+void xnselect_init(struct xnselect *select_block);
+
+int xnselect_bind(struct xnselect *select_block,
+		  struct xnselect_binding *binding,
+		  struct xnselector *selector,
+		  unsigned type,
+		  unsigned bit_index,
+		  unsigned state);
+
+int __xnselect_signal(struct xnselect *select_block, unsigned state);
+
+/** 
+ * Signal a file descriptor state change.
+ * 
+ * @param select_block pointer to an @a xnselect structure representing the file
+ * descriptor whose state changed;
+ * @param state new value of the state.
+ * 
+ * @retval 1 if rescheduling is needed;
+ * @retval 0 otherwise.
+ */
+static inline int
+xnselect_signal(struct xnselect *select_block, unsigned state)
+{
+	if (!emptyq_p(&select_block->bindings))
+		return __xnselect_signal(select_block, state);
+	return 0;
+}
+
+void xnselect_destroy(struct xnselect *select_block);
+
+int xnselector_init(struct xnselector *selector);
+
+int xnselect(struct xnselector *selector,
+	     fd_set *out_fds[XNSELECT_MAX_TYPES],
+	     fd_set *in_fds[XNSELECT_MAX_TYPES],
+	     int nfds,
+	     xnticks_t timeout, xntmode_t timeout_mode);
+
+void xnselector_destroy(struct xnselector *selector);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+/*@}*/
+
+#endif /* XNSELECT_H */
--- ksrc/nucleus/select.c	(revision 0)
+++ ksrc/nucleus/select.c	(revision 0)
@@ -0,0 +1,412 @@
+/*!\file select.c
+ * \brief file descriptors events multiplexing.
+ * \author Gilles Chanteperdrix
+ *
+ * Copyright (C) 2008 Efixo <gilles.chanteperdrix@xenomai.org>
+ *
+ * Xenomai is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * Xenomai is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Xenomai; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * \ingroup select
+ */
+
+/*!
+ * \ingroup nucleus
+ * \defgroup select File descriptors events multiplexing services.
+ *
+ * File descriptors events multiplexing services.
+ *
+ * This module implements the services needed for implementing the posix
+ * "select" service, or any other events multiplexing services.
+ *
+ * Following the implementation of the posix select service, this module defines
+ * three types of events:
+ * - \a XNSELECT_READ meaning that a file descriptor is ready for reading;
+ * - \a XNSELECT_WRITE meaning that a file descriptor is ready for writing;
+ * - \a XNSELECT_EXCEPT meaning that a file descriptor received an exceptional
+ *   event.
+ *
+ * It works by defining two structures:
+ * - a @a struct @a xnselect structure, which should be added to every file
+ * descriptor for every event type (read, write, or except);
+ * - a @a struct @a xnselector structure, the selection structure,  passed by
+ * the thread calling the xnselect service, where this service does all its
+ * housekeeping.
+ *@{*/
+
+#include <nucleus/heap.h>
+#include <nucleus/pod.h>
+#include <nucleus/synch.h>
+#include <nucleus/select.h>
+#include <linux/types.h>
+#include <linux/bitops.h>	/* For hweight_long */
+
+#define link2binding(baddr, memb)				\
+	container_of(baddr, struct xnselect_binding, memb)
+
+/** 
+ * Initialize a @a struct @a xnselect structure.
+ *
+ * This service must be called to initialize a @a struct @a xnselect structure
+ * before it is bound to a selector by the means of xnselect_bind().
+ * 
+ * @param select_block pointer to the xnselect structure to be initialized
+ */
+void xnselect_init(struct xnselect *select_block)
+{
+	initq(&select_block->bindings);
+}
+EXPORT_SYMBOL(xnselect_init);
+
+static inline int xnselect_wakeup(struct xnselector *selector)
+{
+	return xnsynch_flush(&selector->synchbase, 0) == XNSYNCH_RESCHED;
+}
+
+/** 
+ * Bind a file descriptor (represented by its @a xnselect structure) to a
+ * selector block.
+ *
+ * @param select_block pointer to the @a struct @a xnselect to be bound;
+ *
+ * @param binding pointer to a newly allocated (using xnmalloc) @a struct
+ * @a xnselect_binding;
+ *
+ * @param selector pointer to the selector structure;
+ *
+ * @param type type of events (@a XNSELECT_READ, @a XNSELECT_WRITE, or @a
+ * XNSELECT_EXCEPT);
+ *
+ * @param index index of the file descriptor (represented by @a select_block) in the bit fields used by the @a selector structure;
+ *
+ * @param state current state of the file descriptor>.
+ * 
+ * @a select_block must have been initialized with xnselect_init(),
+ * the @a xnselector structure must have been initialized with
+ * xnselector_init(), @a binding may be uninitialized.
+ *
+ * This service must be called with nklock locked, irqs off. For this reason,
+ * the @a binding parameter must have been allocated by the caller outside the
+ * locking section.
+ * 
+ * @retval -EINVAL if @a type or @a index is invalid;
+ * @retval 0 otherwise.
+ */
+int xnselect_bind(struct xnselect *select_block,
+		  struct xnselect_binding *binding,
+		  struct xnselector *selector,
+		  unsigned type,
+		  unsigned index,
+		  unsigned state)
+{
+	if (type >= XNSELECT_MAX_TYPES || index > __FD_SETSIZE)
+		return -EINVAL;
+
+	binding->selector = selector;
+	binding->fd = select_block;
+	binding->type = type;
+	binding->bit_index = index;
+	inith(&binding->link);
+	inith(&binding->slink);
+	
+	appendq(&selector->bindings, &binding->slink);
+	appendq(&select_block->bindings, &binding->link);
+	__FD_SET(index, &selector->fds[type].expected);
+	if (state)
+		__FD_SET(index, &selector->fds[type].pending);
+
+	return 0;
+}
+EXPORT_SYMBOL(xnselect_bind);
+
+/* Must be called with nklock locked irqs off */
+int __xnselect_signal(struct xnselect *select_block, unsigned state)
+{
+	xnholder_t *holder;
+	int resched;
+
+	for(resched = 0, holder = getheadq(&select_block->bindings);
+	    holder; holder = nextq(&select_block->bindings, holder)) {
+		struct xnselect_binding *binding;
+		struct xnselector *selector;
+
+		binding = link2binding(holder, link);
+
+		selector = binding->selector;
+		if (state) {
+			if (!__FD_ISSET(binding->bit_index,
+					&selector->fds[binding->type].pending)) {
+				__FD_SET(binding->bit_index,
+					 &selector->fds[binding->type].pending);
+				if (xnselect_wakeup(selector))
+					resched = 1;
+			}
+		} else
+			__FD_CLR(binding->bit_index, 
+				 &selector->fds[binding->type].pending);
+	}
+
+	return resched;
+}
+EXPORT_SYMBOL(__xnselect_signal);
+
+/** 
+ * Destroy the @a xnselect structure associated with a file descriptor.
+ *
+ * Any binding with a @a xnselector block is destroyed.
+ *
+ * @param select_block pointer to the @a xnselect structure associated with a file descriptor
+ */
+void xnselect_destroy(struct xnselect *select_block)
+{
+	xnholder_t *holder;
+	spl_t s;
+
+	xnlock_get_irqsave(&nklock, s);
+	while ((holder = getq(&select_block->bindings))) {
+		struct xnselect_binding *binding;
+		struct xnselector *selector;
+
+		binding = link2binding(holder, link);
+		selector = binding->selector;
+
+		__FD_CLR(binding->bit_index,
+			 &selector->fds[binding->type].expected);
+		__FD_CLR(binding->bit_index,
+			 &selector->fds[binding->type].pending);
+		removeq(&selector->bindings, &binding->slink);
+		xnlock_put_irqrestore(&nklock, s);
+
+		xnfree(binding);
+		
+		xnlock_get_irqsave(&nklock, s);
+	}
+	xnlock_put_irqrestore(&nklock, s);
+}
+EXPORT_SYMBOL(xnselect_destroy);
+
+static unsigned
+fd_set_andnot(fd_set *result, fd_set *first, fd_set *second, unsigned n)
+{
+	unsigned i, not_empty = 0;
+
+	for (i = 0; i < __FDELT(n); i++)
+		if((result->fds_bits[i] =
+		    first->fds_bits[i] & ~(second->fds_bits[i])))
+			not_empty = 1;
+
+	if (i < __FDSET_LONGS
+	    && (result->fds_bits[i] =
+		first->fds_bits[i] & ~(second->fds_bits[i]) & (__FDMASK(n) - 1)))
+		not_empty = 1;
+
+	return not_empty;
+}
+
+static unsigned
+fd_set_and(fd_set *result, fd_set *first, fd_set *second, unsigned n)
+{
+	unsigned i, not_empty = 0;
+
+	for (i = 0; i < __FDELT(n); i++)
+		if((result->fds_bits[i] =
+		    first->fds_bits[i] & second->fds_bits[i]))
+			not_empty = 1;
+
+	if (i < __FDSET_LONGS
+	    && (result->fds_bits[i] =
+		first->fds_bits[i] & second->fds_bits[i] & (__FDMASK(n) - 1)))
+		not_empty = 1;
+
+	return not_empty;
+}
+
+static void fd_set_zerofill(fd_set *set, unsigned n)
+{
+	unsigned i;
+
+	i = __FDELT(n);
+
+	if (i < __FDSET_LONGS)
+		set->fds_bits[i] &= (__FDMASK(n) - 1);
+
+	for(i++; i < __FDSET_LONGS; i++)
+		set->fds_bits[i] = 0;
+}
+
+static unsigned fd_set_popcount(fd_set *set, unsigned n)
+{
+	unsigned count = 0, i;
+
+	for (i = 0; i < __FDELT(n); i++)
+		if (set->fds_bits[i])
+			count += hweight_long(set->fds_bits[i]);
+
+	if (i < __FDSET_LONGS && (set->fds_bits[i] & (__FDMASK(n) - 1)))
+		count += hweight_long(set->fds_bits[i] & (__FDMASK(n) - 1));
+
+	return count;
+}
+
+/** 
+ * Initialize a selector structure.
+ * 
+ * @param selector The selector structure to be initialized.
+ * 
+ * @retval 0
+ */
+int xnselector_init(struct xnselector *selector)
+{
+	unsigned i;
+
+	xnsynch_init(&selector->synchbase, XNSYNCH_FIFO | XNSYNCH_NOPIP);
+	for (i = 0; i < XNSELECT_MAX_TYPES; i++) {
+		__FD_ZERO(&selector->fds[i].expected);
+		__FD_ZERO(&selector->fds[i].pending);
+	}
+	initq(&selector->bindings);
+	return 0;
+}
+EXPORT_SYMBOL(xnselector_init);
+
+/** 
+ * Check the state of a number of file descriptors, wait for a state change if
+ * no descriptor is ready.
+ * 
+ * @param selector structure to check for pending events
+ * @param out_fds The set of descriptors with pending events if a strictly positive number is returned, or the set of descriptors not yet bound if -ECHRNG is returned;
+ * @param in_fds the set of descriptors which events should be checked
+ * @param nfds the highest-numbered descriptor in any of the @a in_fds sets, plus 1;
+ * @param timeout the timeout, whose meaning depends on @a timeout_mode, note
+ * that xnselect() pass @a timeout and @a timeout_mode unchanged to
+ * xnsynch_sleep_on, so passing a relative value different from XN_INFINITE as a
+ * timeout with @a timeout_mode set to XN_RELATIVE, will cause a longer sleep
+ * than expected if the sleep is interrupted.
+ * @param timeout_mode the mode of @a timeout.
+ * 
+ * @retval -EINVAL if @nfds is negative;
+ * @retval -ECHRNG if some of the descriptors passed in @a in_fds have not yet
+ * been registered with xnselect_bind(), @a out_fds contains the set of such
+ * descriptors;
+ * @retval -EINTR if @a xnselect was interrupted while waiting;
+ * @retval 0 in case of timeout.
+ * @retval the number of file descriptors having received an event.
+ */
+int xnselect(struct xnselector *selector,
+	     fd_set *out_fds[XNSELECT_MAX_TYPES],
+	     fd_set *in_fds[XNSELECT_MAX_TYPES],
+	     int nfds,
+	     xnticks_t timeout, xntmode_t timeout_mode)
+{
+	unsigned i, not_empty = 0;
+	xnthread_t *thread;
+	spl_t s;
+
+	if ((unsigned) nfds > __FD_SETSIZE)
+		return -EINVAL;
+
+	thread = xnpod_current_thread();	
+
+	xnlock_get_irqsave(&nklock, s);
+	for (i = 0; i < XNSELECT_MAX_TYPES; i++)
+		if (out_fds[i]
+		    && fd_set_andnot(out_fds[i], in_fds[i],
+				     &selector->fds[i].expected, nfds))
+			not_empty = 1;
+	xnlock_put_irqrestore(&nklock, s);
+
+	if (not_empty) {
+		for (i = 0; i < XNSELECT_MAX_TYPES; i++)
+			if (out_fds[i])
+				fd_set_zerofill(out_fds[i], nfds);
+		return -ECHRNG;
+	}
+
+	xnlock_get_irqsave(&nklock, s);
+	for (i = 0; i < XNSELECT_MAX_TYPES; i++)
+		if (out_fds[i]
+		    && fd_set_and(out_fds[i], in_fds[i],
+				  &selector->fds[i].pending, nfds))
+			not_empty = 1;
+	
+	while (!not_empty) {
+		xnsynch_sleep_on(&selector->synchbase, timeout, timeout_mode);
+
+		for (i = 0; i < XNSELECT_MAX_TYPES; i++)
+			if (out_fds[i]
+			    && fd_set_and(out_fds[i], in_fds[i],
+					  &selector->fds[i].pending, nfds))
+				not_empty = 1;
+
+		if (xnthread_test_info(thread, XNBREAK | XNTIMEO))
+			break;
+	}
+	xnlock_put_irqrestore(&nklock, s);
+
+	if (not_empty) {
+		unsigned count;
+
+		for (i = 0; i < XNSELECT_MAX_TYPES; i++)
+			if (out_fds[i])
+				fd_set_zerofill(out_fds[i], nfds);
+
+		for (count = 0, i = 0; i < XNSELECT_MAX_TYPES; i++)
+			if (out_fds[i])
+				count += fd_set_popcount(out_fds[i], nfds);
+
+		return count;
+	}
+
+	if (xnthread_test_info(thread, XNBREAK))
+		return -EINTR;
+
+	return 0; /* Timeout */
+}
+EXPORT_SYMBOL(xnselect);
+
+/** 
+ * Destroy a selector block.
+ *
+ * All bindings with file descriptor are destroyed.
+ *
+ * @param selector the selector block to be destroyed
+ */
+void xnselector_destroy(struct xnselector *selector)
+{
+	xnholder_t *holder;
+	spl_t s;
+
+	xnlock_get_irqsave(&nklock, s);
+	while ((holder = getq(&selector->bindings))) {
+		struct xnselect_binding *binding;
+		struct xnselect *fd;
+
+		binding = link2binding(holder, slink);
+		fd = binding->fd;
+		removeq(&fd->bindings, &binding->link);
+		xnlock_put_irqrestore(&nklock, s);
+
+		xnfree(binding);
+
+		xnlock_get_irqsave(&nklock, s);
+	}
+	xnlock_put_irqrestore(&nklock, s);
+
+	if (xnsynch_destroy(&selector->synchbase) == XNSYNCH_RESCHED)
+		xnpod_schedule();
+}
+EXPORT_SYMBOL(xnselector_destroy);
+
+/*@}*/
--- ksrc/nucleus/Makefile	(revision 3455)
+++ ksrc/nucleus/Makefile	(working copy)
@@ -4,7 +4,7 @@ ifeq ($(PATCHLEVEL),6)
 
 obj-$(CONFIG_XENO_OPT_NUCLEUS) += xeno_nucleus.o
 
-xeno_nucleus-y := heap.o intr.o module.o pod.o synch.o thread.o timebase.o timer.o
+xeno_nucleus-y := heap.o intr.o module.o pod.o synch.o thread.o timebase.o timer.o select.o
 
 xeno_nucleus-$(CONFIG_XENO_OPT_PERVASIVE) += shadow.o
 
@@ -26,7 +26,7 @@ obj-$(CONFIG_XENO_OPT_NUCLEUS) := xeno_n
 
 list-multi := xeno_nucleus.o
 
-xeno_nucleus-objs := heap.o intr.o module.o pod.o synch.o thread.o timebase.o timer.o
+xeno_nucleus-objs := heap.o intr.o module.o pod.o synch.o thread.o timebase.o timer.o select.o
 
 opt_objs-y :=
 opt_objs-$(CONFIG_XENO_OPT_PERVASIVE) += shadow.o

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Xenomai-core] [PATCH 2/5] select-like services support to rtdm.
  2008-02-02 14:11 [Xenomai-core] [PATCH 0/5] Support for select v2 Gilles Chanteperdrix
  2008-02-02 14:12 ` [Xenomai-core] [PATCH 1/5] select-like services support to xenomai core Gilles Chanteperdrix
@ 2008-02-02 14:14 ` Gilles Chanteperdrix
  2008-02-02 14:15 ` [Xenomai-core] [PATCH 3/5] posix skin kernel-space support for user-space select Gilles Chanteperdrix
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 15+ messages in thread
From: Gilles Chanteperdrix @ 2008-02-02 14:14 UTC (permalink / raw)
  To: xenomai

[-- Attachment #1: message body and .signature --]
[-- Type: text/plain, Size: 409 bytes --]


This patch adds select-like services support to rtdm.

No changes.

Stats:
 include/rtdm/rtdm.h        |    4
 include/rtdm/rtdm_driver.h |  148 +++++++++++++-
 ksrc/skins/rtdm/core.c     |   26 ++
 ksrc/skins/rtdm/device.c   |   10 +
 ksrc/skins/rtdm/drvlib.c   |  446 ++++++++++++++++++++++++++++++++++-----------
 5 files changed, 512 insertions(+), 122 deletions(-)

-- 


					    Gilles Chanteperdrix.

[-- Attachment #2: xeno-select-rtdm.diff --]
[-- Type: text/plain, Size: 22991 bytes --]

--- include/rtdm/rtdm_driver.h	(revision 3455)
+++ include/rtdm/rtdm_driver.h	(working copy)
@@ -38,6 +38,7 @@
 #include <nucleus/heap.h>
 #include <nucleus/pod.h>
 #include <nucleus/synch.h>
+#include <nucleus/select.h>
 #include <rtdm/rtdm.h>
 
 /* debug support */
@@ -262,6 +263,11 @@ typedef ssize_t (*rtdm_sendmsg_handler_t
 typedef int (*rtdm_rt_handler_t)(struct rtdm_dev_context *context,
 				 rtdm_user_info_t *user_info, void *arg);
 
+typedef int (*rtdm_select_bind_handler_t)(struct rtdm_dev_context *context,
+					  struct xnselector *selector,
+					  unsigned type,
+					  unsigned index);
+
 /**
  * Device operations
  */
@@ -304,6 +310,8 @@ struct rtdm_operations {
 	/** Transmit message handler for non-real-time context (optional) */
 	rtdm_sendmsg_handler_t sendmsg_nrt;
 	/** @} Message-Oriented Device Operations */
+
+	rtdm_select_bind_handler_t select_bind;
 };
 
 struct rtdm_devctx_reserved {
@@ -1004,30 +1012,92 @@ typedef struct {
 	xnsynch_t synch_base;
 } rtdm_event_t;
 
-#define RTDM_EVENT_PENDING		XNSYNCH_SPARE1
+typedef struct {
+	rtdm_event_t event;
+	struct xnselect select_block;
+} rtdm_select_event_t;
 
-void rtdm_event_init(rtdm_event_t *event, unsigned long pending);
-int rtdm_event_wait(rtdm_event_t *event);
-int rtdm_event_timedwait(rtdm_event_t *event, nanosecs_rel_t timeout,
-			 rtdm_toseq_t *timeout_seq);
-void rtdm_event_signal(rtdm_event_t *event);
+#define RTDM_EVENT_PENDING		XNSYNCH_SPARE1
 
-void rtdm_event_clear(rtdm_event_t *event);
+#ifndef TYPE_EQUAL
+#define TYPE_EQUAL(object, type) \
+    __builtin_types_compatible_p(typeof(object), type *)
+#endif /* !TYPE_EQUAL */
+
+#define PICK_VOIDEVENTOP(op, object, args...)				\
+    do {								\
+	if (TYPE_EQUAL((object), rtdm_event_t))				\
+	    _rtdm_event_##op((rtdm_event_t *)(object), ##args);		\
+	else if (TYPE_EQUAL((object), rtdm_select_event_t))		\
+	    _rtdm_select_event_##op((rtdm_select_event_t *)(object), ##args); \
+    } while (0)
+
+#define PICK_INTEVENTOP(op, object, args...)				\
+    ({									\
+	int err = -ENOSYS;						\
+	if (TYPE_EQUAL((object), rtdm_event_t))				\
+	    err = _rtdm_event_##op((rtdm_event_t *)(object), ##args);	\
+	else if (TYPE_EQUAL((object), rtdm_select_event_t))		\
+	    err = _rtdm_select_event_##op((rtdm_select_event_t *)(object), ##args); \
+	err;								\
+    })
 
 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
+void _rtdm_event_init(rtdm_event_t *event, unsigned long pending);
+void _rtdm_select_event_init(rtdm_select_event_t *event, unsigned long pending);
+#define rtdm_event_init(event, pending) PICK_VOIDEVENTOP(init, event, pending)
+
+int rtdm_select_event_bind(rtdm_select_event_t *event,
+			   struct xnselector *selector,
+			   unsigned type,
+			   unsigned bit_index);
+
+int _rtdm_event_wait(rtdm_event_t *event);
+int _rtdm_select_event_wait(rtdm_select_event_t *event);
+#define rtdm_event_wait(event) PICK_INTEVENTOP(wait, event)
+
+int _rtdm_event_timedwait(rtdm_event_t *event, nanosecs_rel_t timeout,
+			  rtdm_toseq_t *timeout_seq);
+int _rtdm_select_event_timedwait(rtdm_select_event_t *event,
+				 nanosecs_rel_t timeout,
+				 rtdm_toseq_t *timeout_seq);
+#define rtdm_event_timedwait(event, timeout, timeout_seq) \
+	PICK_INTEVENTOP(timedwait, event, timeout, timeout_seq)
+
+void _rtdm_event_signal(rtdm_event_t *event);
+void _rtdm_select_event_signal(rtdm_select_event_t *event);
+#define rtdm_event_signal(event) PICK_VOIDEVENTOP(signal, event)
+
+void _rtdm_event_clear(rtdm_event_t *event);
+void _rtdm_select_event_clear(rtdm_select_event_t *event);
+#define rtdm_event_clear(event) PICK_VOIDEVENTOP(clear, event)
+
 void __rtdm_synch_flush(xnsynch_t *synch, unsigned long reason);
 
-static inline void rtdm_event_pulse(rtdm_event_t *event)
+static inline void _rtdm_event_pulse(rtdm_event_t *event)
 {
 	trace_mark(xn_rtdm_event_pulse, "event %p", event);
 	__rtdm_synch_flush(&event->synch_base, 0);
 }
 
-static inline void rtdm_event_destroy(rtdm_event_t *event)
+static inline void _rtdm_select_event_pulse(rtdm_select_event_t *event)
+{
+	_rtdm_event_pulse(&event->event);
+}
+#define rtdm_event_pulse(event) PICK_VOIDEVENTOP(pulse, event)
+
+static inline void _rtdm_event_destroy(rtdm_event_t *event)
 {
 	trace_mark(xn_rtdm_event_destroy, "event %p", event);
 	__rtdm_synch_flush(&event->synch_base, XNRMID);
 }
+
+static inline void _rtdm_select_event_destroy(rtdm_select_event_t *event)
+{
+	xnselect_destroy(&event->select_block);
+	_rtdm_event_destroy(&event->event);
+}
+#define rtdm_event_destroy(event) PICK_VOIDEVENTOP(destroy, event);
 #endif /* !DOXYGEN_CPP */
 
 /* --- semaphore services --- */
@@ -1037,18 +1107,66 @@ typedef struct {
 	xnsynch_t synch_base;
 } rtdm_sem_t;
 
-void rtdm_sem_init(rtdm_sem_t *sem, unsigned long value);
-int rtdm_sem_down(rtdm_sem_t *sem);
-int rtdm_sem_timeddown(rtdm_sem_t *sem, nanosecs_rel_t timeout,
-		       rtdm_toseq_t *timeout_seq);
-void rtdm_sem_up(rtdm_sem_t *sem);
+typedef struct {
+	rtdm_sem_t sem;
+	struct xnselect select_block;
+} rtdm_select_sem_t;
 
 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
-static inline void rtdm_sem_destroy(rtdm_sem_t *sem)
+#define PICK_VOIDSEMOP(op, object, args...)				\
+    do {								\
+	if (TYPE_EQUAL((object), rtdm_sem_t))				\
+	    _rtdm_sem_##op((rtdm_sem_t *)(object), ##args);		\
+	else if (TYPE_EQUAL((object), rtdm_select_sem_t))		\
+	    _rtdm_select_sem_##op((rtdm_select_sem_t *)(object), ##args); \
+    } while (0)
+
+#define PICK_INTSEMOP(op, object, args...)				\
+    ({									\
+	int err = -ENOSYS;						\
+	if (TYPE_EQUAL((object), rtdm_sem_t))				\
+	    err = _rtdm_sem_##op((rtdm_sem_t *)(object), ##args);	\
+	else if (TYPE_EQUAL((object), rtdm_select_sem_t))		\
+	    err = _rtdm_select_sem_##op((rtdm_select_sem_t *)(object), ##args);	\
+	err;								\
+    })
+
+void _rtdm_sem_init(rtdm_sem_t *sem, unsigned long value);
+void _rtdm_select_sem_init(rtdm_select_sem_t *sem, unsigned long value);
+#define rtdm_sem_init(sem, value) PICK_VOIDSEMOP(init, sem, value)
+
+int rtdm_select_sem_bind(rtdm_select_sem_t *sem,
+			 struct xnselector *selector,
+			 unsigned type,
+			 unsigned bit_index);
+
+int _rtdm_sem_down(rtdm_sem_t *sem);
+int _rtdm_select_sem_down(rtdm_select_sem_t *sem);
+#define rtdm_sem_down(sem) PICK_INTSEMOP(down, sem)
+
+int _rtdm_sem_timeddown(rtdm_sem_t *sem, nanosecs_rel_t timeout,
+		       rtdm_toseq_t *timeout_seq);
+int _rtdm_select_sem_timeddown(rtdm_select_sem_t *sem, nanosecs_rel_t timeout,
+			       rtdm_toseq_t *timeout_seq);
+#define rtdm_sem_timeddown(sem, timeout, timeout_seq) \
+	PICK_INTSEMOP(timeddown, sem, timeout, timeout_seq)
+
+void _rtdm_sem_up(rtdm_sem_t *sem);
+void _rtdm_select_sem_up(rtdm_select_sem_t *sem);
+#define rtdm_sem_up(sem) PICK_VOIDSEMOP(up, sem)
+
+static inline void _rtdm_sem_destroy(rtdm_sem_t *sem)
 {
 	trace_mark(xn_rtdm_sem_destroy, "sem %p", sem);
 	__rtdm_synch_flush(&sem->synch_base, XNRMID);
 }
+
+static inline void _rtdm_select_sem_destroy(rtdm_select_sem_t *sem)
+{
+	xnselect_destroy(&sem->select_block);
+	_rtdm_sem_destroy(&sem->sem);
+}
+#define rtdm_sem_destroy(sem) PICK_VOIDSEMOP(destroy, sem)
 #endif /* !DOXYGEN_CPP */
 
 /* --- mutex services --- */
--- include/rtdm/rtdm.h	(revision 3455)
+++ include/rtdm/rtdm.h	(working copy)
@@ -247,6 +247,10 @@ ssize_t __rt_dev_recvmsg(rtdm_user_info_
 			 struct msghdr *msg, int flags);
 ssize_t __rt_dev_sendmsg(rtdm_user_info_t *user_info, int fd,
 			 const struct msghdr *msg, int flags);
+struct xnselector;
+int __rt_dev_select_bind(int fd,
+			 struct xnselector *selector,
+			 unsigned type, unsigned index);
 #endif /* __KERNEL__ */
 
 /* Define RTDM_NO_DEFAULT_USER_API to switch off the default rt_dev_xxx
--- ksrc/skins/rtdm/device.c	(revision 3455)
+++ ksrc/skins/rtdm/device.c	(working copy)
@@ -70,6 +70,14 @@ int rtdm_no_support(void)
 	return -ENOSYS;
 }
 
+int rtdm_select_bind_no_support(struct rtdm_dev_context *context,
+				struct xnselector *selector,
+				unsigned type,
+				unsigned index)
+{
+	return -EBADF;
+}
+  
 static inline int get_name_hash(const char *str, int limit, int hashkey_mask)
 {
 	int hash = 0;
@@ -242,6 +250,8 @@ int rtdm_dev_register(struct rtdm_device
 	SET_DEFAULT_OP_IF_NULL(device->ops, write);
 	SET_DEFAULT_OP_IF_NULL(device->ops, recvmsg);
 	SET_DEFAULT_OP_IF_NULL(device->ops, sendmsg);
+	if (!device->ops.select_bind)
+		device->ops.select_bind = rtdm_select_bind_no_support;
 
 	atomic_set(&device->reserved.refcount, 0);
 	device->reserved.exclusive_context = NULL;
--- ksrc/skins/rtdm/drvlib.c	(revision 3455)
+++ ksrc/skins/rtdm/drvlib.c	(working copy)
@@ -728,23 +728,7 @@ EXPORT_SYMBOL(rtdm_toseq_init);
  * @{
  */
 
-/**
- * @brief Initialise an event
- *
- * @param[in,out] event Event handle
- * @param[in] pending Non-zero if event shall be initialised as set, 0 otherwise
- *
- * Environments:
- *
- * This service can be called from:
- *
- * - Kernel module initialization/cleanup code
- * - Kernel-based task
- * - User-space task (RT, non-RT)
- *
- * Rescheduling: never.
- */
-void rtdm_event_init(rtdm_event_t *event, unsigned long pending)
+void _rtdm_event_init(rtdm_event_t *event, unsigned long pending)
 {
 	spl_t s;
 
@@ -760,10 +744,36 @@ void rtdm_event_init(rtdm_event_t *event
 	xnlock_put_irqrestore(&nklock, s);
 }
 
-EXPORT_SYMBOL(rtdm_event_init);
+EXPORT_SYMBOL(_rtdm_event_init);
+
+void _rtdm_select_event_init(rtdm_select_event_t *event, unsigned long pending)
+{
+	_rtdm_event_init(&event->event, pending);
+	xnselect_init(&event->select_block);
+}
+
+EXPORT_SYMBOL(_rtdm_select_event_init);
 
 #ifdef DOXYGEN_CPP /* Only used for doxygen doc generation */
 /**
+ * @brief Initialise an event
+ *
+ * @param[in,out] event Event handle
+ * @param[in] pending Non-zero if event shall be initialised as set, 0 otherwise
+ *
+ * Environments:
+ *
+ * This service can be called from:
+ *
+ * - Kernel module initialization/cleanup code
+ * - Kernel-based task
+ * - User-space task (RT, non-RT)
+ *
+ * Rescheduling: never.
+ */
+void rtdm_event_init(rtdm_event_t *event, unsigned long pending);
+
+/**
  * @brief Destroy an event
  *
  * @param[in,out] event Event handle as returned by rtdm_event_init()
@@ -801,7 +811,6 @@ void rtdm_event_destroy(rtdm_event_t *ev
  * Rescheduling: possible.
  */
 void rtdm_event_pulse(rtdm_event_t *event);
-#endif /* DOXYGEN_CPP */
 
 /**
  * @brief Signal an event occurrence
@@ -823,22 +832,7 @@ void rtdm_event_pulse(rtdm_event_t *even
  *
  * Rescheduling: possible.
  */
-void rtdm_event_signal(rtdm_event_t *event)
-{
-	spl_t s;
-
-	trace_mark(xn_rtdm_event_signal, "event %p", event);
-
-	xnlock_get_irqsave(&nklock, s);
-
-	xnsynch_set_flags(&event->synch_base, RTDM_EVENT_PENDING);
-	if (xnsynch_flush(&event->synch_base, 0))
-		xnpod_schedule();
-
-	xnlock_put_irqrestore(&nklock, s);
-}
-
-EXPORT_SYMBOL(rtdm_event_signal);
+void rtdm_event_signal(rtdm_event_t *event);
 
 /**
  * @brief Wait on event occurrence
@@ -867,12 +861,7 @@ EXPORT_SYMBOL(rtdm_event_signal);
  *
  * Rescheduling: possible.
  */
-int rtdm_event_wait(rtdm_event_t *event)
-{
-	return rtdm_event_timedwait(event, 0, NULL);
-}
-
-EXPORT_SYMBOL(rtdm_event_wait);
+int rtdm_event_wait(rtdm_event_t *event);
 
 /**
  * @brief Wait on event occurrence with timeout
@@ -910,6 +899,81 @@ EXPORT_SYMBOL(rtdm_event_wait);
  * Rescheduling: possible.
  */
 int rtdm_event_timedwait(rtdm_event_t *event, nanosecs_rel_t timeout,
+			 rtdm_toseq_t *timeout_seq);
+
+/**
+ * @brief Clear event state
+ *
+ * @param[in,out] event Event handle as returned by rtdm_event_init()
+ *
+ * Environments:
+ *
+ * This service can be called from:
+ *
+ * - Kernel module initialization/cleanup code
+ * - Interrupt service routine
+ * - Kernel-based task
+ * - User-space task (RT, non-RT)
+ *
+ * Rescheduling: never.
+ */
+void rtdm_event_clear(rtdm_event_t *event);
+#endif /* DOXYGEN_CPP */
+void _rtdm_event_signal(rtdm_event_t *event)
+{
+	spl_t s;
+
+	trace_mark(xn_rtdm_event_signal, "event %p", event);
+
+	xnlock_get_irqsave(&nklock, s);
+
+	xnsynch_set_flags(&event->synch_base, RTDM_EVENT_PENDING);
+	if (xnsynch_flush(&event->synch_base, 0))
+		xnpod_schedule();
+
+	xnlock_put_irqrestore(&nklock, s);
+}
+
+EXPORT_SYMBOL(_rtdm_event_signal);
+
+void _rtdm_select_event_signal(rtdm_select_event_t *select_event)
+{
+	rtdm_event_t *event = &select_event->event;
+	int resched = 0;
+	spl_t s;
+
+	trace_mark(xn_rtdm_event_signal, "event %p", event);
+
+	xnlock_get_irqsave(&nklock, s);
+
+	xnsynch_set_flags(&event->synch_base, RTDM_EVENT_PENDING);
+	if (xnsynch_flush(&event->synch_base, 0))
+		resched = 1;
+	if (xnselect_signal(&select_event->select_block, 1))
+		resched = 1;
+	if (resched)
+		xnpod_schedule();
+
+	xnlock_put_irqrestore(&nklock, s);
+}
+
+EXPORT_SYMBOL(_rtdm_select_event_signal);
+
+int _rtdm_event_wait(rtdm_event_t *event)
+{
+	return _rtdm_event_timedwait(event, 0, NULL);
+}
+
+EXPORT_SYMBOL(_rtdm_event_wait);
+
+int _rtdm_select_event_wait(rtdm_select_event_t *event)
+{
+	return _rtdm_select_event_timedwait(event, 0, NULL);
+}
+
+EXPORT_SYMBOL(_rtdm_select_event_wait);
+
+int _rtdm_event_timedwait(rtdm_event_t *event, nanosecs_rel_t timeout,
 			 rtdm_toseq_t *timeout_seq)
 {
 	xnthread_t *thread;
@@ -968,25 +1032,74 @@ unlock_out:
 	return err;
 }
 
-EXPORT_SYMBOL(rtdm_event_timedwait);
+EXPORT_SYMBOL(_rtdm_event_timedwait);
 
-/**
- * @brief Clear event state
- *
- * @param[in,out] event Event handle as returned by rtdm_event_init()
- *
- * Environments:
- *
- * This service can be called from:
- *
- * - Kernel module initialization/cleanup code
- * - Interrupt service routine
- * - Kernel-based task
- * - User-space task (RT, non-RT)
- *
- * Rescheduling: never.
- */
-void rtdm_event_clear(rtdm_event_t *event)
+int _rtdm_select_event_timedwait(rtdm_select_event_t *select_event,
+				 nanosecs_rel_t timeout,
+				 rtdm_toseq_t *timeout_seq)
+{
+	rtdm_event_t *event = &select_event->event;
+	xnthread_t *thread;
+	spl_t s;
+	int err = 0;
+
+	XENO_ASSERT(RTDM, !xnpod_unblockable_p(), return -EPERM;);
+
+	trace_mark(xn_rtdm_event_timedwait,
+		   "event %p timeout %Lu timeout_seq %p timeout_seq_value %Lu",
+		   event, timeout, timeout_seq, timeout_seq ? *timeout_seq : 0);
+
+	xnlock_get_irqsave(&nklock, s);
+
+	if (unlikely(testbits(event->synch_base.status, RTDM_SYNCH_DELETED)))
+		err = -EIDRM;
+	else if (likely(xnsynch_test_flags(&event->synch_base,
+					   RTDM_EVENT_PENDING))) {
+		xnsynch_clear_flags(&event->synch_base, RTDM_EVENT_PENDING);
+		xnselect_signal(&select_event->select_block, 0);
+	} else {
+		/* non-blocking mode */
+		if (timeout < 0) {
+			err = -EWOULDBLOCK;
+			goto unlock_out;
+		}
+
+		thread = xnpod_current_thread();
+
+		if (timeout_seq && (timeout > 0)) {
+			/* timeout sequence */
+			xnsynch_sleep_on(&event->synch_base, *timeout_seq,
+					 XN_ABSOLUTE);
+		} else {
+			/* infinite or relative timeout */
+			xnsynch_sleep_on(&event->synch_base,
+					 xntbase_ns2ticks_ceil
+					 (xnthread_time_base(thread), timeout),
+					 XN_RELATIVE);
+		}
+
+		if (likely
+		    (!xnthread_test_info(thread, XNTIMEO | XNRMID | XNBREAK))) {
+			xnsynch_clear_flags(&event->synch_base,
+					    RTDM_EVENT_PENDING);
+			xnselect_signal(&select_event->select_block, 0);
+		} else if (xnthread_test_info(thread, XNTIMEO))
+			err = -ETIMEDOUT;
+		else if (xnthread_test_info(thread, XNRMID))
+			err = -EIDRM;
+		else /* XNBREAK */
+			err = -EINTR;
+	}
+
+unlock_out:
+	xnlock_put_irqrestore(&nklock, s);
+
+	return err;
+}
+
+EXPORT_SYMBOL(_rtdm_select_event_timedwait);
+
+void _rtdm_event_clear(rtdm_event_t *event)
 {
 	spl_t s;
 
@@ -999,7 +1112,23 @@ void rtdm_event_clear(rtdm_event_t *even
 	xnlock_put_irqrestore(&nklock, s);
 }
 
-EXPORT_SYMBOL(rtdm_event_clear);
+EXPORT_SYMBOL(_rtdm_event_clear);
+
+void _rtdm_select_event_clear(rtdm_select_event_t *event)
+{
+	spl_t s;
+
+	trace_mark(xn_rtdm_event_clear, "event %p", event);
+
+	xnlock_get_irqsave(&nklock, s);
+
+	xnsynch_clear_flags(&event->event.synch_base, RTDM_EVENT_PENDING);
+	xnselect_signal(&event->select_block, 0);
+
+	xnlock_put_irqrestore(&nklock, s);
+}
+
+EXPORT_SYMBOL(_rtdm_select_event_clear);
 /** @} */
 
 /*!
@@ -1007,6 +1136,32 @@ EXPORT_SYMBOL(rtdm_event_clear);
  * @{
  */
 
+void _rtdm_sem_init(rtdm_sem_t *sem, unsigned long value)
+{
+	spl_t s;
+
+	trace_mark(xn_rtdm_sem_init, "sem %p value %lu", sem, value);
+
+	/* Make atomic for re-initialisation support */
+	xnlock_get_irqsave(&nklock, s);
+
+	sem->value = value;
+	xnsynch_init(&sem->synch_base, XNSYNCH_PRIO);
+
+	xnlock_put_irqrestore(&nklock, s);
+}
+
+EXPORT_SYMBOL(_rtdm_sem_init);
+
+void _rtdm_select_sem_init(rtdm_select_sem_t *sem, unsigned long value)
+{
+	_rtdm_sem_init(&sem->sem, value);
+	xnselect_init(&sem->select_block);
+}
+
+EXPORT_SYMBOL(_rtdm_select_sem_init);
+
+#ifdef DOXYGEN_CPP /* Only used for doxygen doc generation */
 /**
  * @brief Initialise a semaphore
  *
@@ -1023,24 +1178,8 @@ EXPORT_SYMBOL(rtdm_event_clear);
  *
  * Rescheduling: never.
  */
-void rtdm_sem_init(rtdm_sem_t *sem, unsigned long value)
-{
-	spl_t s;
+void rtdm_sem_init(rtdm_sem_t *sem, unsigned long value);
 
-	trace_mark(xn_rtdm_sem_init, "sem %p value %lu", sem, value);
-
-	/* Make atomic for re-initialisation support */
-	xnlock_get_irqsave(&nklock, s);
-
-	sem->value = value;
-	xnsynch_init(&sem->synch_base, XNSYNCH_PRIO);
-
-	xnlock_put_irqrestore(&nklock, s);
-}
-
-EXPORT_SYMBOL(rtdm_sem_init);
-
-#ifdef DOXYGEN_CPP /* Only used for doxygen doc generation */
 /**
  * @brief Destroy a semaphore
  *
@@ -1057,7 +1196,6 @@ EXPORT_SYMBOL(rtdm_sem_init);
  * Rescheduling: possible.
  */
 void rtdm_sem_destroy(rtdm_sem_t *sem);
-#endif /* DOXYGEN_CPP */
 
 /**
  * @brief Decrement a semaphore
@@ -1086,12 +1224,7 @@ void rtdm_sem_destroy(rtdm_sem_t *sem);
  *
  * Rescheduling: possible.
  */
-int rtdm_sem_down(rtdm_sem_t *sem)
-{
-	return rtdm_sem_timeddown(sem, 0, NULL);
-}
-
-EXPORT_SYMBOL(rtdm_sem_down);
+int rtdm_sem_down(rtdm_sem_t *sem);
 
 /**
  * @brief Decrement a semaphore with timeout
@@ -1132,7 +1265,46 @@ EXPORT_SYMBOL(rtdm_sem_down);
  * Rescheduling: possible.
  */
 int rtdm_sem_timeddown(rtdm_sem_t *sem, nanosecs_rel_t timeout,
-		       rtdm_toseq_t *timeout_seq)
+		       rtdm_toseq_t *timeout_seq);
+
+/**
+ * @brief Increment a semaphore
+ *
+ * This function increments the given semphore's value, waking up a potential
+ * waiter which was blocked upon rtdm_sem_down().
+ *
+ * @param[in,out] sem Semaphore handle as returned by rtdm_sem_init()
+ *
+ * Environments:
+ *
+ * This service can be called from:
+ *
+ * - Kernel module initialization/cleanup code
+ * - Interrupt service routine
+ * - Kernel-based task
+ * - User-space task (RT, non-RT)
+ *
+ * Rescheduling: possible.
+ */
+void rtdm_sem_up(rtdm_sem_t *sem);
+#endif /* DOXYGEN_CPP */
+
+int _rtdm_sem_down(rtdm_sem_t *sem)
+{
+	return _rtdm_sem_timeddown(sem, 0, NULL);
+}
+
+EXPORT_SYMBOL(_rtdm_sem_down);
+
+int _rtdm_select_sem_down(rtdm_select_sem_t *sem)
+{
+	return _rtdm_select_sem_timeddown(sem, 0, NULL);
+}
+
+EXPORT_SYMBOL(_rtdm_select_sem_down);
+
+int _rtdm_sem_timeddown(rtdm_sem_t *sem, nanosecs_rel_t timeout,
+			rtdm_toseq_t *timeout_seq)
 {
 	xnthread_t *thread;
 	spl_t s;
@@ -1182,28 +1354,67 @@ int rtdm_sem_timeddown(rtdm_sem_t *sem, 
 	return err;
 }
 
-EXPORT_SYMBOL(rtdm_sem_timeddown);
+EXPORT_SYMBOL(_rtdm_sem_timeddown);
 
-/**
- * @brief Increment a semaphore
- *
- * This function increments the given semphore's value, waking up a potential
- * waiter which was blocked upon rtdm_sem_down().
- *
- * @param[in,out] sem Semaphore handle as returned by rtdm_sem_init()
- *
- * Environments:
- *
- * This service can be called from:
- *
- * - Kernel module initialization/cleanup code
- * - Interrupt service routine
- * - Kernel-based task
- * - User-space task (RT, non-RT)
- *
- * Rescheduling: possible.
- */
-void rtdm_sem_up(rtdm_sem_t *sem)
+int _rtdm_select_sem_timeddown(rtdm_select_sem_t *select_sem,
+			       nanosecs_rel_t timeout,
+			       rtdm_toseq_t *timeout_seq)
+{
+	rtdm_sem_t *sem = &select_sem->sem;
+	xnthread_t *thread;
+	spl_t s;
+	int err = 0;
+
+	XENO_ASSERT(RTDM, !xnpod_unblockable_p(), return -EPERM;);
+
+	trace_mark(xn_rtdm_sem_timedwait,
+		   "sem %p timeout %Lu timeout_seq %p timeout_seq_value %Lu",
+		   sem, timeout, timeout_seq, timeout_seq ? *timeout_seq : 0);
+
+	xnlock_get_irqsave(&nklock, s);
+
+	if (testbits(sem->synch_base.status, RTDM_SYNCH_DELETED))
+		err = -EIDRM;
+	else if (sem->value > 0) {
+		sem->value--;
+		if (!sem->value)
+			xnselect_signal(&select_sem->select_block, 0);
+	} else if (timeout < 0) /* non-blocking mode */
+		err = -EWOULDBLOCK;
+	else {
+		thread = xnpod_current_thread();
+
+		if (timeout_seq && (timeout > 0)) {
+			/* timeout sequence */
+			xnsynch_sleep_on(&sem->synch_base, *timeout_seq,
+					 XN_ABSOLUTE);
+		} else {
+			/* infinite or relative timeout */
+			xnsynch_sleep_on(&sem->synch_base,
+					 xntbase_ns2ticks_ceil
+					 (xnthread_time_base(thread), timeout),
+					 XN_RELATIVE);
+		}
+
+		if (xnthread_test_info(thread, XNTIMEO | XNRMID | XNBREAK)) {
+			if (xnthread_test_info(thread, XNTIMEO))
+				err = -ETIMEDOUT;
+			else if (xnthread_test_info(thread, XNRMID))
+				err = -EIDRM;
+			else /* XNBREAK */
+				err = -EINTR;
+		} else if (!sem->value)
+			xnselect_signal(&select_sem->select_block, 0);
+	}
+
+	xnlock_put_irqrestore(&nklock, s);
+
+	return err;
+}
+
+EXPORT_SYMBOL(_rtdm_select_sem_timeddown);
+
+void _rtdm_sem_up(rtdm_sem_t *sem)
 {
 	spl_t s;
 
@@ -1219,7 +1430,28 @@ void rtdm_sem_up(rtdm_sem_t *sem)
 	xnlock_put_irqrestore(&nklock, s);
 }
 
-EXPORT_SYMBOL(rtdm_sem_up);
+EXPORT_SYMBOL(_rtdm_sem_up);
+
+void _rtdm_select_sem_up(rtdm_select_sem_t *select_sem)
+{
+	rtdm_sem_t *sem = &select_sem->sem;
+	spl_t s;
+
+	trace_mark(xn_rtdm_sem_up, "sem %p", sem);
+
+	xnlock_get_irqsave(&nklock, s);
+
+	if (xnsynch_wakeup_one_sleeper(&sem->synch_base))
+		xnpod_schedule();
+	else
+		if (sem->value++ == 0
+		    && xnselect_signal(&select_sem->select_block, 1))
+			xnpod_schedule();
+
+	xnlock_put_irqrestore(&nklock, s);
+}
+
+EXPORT_SYMBOL(_rtdm_select_sem_up);
 /** @} */
 
 /*!
--- ksrc/skins/rtdm/core.c	(revision 3455)
+++ ksrc/skins/rtdm/core.c	(working copy)
@@ -294,6 +294,32 @@ err_out:
 
 EXPORT_SYMBOL(__rt_dev_socket);
 
+int __rt_dev_select_bind(int fd,
+			 struct xnselector *selector,
+			 unsigned type, unsigned index)
+{
+	struct rtdm_dev_context *context;
+	struct rtdm_operations  *ops;
+	int ret;
+
+	context = rtdm_context_get(fd);
+
+	ret = -EBADF;
+	if (unlikely(!context))
+		goto err_out;
+
+	ops = context->ops;
+
+	ret = ops->select_bind(context, selector, type, index);
+
+	XENO_ASSERT(RTDM, !rthal_local_irq_test(), rthal_local_irq_enable(););
+
+	rtdm_context_unlock(context);
+
+  err_out:
+	return ret;
+}
+
 int __rt_dev_close(rtdm_user_info_t *user_info, int fd)
 {
 	struct rtdm_dev_context *context;

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Xenomai-core] [PATCH 3/5] posix skin kernel-space support for user-space select.
  2008-02-02 14:11 [Xenomai-core] [PATCH 0/5] Support for select v2 Gilles Chanteperdrix
  2008-02-02 14:12 ` [Xenomai-core] [PATCH 1/5] select-like services support to xenomai core Gilles Chanteperdrix
  2008-02-02 14:14 ` [Xenomai-core] [PATCH 2/5] select-like services support to rtdm Gilles Chanteperdrix
@ 2008-02-02 14:15 ` Gilles Chanteperdrix
  2008-02-02 14:16 ` [Xenomai-core] [PATCH 4/5] posix skin user-space support for select Gilles Chanteperdrix
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 15+ messages in thread
From: Gilles Chanteperdrix @ 2008-02-02 14:15 UTC (permalink / raw)
  To: xenomai

[-- Attachment #1: message body and .signature --]
[-- Type: text/plain, Size: 1089 bytes --]


This patch adds user-space select support to xenomai posix skin kernel space.

Changes:
- select handles null fd_sets (by passing them to xnselect);
- select returns -EBADF without allocating a struct xnselector, in the
  common case when the wrapped select is called with Linux-only file
  descriptors;
- walking fd_sets to bind unbound file descriptors is now optimized by using
  find_first_bit/find_next_bit;
- the timeout, when not null, is passed as an XN_ABSOLUTE value, so it will be
  handled as a relative timeout if time changes, but will have the proper effect
  if xnsynch_sleep_on is called several times with this timeout value;
- select now returns the remaining time before timeout.

Stats:
 include/posix/syscall.h     |    1
 ksrc/skins/posix/internal.h |   26 ++++++
 ksrc/skins/posix/mq.c       |   78 ++++++++++++++++++-
 ksrc/skins/posix/syscall.c  |  177 ++++++++++++++++++++++++++++++++++++++++++++
 ksrc/skins/posix/thread.c   |    5 +
 ksrc/skins/posix/thread.h   |    4
 6 files changed, 287 insertions(+), 4 deletions(-)

-- 


					    Gilles Chanteperdrix.

[-- Attachment #2: xeno-select-posix-kernel.diff --]
[-- Type: text/plain, Size: 12498 bytes --]

--- include/posix/syscall.h	(revision 3455)
+++ include/posix/syscall.h	(working copy)
@@ -100,6 +100,7 @@
 #define __pse51_condattr_setpshared   74
 #define __pse51_thread_getschedparam  75
 #define __pse51_thread_kill           76
+#define __pse51_select                77
 
 #ifdef __KERNEL__
 
--- ksrc/skins/posix/syscall.c	(revision 3455)
+++ ksrc/skins/posix/syscall.c	(working copy)
@@ -34,6 +34,9 @@
 #include <posix/sem.h>
 #include <posix/shm.h>
 #include <posix/timer.h>
+#ifdef CONFIG_XENO_SKIN_RTDM
+#include <rtdm/core.h>
+#endif /* CONFIG_XENO_SKIN_RTDM */
 
 int pse51_muxid;
 
@@ -1887,6 +1890,179 @@ static int __timer_getoverrun(struct pt_
 	return rc >= 0 ? rc : -thread_get_errno();
 }
 
+static int fd_valid_p(int fd)
+{
+	pse51_assoc_t *assoc;
+#ifdef CONFIG_XENO_SKIN_RTDM
+	const int rtdm_fd_start = FD_SETSIZE - RTDM_FD_MAX;
+	
+	if (fd >= rtdm_fd_start) {
+		struct rtdm_dev_context *ctx;
+		ctx = rtdm_context_get(fd - rtdm_fd_start);
+		if (ctx) {
+			rtdm_context_unlock(ctx);
+			return 1;
+		}
+		return 0;
+	}
+#endif /* CONFIG_XENO_SKIN_RTDM */
+
+	assoc = pse51_assoc_lookup(&pse51_queues()->uqds, fd);
+	return assoc != NULL;
+}
+
+static int first_fd_valid_p(fd_set *fds[XNSELECT_MAX_TYPES], int nfds)
+{
+	int i, fd;
+
+	for (i = 0; i < XNSELECT_MAX_TYPES; i++)
+		if (fds[i]
+		    && (fd = find_first_bit(fds[i]->fds_bits, nfds)) < nfds)
+			return fd_valid_p(fd);
+
+	return 1;
+}
+
+static int select_bind_one(struct xnselector *selector, unsigned type, int fd)
+{
+	pse51_assoc_t *assoc;
+#ifdef CONFIG_XENO_SKIN_RTDM
+	const int rtdm_fd_start = FD_SETSIZE - RTDM_FD_MAX;
+	
+	if (fd >= rtdm_fd_start)
+		return __rt_dev_select_bind(fd - rtdm_fd_start,
+					    selector, type, fd);
+#endif /* CONFIG_XENO_SKIN_RTDM */
+
+	assoc = pse51_assoc_lookup(&pse51_queues()->uqds, fd);
+	if (!assoc)
+		return -EBADF;
+
+	return pse51_mq_select_bind(assoc2ufd(assoc)->kfd, selector, type, fd);
+}
+
+static int select_bind_all(struct xnselector *selector,
+			   fd_set *fds[XNSELECT_MAX_TYPES], int nfds)
+{
+	unsigned fd, type;
+	int err;
+
+	for (type = 0; type < XNSELECT_MAX_TYPES; type++) {
+		fd_set *set = fds[type];
+		if (set)
+			for (fd = find_first_bit(set->fds_bits, nfds);
+			     fd < nfds;
+			     fd = find_next_bit(set->fds_bits, nfds, fd + 1)) {
+				err = select_bind_one(selector, type, fd);
+				if (err)
+					return err;
+			}
+	}
+
+	return 0;
+}
+
+/* int select(int, fd_set *, fd_set *, fd_set *, struct timeval *) */
+static int __select(struct pt_regs *regs)
+{
+	fd_set __user *ufd_sets[XNSELECT_MAX_TYPES] = {
+		[XNSELECT_READ] = (fd_set __user *) __xn_reg_arg2(regs),
+		[XNSELECT_WRITE] = (fd_set __user *) __xn_reg_arg3(regs),
+		[XNSELECT_EXCEPT] = (fd_set __user *) __xn_reg_arg4(regs)
+	};
+	fd_set *in_fds[XNSELECT_MAX_TYPES] = {NULL, NULL, NULL};
+	fd_set *out_fds[XNSELECT_MAX_TYPES] = {NULL, NULL, NULL};
+	fd_set in_fds_storage[XNSELECT_MAX_TYPES],
+		out_fds_storage[XNSELECT_MAX_TYPES];
+	xnticks_t timeout = XN_INFINITE;
+	xntmode_t mode = XN_RELATIVE;
+	struct xnselector *selector;
+	struct timeval tv;
+	pthread_t thread;
+	int i, err, nfds;
+
+	thread = pse51_current_thread();
+	if (!thread)
+		return -EPERM;
+
+	if (__xn_reg_arg5(regs)) {
+		if (__xn_copy_from_user(&tv,
+					(void __user *)__xn_reg_arg5(regs),
+					sizeof(tv)))
+			return -EFAULT;
+
+		if (tv.tv_usec > 1000000)
+			return -EINVAL;
+
+		timeout = clock_get_ticks(CLOCK_MONOTONIC) + tv2ticks_ceil(&tv);
+		mode = XN_ABSOLUTE;
+	}
+
+	nfds = __xn_reg_arg1(regs);
+
+	for (i = 0; i < XNSELECT_MAX_TYPES; i++)
+		if (ufd_sets[i]) {
+			in_fds[i] = &in_fds_storage[i];
+			out_fds[i] = & out_fds_storage[i];
+			if (__xn_copy_from_user(in_fds[i],
+						(void __user *) ufd_sets[i],
+						__FDELT(nfds + __NFDBITS - 1)
+						* sizeof(long)))
+				return -EFAULT;
+		}
+
+	selector = thread->selector;
+	if (!selector) {
+		/* This function may be called from pure Linux fd_sets, we want
+		   to avoid the xnselector allocation in this case, so, we do a
+		   simple test: test if the first file descriptor we find in the
+		   fd_set is an RTDM descriptor or a message queue descriptor. */
+		if (!first_fd_valid_p(in_fds, nfds))
+			return -EBADF;
+
+		if (!(selector = xnmalloc(sizeof(*thread->selector))))
+			return -ENOMEM;
+		xnselector_init(selector);
+		thread->selector = selector;
+
+		/* Bind directly the file descriptors, we do not need to go
+		   through xnselect returning -ECHRNG */
+		if ((err = select_bind_all(selector, in_fds, nfds)))
+			return err;
+	}
+
+	do {
+		err = xnselect(selector, out_fds, in_fds, nfds, timeout, mode);
+
+		if (err == -ECHRNG) {
+			int err = select_bind_all(selector, out_fds, nfds);
+			if (err)
+				return err;
+		}
+	} while (err == -ECHRNG);
+
+	if (__xn_reg_arg5(regs) && (err > 0 || err == -EINTR)) {
+		xnsticks_t diff = timeout - clock_get_ticks(CLOCK_MONOTONIC);
+		if (diff > 0)
+			ticks2tv(&tv, diff);
+		else
+			tv.tv_sec = tv.tv_usec = 0;
+
+		if (__xn_copy_to_user((void __user *)__xn_reg_arg5(regs),
+				      &tv, sizeof(tv)))
+			return -EFAULT;
+	}
+
+	if (err > 0)
+		for (i = 0; i < XNSELECT_MAX_TYPES; i++)
+			if (ufd_sets[i]
+			    && __xn_copy_to_user((void __user *) ufd_sets[i],
+						 out_fds[i], sizeof(fd_set)))
+				return -EFAULT;
+	return err;
+}
+
+
 #ifdef CONFIG_XENO_OPT_POSIX_SHM
 
 /* shm_open(name, oflag, mode, ufd) */
@@ -2285,6 +2461,7 @@ static xnsysent_t __systab[] = {
 	    {&__pthread_condattr_getpshared, __xn_exec_any},
 	[__pse51_condattr_setpshared] =
 	    {&__pthread_condattr_setpshared, __xn_exec_any},
+	[__pse51_select] = {&__select, __xn_exec_primary},
 };
 
 static void __shadow_delete_hook(xnthread_t *thread)
--- ksrc/skins/posix/mq.c	(revision 3455)
+++ ksrc/skins/posix/mq.c	(working copy)
@@ -61,6 +61,8 @@ struct pse51_mq {
 
 	xnholder_t link;	/* link in mqq */
 
+	struct xnselect read_select;
+	struct xnselect write_select;
 #define link2mq(laddr) \
     ((pse51_mq_t *) (((char *)laddr) - offsetof(pse51_mq_t, link)))
 };
@@ -145,6 +147,8 @@ static int pse51_mq_init(pse51_mq_t * mq
 
 	mq->attr = *attr;
 	mq->target = NULL;
+	xnselect_init(&mq->read_select);
+	xnselect_init(&mq->write_select);
 
 	return 0;
 }
@@ -160,6 +164,8 @@ static void pse51_mq_destroy(pse51_mq_t 
 	    (xnsynch_destroy(&mq->senders) == XNSYNCH_RESCHED) || need_resched;
 	removeq(&pse51_mqq, &mq->link);
 	xnlock_put_irqrestore(&nklock, s);
+ 	xnselect_destroy(&mq->read_select);
+ 	xnselect_destroy(&mq->write_select);
 	xnarch_free_host_mem(mq->mem, mq->memsize);
 
 	if (need_resched)
@@ -583,6 +589,7 @@ int pse51_mq_timedsend_inner(pse51_direc
 void pse51_mq_finish_send(mqd_t fd, pse51_direct_msg_t *msgp)
 {
 	pse51_desc_t *desc;
+	int resched = 0;
 	pse51_mq_t *mq;
 
 	pse51_desc_get(&desc, fd, PSE51_MQ_MAGIC);
@@ -595,6 +602,11 @@ void pse51_mq_finish_send(mqd_t fd, pse5
 
 		insertpqf(&mq->queued, &msg->link, msg->link.prio);
 
+ 		if (countpq(&mq->queued) == 1)
+ 			resched = xnselect_signal(&mq->read_select, 1);
+ 		if (countpq(&mq->queued) == mq->attr.mq_maxmsg)
+ 			xnselect_signal(&mq->write_select, 0);
+
 		if (!(msgp->flags & PSE51_MSG_RESCHED)) {
 			if (mq->target && countpq(&mq->queued) == 1) {
 				/* First message ? no pending reader ? attempt
@@ -605,7 +617,7 @@ void pse51_mq_finish_send(mqd_t fd, pse5
 			return;	/* Do not reschedule */
 		}
 	}
-	if (xnsynch_wakeup_one_sleeper(&mq->receivers))
+	if (xnsynch_wakeup_one_sleeper(&mq->receivers) || resched)
 		xnpod_schedule();
 }
 
@@ -676,10 +688,10 @@ int pse51_mq_timedrcv_inner(pse51_direct
 
 void pse51_mq_finish_rcv(mqd_t fd, pse51_direct_msg_t *msgp)
 {
-
 	if (!(msgp->flags & PSE51_MSG_DIRECT)) {
 		pse51_desc_t *desc;
 		pse51_msg_t *msg;
+		int resched = 0;
 		pse51_mq_t *mq;
 
 		pse51_desc_get(&desc, fd, PSE51_MQ_MAGIC);
@@ -688,7 +700,12 @@ void pse51_mq_finish_rcv(mqd_t fd, pse51
 
 		pse51_mq_msg_free(mq, msg);
 
-		if (xnsynch_wakeup_one_sleeper(&mq->senders))
+		if (countpq(&mq->queued) == 0)
+			xnselect_signal(&mq->read_select, 0);
+		if (countpq(&mq->queued) == mq->attr.mq_maxmsg - 1)
+			resched = xnselect_signal(&mq->write_select, 1);
+
+		if (xnsynch_wakeup_one_sleeper(&mq->senders) || resched)
 			xnpod_schedule();
 	}
 }
@@ -1187,6 +1204,61 @@ int mq_notify(mqd_t fd, const struct sig
 	return -1;
 }
 
+int pse51_mq_select_bind(mqd_t fd, struct xnselector *selector,
+			 unsigned type, unsigned index)
+{
+	struct xnselect_binding *binding;
+	pse51_desc_t *desc;
+	pse51_mq_t *mq;
+	int err;
+	spl_t s;
+	
+	if (type == XNSELECT_READ || type == XNSELECT_WRITE) {
+		binding = xnmalloc(sizeof(*binding));
+		if (!binding)
+			return -ENOMEM;
+	} else
+		return -EBADF;
+
+	xnlock_get_irqsave(&nklock, s);
+	err = -pse51_desc_get(&desc, fd, PSE51_MQ_MAGIC);
+	if (err)
+		goto unlock_and_error;
+
+	mq = node2mq(pse51_desc_node(desc));
+
+	switch(type) {
+	case XNSELECT_READ:
+		err = -EBADF;
+		if ((pse51_desc_getflags(desc) & PSE51_PERMS_MASK) == O_WRONLY)
+			goto unlock_and_error;
+
+		err = xnselect_bind(&mq->read_select, binding,
+				    selector, type, index, countpq(&mq->queued));
+		if (err)
+			goto unlock_and_error;
+		break;
+
+	case XNSELECT_WRITE:
+		err = -EBADF;
+		if ((pse51_desc_getflags(desc) & PSE51_PERMS_MASK) == O_RDONLY)
+			goto unlock_and_error;
+
+		err = xnselect_bind(&mq->write_select, binding,
+				    selector, type, index,
+				    countpq(&mq->queued) < mq->attr.mq_maxmsg);
+		if (err)
+			goto unlock_and_error;
+		break;
+	}
+	xnlock_put_irqrestore(&nklock, s);
+	return 0;
+
+      unlock_and_error:
+	xnlock_put_irqrestore(&nklock, s);
+	return err;
+}
+
 #ifdef CONFIG_XENO_OPT_PERVASIVE
 static void uqd_cleanup(pse51_assoc_t *assoc)
 {
--- ksrc/skins/posix/thread.c	(revision 3455)
+++ ksrc/skins/posix/thread.c	(working copy)
@@ -84,6 +84,10 @@ static void thread_delete_hook(xnthread_
 	pse51_mark_deleted(thread);
 	pse51_signal_cleanup_thread(thread);
 	pse51_timer_cleanup_thread(thread);
+	if (thread->selector) {
+		xnselector_destroy(thread->selector);
+		thread->selector = NULL;
+	}
 
 	switch (thread_getdetachstate(thread)) {
 	case PTHREAD_CREATE_DETACHED:
@@ -216,6 +220,7 @@ int pthread_create(pthread_t *tid,
 	pse51_signal_init_thread(thread, cur);
 	pse51_tsd_init_thread(thread);
 	pse51_timer_init_thread(thread);
+	thread->selector = NULL;
 
 	if (thread->attr.policy == SCHED_RR) {
 		xnthread_time_slice(&thread->threadbase) = pse51_time_slice;
--- ksrc/skins/posix/thread.h	(revision 3455)
+++ ksrc/skins/posix/thread.h	(working copy)
@@ -21,6 +21,7 @@
 #define _POSIX_THREAD_H
 
 #include <posix/internal.h>
+#include <nucleus/select.h>
 
 typedef unsigned long long pse51_sigset_t;
 
@@ -90,6 +91,9 @@ struct pse51_thread {
     /* For timers. */
     xnqueue_t timersq;
     
+    /* For select. */
+    struct xnselector *selector;
+
 #ifdef CONFIG_XENO_OPT_PERVASIVE
     struct pse51_hkey hkey;
 #endif /* CONFIG_XENO_OPT_PERVASIVE */
--- ksrc/skins/posix/internal.h	(revision 3455)
+++ ksrc/skins/posix/internal.h	(working copy)
@@ -22,6 +22,7 @@
 #include <nucleus/xenomai.h>
 #include <nucleus/core.h>
 #include <nucleus/ppd.h>
+#include <nucleus/select.h>
 #include <posix/posix.h>
 #include <posix/registry.h>
 
@@ -153,12 +154,32 @@ static inline xnticks_t ts2ticks_ceil(co
     return rem ? ticks+1 : ticks;
 }
 
+static inline xnticks_t tv2ticks_ceil(const struct timeval *tv)
+{
+    xntime_t nsecs = tv->tv_usec * 1000;
+    unsigned long rem;
+    xnticks_t ticks;
+    if(tv->tv_sec)
+        nsecs += (xntime_t) tv->tv_sec * ONE_BILLION;
+    ticks = xnarch_ulldiv(nsecs, xntbase_get_tickval(pse51_tbase), &rem);
+    return rem ? ticks+1 : ticks;
+}
+
+static inline void ticks2tv(struct timeval *tv, xnticks_t ticks)
+{
+    unsigned long nsecs;
+    tv->tv_sec = xnarch_uldivrem(xntbase_ticks2ns(pse51_tbase, ticks),
+                                 ONE_BILLION,
+                                 &nsecs);
+    tv->tv_usec = nsecs / 1000;
+}
+
 static inline xnticks_t clock_get_ticks(clockid_t clock_id)
 {
     if(clock_id == CLOCK_REALTIME)
         return xntbase_get_time(pse51_tbase);
     else
-        return xntbase_ns2ticks(pse51_tbase, xnpod_get_cpu_time());
+        return xntbase_get_jiffies(pse51_tbase);
 }
 
 static inline int clock_flag(int flag, clockid_t clock_id)
@@ -179,4 +200,7 @@ static inline int clock_flag(int flag, c
 	return -EINVAL;
 }
 
+int pse51_mq_select_bind(mqd_t fd, struct xnselector *selector,
+			 unsigned type, unsigned index);
+
 #endif /* !_POSIX_INTERNAL_H */

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Xenomai-core] [PATCH 4/5] posix skin user-space support for select.
  2008-02-02 14:11 [Xenomai-core] [PATCH 0/5] Support for select v2 Gilles Chanteperdrix
                   ` (2 preceding siblings ...)
  2008-02-02 14:15 ` [Xenomai-core] [PATCH 3/5] posix skin kernel-space support for user-space select Gilles Chanteperdrix
@ 2008-02-02 14:16 ` Gilles Chanteperdrix
  2008-02-02 14:29 ` [Xenomai-core] [PATCH 0/5] Support for select v2 Jan Kiszka
  2008-02-03 22:16 ` Jan Kiszka
  5 siblings, 0 replies; 15+ messages in thread
From: Gilles Chanteperdrix @ 2008-02-02 14:16 UTC (permalink / raw)
  To: xenomai

[-- Attachment #1: message body and .signature --]
[-- Type: text/plain, Size: 424 bytes --]


This patch adds support for select to xenomai posix skin user-space.

No changes.

Stats:
 include/posix/sys/select.h     |   23 +++++++++++++++++++++++
 src/skins/posix/Makefile.am    |    1 +
 src/skins/posix/posix.wrappers |    1 +
 src/skins/posix/select.c       |   26 ++++++++++++++++++++++++++
 src/skins/posix/wrappers.c     |    9 +++++++++
 5 files changed, 60 insertions(+)

-- 


					    Gilles Chanteperdrix.

[-- Attachment #2: xeno-select-posix-user.diff --]
[-- Type: text/plain, Size: 2347 bytes --]

--- include/posix/sys/select.h	(revision 0)
+++ include/posix/sys/select.h	(revision 0)
@@ -0,0 +1,23 @@
+#ifndef _XENO_POSIX_SELECT_H
+#define _XENO_POSIX_SELECT_H
+
+#if !(defined(__KERNEL__) || defined(__XENO_SIM__))
+
+#include_next <sys/select.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int __real_select (int __nfds, fd_set *__restrict __readfds,
+			  fd_set *__restrict __writefds,
+			  fd_set *__restrict __exceptfds,
+			  struct timeval *__restrict __timeout);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !(__KERNEL__ || __XENO_SIM__) */
+
+#endif /* _XENO_POSIX_SELECT_H */
--- src/skins/posix/wrappers.c	(revision 3455)
+++ src/skins/posix/wrappers.c	(working copy)
@@ -30,6 +30,7 @@
 #include <unistd.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
+#include <sys/select.h>
 
 /* sched */
 int __real_pthread_setschedparam(pthread_t thread,
@@ -235,3 +236,11 @@ int __real_munmap(void *addr, size_t len
 {
 	return munmap(addr, len);
 }
+
+int __real_select (int __nfds, fd_set *__restrict __readfds,
+		   fd_set *__restrict __writefds,
+		   fd_set *__restrict __exceptfds,
+		   struct timeval *__restrict __timeout)
+{
+	return select(__nfds, __readfds, __writefds, __exceptfds, __timeout);
+}
--- src/skins/posix/select.c	(revision 0)
+++ src/skins/posix/select.c	(revision 0)
@@ -0,0 +1,26 @@
+#include <errno.h>
+#include <posix/syscall.h>
+#include <sys/select.h>
+
+extern int __pse51_muxid;
+
+int __wrap_select (int __nfds, fd_set *__restrict __readfds,
+		   fd_set *__restrict __writefds,
+		   fd_set *__restrict __exceptfds,
+		   struct timeval *__restrict __timeout)
+{
+	int err;
+
+	err = XENOMAI_SKINCALL5(__pse51_muxid, __pse51_select, __nfds,
+				__readfds, __writefds, __exceptfds, __timeout);
+
+	if (err == -EBADF || err == -EPERM)
+		return __real_select(__nfds, __readfds,
+				     __writefds, __exceptfds, __timeout);
+
+	if (err > 0)
+		return err;
+
+	errno = -err;
+	return -1;
+}
--- src/skins/posix/posix.wrappers	(revision 3455)
+++ src/skins/posix/posix.wrappers	(working copy)
@@ -87,3 +87,4 @@
 --wrap shm_unlink
 --wrap mmap
 --wrap munmap
+--wrap select
--- src/skins/posix/Makefile.am	(revision 3455)
+++ src/skins/posix/Makefile.am	(working copy)
@@ -15,6 +15,7 @@ libpthread_rt_la_SOURCES = \
 	mutex.c \
 	shm.c \
 	interrupt.c \
+	select.c \
 	rtdm.c \
 	wrappers.c
 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Xenomai-core] [PATCH 5/5] RTDM: check file descriptor owner.
  2008-02-02 14:12 ` [Xenomai-core] [PATCH 1/5] select-like services support to xenomai core Gilles Chanteperdrix
@ 2008-02-02 14:18   ` Gilles Chanteperdrix
  2008-02-03 22:18     ` Jan Kiszka
  0 siblings, 1 reply; 15+ messages in thread
From: Gilles Chanteperdrix @ 2008-02-02 14:18 UTC (permalink / raw)
  To: xenomai

[-- Attachment #1: message body and .signature --]
[-- Type: text/plain, Size: 443 bytes --]


This patch makes RTDM service rtdm_context_get check the owner of a file
descriptor. This will prevent a process to close an RTDM file descriptor
belonging to another process.

Stats:
 include/rtdm/rtdm.h        |    2 +-
 include/rtdm/rtdm_driver.h |    2 +-
 ksrc/skins/posix/syscall.c |    5 +++--
 ksrc/skins/rtdm/core.c     |   15 +++++++++------
 4 files changed, 14 insertions(+), 10 deletions(-)

-- 


					    Gilles Chanteperdrix.

[-- Attachment #2: xeno-rtdm-check-owner.diff --]
[-- Type: text/plain, Size: 4073 bytes --]

diff -Naurdp -x '*~' trunk/include/rtdm/rtdm.h rtdm_check_context/include/rtdm/rtdm.h
--- trunk/include/rtdm/rtdm.h	2008-01-25 21:20:40.000000000 +0100
+++ rtdm_check_context/include/rtdm/rtdm.h	2008-02-02 14:22:36.000000000 +0100
@@ -248,7 +248,7 @@ ssize_t __rt_dev_recvmsg(rtdm_user_info_
 ssize_t __rt_dev_sendmsg(rtdm_user_info_t *user_info, int fd,
 			 const struct msghdr *msg, int flags);
 struct xnselector;
-int __rt_dev_select_bind(int fd,
+int __rt_dev_select_bind(rtdm_user_info_t *user_info, int fd,
 			 struct xnselector *selector,
 			 unsigned type, unsigned index);
 #endif /* __KERNEL__ */
diff -Naurdp -x '*~' trunk/include/rtdm/rtdm_driver.h rtdm_check_context/include/rtdm/rtdm_driver.h
--- trunk/include/rtdm/rtdm_driver.h	2008-01-25 21:33:13.000000000 +0100
+++ rtdm_check_context/include/rtdm/rtdm_driver.h	2008-02-02 14:16:18.000000000 +0100
@@ -461,7 +461,7 @@ int rtdm_dev_unregister(struct rtdm_devi
 #define rtdm_getpeername	rt_dev_getpeername
 #define rtdm_shutdown		rt_dev_shutdown
 
-struct rtdm_dev_context *rtdm_context_get(int fd);
+struct rtdm_dev_context *rtdm_context_get(rtdm_user_info_t *user_info, int fd);
 
 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
 static inline void rtdm_context_lock(struct rtdm_dev_context *context)
diff -Naurdp -x '*~' trunk/ksrc/skins/posix/syscall.c rtdm_check_context/ksrc/skins/posix/syscall.c
--- trunk/ksrc/skins/posix/syscall.c	2008-02-02 14:30:56.000000000 +0100
+++ rtdm_check_context/ksrc/skins/posix/syscall.c	2008-02-02 14:33:30.000000000 +0100
@@ -1898,7 +1898,7 @@ static int fd_valid_p(int fd)
 	
 	if (fd >= rtdm_fd_start) {
 		struct rtdm_dev_context *ctx;
-		ctx = rtdm_context_get(fd - rtdm_fd_start);
+		ctx = rtdm_context_get(current, fd - rtdm_fd_start);
 		if (ctx) {
 			rtdm_context_unlock(ctx);
 			return 1;
@@ -1930,7 +1930,8 @@ static int select_bind_one(struct xnsele
 	const int rtdm_fd_start = FD_SETSIZE - RTDM_FD_MAX;
 	
 	if (fd >= rtdm_fd_start)
-		return __rt_dev_select_bind(fd - rtdm_fd_start,
+		return __rt_dev_select_bind(current,
+					    fd - rtdm_fd_start,
 					    selector, type, fd);
 #endif /* CONFIG_XENO_SKIN_RTDM */
 
diff -Naurdp -x '*~' trunk/ksrc/skins/rtdm/core.c rtdm_check_context/ksrc/skins/rtdm/core.c
--- trunk/ksrc/skins/rtdm/core.c	2008-01-25 21:20:40.000000000 +0100
+++ rtdm_check_context/ksrc/skins/rtdm/core.c	2008-02-02 14:20:06.000000000 +0100
@@ -70,7 +70,7 @@ DEFINE_XNLOCK(rt_fildes_lock);
  *
  * Rescheduling: never.
  */
-struct rtdm_dev_context *rtdm_context_get(int fd)
+struct rtdm_dev_context *rtdm_context_get(rtdm_user_info_t *user_info, int fd)
 {
 	struct rtdm_dev_context *context;
 	spl_t s;
@@ -82,7 +82,9 @@ struct rtdm_dev_context *rtdm_context_ge
 
 	context = fildes_table[fd].context;
 	if (unlikely(!context ||
-		     test_bit(RTDM_CLOSING, &context->context_flags))) {
+		     test_bit(RTDM_CLOSING, &context->context_flags) ||
+		     context->reserved.owner != (user_info
+						 ? user_info->mm : NULL))) {
 		xnlock_put_irqrestore(&rt_fildes_lock, s);
 		return NULL;
 	}
@@ -294,7 +296,7 @@ err_out:
 
 EXPORT_SYMBOL(__rt_dev_socket);
 
-int __rt_dev_select_bind(int fd,
+int __rt_dev_select_bind(rtdm_user_info_t *user_info, int fd,
 			 struct xnselector *selector,
 			 unsigned type, unsigned index)
 {
@@ -302,7 +304,7 @@ int __rt_dev_select_bind(int fd,
 	struct rtdm_operations  *ops;
 	int ret;
 
-	context = rtdm_context_get(fd);
+	context = rtdm_context_get(user_info, fd);
 
 	ret = -EBADF;
 	if (unlikely(!context))
@@ -338,7 +340,8 @@ again:
 
 	context = fildes_table[fd].context;
 
-	if (unlikely(!context)) {
+	if (unlikely(!context ||
+		     (user_info && context->reserved.owner != user_info->mm))) {
 		xnlock_put_irqrestore(&rt_fildes_lock, s);
 		goto err_out;	/* -EBADF */
 	}
@@ -434,7 +437,7 @@ do {									\
 	struct rtdm_operations *ops;					\
 	int ret;							\
 									\
-	context = rtdm_context_get(fd);					\
+	context = rtdm_context_get(user_info, fd);			\
 	ret = -EBADF;							\
 	if (unlikely(!context))						\
 		goto err_out;						\

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Xenomai-core] [PATCH 0/5] Support for select v2.
  2008-02-02 14:11 [Xenomai-core] [PATCH 0/5] Support for select v2 Gilles Chanteperdrix
                   ` (3 preceding siblings ...)
  2008-02-02 14:16 ` [Xenomai-core] [PATCH 4/5] posix skin user-space support for select Gilles Chanteperdrix
@ 2008-02-02 14:29 ` Jan Kiszka
  2008-02-02 14:36   ` Gilles Chanteperdrix
  2008-02-02 15:12   ` Gilles Chanteperdrix
  2008-02-03 22:16 ` Jan Kiszka
  5 siblings, 2 replies; 15+ messages in thread
From: Jan Kiszka @ 2008-02-02 14:29 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 384 bytes --]

Gilles Chanteperdrix wrote:
> Hi,
> 
> after some tests, bug fixes and optimizations, here comes a second version of 
> the patch-set adding select support to xenomai posix skin.

It's on my agenda for today or tomorrow to have a closer look at this.
Just one general question already: Why is it "select" and not "poll and
select"? Is it trivial to extend later on?

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 254 bytes --]

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Xenomai-core] [PATCH 0/5] Support for select v2.
  2008-02-02 14:29 ` [Xenomai-core] [PATCH 0/5] Support for select v2 Jan Kiszka
@ 2008-02-02 14:36   ` Gilles Chanteperdrix
  2008-02-02 15:12   ` Gilles Chanteperdrix
  1 sibling, 0 replies; 15+ messages in thread
From: Gilles Chanteperdrix @ 2008-02-02 14:36 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:
 > Gilles Chanteperdrix wrote:
 > > Hi,
 > > 
 > > after some tests, bug fixes and optimizations, here comes a second version of 
 > > the patch-set adding select support to xenomai posix skin.
 > 
 > It's on my agenda for today or tomorrow to have a closer look at this.
 > Just one general question already: Why is it "select" and not "poll and
 > select"? Is it trivial to extend later on?

Because making an O(1) poll is impossible, when entering poll, you have
to scan the whole list of file descriptors for new descriptors, and this
will take O(n). In select implementation, this is done with bounded bit
operations so remains O(1). Of course, the downside is that you are
limited to FD_SETSIZE (that is 1024) descriptors, but I do not find this
limitation unbearable for real-time applications.

Anyway, you can implement poll in user-space to use select. I saw this
for instance in Asterisk sources.

-- 


					    Gilles Chanteperdrix.


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Xenomai-core] [PATCH 0/5] Support for select v2.
  2008-02-02 14:29 ` [Xenomai-core] [PATCH 0/5] Support for select v2 Jan Kiszka
  2008-02-02 14:36   ` Gilles Chanteperdrix
@ 2008-02-02 15:12   ` Gilles Chanteperdrix
  1 sibling, 0 replies; 15+ messages in thread
From: Gilles Chanteperdrix @ 2008-02-02 15:12 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

[-- Attachment #1: message body and .signature --]
[-- Type: text/plain, Size: 560 bytes --]

Jan Kiszka wrote:
 > Gilles Chanteperdrix wrote:
 > > Hi,
 > > 
 > > after some tests, bug fixes and optimizations, here comes a second version of 
 > > the patch-set adding select support to xenomai posix skin.
 > 
 > It's on my agenda for today or tomorrow to have a closer look at this.
 > Just one general question already: Why is it "select" and not "poll and
 > select"? Is it trivial to extend later on?

The patch I sent for adding select support to RTnet sockets was
uselessly complicated. Here is a simpler one.

-- 


					    Gilles Chanteperdrix.

[-- Attachment #2: rtnet-select.2.diff --]
[-- Type: text/plain, Size: 3128 bytes --]

Index: stack/ipv4/af_inet.c
===================================================================
--- stack/ipv4/af_inet.c	(r������vision 6193)
+++ stack/ipv4/af_inet.c	(copie de travail)
@@ -294,6 +294,7 @@ static struct rtdm_device ipv4_device = 
         ioctl_nrt:      rt_udp_ioctl,
         recvmsg_rt:     rt_udp_recvmsg,
         sendmsg_rt:     rt_udp_sendmsg,
+	select_bind:    rt_socket_select_bind,
 #ifdef CONFIG_RTNET_RTDM_SELECT
         poll_rt:        rt_udp_poll,
         /* there should be only the function poll() */
Index: stack/include/rtnet_socket.h
===================================================================
--- stack/include/rtnet_socket.h	(r������vision 6193)
+++ stack/include/rtnet_socket.h	(copie de travail)
@@ -51,7 +51,7 @@ struct rtsocket {
     unsigned int            priority;
     nanosecs_rel_t          timeout;    /* receive timeout, 0 for infinite */
 
-    rtdm_sem_t              pending_sem;
+    rtdm_select_sem_t       pending_sem;
 #ifdef CONFIG_RTNET_RTDM_SELECT
     wait_queue_primitive_t  *wakeup_select; /* for selecting calls - this
                                                SHOULD be the head of a wait
@@ -96,6 +96,10 @@ static inline struct rtdm_dev_context *r
     atomic_dec(&(rt_socket_context(sock)->close_lock_count))
 
 extern int rt_socket_init(struct rtdm_dev_context *context);
+extern int rt_socket_select_bind(struct rtdm_dev_context *context,
+				 struct xnselector *selector,
+				 unsigned type,
+				 unsigned index);
 extern int rt_socket_cleanup(struct rtdm_dev_context *context);
 extern int rt_socket_common_ioctl(struct rtdm_dev_context *context,
                                   rtdm_user_info_t *user_info,
Index: stack/packet/af_packet.c
===================================================================
--- stack/packet/af_packet.c	(r������vision 6193)
+++ stack/packet/af_packet.c	(copie de travail)
@@ -467,7 +467,8 @@ static struct rtdm_device   packet_proto
         ioctl_rt:       rt_packet_ioctl,
         ioctl_nrt:      rt_packet_ioctl,
         recvmsg_rt:     rt_packet_recvmsg,
-        sendmsg_rt:     rt_packet_sendmsg
+        sendmsg_rt:     rt_packet_sendmsg,
+	select_bind:    rt_socket_select_bind,	
     },
 
     device_class:       RTDM_CLASS_NETWORK,
Index: stack/socket.c
===================================================================
--- stack/socket.c	(r������vision 6193)
+++ stack/socket.c	(copie de travail)
@@ -87,7 +87,25 @@ int rt_socket_init(struct rtdm_dev_conte
     return 0;
 }
 
+int rt_socket_select_bind(struct rtdm_dev_context *context,
+			  struct xnselector *selector,
+			  unsigned type,
+			  unsigned index)
+{
+    struct rtsocket     *sock = (struct rtsocket *)&context->dev_private;
+
+    switch(type) {
+    case XNSELECT_READ:
+	return rtdm_select_sem_bind(&sock->pending_sem, selector, type, index);
+
+    case XNSELECT_WRITE:
+    case XNSELECT_EXCEPT:
+	return -EBADF;
+    }
 
+    return -EINVAL;
+}
+EXPORT_SYMBOL(rt_socket_select_bind);
 
 /***
  *  rt_socket_cleanup - releases resources allocated for the socket

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Xenomai-core] [PATCH 0/5] Support for select v2.
  2008-02-02 14:11 [Xenomai-core] [PATCH 0/5] Support for select v2 Gilles Chanteperdrix
                   ` (4 preceding siblings ...)
  2008-02-02 14:29 ` [Xenomai-core] [PATCH 0/5] Support for select v2 Jan Kiszka
@ 2008-02-03 22:16 ` Jan Kiszka
  2008-02-04  6:34   ` Gilles Chanteperdrix
  2008-02-09 15:41   ` Gilles Chanteperdrix
  5 siblings, 2 replies; 15+ messages in thread
From: Jan Kiszka @ 2008-02-03 22:16 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 866 bytes --]

Gilles Chanteperdrix wrote:
> Hi,
> 
> after some tests, bug fixes and optimizations, here comes a second version of 
> the patch-set adding select support to xenomai posix skin.
> 

Puh, a lot of code, and my brain is still full of KGDB stuff I'm trying
to polish for mainline since days.

The approach looks consistent to me. I would just suggest to make the
whole thing configurable, so that it doesn't add overhead to systems
which do not use it.

Out of curiosity: Did you already have a chance to compare a
multi-threaded demo application with one based on these new select services?

I guess your current test cases are built on top of RTnet, aren't they?
Would be nice, also for regression testing, to have some demo for
/examples, e.g. exploiting the CAN stack (because it has virtual CAN,
thus it is usable without hardware).

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 254 bytes --]

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Xenomai-core] [PATCH 5/5] RTDM: check file descriptor owner.
  2008-02-02 14:18   ` [Xenomai-core] [PATCH 5/5] RTDM: check file descriptor owner Gilles Chanteperdrix
@ 2008-02-03 22:18     ` Jan Kiszka
  2008-02-04  6:40       ` Gilles Chanteperdrix
  0 siblings, 1 reply; 15+ messages in thread
From: Jan Kiszka @ 2008-02-03 22:18 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 635 bytes --]

Gilles Chanteperdrix wrote:
> This patch makes RTDM service rtdm_context_get check the owner of a file
> descriptor. This will prevent a process to close an RTDM file descriptor
> belonging to another process.

I assume this is a safety belt against crazy applications, right? Hope
one day we can solve this via process-local FD name spaces.

I'm OK with this if you keep the API of rtdm_context_get as is and add
an internal checked service __rtdm_context_get(user_info, fd) instead.
rtdm_context_get would then call __rtdm_context_get(NULL, fd) because it
is supposed to operate on kernel file descriptors only.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 254 bytes --]

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Xenomai-core] [PATCH 0/5] Support for select v2.
  2008-02-03 22:16 ` Jan Kiszka
@ 2008-02-04  6:34   ` Gilles Chanteperdrix
  2008-02-09 15:41   ` Gilles Chanteperdrix
  1 sibling, 0 replies; 15+ messages in thread
From: Gilles Chanteperdrix @ 2008-02-04  6:34 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:
 > Gilles Chanteperdrix wrote:
 > > Hi,
 > > 
 > > after some tests, bug fixes and optimizations, here comes a second version of 
 > > the patch-set adding select support to xenomai posix skin.
 > > 
 > 
 > Puh, a lot of code, and my brain is still full of KGDB stuff I'm trying
 > to polish for mainline since days.
 > 
 > The approach looks consistent to me. I would just suggest to make the
 > whole thing configurable, so that it doesn't add overhead to systems
 > which do not use it.

The core support does not take that much code. The RTDM patch however is
huge, that is because we duplicate each rtdm_event and rtdm_sem service
for the select-enabled objects. What would you think of adding select
support to the rtdm_event and rtdm_sem objects without creating the new
rtdm_select_event_t and rtdm_select_sem_t objects if the whole select
support was configurable ? That is if select support is not selected,
RTDM is as before, if select is enabled, rtdm_event_t and rtdm_sem_t
objects may be used with select.

 > 
 > Out of curiosity: Did you already have a chance to compare a
 > multi-threaded demo application with one based on these new select services?

We compared two standard Linux applications, one using select, the other
being threaded, and there is no question: the select based scales much
better. But as usual, it was on low end ARM hardware.

 > 
 > I guess your current test cases are built on top of RTnet, aren't they?
 > Would be nice, also for regression testing, to have some demo for
 > /examples, e.g. exploiting the CAN stack (because it has virtual CAN,
 > thus it is usable without hardware).

Ok, will probably do that.


-- 


					    Gilles Chanteperdrix.


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Xenomai-core] [PATCH 5/5] RTDM: check file descriptor owner.
  2008-02-03 22:18     ` Jan Kiszka
@ 2008-02-04  6:40       ` Gilles Chanteperdrix
  0 siblings, 0 replies; 15+ messages in thread
From: Gilles Chanteperdrix @ 2008-02-04  6:40 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:
 > Gilles Chanteperdrix wrote:
 > > This patch makes RTDM service rtdm_context_get check the owner of a file
 > > descriptor. This will prevent a process to close an RTDM file descriptor
 > > belonging to another process.
 > 
 > I assume this is a safety belt against crazy applications, right?

Not that much crazy: there is no way for an application to know if some
file descriptors were passed to it accross exec, so the only way to be
sure to avoid leaks is to forcibly close all file descriptors. When such
an application was compiled for Xenomai, it suddenly closed all file
descriptors in the system.

 > Hope one day we can solve this via process-local FD name spaces.

I am thinking about this FD rework, we should start writing our
requirements in the wiki.

 > 
 > I'm OK with this if you keep the API of rtdm_context_get as is and add
 > an internal checked service __rtdm_context_get(user_info, fd) instead.
 > rtdm_context_get would then call __rtdm_context_get(NULL, fd) because it
 > is supposed to operate on kernel file descriptors only.

Ok, will do that.

-- 


					    Gilles Chanteperdrix.


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Xenomai-core] [PATCH 0/5] Support for select v2.
  2008-02-03 22:16 ` Jan Kiszka
  2008-02-04  6:34   ` Gilles Chanteperdrix
@ 2008-02-09 15:41   ` Gilles Chanteperdrix
  2008-02-09 15:58     ` Jan Kiszka
  1 sibling, 1 reply; 15+ messages in thread
From: Gilles Chanteperdrix @ 2008-02-09 15:41 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:
 > Gilles Chanteperdrix wrote:
 > > Hi,
 > > 
 > > after some tests, bug fixes and optimizations, here comes a second version of 
 > > the patch-set adding select support to xenomai posix skin.
 > > 
 > 
 > Puh, a lot of code, and my brain is still full of KGDB stuff I'm trying
 > to polish for mainline since days.
 > 
 > The approach looks consistent to me. I would just suggest to make the
 > whole thing configurable, so that it doesn't add overhead to systems
 > which do not use it.

I am getting back to this select stuff. So I have a question, would you
agree if the select support was made configurable, but if when this
support was enabled, support for select was added to vanilla
rtdm_event_t and rtdm_sem_t ? This would ease maintenance, since it
would avoid a lot of code duplication, without adding to much overhead
in my opinion (an empty list test when signaling the objects).

 > 
 > Out of curiosity: Did you already have a chance to compare a
 > multi-threaded demo application with one based on these new select services?
 > 
 > I guess your current test cases are built on top of RTnet, aren't they?
 > Would be nice, also for regression testing, to have some demo for
 > /examples, e.g. exploiting the CAN stack (because it has virtual CAN,
 > thus it is usable without hardware).

Ok, I had a look at the CAN stack, if I understand correctly when
receiving, the recv_sem defined in rcan_socket.h is used, and when
sending, the tx_sem defined in rtcan_dev.h is used. Can you confirm this
? 

-- 


					    Gilles Chanteperdrix.


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Xenomai-core] [PATCH 0/5] Support for select v2.
  2008-02-09 15:41   ` Gilles Chanteperdrix
@ 2008-02-09 15:58     ` Jan Kiszka
  0 siblings, 0 replies; 15+ messages in thread
From: Jan Kiszka @ 2008-02-09 15:58 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 1861 bytes --]

Gilles Chanteperdrix wrote:
> Jan Kiszka wrote:
>  > Gilles Chanteperdrix wrote:
>  > > Hi,
>  > > 
>  > > after some tests, bug fixes and optimizations, here comes a second version of 
>  > > the patch-set adding select support to xenomai posix skin.
>  > > 
>  > 
>  > Puh, a lot of code, and my brain is still full of KGDB stuff I'm trying
>  > to polish for mainline since days.
>  > 
>  > The approach looks consistent to me. I would just suggest to make the
>  > whole thing configurable, so that it doesn't add overhead to systems
>  > which do not use it.
> 
> I am getting back to this select stuff. So I have a question, would you
> agree if the select support was made configurable, but if when this
> support was enabled, support for select was added to vanilla
> rtdm_event_t and rtdm_sem_t ? This would ease maintenance, since it
> would avoid a lot of code duplication, without adding to much overhead
> in my opinion (an empty list test when signaling the objects).

Looking at the code again, this really makes sense, go for it.

> 
>  > 
>  > Out of curiosity: Did you already have a chance to compare a
>  > multi-threaded demo application with one based on these new select services?
>  > 
>  > I guess your current test cases are built on top of RTnet, aren't they?
>  > Would be nice, also for regression testing, to have some demo for
>  > /examples, e.g. exploiting the CAN stack (because it has virtual CAN,
>  > thus it is usable without hardware).
> 
> Ok, I had a look at the CAN stack, if I understand correctly when
> receiving, the recv_sem defined in rcan_socket.h is used, and when
> sending, the tx_sem defined in rtcan_dev.h is used. Can you confirm this
> ? 

Yep, that's correct. rx_sem counts received packets, tx_sem the number
of available output slots in the CAN port.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 254 bytes --]

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2008-02-09 15:58 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-02-02 14:11 [Xenomai-core] [PATCH 0/5] Support for select v2 Gilles Chanteperdrix
2008-02-02 14:12 ` [Xenomai-core] [PATCH 1/5] select-like services support to xenomai core Gilles Chanteperdrix
2008-02-02 14:18   ` [Xenomai-core] [PATCH 5/5] RTDM: check file descriptor owner Gilles Chanteperdrix
2008-02-03 22:18     ` Jan Kiszka
2008-02-04  6:40       ` Gilles Chanteperdrix
2008-02-02 14:14 ` [Xenomai-core] [PATCH 2/5] select-like services support to rtdm Gilles Chanteperdrix
2008-02-02 14:15 ` [Xenomai-core] [PATCH 3/5] posix skin kernel-space support for user-space select Gilles Chanteperdrix
2008-02-02 14:16 ` [Xenomai-core] [PATCH 4/5] posix skin user-space support for select Gilles Chanteperdrix
2008-02-02 14:29 ` [Xenomai-core] [PATCH 0/5] Support for select v2 Jan Kiszka
2008-02-02 14:36   ` Gilles Chanteperdrix
2008-02-02 15:12   ` Gilles Chanteperdrix
2008-02-03 22:16 ` Jan Kiszka
2008-02-04  6:34   ` Gilles Chanteperdrix
2008-02-09 15:41   ` Gilles Chanteperdrix
2008-02-09 15:58     ` Jan Kiszka

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.