All of lore.kernel.org
 help / color / mirror / Atom feed
* [Xenomai] RTDM rework
@ 2014-02-01 18:23 Gilles Chanteperdrix
  2014-02-01 18:27 ` [Xenomai] [PATCH 1/3] cobalt/rtdm: base protocol devices on xnid Gilles Chanteperdrix
  2014-02-02  0:21 ` [Xenomai] RTDM rework Gilles Chanteperdrix
  0 siblings, 2 replies; 7+ messages in thread
From: Gilles Chanteperdrix @ 2014-02-01 18:23 UTC (permalink / raw)
  To: Jan Kiszka, Philippe Gerum; +Cc: Xenomai


Hi Jan, Philippe,

I have started working on rebasing RTDM on the common fd implementation
(xnfd). Before I start changing the drivers, the current state of the
changes follow as patches. These patches are based on the commits in the
"for-forge" branch in xenomai-gch repository. Please do not pull from
this branch just yet, it is probably going to be rebased.

The thing which I know we will discuss, even before you read the patches:
- struct xnfd appears instead of struct rtdm_dev_context in callbacks,
we already discussed that, you prefer rtdm typedefs, the thing is, in
forge, the habit to typedef structs seems gone, and typedef struct xnfd
rtdm_dev_contex_t would be confusing since struct rtdm_dev_context still
exists, albeit is no longer exported to drivers;
- the xnfd structure is defined in cobalt, and not cobalt/posix, this
was made so that both rtdm and posix can use it, but maybe it makes more
sense to move it to posix (after all, file descriptors are a posix
thing), and get rtdm to use it anyway;
- doc is probably out of sync, this will be arranged in later commits
- maybe select should be moved to fd.c now, posix/select.c contains 3
functions, and it now supports xnfds exclusively;
- context_flags are gone, since the two flags it used are no longer
used, since driver have a private structure, drivers can move their
flags to their private structure if they want;
- handling -EAGAIN in the close callback is gone, the close callback now
returns void, it is possible to delay file descriptor destruction by
using rtdm_lock/rtdm_unlock, so the -EAGAIN return value was IMO redundant.

Regards.

-- 
                                                                Gilles.


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

* [Xenomai] [PATCH 1/3] cobalt/rtdm: base protocol devices on xnid
  2014-02-01 18:23 [Xenomai] RTDM rework Gilles Chanteperdrix
@ 2014-02-01 18:27 ` Gilles Chanteperdrix
  2014-02-01 18:27   ` [Xenomai] [PATCH 2/3] cobalt/rtdm: base named devices on nucleus registry Gilles Chanteperdrix
  2014-02-01 18:27   ` [Xenomai] [PATCH 3/3] cobalt/rtdm: base on common fd implementation Gilles Chanteperdrix
  2014-02-02  0:21 ` [Xenomai] RTDM rework Gilles Chanteperdrix
  1 sibling, 2 replies; 7+ messages in thread
From: Gilles Chanteperdrix @ 2014-02-01 18:27 UTC (permalink / raw)
  To: xenomai

---
 include/cobalt/kernel/rtdm/driver.h |    6 +-
 kernel/cobalt/rtdm/device.c         |  103 ++++++++++++-----------------------
 kernel/cobalt/rtdm/internal.h       |    4 +-
 kernel/cobalt/rtdm/proc.c           |   60 ++++++++++----------
 4 files changed, 71 insertions(+), 102 deletions(-)

diff --git a/include/cobalt/kernel/rtdm/driver.h b/include/cobalt/kernel/rtdm/driver.h
index 3e1795c..881f517 100644
--- a/include/cobalt/kernel/rtdm/driver.h
+++ b/include/cobalt/kernel/rtdm/driver.h
@@ -38,6 +38,7 @@
 #include <cobalt/kernel/clock.h>
 #include <cobalt/kernel/apc.h>
 #include <cobalt/kernel/shadow.h>
+#include <cobalt/kernel/tree.h>
 #include <rtdm/rtdm.h>
 
 /* debug support */
@@ -443,7 +444,10 @@ rtdm_private_to_context(void *dev_private)
 }
 
 struct rtdm_dev_reserved {
-	struct list_head entry;
+	union {
+		struct list_head entry;
+		struct xnid id;
+	};
 	atomic_t refcount;
 	struct rtdm_dev_context *exclusive_context;
 };
diff --git a/kernel/cobalt/rtdm/device.c b/kernel/cobalt/rtdm/device.c
index 1aa2542..38353ee 100644
--- a/kernel/cobalt/rtdm/device.c
+++ b/kernel/cobalt/rtdm/device.c
@@ -45,19 +45,13 @@
 	((device).operation##_rt || (device).operation##_nrt)
 
 unsigned int devname_hashtab_size = DEF_DEVNAME_HASHTAB_SIZE;
-unsigned int protocol_hashtab_size = DEF_PROTO_HASHTAB_SIZE;
 module_param(devname_hashtab_size, uint, 0400);
-module_param(protocol_hashtab_size, uint, 0400);
 MODULE_PARM_DESC(devname_hashtab_size,
 		 "Size of hash table for named devices (must be power of 2)");
-MODULE_PARM_DESC(protocol_hashtab_size,
-		 "Size of hash table for protocol devices "
-		 "(must be power of 2)");
 
 struct list_head *rtdm_named_devices;	/* hash table */
-struct list_head *rtdm_protocol_devices;	/* hash table */
 static int name_hashkey_mask;
-static int proto_hashkey_mask;
+struct rb_root rtdm_protocol_devices;
 
 int rtdm_apc;
 EXPORT_SYMBOL_GPL(rtdm_apc);
@@ -92,9 +86,10 @@ static inline int get_name_hash(const char *str, int limit, int hashkey_mask)
 	return hash & hashkey_mask;
 }
 
-static inline int get_proto_hash(int protocol_family, int socket_type)
+static inline unsigned long long get_proto_id(int pf, int type)
 {
-	return protocol_family & proto_hashkey_mask;
+	unsigned long long llpf = (unsigned)pf;
+	return (llpf << 32) | (unsigned)type;
 }
 
 static inline void rtdm_reference_device(struct rtdm_device *device)
@@ -132,31 +127,26 @@ struct rtdm_device *get_named_device(const char *name)
 
 struct rtdm_device *get_protocol_device(int protocol_family, int socket_type)
 {
-	struct list_head *entry;
 	struct rtdm_device *device;
-	int hashkey;
+	unsigned long long id;
+	struct xnid *xnid;
 	spl_t s;
 
-	hashkey = get_proto_hash(protocol_family, socket_type);
+	id = get_proto_id(protocol_family, socket_type);
 
 	xnlock_get_irqsave(&rt_dev_lock, s);
 
-	list_for_each(entry, &rtdm_protocol_devices[hashkey]) {
-		device = list_entry(entry, struct rtdm_device, reserved.entry);
-
-		if ((device->protocol_family == protocol_family) &&
-		    (device->socket_type == socket_type)) {
-			rtdm_reference_device(device);
-
-			xnlock_put_irqrestore(&rt_dev_lock, s);
+	xnid = xnid_fetch(&rtdm_protocol_devices, id);
+	if (xnid) {
+		device = container_of(xnid, struct rtdm_device, reserved.id);
 
-			return device;
-		}
-	}
+		rtdm_reference_device(device);
+	} else
+		device = NULL;
 
 	xnlock_put_irqrestore(&rt_dev_lock, s);
 
-	return NULL;
+	return device;
 }
 
 /*!
@@ -193,6 +183,7 @@ struct rtdm_device *get_protocol_device(int protocol_family, int socket_type)
  */
 int rtdm_dev_register(struct rtdm_device *device)
 {
+	unsigned long long id;
 	int hashkey;
 	spl_t s;
 	struct list_head *entry;
@@ -333,34 +324,24 @@ int rtdm_dev_register(struct rtdm_device *device)
 			   device->device_sub_class, device->profile_version,
 			   device->driver_version);
 
-		hashkey = get_proto_hash(device->protocol_family,
-					 device->socket_type);
+		id = get_proto_id(device->protocol_family,
+				device->socket_type);
 
-		list_for_each(entry, &rtdm_protocol_devices[hashkey]) {
-			existing_dev =
-			    list_entry(entry, struct rtdm_device,
-				       reserved.entry);
-			if ((device->protocol_family ==
-			     existing_dev->protocol_family)
-			    && (device->socket_type ==
-				existing_dev->socket_type)) {
-				printk(XENO_ERR "protocol %u:%u already "
-				       "registered by RTDM device\n",
-				       device->protocol_family,
-				       device->socket_type);
-				ret = -EEXIST;
-				goto err;
-			}
-		}
+		xnlock_get_irqsave(&rt_dev_lock, s);
+		ret = xnid_enter(&rtdm_protocol_devices, 
+				&device->reserved.id, id);
+		xnlock_put_irqrestore(&rt_dev_lock, s);
+		if (ret < 0)
+			goto err;
 
 		ret = rtdm_proc_register_device(device);
-		if (ret)
+		if (ret) {
+			xnlock_get_irqsave(&rt_dev_lock, s);
+			xnid_remove(&rtdm_protocol_devices, 
+				&device->reserved.id);
+			xnlock_put_irqrestore(&rt_dev_lock, s);
 			goto err;
-
-		xnlock_get_irqsave(&rt_dev_lock, s);
-		list_add_tail(&device->reserved.entry,
-			      &rtdm_protocol_devices[hashkey]);
-		xnlock_put_irqrestore(&rt_dev_lock, s);
+		}
 
 		up(&nrt_dev_lock);
 	}
@@ -441,7 +422,10 @@ int rtdm_dev_unregister(struct rtdm_device *device, unsigned int poll_delay)
 		xnlock_get_irqsave(&rt_dev_lock, s);
 	}
 
-	list_del(&reg_dev->reserved.entry);
+	if ((device->device_flags & RTDM_DEVICE_TYPE_MASK) == RTDM_NAMED_DEVICE)
+		list_del(&reg_dev->reserved.entry);
+	else
+		xnid_remove(&rtdm_protocol_devices, &reg_dev->reserved.id);
 
 	xnlock_put_irqrestore(&rt_dev_lock, s);
 
@@ -470,9 +454,7 @@ int __init rtdm_dev_init(void)
 		return rtdm_apc;
 
 	name_hashkey_mask = devname_hashtab_size - 1;
-	proto_hashkey_mask = protocol_hashtab_size - 1;
-	if (((devname_hashtab_size & name_hashkey_mask) != 0) ||
-	    ((protocol_hashtab_size & proto_hashkey_mask) != 0)) {
+	if (((devname_hashtab_size & name_hashkey_mask) != 0)) {
 		err = -EINVAL;
 		goto err_out1;
 	}
@@ -487,23 +469,11 @@ int __init rtdm_dev_init(void)
 
 	for (i = 0; i < devname_hashtab_size; i++)
 		INIT_LIST_HEAD(&rtdm_named_devices[i]);
-
-	rtdm_protocol_devices = (struct list_head *)
-	    kmalloc(protocol_hashtab_size * sizeof(struct list_head),
-		    GFP_KERNEL);
-	if (!rtdm_protocol_devices) {
-		err = -ENOMEM;
-		goto err_out2;
-	}
-
-	for (i = 0; i < protocol_hashtab_size; i++)
-		INIT_LIST_HEAD(&rtdm_protocol_devices[i]);
+	
+	xntree_init(&rtdm_protocol_devices);
 
 	return 0;
 
-err_out2:
-	kfree(rtdm_named_devices);
-
 err_out1:
 	xnapc_free(rtdm_apc);
 
@@ -518,7 +488,6 @@ void rtdm_dev_cleanup(void)
 	 */
 	xnapc_free(rtdm_apc);
 	kfree(rtdm_named_devices);
-	kfree(rtdm_protocol_devices);
 }
 
 /*@}*/
diff --git a/kernel/cobalt/rtdm/internal.h b/kernel/cobalt/rtdm/internal.h
index b5184c1..0bebe8b 100644
--- a/kernel/cobalt/rtdm/internal.h
+++ b/kernel/cobalt/rtdm/internal.h
@@ -23,6 +23,7 @@
 #include <linux/list.h>
 #include <linux/sem.h>
 #include <cobalt/kernel/ppd.h>
+#include <cobalt/kernel/tree.h>
 #include <rtdm/driver.h>
 
 #define RTDM_FD_MAX			CONFIG_XENO_OPT_RTDM_FILDES
@@ -49,9 +50,8 @@ extern struct rtdm_fildes fildes_table[];
 extern int open_fildes;
 extern struct semaphore nrt_dev_lock;
 extern unsigned int devname_hashtab_size;
-extern unsigned int protocol_hashtab_size;
 extern struct list_head *rtdm_named_devices;
-extern struct list_head *rtdm_protocol_devices;
+extern struct rb_root rtdm_protocol_devices;
 extern struct xnpersonality rtdm_personality;
 
 extern int rtdm_initialised;
diff --git a/kernel/cobalt/rtdm/proc.c b/kernel/cobalt/rtdm/proc.c
index ccbbf90..218bf8b 100644
--- a/kernel/cobalt/rtdm/proc.c
+++ b/kernel/cobalt/rtdm/proc.c
@@ -142,51 +142,49 @@ static struct xnvfile_regular named_vfile = {
 	.entry = { .lockops = &lockops }
 };
 
+struct vfile_proto_data {
+	struct rtdm_device *curr;
+};
+
+static void *proto_next(struct xnvfile_regular_iterator *it)
+{
+	struct vfile_proto_data *priv = xnvfile_iterator_priv(it);
+
+	return priv->curr = xnid_next_entry(priv->curr, reserved.id);
+}
+
 static void *proto_begin(struct xnvfile_regular_iterator *it)
 {
 
-	struct vfile_device_data *priv = xnvfile_iterator_priv(it);
-	struct list_head *devlist;
+	struct vfile_proto_data *priv = xnvfile_iterator_priv(it);
+	struct rtdm_device *dev = NULL;
 	loff_t pos = 0;
 
-	priv->devmap = rtdm_protocol_devices;
-	priv->hmax = protocol_hashtab_size;
-	priv->h = 0;
+	xntree_for_each_entry(dev, &rtdm_protocol_devices, reserved.id)
+		if (pos++ >= it->pos)
+			break;
+	
+	if (dev == NULL)
+		return NULL;	/* Empty */
 
-	devlist = next_devlist(priv);
-	if (devlist == NULL)
-		return NULL;	/* All devlists empty. */
-
-	priv->curr = devlist->next;	/* Skip head. */
-
-	/*
-	 * priv->curr now points to the first device; advance to the requested
-	 * position from there.
-	 */
-	while (priv->curr && pos++ < it->pos)
-		priv->curr = next_dev(it);
+	priv->curr = dev;
 
 	if (pos == 1)
 		/* Output the header once, only if some device follows. */
-		xnvfile_puts(it, "Hash\tName\t\t\t\tDriver\t\t/proc\n");
+		xnvfile_puts(it, "Name\t\t\t\tDriver\t\t/proc\n");
 
 	return priv->curr;
 }
 
 static int proto_show(struct xnvfile_regular_iterator *it, void *data)
 {
-	struct vfile_device_data *priv = xnvfile_iterator_priv(it);
-	struct list_head *curr = data;
-	struct rtdm_device *device;
+	struct rtdm_device *device = data;
 	char pnum[32];
 
-	device = list_entry(curr, struct rtdm_device, reserved.entry);
-
 	snprintf(pnum, sizeof(pnum), "%u:%u",
 		 device->protocol_family, device->socket_type);
 
-	xnvfile_printf(it, "%02X\t%-31s\t%-15s\t%s\n",
-		       priv->h,
+	xnvfile_printf(it, "%-31s\t%-15s\t%s\n",
 		       pnum, device->driver_name,
 		       device->proc_name);
 	return 0;
@@ -194,12 +192,12 @@ static int proto_show(struct xnvfile_regular_iterator *it, void *data)
 
 static struct xnvfile_regular_ops proto_vfile_ops = {
 	.begin = proto_begin,
-	.next = next_dev,
+	.next = proto_next,
 	.show = proto_show,
 };
 
 static struct xnvfile_regular proto_vfile = {
-	.privsz = sizeof(struct vfile_device_data),
+	.privsz = sizeof(struct vfile_proto_data),
 	.ops = &proto_vfile_ops,
 	.entry = { .lockops = &lockops }
 };
@@ -323,11 +321,9 @@ static int devinfo_vfile_show(struct xnvfile_regular_iterator *it, void *data)
 			if (device == xnvfile_priv(it->vfile))
 				goto found;
 
-	for (i = 0; i < protocol_hashtab_size; i++)
-		list_for_each_entry(device, &rtdm_protocol_devices[i],
-				    reserved.entry)
-			if (device == xnvfile_priv(it->vfile))
-				goto found;
+	xntree_for_each_entry(device, &rtdm_protocol_devices, reserved.id)
+		if (device == xnvfile_priv(it->vfile))
+			goto found;
 
 	up(&nrt_dev_lock);
 	return -ENODEV;
-- 
1.7.10.4



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

* [Xenomai] [PATCH 2/3] cobalt/rtdm: base named devices on nucleus registry
  2014-02-01 18:27 ` [Xenomai] [PATCH 1/3] cobalt/rtdm: base protocol devices on xnid Gilles Chanteperdrix
@ 2014-02-01 18:27   ` Gilles Chanteperdrix
  2014-02-01 18:27   ` [Xenomai] [PATCH 3/3] cobalt/rtdm: base on common fd implementation Gilles Chanteperdrix
  1 sibling, 0 replies; 7+ messages in thread
From: Gilles Chanteperdrix @ 2014-02-01 18:27 UTC (permalink / raw)
  To: xenomai

---
 include/cobalt/kernel/rtdm/driver.h |    6 +-
 kernel/cobalt/rtdm/device.c         |  115 +++++++++++------------------------
 kernel/cobalt/rtdm/internal.h       |    2 +-
 kernel/cobalt/rtdm/proc.c           |   94 ++++++++--------------------
 4 files changed, 66 insertions(+), 151 deletions(-)

diff --git a/include/cobalt/kernel/rtdm/driver.h b/include/cobalt/kernel/rtdm/driver.h
index 881f517..1fe74e6 100644
--- a/include/cobalt/kernel/rtdm/driver.h
+++ b/include/cobalt/kernel/rtdm/driver.h
@@ -445,7 +445,10 @@ rtdm_private_to_context(void *dev_private)
 
 struct rtdm_dev_reserved {
 	union {
-		struct list_head entry;
+		struct {
+			struct list_head entry;
+			xnhandle_t handle;
+		};
 		struct xnid id;
 	};
 	atomic_t refcount;
@@ -460,6 +463,7 @@ struct rtdm_dev_reserved {
  * not reside in write-protected memory.
  */
 struct rtdm_device {
+	unsigned magic;
 	/** Revision number of this structure, see
 	 *  @ref drv_versioning "Driver Versioning" defines */
 	int struct_version;
diff --git a/kernel/cobalt/rtdm/device.c b/kernel/cobalt/rtdm/device.c
index 38353ee..aca34f7 100644
--- a/kernel/cobalt/rtdm/device.c
+++ b/kernel/cobalt/rtdm/device.c
@@ -31,6 +31,8 @@
 #include <cobalt/kernel/apc.h>
 #include "rtdm/internal.h"
 
+#define RTDM_DEVICE_MAGIC	0x82846877
+
 #define SET_DEFAULT_OP(device, operation)				\
 	(device).operation##_rt  = (void *)rtdm_no_support;		\
 	(device).operation##_nrt = (void *)rtdm_no_support
@@ -44,13 +46,7 @@
 #define ANY_HANDLER(device, operation)					\
 	((device).operation##_rt || (device).operation##_nrt)
 
-unsigned int devname_hashtab_size = DEF_DEVNAME_HASHTAB_SIZE;
-module_param(devname_hashtab_size, uint, 0400);
-MODULE_PARM_DESC(devname_hashtab_size,
-		 "Size of hash table for named devices (must be power of 2)");
-
-struct list_head *rtdm_named_devices;	/* hash table */
-static int name_hashkey_mask;
+struct list_head rtdm_named_devices;	/* hash table */
 struct rb_root rtdm_protocol_devices;
 
 int rtdm_apc;
@@ -74,18 +70,6 @@ int rtdm_select_bind_no_support(struct rtdm_dev_context *context,
 	return -EBADF;
 }
 
-static inline int get_name_hash(const char *str, int limit, int hashkey_mask)
-{
-	int hash = 0;
-
-	while (*str != 0) {
-		hash += *str++;
-		if (--limit == 0)
-			break;
-	}
-	return hash & hashkey_mask;
-}
-
 static inline unsigned long long get_proto_id(int pf, int type)
 {
 	unsigned long long llpf = (unsigned)pf;
@@ -99,30 +83,28 @@ static inline void rtdm_reference_device(struct rtdm_device *device)
 
 struct rtdm_device *get_named_device(const char *name)
 {
-	struct list_head *entry;
 	struct rtdm_device *device;
-	int hashkey;
+	xnhandle_t handle;
+	int err;
 	spl_t s;
 
-	hashkey = get_name_hash(name, RTDM_MAX_DEVNAME_LEN, name_hashkey_mask);
+	err = xnregistry_bind(name, XN_NONBLOCK, XN_RELATIVE, &handle);
+	if (err == -EWOULDBLOCK)
+		return NULL;
 
 	xnlock_get_irqsave(&rt_dev_lock, s);
 
-	list_for_each(entry, &rtdm_named_devices[hashkey]) {
-		device = list_entry(entry, struct rtdm_device, reserved.entry);
-
-		if (strcmp(name, device->device_name) == 0) {
+	device = xnregistry_fetch(handle);
+	if (device) {
+		if (device->magic != RTDM_DEVICE_MAGIC)
+			device = NULL;
+		else
 			rtdm_reference_device(device);
-
-			xnlock_put_irqrestore(&rt_dev_lock, s);
-
-			return device;
-		}
 	}
 
 	xnlock_put_irqrestore(&rt_dev_lock, s);
 
-	return NULL;
+	return device;
 }
 
 struct rtdm_device *get_protocol_device(int protocol_family, int socket_type)
@@ -184,10 +166,7 @@ struct rtdm_device *get_protocol_device(int protocol_family, int socket_type)
 int rtdm_dev_register(struct rtdm_device *device)
 {
 	unsigned long long id;
-	int hashkey;
 	spl_t s;
-	struct list_head *entry;
-	struct rtdm_device *existing_dev;
 	int ret;
 
 	/* Catch unsuccessful initialisation */
@@ -281,6 +260,8 @@ int rtdm_dev_register(struct rtdm_device *device)
 
 	down(&nrt_dev_lock);
 
+	device->magic = RTDM_DEVICE_MAGIC;
+
 	if ((device->device_flags & RTDM_DEVICE_TYPE_MASK) == RTDM_NAMED_DEVICE) {
 		trace_mark(xn_rtdm, nameddev_register, "device %p name %s "
 			   "flags %d class %d sub_class %d profile_version %d "
@@ -288,29 +269,19 @@ int rtdm_dev_register(struct rtdm_device *device)
 			   device->device_flags, device->device_class,
 			   device->device_sub_class, device->profile_version,
 			   device->driver_version);
-
-		hashkey =
-		    get_name_hash(device->device_name, RTDM_MAX_DEVNAME_LEN,
-				  name_hashkey_mask);
-
-		list_for_each(entry, &rtdm_named_devices[hashkey]) {
-			existing_dev =
-			    list_entry(entry, struct rtdm_device,
-				       reserved.entry);
-			if (strcmp(device->device_name,
-				   existing_dev->device_name) == 0) {
-				ret = -EEXIST;
-				goto err;
-			}
-		}
-
 		ret = rtdm_proc_register_device(device);
 		if (ret)
 			goto err;
 
+		ret = xnregistry_enter(device->device_name, device, 
+				&device->reserved.handle, NULL);
+		if (ret) {
+			rtdm_proc_unregister_device(device);
+			goto err;
+		}
+
 		xnlock_get_irqsave(&rt_dev_lock, s);
-		list_add_tail(&device->reserved.entry,
-			      &rtdm_named_devices[hashkey]);
+		list_add_tail(&device->reserved.entry, &rtdm_named_devices);
 		xnlock_put_irqrestore(&rt_dev_lock, s);
 
 		up(&nrt_dev_lock);
@@ -381,9 +352,10 @@ EXPORT_SYMBOL_GPL(rtdm_dev_register);
  */
 int rtdm_dev_unregister(struct rtdm_device *device, unsigned int poll_delay)
 {
-	spl_t s;
 	struct rtdm_device *reg_dev;
 	unsigned long warned = 0;
+	xnhandle_t handle = 0;
+	spl_t s;
 
 	if (!rtdm_initialised)
 		return -ENOSYS;
@@ -422,15 +394,20 @@ int rtdm_dev_unregister(struct rtdm_device *device, unsigned int poll_delay)
 		xnlock_get_irqsave(&rt_dev_lock, s);
 	}
 
-	if ((device->device_flags & RTDM_DEVICE_TYPE_MASK) == RTDM_NAMED_DEVICE)
+	if ((device->device_flags & RTDM_DEVICE_TYPE_MASK) == 
+		RTDM_NAMED_DEVICE) {
+		handle = reg_dev->reserved.handle;
 		list_del(&reg_dev->reserved.entry);
-	else
+	} else
 		xnid_remove(&rtdm_protocol_devices, &reg_dev->reserved.id);
 
 	xnlock_put_irqrestore(&rt_dev_lock, s);
 
 	rtdm_proc_unregister_device(device);
 
+	if (handle)
+		xnregistry_remove(handle);
+
 	up(&nrt_dev_lock);
 
 	if (reg_dev->reserved.exclusive_context)
@@ -444,8 +421,6 @@ EXPORT_SYMBOL_GPL(rtdm_dev_unregister);
 
 int __init rtdm_dev_init(void)
 {
-	int err, i;
-
 	sema_init(&nrt_dev_lock, 1);
 
 	rtdm_apc = xnapc_alloc("deferred RTDM close", rtdm_apc_handler,
@@ -453,31 +428,10 @@ int __init rtdm_dev_init(void)
 	if (rtdm_apc < 0)
 		return rtdm_apc;
 
-	name_hashkey_mask = devname_hashtab_size - 1;
-	if (((devname_hashtab_size & name_hashkey_mask) != 0)) {
-		err = -EINVAL;
-		goto err_out1;
-	}
-
-	rtdm_named_devices = (struct list_head *)
-	    kmalloc(devname_hashtab_size * sizeof(struct list_head),
-		    GFP_KERNEL);
-	if (!rtdm_named_devices) {
-		err = -ENOMEM;
-		goto err_out1;
-	}
-
-	for (i = 0; i < devname_hashtab_size; i++)
-		INIT_LIST_HEAD(&rtdm_named_devices[i]);
-	
+	INIT_LIST_HEAD(&rtdm_named_devices);
 	xntree_init(&rtdm_protocol_devices);
 
 	return 0;
-
-err_out1:
-	xnapc_free(rtdm_apc);
-
-	return err;
 }
 
 void rtdm_dev_cleanup(void)
@@ -487,7 +441,6 @@ void rtdm_dev_cleanup(void)
 	 * to deregister as long as there are references.
 	 */
 	xnapc_free(rtdm_apc);
-	kfree(rtdm_named_devices);
 }
 
 /*@}*/
diff --git a/kernel/cobalt/rtdm/internal.h b/kernel/cobalt/rtdm/internal.h
index 0bebe8b..3288068 100644
--- a/kernel/cobalt/rtdm/internal.h
+++ b/kernel/cobalt/rtdm/internal.h
@@ -50,7 +50,7 @@ extern struct rtdm_fildes fildes_table[];
 extern int open_fildes;
 extern struct semaphore nrt_dev_lock;
 extern unsigned int devname_hashtab_size;
-extern struct list_head *rtdm_named_devices;
+extern struct list_head rtdm_named_devices;
 extern struct rb_root rtdm_protocol_devices;
 extern struct xnpersonality rtdm_personality;
 
diff --git a/kernel/cobalt/rtdm/proc.c b/kernel/cobalt/rtdm/proc.c
index 218bf8b..28ec6ab 100644
--- a/kernel/cobalt/rtdm/proc.c
+++ b/kernel/cobalt/rtdm/proc.c
@@ -23,10 +23,7 @@
 struct xnvfile_directory rtdm_vfroot;	/* /proc/xenomai/rtdm */
 
 struct vfile_device_data {
-	int h;
-	int hmax;
-	struct list_head *devmap;
-	struct list_head *curr;
+	struct rtdm_device *curr;
 };
 
 static int get_nrt_lock(struct xnvfile *vfile)
@@ -44,95 +41,59 @@ static struct xnvfile_lock_ops lockops = {
 	.put = put_nrt_lock,
 };
 
-static struct list_head *next_devlist(struct vfile_device_data *priv)
-{
-	struct list_head *head;
-
-	while (priv->h < priv->hmax) {
-		head = priv->devmap + priv->h;
-		if (!list_empty(head))
-			return head;
-		priv->h++;
-	}
-
-	return NULL;
-}
-
-static void *next_dev(struct xnvfile_regular_iterator *it)
+static void *named_next(struct xnvfile_regular_iterator *it)
 {
 	struct vfile_device_data *priv = xnvfile_iterator_priv(it);
+	struct rtdm_device *device = priv->curr;
 	struct list_head *next;
 
-	next = priv->curr->next;
-seek:
-	if (next == priv->devmap + priv->h) {
-		/* Done with the current hash slot, let's progress. */
-		if (priv->h >= priv->hmax) {
-			next = NULL; /* all done. */
-			goto out;
-		}
-
-		priv->h++;
-		next = next_devlist(priv);
-		if (next) {
-			next = next->next; /* skip head. */
-			goto seek;
-		}
+	next = device->reserved.entry.next;
+	if (next == &rtdm_named_devices) {
+		priv->curr = NULL; /* all done. */
+		goto out;
 	}
-out:
-	priv->curr = next;
 
-	return next;
+	priv->curr = list_entry(next, struct rtdm_device, reserved.entry);
+
+  out:
+	return priv->curr;
 }
 
 static void *named_begin(struct xnvfile_regular_iterator *it)
 {
 	struct vfile_device_data *priv = xnvfile_iterator_priv(it);
-	struct list_head *devlist;
+	struct rtdm_device *device;
 	loff_t pos = 0;
 
-	priv->devmap = rtdm_named_devices;
-	priv->hmax = devname_hashtab_size;
-	priv->h = 0;
-
-	devlist = next_devlist(priv);
-	if (devlist == NULL)
-		return NULL;	/* All devlists empty. */
+	list_for_each_entry(device, &rtdm_named_devices, reserved.entry)
+		if (pos++ >= it->pos)
+			break;
 
-	priv->curr = devlist->next;	/* Skip head. */
+	if (&device->reserved.entry == &rtdm_named_devices)
+		return NULL;	/* End of list. */
 
-	/*
-	 * priv->curr now points to the first device; advance to the requested
-	 * position from there.
-	 */
-	while (priv->curr && pos++ < it->pos)
-		priv->curr = next_dev(it);
+	priv->curr = device;	/* Skip head. */
 
 	if (pos == 1)
 		/* Output the header once, only if some device follows. */
-		xnvfile_puts(it, "Hash\tName\t\t\t\tDriver\t\t/proc\n");
+		xnvfile_puts(it, "Name\t\t\t\tDriver\t\t/proc\n");
 
 	return priv->curr;
 }
 
 static int named_show(struct xnvfile_regular_iterator *it, void *data)
 {
-	struct vfile_device_data *priv = xnvfile_iterator_priv(it);
-	struct list_head *curr = data;
-	struct rtdm_device *device;
+	struct rtdm_device *device = data;
 
-	device = list_entry(curr, struct rtdm_device, reserved.entry);
-	xnvfile_printf(it, "%02X\t%-31s\t%-15s\t%s\n",
-		       priv->h, device->device_name,
-		       device->driver_name,
-		       device->proc_name);
+	xnvfile_printf(it, "%-31s\t%-15s\t%s\n", device->device_name, 
+		device->driver_name, device->proc_name);
 
 	return 0;
 }
 
 static struct xnvfile_regular_ops named_vfile_ops = {
 	.begin = named_begin,
-	.next = next_dev,
+	.next = named_next,
 	.show = named_show,
 };
 
@@ -306,7 +267,6 @@ static struct xnvfile_regular allfd_vfile = {
 static int devinfo_vfile_show(struct xnvfile_regular_iterator *it, void *data)
 {
 	struct rtdm_device *device;
-	int i;
 
 	if (down_interruptible(&nrt_dev_lock))
 		return -ERESTARTSYS;
@@ -315,11 +275,9 @@ static int devinfo_vfile_show(struct xnvfile_regular_iterator *it, void *data)
 	 * As the device may have disappeared while the handler was called,
 	 * first match the pointer against registered devices.
 	 */
-	for (i = 0; i < devname_hashtab_size; i++)
-		list_for_each_entry(device, &rtdm_named_devices[i],
-				    reserved.entry)
-			if (device == xnvfile_priv(it->vfile))
-				goto found;
+	list_for_each_entry(device, &rtdm_named_devices, reserved.entry)
+		if (device == xnvfile_priv(it->vfile))
+			goto found;
 
 	xntree_for_each_entry(device, &rtdm_protocol_devices, reserved.id)
 		if (device == xnvfile_priv(it->vfile))
-- 
1.7.10.4



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

* [Xenomai] [PATCH 3/3] cobalt/rtdm: base on common fd implementation
  2014-02-01 18:27 ` [Xenomai] [PATCH 1/3] cobalt/rtdm: base protocol devices on xnid Gilles Chanteperdrix
  2014-02-01 18:27   ` [Xenomai] [PATCH 2/3] cobalt/rtdm: base named devices on nucleus registry Gilles Chanteperdrix
@ 2014-02-01 18:27   ` Gilles Chanteperdrix
  1 sibling, 0 replies; 7+ messages in thread
From: Gilles Chanteperdrix @ 2014-02-01 18:27 UTC (permalink / raw)
  To: xenomai

---
 include/cobalt/kernel/rtdm/driver.h |  328 +++-----------------
 include/cobalt/kernel/rtdm/rtdm.h   |   48 +--
 kernel/cobalt/posix/select.c        |   30 +-
 kernel/cobalt/rtdm/core.c           |  564 +++++------------------------------
 kernel/cobalt/rtdm/device.c         |   46 +--
 kernel/cobalt/rtdm/drvlib.c         |   36 +--
 kernel/cobalt/rtdm/internal.h       |    6 -
 kernel/cobalt/rtdm/proc.c           |   33 +-
 kernel/cobalt/rtdm/syscall.c        |   80 +----
 lib/cobalt/rtdm.c                   |  501 +++++++++++++------------------
 10 files changed, 394 insertions(+), 1278 deletions(-)

diff --git a/include/cobalt/kernel/rtdm/driver.h b/include/cobalt/kernel/rtdm/driver.h
index 1fe74e6..e2b01e5 100644
--- a/include/cobalt/kernel/rtdm/driver.h
+++ b/include/cobalt/kernel/rtdm/driver.h
@@ -39,6 +39,7 @@
 #include <cobalt/kernel/apc.h>
 #include <cobalt/kernel/shadow.h>
 #include <cobalt/kernel/tree.h>
+#include <cobalt/kernel/fd.h>
 #include <rtdm/rtdm.h>
 
 /* debug support */
@@ -77,22 +78,6 @@ enum rtdm_selecttype;
 /** @} Device Flags */
 
 /*!
- * @anchor ctx_flags @name Context Flags
- * Dynamic flags describing the state of an open RTDM device (bit numbers)
- * @{
- */
-/** Set by RTDM if the device instance was created in non-real-time
- *  context. */
-#define RTDM_CREATED_IN_NRT		0
-
-/** Set by RTDM when the device is being closed. */
-#define RTDM_CLOSING			1
-
-/** Lowest bit number the driver developer can use freely */
-#define RTDM_USER_CONTEXT_FLAG		8  /* first user-definable flag */
-/** @} Context Flags */
-
-/*!
  * @anchor drv_versioning @name Driver Versioning
  * Current revisions of RTDM structures, encoding of driver versions. See
  * @ref api_versioning "API Versioning" for the interface revision.
@@ -153,9 +138,7 @@ enum rtdm_selecttype {
 /**
  * Named device open handler
  *
- * @param[in] context Context structure associated with opened device instance
- * @param[in] user_info Opaque pointer to information about user mode caller,
- * NULL if kernel mode call
+ * @param[in] context File descriptor structure associated with opened device instance
  * @param[in] oflag Open flags as passed by the user
  *
  * @return 0 on success. On failure return either -ENOSYS, to request that
@@ -164,15 +147,12 @@ enum rtdm_selecttype {
  *
  * @see @c open() in IEEE Std 1003.1,
  * http://www.opengroup.org/onlinepubs/009695399 */
-typedef int (*rtdm_open_handler_t)(struct rtdm_dev_context *context,
-				   rtdm_user_info_t *user_info, int oflag);
+typedef int (*rtdm_open_handler_t)(struct xnfd *context, int oflag);
 
 /**
  * Socket creation handler for protocol devices
  *
- * @param[in] context Context structure associated with opened device instance
- * @param[in] user_info Opaque pointer to information about user mode caller,
- * NULL if kernel mode call
+ * @param[in] context File descriptor structure associated with opened device instance
  * @param[in] protocol Protocol number as passed by the user
  *
  * @return 0 on success. On failure return either -ENOSYS, to request that
@@ -181,203 +161,15 @@ typedef int (*rtdm_open_handler_t)(struct rtdm_dev_context *context,
  *
  * @see @c socket() in IEEE Std 1003.1,
  * http://www.opengroup.org/onlinepubs/009695399 */
-typedef int (*rtdm_socket_handler_t)(struct rtdm_dev_context *context,
-				     rtdm_user_info_t *user_info, int protocol);
-
-/**
- * Close handler
- *
- * @param[in] context Context structure associated with opened device instance
- * @param[in] user_info Opaque pointer to information about user mode caller,
- * NULL if kernel mode or deferred user mode call
- *
- * @return 0 on success. On failure return either -ENOSYS, to request that
- * this handler be called again from the opposite realtime/non-realtime
- * context, -EAGAIN to request a recall after a grace period, or a valid
- * negative error code according to IEEE Std 1003.1.
- *
- * @note Drivers must be prepared for that case that the close handler is
- * invoked more than once per open context (even if the handler already
- * completed an earlier run successfully). The driver has to avoid releasing
- * resources twice as well as returning false errors on successive close
- * invocations.
- *
- * @see @c close() in IEEE Std 1003.1,
- * http://www.opengroup.org/onlinepubs/009695399 */
-typedef int (*rtdm_close_handler_t)(struct rtdm_dev_context *context,
-				    rtdm_user_info_t *user_info);
+typedef int (*rtdm_socket_handler_t)(struct xnfd *context, int protocol);
 
-/**
- * IOCTL handler
- *
- * @param[in] context Context structure associated with opened device instance
- * @param[in] user_info Opaque pointer to information about user mode caller,
- * NULL if kernel mode call
- * @param[in] request Request number as passed by the user
- * @param[in,out] arg Request argument as passed by the user
- *
- * @return A positive value or 0 on success. On failure return either
- * -ENOSYS, to request that the function be called again from the opposite
- * realtime/non-realtime context, or another negative error code.
- *
- * @see @c ioctl() in IEEE Std 1003.1,
- * http://www.opengroup.org/onlinepubs/009695399 */
-typedef int (*rtdm_ioctl_handler_t)(struct rtdm_dev_context *context,
-				    rtdm_user_info_t *user_info,
-				    unsigned int request, void __user *arg);
-
-/**
- * Select binding handler
- *
- * @param[in] context Context structure associated with opened device instance
- * @param[in,out] selector Object that shall be bound to the given event
- * @param[in] type Event type the selector is interested in
- * @param[in] fd_index Opaque value, to be passed to rtdm_event_select_bind or
- * rtdm_sem_select_bind unmodfied
- *
- * @return 0 on success. On failure return either -ENOSYS, to request that
- * this handler be called again from the opposite realtime/non-realtime
- * context, or another negative error code.
- */
-typedef int (*rtdm_select_bind_handler_t)(struct rtdm_dev_context *context,
-					  rtdm_selector_t *selector,
-					  enum rtdm_selecttype type,
-					  unsigned fd_index);
-
-/**
- * Read handler
- *
- * @param[in] context Context structure associated with opened device instance
- * @param[in] user_info Opaque pointer to information about user mode caller,
- * NULL if kernel mode call
- * @param[out] buf Input buffer as passed by the user
- * @param[in] nbyte Number of bytes the user requests to read
- *
- * @return On success, the number of bytes read. On failure return either
- * -ENOSYS, to request that this handler be called again from the opposite
- * realtime/non-realtime context, or another negative error code.
- *
- * @see @c read() in IEEE Std 1003.1,
- * http://www.opengroup.org/onlinepubs/009695399 */
-typedef ssize_t (*rtdm_read_handler_t)(struct rtdm_dev_context *context,
-				       rtdm_user_info_t *user_info,
-				       void *buf, size_t nbyte);
-
-/**
- * Write handler
- *
- * @param[in] context Context structure associated with opened device instance
- * @param[in] user_info Opaque pointer to information about user mode caller,
- * NULL if kernel mode call
- * @param[in] buf Output buffer as passed by the user
- * @param[in] nbyte Number of bytes the user requests to write
- *
- * @return On success, the number of bytes written. On failure return
- * either -ENOSYS, to request that this handler be called again from the
- * opposite realtime/non-realtime context, or another negative error code.
- *
- * @see @c write() in IEEE Std 1003.1,
- * http://www.opengroup.org/onlinepubs/009695399 */
-typedef ssize_t (*rtdm_write_handler_t)(struct rtdm_dev_context *context,
-					rtdm_user_info_t *user_info,
-					const void *buf, size_t nbyte);
-
-/**
- * Receive message handler
- *
- * @param[in] context Context structure associated with opened device instance
- * @param[in] user_info Opaque pointer to information about user mode caller,
- * NULL if kernel mode call
- * @param[in,out] msg Message descriptor as passed by the user, automatically
- * mirrored to safe kernel memory in case of user mode call
- * @param[in] flags Message flags as passed by the user
- *
- * @return On success, the number of bytes received. On failure return
- * either -ENOSYS, to request that this handler be called again from the
- * opposite realtime/non-realtime context, or another negative error code.
- *
- * @see @c recvmsg() in IEEE Std 1003.1,
- * http://www.opengroup.org/onlinepubs/009695399 */
-typedef ssize_t (*rtdm_recvmsg_handler_t)(struct rtdm_dev_context *context,
-					  rtdm_user_info_t *user_info,
-					  struct msghdr *msg, int flags);
-
-/**
- * Transmit message handler
- *
- * @param[in] context Context structure associated with opened device instance
- * @param[in] user_info Opaque pointer to information about user mode caller,
- * NULL if kernel mode call
- * @param[in] msg Message descriptor as passed by the user, automatically
- * mirrored to safe kernel memory in case of user mode call
- * @param[in] flags Message flags as passed by the user
- *
- * @return On success, the number of bytes transmitted. On failure return
- * either -ENOSYS, to request that this handler be called again from the
- * opposite realtime/non-realtime context, or another negative error code.
- *
- * @see @c sendmsg() in IEEE Std 1003.1,
- * http://www.opengroup.org/onlinepubs/009695399 */
-typedef ssize_t (*rtdm_sendmsg_handler_t)(struct rtdm_dev_context *context,
-					  rtdm_user_info_t *user_info,
-					  const struct msghdr *msg, int flags);
 /** @} Operation Handler Prototypes */
 
-typedef int (*rtdm_rt_handler_t)(struct rtdm_dev_context *context,
-				 rtdm_user_info_t *user_info, void *arg);
-/**
- * Device operations
- */
-struct rtdm_operations {
-	/*! @name Common Operations
-	 * @{ */
-	/** Close handler for real-time contexts (optional, deprecated)
-	 *  @deprecated Only use non-real-time close handler in new drivers. */
-	rtdm_close_handler_t close_rt;
-	/** Close handler for non-real-time contexts (required) */
-	rtdm_close_handler_t close_nrt;
-
-	/** IOCTL from real-time context (optional) */
-	rtdm_ioctl_handler_t ioctl_rt;
-	/** IOCTL from non-real-time context (optional) */
-	rtdm_ioctl_handler_t ioctl_nrt;
-
-	/** Select binding handler for any context (optional) */
-	rtdm_select_bind_handler_t select_bind;
-	/** @} Common Operations */
-
-	/*! @name Stream-Oriented Device Operations
-	 * @{ */
-	/** Read handler for real-time context (optional) */
-	rtdm_read_handler_t read_rt;
-	/** Read handler for non-real-time context (optional) */
-	rtdm_read_handler_t read_nrt;
-
-	/** Write handler for real-time context (optional) */
-	rtdm_write_handler_t write_rt;
-	/** Write handler for non-real-time context (optional) */
-	rtdm_write_handler_t write_nrt;
-	/** @} Stream-Oriented Device Operations */
-
-	/*! @name Message-Oriented Device Operations
-	 * @{ */
-	/** Receive message handler for real-time context (optional) */
-	rtdm_recvmsg_handler_t recvmsg_rt;
-	/** Receive message handler for non-real-time context (optional) */
-	rtdm_recvmsg_handler_t recvmsg_nrt;
-
-	/** Transmit message handler for real-time context (optional) */
-	rtdm_sendmsg_handler_t sendmsg_rt;
-	/** Transmit message handler for non-real-time context (optional) */
-	rtdm_sendmsg_handler_t sendmsg_nrt;
-	/** @} Message-Oriented Device Operations */
-};
-
 struct rtdm_process;
 
 struct rtdm_devctx_reserved {
 	struct rtdm_process *owner;
-	struct list_head cleanup;
+	void (*close)(struct xnfd *fd);
 };
 
 /**
@@ -392,19 +184,9 @@ struct rtdm_devctx_reserved {
  * device registration.
  */
 struct rtdm_dev_context {
-	/** Context flags, see @ref ctx_flags "Context Flags" for details */
-	unsigned long context_flags;
-
-	/** Associated file descriptor */
-	int fd;
-
-	/** Lock counter of context, held while structure is referenced by an
-	 *  operation handler */
-	atomic_t close_lock_count;
+	struct xnfd fd;
 
 	/** Set of active device operation handlers */
-	struct rtdm_operations *ops;
-
 	/** Reference to owning device */
 	struct rtdm_device *device;
 
@@ -415,6 +197,11 @@ struct rtdm_dev_context {
 	char dev_private[0];
 };
 
+static inline struct rtdm_dev_context *rtdm_context(struct xnfd *fd)
+{
+	return container_of(fd, struct rtdm_dev_context, fd);
+}
+
 /**
  * Locate the driver private area associated to a device context structure
  *
@@ -424,9 +211,9 @@ struct rtdm_dev_context {
  * context.
  */
 static inline void *
-rtdm_context_to_private(struct rtdm_dev_context *context)
+rtdm_context_to_private(struct xnfd *context)
 {
-	return (void *)context->dev_private;
+	return (void *)rtdm_context(context)->dev_private;
 }
 
 /**
@@ -437,10 +224,12 @@ rtdm_context_to_private(struct rtdm_dev_context *context)
  * @return The address of the device context structure defining @a
  * dev_private.
  */
-static inline struct rtdm_dev_context *
+static inline struct xnfd *
 rtdm_private_to_context(void *dev_private)
 {
-	return container_of(dev_private, struct rtdm_dev_context, dev_private);
+	struct rtdm_dev_context *ctx;
+	ctx = container_of(dev_private, struct rtdm_dev_context, dev_private);
+	return &ctx->fd;
 }
 
 struct rtdm_dev_reserved {
@@ -453,6 +242,7 @@ struct rtdm_dev_reserved {
 	};
 	atomic_t refcount;
 	struct rtdm_dev_context *exclusive_context;
+	void (*close)(struct xnfd *);
 };
 
 /**
@@ -485,23 +275,17 @@ struct rtdm_device {
 	 *  optional (but deprecated) if open_nrt is non-NULL, ignored for
 	 *  protocol devices
 	 *  @deprecated Only use non-real-time open handler in new drivers. */
-	rtdm_open_handler_t open_rt;
-	/** Named device instance creation for non-real-time contexts,
-	 *  optional if open_rt is non-NULL, ignored for protocol devices */
-	rtdm_open_handler_t open_nrt;
+	rtdm_open_handler_t open;
 
 	/** Protocol socket creation for real-time contexts,
 	 *  optional (but deprecated) if socket_nrt is non-NULL, ignored for
 	 *  named devices
 	 *  @deprecated Only use non-real-time socket creation handler in new
 	 *  drivers. */
-	rtdm_socket_handler_t socket_rt;
-	/** Protocol socket creation for non-real-time contexts,
-	 *  optional if socket_rt is non-NULL, ignored for named devices */
-	rtdm_socket_handler_t socket_nrt;
+	rtdm_socket_handler_t socket;
 
 	/** Default operations on newly opened device instance */
-	struct rtdm_operations ops;
+	struct xnfd_ops ops;
 
 	/** Device class ID, see @ref RTDM_CLASS_xxx */
 	int device_class;
@@ -566,36 +350,16 @@ int rtdm_dev_unregister(struct rtdm_device *device, unsigned int poll_delay);
 #define rtdm_getpeername	rt_dev_getpeername
 #define rtdm_shutdown		rt_dev_shutdown
 
-struct rtdm_dev_context *rtdm_context_get(int fd);
-
 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
 
-#define CONTEXT_IS_LOCKED(context) \
-	(atomic_read(&(context)->close_lock_count) > 1 || \
-	 (test_bit(RTDM_CLOSING, &(context)->context_flags) && \
-	  atomic_read(&(context)->close_lock_count) > 0))
-
-static inline void rtdm_context_lock(struct rtdm_dev_context *context)
+static inline void rtdm_context_lock(struct xnfd *context)
 {
-	/* just warn if context was a dangling pointer */
-	XENO_ASSERT(RTDM, CONTEXT_IS_LOCKED(context));
-	atomic_inc(&context->close_lock_count);
+	xnfd_lock(context);
 }
 
-extern int rtdm_apc;
-
-static inline void rtdm_context_unlock(struct rtdm_dev_context *context)
+static inline void rtdm_context_unlock(struct xnfd *context)
 {
-	/* just warn if context was a dangling pointer */
-	XENO_ASSERT(RTDM, CONTEXT_IS_LOCKED(context));
-	smp_mb__before_atomic_dec();
-	if (unlikely(atomic_dec_and_test(&context->close_lock_count)))
-		xnapc_schedule(rtdm_apc);
-}
-
-static inline void rtdm_context_put(struct rtdm_dev_context *context)
-{
-	rtdm_context_unlock(context);
+	xnfd_unlock(context);
 }
 
 /* --- clock services --- */
@@ -610,14 +374,6 @@ static inline nanosecs_abs_t rtdm_clock_read_monotonic(void)
 }
 #endif /* !DOXYGEN_CPP */
 
-/*!
- * @addtogroup rtdmsync
- * @{
- */
-
-int rtdm_select_bind(int fd, rtdm_selector_t *selector,
-		     enum rtdm_selecttype type, unsigned fd_index);
-
 /* --- spin lock services --- */
 /*!
  * @name Global Lock across Scheduler Invocation
@@ -1308,38 +1064,38 @@ static inline void rtdm_free(void *ptr)
 	xnfree(ptr);
 }
 
-int rtdm_mmap_to_user(rtdm_user_info_t *user_info,
+int rtdm_mmap_to_user(struct xnfd *context,
 		      void *src_addr, size_t len,
 		      int prot, void **pptr,
 		      struct vm_operations_struct *vm_ops,
 		      void *vm_private_data);
-int rtdm_iomap_to_user(rtdm_user_info_t *user_info,
+int rtdm_iomap_to_user(struct xnfd *context,
 		       phys_addr_t src_addr, size_t len,
 		       int prot, void **pptr,
 		       struct vm_operations_struct *vm_ops,
 		       void *vm_private_data);
-int rtdm_munmap(rtdm_user_info_t *user_info, void *ptr, size_t len);
+int rtdm_munmap(struct xnfd *context, void *ptr, size_t len);
 
-static inline int rtdm_read_user_ok(rtdm_user_info_t *user_info,
+static inline int rtdm_read_user_ok(struct xnfd *context,
 				    const void __user *ptr, size_t size)
 {
 	return access_rok(ptr, size);
 }
 
-static inline int rtdm_rw_user_ok(rtdm_user_info_t *user_info,
+static inline int rtdm_rw_user_ok(struct xnfd *context,
 				  const void __user *ptr, size_t size)
 {
 	return access_wok(ptr, size);
 }
 
-static inline int rtdm_copy_from_user(rtdm_user_info_t *user_info,
+static inline int rtdm_copy_from_user(struct xnfd *context,
 				      void *dst, const void __user *src,
 				      size_t size)
 {
 	return __xn_copy_from_user(dst, src, size) ? -EFAULT : 0;
 }
 
-static inline int rtdm_safe_copy_from_user(rtdm_user_info_t *user_info,
+static inline int rtdm_safe_copy_from_user(struct xnfd *context,
 					   void *dst, const void __user *src,
 					   size_t size)
 {
@@ -1347,14 +1103,14 @@ static inline int rtdm_safe_copy_from_user(rtdm_user_info_t *user_info,
 		__xn_copy_from_user(dst, src, size)) ? -EFAULT : 0;
 }
 
-static inline int rtdm_copy_to_user(rtdm_user_info_t *user_info,
+static inline int rtdm_copy_to_user(struct xnfd *context,
 				    void __user *dst, const void *src,
 				    size_t size)
 {
 	return __xn_copy_to_user(dst, src, size) ? -EFAULT : 0;
 }
 
-static inline int rtdm_safe_copy_to_user(rtdm_user_info_t *user_info,
+static inline int rtdm_safe_copy_to_user(struct xnfd *context,
 					 void __user *dst, const void *src,
 					 size_t size)
 {
@@ -1362,7 +1118,7 @@ static inline int rtdm_safe_copy_to_user(rtdm_user_info_t *user_info,
 		__xn_copy_to_user(dst, src, size)) ? -EFAULT : 0;
 }
 
-static inline int rtdm_strncpy_from_user(rtdm_user_info_t *user_info,
+static inline int rtdm_strncpy_from_user(struct xnfd *context,
 					 char *dst,
 					 const char __user *src, size_t count)
 {
@@ -1371,13 +1127,15 @@ static inline int rtdm_strncpy_from_user(rtdm_user_info_t *user_info,
 	return __xn_strncpy_from_user(dst, src, count);
 }
 
-static inline int rtdm_rt_capable(rtdm_user_info_t *user_info)
+static inline int rtdm_rt_capable(struct xnfd *context)
 {
 	if (!XENO_ASSERT(RTDM, !xnsched_interrupt_p()))
 		return 0;
 
-	return (user_info ? xnshadow_thread(user_info) != NULL
-			  : !xnsched_root_p());
+	if (xnfd_owner(context) == &__xnsys_global_ppd)
+		return !xnsched_root_p();
+
+	return xnshadow_thread(current) != NULL;
 }
 
 static inline int rtdm_in_rt_context(void)
@@ -1387,8 +1145,4 @@ static inline int rtdm_in_rt_context(void)
 
 #endif /* !DOXYGEN_CPP */
 
-int rtdm_exec_in_rt(struct rtdm_dev_context *context,
-		    rtdm_user_info_t *user_info, void *arg,
-		    rtdm_rt_handler_t handler);
-
 #endif /* _COBALT_RTDM_DRIVER_H */
diff --git a/include/cobalt/kernel/rtdm/rtdm.h b/include/cobalt/kernel/rtdm/rtdm.h
index f90ecf0..cbf324c 100644
--- a/include/cobalt/kernel/rtdm/rtdm.h
+++ b/include/cobalt/kernel/rtdm/rtdm.h
@@ -25,36 +25,20 @@
 #include <linux/ioctl.h>
 #include <linux/sched.h>
 #include <linux/socket.h>
+#include <cobalt/kernel/ppd.h>
+
+#define RTDM_MAGIC 0x5254444d
 
 typedef u32 socklen_t;
 typedef struct task_struct rtdm_user_info_t;
 
-int __rt_dev_open(rtdm_user_info_t *user_info,
-		  const char *path, int oflag);
-
-int __rt_dev_socket(rtdm_user_info_t *user_info,
-		    int protocol_family,
-		    int socket_type, int protocol);
-
-int __rt_dev_close(rtdm_user_info_t *user_info,
-		   int fd);
-
-int __rt_dev_ioctl(rtdm_user_info_t *user_info,
-		   int fd, int request, ...);
-
-ssize_t __rt_dev_read(rtdm_user_info_t *user_info,
-		      int fd, void *buf,
-		      size_t nbyte);
-
-ssize_t __rt_dev_write(rtdm_user_info_t *user_info,
-		       int fd, const void *buf,
-		       size_t nbyte);
+int __rt_dev_open(struct xnsys_ppd *p, int ufd, const char *path, int oflag);
 
-ssize_t __rt_dev_recvmsg(rtdm_user_info_t *user_info,
-			 int fd, struct msghdr *msg, int flags);
+int __rt_dev_socket(struct xnsys_ppd *p, int ufd, 
+		int protocol_family, int socket_type, int protocol);
 
-ssize_t __rt_dev_sendmsg(rtdm_user_info_t *user_info,
-			 int fd, const struct msghdr *msg, int flags);
+int 
+__rt_dev_ioctl_fallback(struct xnfd *fd, unsigned request, void __user *arg);
 
 /*
  * Define RTDM_NO_DEFAULT_USER_API to switch off the default
@@ -63,28 +47,28 @@ ssize_t __rt_dev_sendmsg(rtdm_user_info_t *user_info,
 #ifndef RTDM_NO_DEFAULT_USER_API
 
 #define rt_dev_open(path, oflag, ...)				\
-	__rt_dev_open(NULL, path, oflag)
+	__rt_dev_open(&__xnsys_global_ppd, -1, path, oflag)
 
 #define rt_dev_socket(protocol_family, socket_type, protocol)	\
-	__rt_dev_socket(NULL, protocol_family, socket_type, protocol)
+	__rt_dev_socket(&__xnsys_global_ppd, -1, protocol_family, socket_type, protocol)
 
 #define rt_dev_close(fd)					\
-	__rt_dev_close(NULL, fd)
+	xnfd_close(&__xnsys_global_ppd, fd, RTDM_MAGIC)
 
 #define rt_dev_ioctl(fd, request, ...)				\
-	__rt_dev_ioctl(NULL, fd, request, __VA_ARGS__)
+	xnfd_ioctl(&__xnsys_global_ppd, fd, request, __VA_ARGS__)
 
 #define rt_dev_read(fd, buf, nbyte)				\
-	__rt_dev_read(NULL, fd, buf, nbyte)
+	xnfd_read(&__xnsys_global_ppd, fd, buf, nbyte)
 
 #define rt_dev_write(fd, buf, nbyte)				\
-	__rt_dev_write(NULL, fd, buf, nbyte)
+	xnfd_write(&__xnsys_global_ppd, fd, buf, nbyte)
 
 #define rt_dev_recvmsg(fd, msg, flags)				\
-	__rt_dev_recvmsg(NULL, fd, msg, flags)
+	xnfd_recvmsg(&__xnsys_global_ppd, fd, msg, flags)
 
 #define rt_dev_sendmsg(fd, msg, flags)				\
-	__rt_dev_sendmsg(NULL, fd, msg, flags)
+	xnfd_sendmsg(&__xnsys_global_ppd, fd, msg, flags)
 
 static inline
 ssize_t rt_dev_recvfrom(int fd, void *buf, size_t len, int flags,
diff --git a/kernel/cobalt/posix/select.c b/kernel/cobalt/posix/select.c
index 1c56abd..2e3d77a 100644
--- a/kernel/cobalt/posix/select.c
+++ b/kernel/cobalt/posix/select.c
@@ -21,34 +21,13 @@
  */
 #include <linux/types.h>
 #include <linux/err.h>
-#include <rtdm/driver.h>
 #include <cobalt/kernel/fd.h>
+#include <cobalt/kernel/select.h>
 #include "internal.h"
 #include "clock.h"
 #include "mqueue.h"
 #include "select.h"
 
-#define RTDM_FD_MAX CONFIG_XENO_OPT_RTDM_FILDES
-
-static int fd_valid_p(int fd)
-{
-	const int rtdm_fd_start = __FD_SETSIZE - RTDM_FD_MAX;
-	struct rtdm_dev_context *ctx;
-
-	if (xnfd_valid_p(fd))
-		return 1;
-
-	if (fd >= rtdm_fd_start) {
-		ctx = rtdm_context_get(fd - rtdm_fd_start);
-		if (ctx == NULL)
-			return 0;
-		rtdm_context_unlock(ctx);
-		return 1;
-	}
-
-	return 0;
-}
-
 static int first_fd_valid_p(fd_set *fds[XNSELECT_MAX_TYPES], int nfds)
 {
 	int i, fd;
@@ -56,7 +35,7 @@ static int first_fd_valid_p(fd_set *fds[XNSELECT_MAX_TYPES], int nfds)
 	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 xnfd_valid_p(fd);
 
 	/* All empty is correct, used as a "sleep" mechanism by strange
 	   applications. */
@@ -65,17 +44,12 @@ static int first_fd_valid_p(fd_set *fds[XNSELECT_MAX_TYPES], int nfds)
 
 static int select_bind_one(struct xnselector *selector, unsigned type, int fd)
 {
-	const int rtdm_fd_start = __FD_SETSIZE - RTDM_FD_MAX;
 	int rc;
 
 	rc = xnfd_select_bind(fd, selector, type);
 	if (rc != -ENOENT)
 		return rc;
 
-	if (fd >= rtdm_fd_start)
-		return rtdm_select_bind(fd - rtdm_fd_start,
-					selector, type, fd);
-
 	return -EBADF;
 }
 
diff --git a/kernel/cobalt/rtdm/core.c b/kernel/cobalt/rtdm/core.c
index b4f2a81..95cba0d 100644
--- a/kernel/cobalt/rtdm/core.c
+++ b/kernel/cobalt/rtdm/core.c
@@ -37,96 +37,61 @@
 #define CLOSURE_RETRY_PERIOD_MS	100
 
 #define FD_BITMAP_SIZE  ((RTDM_FD_MAX + BITS_PER_LONG-1) / BITS_PER_LONG)
-
-struct rtdm_fildes fildes_table[RTDM_FD_MAX] =
-	{ [0 ... RTDM_FD_MAX-1] = { NULL } };
 static unsigned long used_fildes[FD_BITMAP_SIZE];
-int open_fildes;	/* number of used descriptors */
-
-static void close_callback(struct work_struct *work);
-static DECLARE_DELAYED_WORK(close_work, close_callback);
-static LIST_HEAD(cleanup_queue);
+int open_fildes;       /* number of used descriptors */
 
 DEFINE_XNLOCK(rt_fildes_lock);
 
-/**
- * @brief Retrieve and lock a device context
- *
- * @param[in] fd File descriptor
- *
- * @return Pointer to associated device context, or NULL on error
- *
- * @note The device context has to be unlocked using rtdm_context_put() when
- * it is no longer referenced.
- *
- * 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.
- */
-struct rtdm_dev_context *rtdm_context_get(int fd)
+static void cleanup_instance(struct rtdm_device *device,
+			     struct rtdm_dev_context *context)
 {
-	struct rtdm_dev_context *context;
-	spl_t s;
-
-	if ((unsigned int)fd >= RTDM_FD_MAX)
-		return NULL;
-
-	xnlock_get_irqsave(&rt_fildes_lock, s);
-
-	context = fildes_table[fd].context;
-	if (unlikely(!context)) {
-		xnlock_put_irqrestore(&rt_fildes_lock, s);
-		return NULL;
+	if (context) {
+		if (device->reserved.exclusive_context)
+			context->device = NULL;
+		else
+			kfree(context);
 	}
 
-	atomic_inc(&context->close_lock_count);
-
-	xnlock_put_irqrestore(&rt_fildes_lock, s);
-
-	return context;
+	rtdm_dereference_device(device);
 }
 
-EXPORT_SYMBOL_GPL(rtdm_context_get);
+void __rt_dev_close(struct xnfd *fd)
+{
+	struct rtdm_dev_context *context = rtdm_context(fd);
+	
+	context->reserved.close(fd);
+	cleanup_instance(context->device, context);
+}
 
-static int create_instance(struct rtdm_device *device,
-			   struct rtdm_dev_context **context_ptr,
-			   struct rtdm_fildes **fildes_ptr,
-			   rtdm_user_info_t *user_info, int nrt_mem)
+static int create_instance(struct xnsys_ppd *p, int fd, 
+			struct rtdm_device *device,
+			struct rtdm_dev_context **context_ptr)
 {
 	struct rtdm_dev_context *context;
 	spl_t s;
-	int fd;
+	int err;
 
 	/*
 	 * Reset to NULL so that we can always use cleanup_files/instance to
 	 * revert also partially successful allocations.
 	 */
 	*context_ptr = NULL;
-	*fildes_ptr = NULL;
 
-	/* Reserve a file descriptor */
-	xnlock_get_irqsave(&rt_fildes_lock, s);
+	if (p == &__xnsys_global_ppd) {
+		xnlock_get_irqsave(&rt_fildes_lock, s);
+
+		if (unlikely(open_fildes >= RTDM_FD_MAX)) {
+			xnlock_put_irqrestore(&rt_fildes_lock, s);
+			return -ENFILE;
+		}
 
-	if (unlikely(open_fildes >= RTDM_FD_MAX)) {
+		fd = find_first_zero_bit(used_fildes, RTDM_FD_MAX);
+		__set_bit(fd, used_fildes);
+		open_fildes++;
+		
 		xnlock_put_irqrestore(&rt_fildes_lock, s);
-		return -ENFILE;
 	}
 
-	fd = find_first_zero_bit(used_fildes, RTDM_FD_MAX);
-	__set_bit(fd, used_fildes);
-	open_fildes++;
-
-	xnlock_put_irqrestore(&rt_fildes_lock, s);
-
-	*fildes_ptr = &fildes_table[fd];
-
 	context = device->reserved.exclusive_context;
 	if (context) {
 		xnlock_get_irqsave(&rt_dev_lock, s);
@@ -139,147 +104,54 @@ static int create_instance(struct rtdm_device *device,
 
 		xnlock_put_irqrestore(&rt_dev_lock, s);
 	} else {
-		if (nrt_mem)
-			context = kmalloc(sizeof(struct rtdm_dev_context) +
-					  device->context_size, GFP_KERNEL);
-		else
-			context = xnmalloc(sizeof(struct rtdm_dev_context) +
-					   device->context_size);
+		context = kmalloc(sizeof(struct rtdm_dev_context) +
+				device->context_size, GFP_KERNEL);
 		if (unlikely(!context))
 			return -ENOMEM;
 
 		context->device = device;
 	}
 
-	*context_ptr = context;
-
-	context->fd = fd;
-	context->ops = &device->ops;
-	atomic_set(&context->close_lock_count, 1);
-
-	context->reserved.owner = xnshadow_private_get(__rtdm_muxid);
-	INIT_LIST_HEAD(&context->reserved.cleanup);
-
-	return 0;
-}
-
-static void __cleanup_fildes(struct rtdm_fildes *fildes)
-{
-	__clear_bit((fildes - fildes_table), used_fildes);
-	fildes->context = NULL;
-	open_fildes--;
-}
-
-static void cleanup_fildes(struct rtdm_fildes *fildes)
-{
-	spl_t s;
-
-	if (!fildes)
-		return;
-
-	xnlock_get_irqsave(&rt_fildes_lock, s);
-	__cleanup_fildes(fildes);
-	xnlock_put_irqrestore(&rt_fildes_lock, s);
-}
-
-static void cleanup_instance(struct rtdm_device *device,
-			     struct rtdm_dev_context *context,
-			     int nrt_mem)
-{
-	if (context) {
-		if (device->reserved.exclusive_context)
+	err = xnfd_enter(p, &context->fd, fd, RTDM_MAGIC, &device->ops);
+	if (err < 0) {
+		if (device->reserved.exclusive_context) {
+			xnlock_get_irqsave(&rt_dev_lock, s);
 			context->device = NULL;
-		else {
-			if (nrt_mem)
-				kfree(context);
-			else
-				xnfree(context);
-		}
-	}
-
-	rtdm_dereference_device(device);
-}
-
-static void close_callback(struct work_struct *work)
-{
-	struct rtdm_dev_context *context;
-	LIST_HEAD(deferred_list);
-	int reschedule = 0;
-	int err;
-	spl_t s;
-
-	xnlock_get_irqsave(&rt_fildes_lock, s);
-
-	while (!list_empty(&cleanup_queue)) {
-		context = list_first_entry(&cleanup_queue,
-					   struct rtdm_dev_context,
-					   reserved.cleanup);
-		list_del(&context->reserved.cleanup);
-		atomic_inc(&context->close_lock_count);
-
-		xnlock_put_irqrestore(&rt_fildes_lock, s);
-
-		err = context->ops->close_nrt(context, NULL);
-
-		if (err == -EAGAIN ||
-		    atomic_read(&context->close_lock_count) > 1) {
-			atomic_dec(&context->close_lock_count);
-			list_add_tail(&context->reserved.cleanup,
-				      &deferred_list);
-			if (err == -EAGAIN)
-				reschedule = 1;
-		} else {
-			trace_mark(xn_rtdm, fd_closed, "fd %d", context->fd);
-
-			cleanup_instance(context->device, context,
-					 test_bit(RTDM_CREATED_IN_NRT,
-						  &context->context_flags));
-		}
-
-		xnlock_get_irqsave(&rt_fildes_lock, s);
+			xnlock_put_irqrestore(&rt_dev_lock, s);
+		} else
+			kfree(context);
+		
+		return err;
 	}
 
-	list_splice(&deferred_list, &cleanup_queue);
-
-	xnlock_put_irqrestore(&rt_fildes_lock, s);
+	if (p == &__xnsys_global_ppd)
+		context->reserved.owner = NULL;
+	else
+		context->reserved.owner = xnshadow_private_get(__rtdm_muxid);
+	context->reserved.close = device->reserved.close;
+	*context_ptr = context;
 
-	if (reschedule)
-		schedule_delayed_work(&close_work,
-				      (HZ * CLOSURE_RETRY_PERIOD_MS) / 1000);
+	return 0;
 }
 
-void rtdm_apc_handler(void *cookie)
-{
-	schedule_delayed_work(&close_work, 0);
-}
-
-
-int __rt_dev_open(rtdm_user_info_t *user_info, const char *path, int oflag)
+int __rt_dev_open(struct xnsys_ppd *p, int ufd, const char *path, int oflag)
 {
 	struct rtdm_device *device;
-	struct rtdm_fildes *fildes;
 	struct rtdm_dev_context *context;
 	int ret;
-	int nrt_mode = !rtdm_in_rt_context();
 
 	device = get_named_device(path);
-	trace_mark(xn_rtdm, open, "user_info %p path %s oflag %d device %p",
-		   user_info, path, oflag, device);
+	trace_mark(xn_rtdm, open, "sys_ppd %p path %s oflag %d device %p",
+		   p, path, oflag, device);
 	ret = -ENODEV;
 	if (!device)
 		goto err_out;
 
-	ret = create_instance(device, &context, &fildes, user_info, nrt_mode);
+	ret = create_instance(p, ufd, device, &context);
 	if (ret != 0)
 		goto cleanup_out;
 
-	if (nrt_mode) {
-		context->context_flags = (1 << RTDM_CREATED_IN_NRT);
-		ret = device->open_nrt(context, user_info, oflag);
-	} else {
-		context->context_flags = 0;
-		ret = device->open_rt(context, user_info, oflag);
-	}
+	ret = device->open(&context->fd, oflag);
 
 	if (!XENO_ASSERT(RTDM, !spltest()))
 		splnone();
@@ -287,51 +159,39 @@ int __rt_dev_open(rtdm_user_info_t *user_info, const char *path, int oflag)
 	if (unlikely(ret < 0))
 		goto cleanup_out;
 
-	fildes->context = context;
-
 	trace_mark(xn_rtdm, fd_created,
-		   "device %p fd %d", device, context->fd);
+		"device %p fd %d", device, xnfd_index(&context->fd));
 
-	return context->fd;
+	return xnfd_index(&context->fd);
 
 cleanup_out:
-	cleanup_fildes(fildes);
-	cleanup_instance(device, context, nrt_mode);
+	cleanup_instance(device, context);
 
 err_out:
 	return ret;
 }
-
 EXPORT_SYMBOL_GPL(__rt_dev_open);
 
-int __rt_dev_socket(rtdm_user_info_t *user_info, int protocol_family,
+int __rt_dev_socket(struct xnsys_ppd *p, int ufd, int protocol_family,
 		    int socket_type, int protocol)
 {
 	struct rtdm_device *device;
-	struct rtdm_fildes *fildes;
 	struct rtdm_dev_context *context;
 	int ret;
-	int nrt_mode = !rtdm_in_rt_context();
 
 	device = get_protocol_device(protocol_family, socket_type);
-	trace_mark(xn_rtdm, socket, "user_info %p protocol_family %d "
+	trace_mark(xn_rtdm, socket, "sys_ppd %p protocol_family %d "
 		   "socket_type %d protocol %d device %p",
-		   user_info, protocol_family, socket_type, protocol, device);
+		   p, protocol_family, socket_type, protocol, device);
 	ret = -EAFNOSUPPORT;
 	if (!device)
 		goto err_out;
 
-	ret = create_instance(device, &context, &fildes, user_info, nrt_mode);
+	ret = create_instance(p, ufd, device, &context);
 	if (ret != 0)
 		goto cleanup_out;
 
-	if (nrt_mode) {
-		context->context_flags = (1 << RTDM_CREATED_IN_NRT);
-		ret = device->socket_nrt(context, user_info, protocol);
-	} else {
-		context->context_flags = 0;
-		ret = device->socket_rt(context, user_info, protocol);
-	}
+	ret = device->socket(&context->fd, protocol);
 
 	if (!XENO_ASSERT(RTDM, !spltest()))
 		splnone();
@@ -339,302 +199,36 @@ int __rt_dev_socket(rtdm_user_info_t *user_info, int protocol_family,
 	if (unlikely(ret < 0))
 		goto cleanup_out;
 
-	fildes->context = context;
-
 	trace_mark(xn_rtdm, fd_created,
-		   "device %p fd %d", device, context->fd);
+		"device %p fd %d", device, xnfd_index(&context->fd));
 
-	return context->fd;
+	return xnfd_index(&context->fd);
 
 cleanup_out:
-	cleanup_fildes(fildes);
-	cleanup_instance(device, context, nrt_mode);
+	cleanup_instance(device, context);
 
 err_out:
 	return ret;
 }
-
 EXPORT_SYMBOL_GPL(__rt_dev_socket);
 
-int __rt_dev_close(rtdm_user_info_t *user_info, int fd)
-{
-	struct rtdm_dev_context *context;
-	spl_t s;
-	int ret;
-	int nrt_mode = !rtdm_in_rt_context();
-
-	trace_mark(xn_rtdm, close, "user_info %p fd %d", user_info, fd);
-
-	ret = -EBADF;
-	if (unlikely((unsigned int)fd >= RTDM_FD_MAX))
-		goto err_out;
-
-	xnlock_get_irqsave(&rt_fildes_lock, s);
-
-	context = fildes_table[fd].context;
-
-	if (unlikely(!context)) {
-		xnlock_put_irqrestore(&rt_fildes_lock, s);
-		goto err_out;	/* -EBADF */
-	}
-
-	/* Avoid asymmetric close context by switching to nrt. */
-	if (unlikely(test_bit(RTDM_CREATED_IN_NRT, &context->context_flags)) &&
-	    !nrt_mode) {
-		xnlock_put_irqrestore(&rt_fildes_lock, s);
-
-		ret = -ENOSYS;
-		goto err_out;
-	}
-
-	set_bit(RTDM_CLOSING, &context->context_flags);
-	atomic_inc(&context->close_lock_count);
-
-	__cleanup_fildes(&fildes_table[fd]);
-
-	xnlock_put_irqrestore(&rt_fildes_lock, s);
-
-	if (nrt_mode)
-		ret = context->ops->close_nrt(context, user_info);
-	else
-		ret = context->ops->close_rt(context, user_info);
-
-	if (!XENO_ASSERT(RTDM, !spltest()))
-		splnone();
-
-	xnlock_get_irqsave(&rt_fildes_lock, s);
-
-	if (ret == -EAGAIN || atomic_read(&context->close_lock_count) > 2) {
-		atomic_dec(&context->close_lock_count);
-		list_add(&context->reserved.cleanup, &cleanup_queue);
-
-		xnlock_put_irqrestore(&rt_fildes_lock, s);
-
-		if (ret == -EAGAIN) {
-			xnapc_schedule(rtdm_apc);
-			ret = 0;
-		}
-		goto unlock_out;
-	}
-
-	xnlock_put_irqrestore(&rt_fildes_lock, s);
-
-	trace_mark(xn_rtdm, fd_closed, "fd %d", context->fd);
-
-	cleanup_instance(context->device, context,
-			 test_bit(RTDM_CREATED_IN_NRT,
-				  &context->context_flags));
-
-	return ret;
-
-unlock_out:
-	rtdm_context_unlock(context);
-
-err_out:
-	return ret;
-}
-
-EXPORT_SYMBOL_GPL(__rt_dev_close);
-
-void cleanup_process_files(struct rtdm_process *owner)
+int 
+__rt_dev_ioctl_fallback(struct xnfd *fd, unsigned request, void __user *arg)
 {
-	struct rtdm_dev_context *context;
-	unsigned int fd;
-	int ret;
-	spl_t s;
-
-	for (fd = 0; fd < RTDM_FD_MAX; fd++) {
-		xnlock_get_irqsave(&rt_fildes_lock, s);
-
-		context = fildes_table[fd].context;
-		if (context && context->reserved.owner != owner)
-			context = NULL;
-
-		xnlock_put_irqrestore(&rt_fildes_lock, s);
-
-		if (context) {
-			if (XENO_DEBUG(RTDM_APPL))
-				printk(XENO_INFO "closing RTDM file descriptor %d\n",
-				       fd);
-
-			ret = __rt_dev_close(NULL, fd);
-			XENO_ASSERT(RTDM, ret == 0 || ret == -EBADF);
-		}
-	}
+	struct rtdm_device *dev = rtdm_context(fd)->device;
+	struct rtdm_device_info dev_info;
+	
+	if (request != RTIOC_DEVICE_INFO)
+		return -ENOSYS;
+	
+	dev_info.device_flags = dev->device_flags;
+	dev_info.device_class = dev->device_class;
+	dev_info.device_sub_class = dev->device_sub_class;
+	dev_info.profile_version = dev->profile_version;
+	
+	return rtdm_safe_copy_to_user(fd, arg, &dev_info,  sizeof(dev_info));
 }
 
-#define MAJOR_FUNCTION_WRAPPER_TH(operation, args...)			\
-do {									\
-	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;						\
-									\
-	if (rtdm_in_rt_context())					\
-		ret = ops->operation##_rt(context, user_info, args);	\
-	else								\
-		ret = ops->operation##_nrt(context, user_info, args);	\
-									\
-	if (!XENO_ASSERT(RTDM, !spltest()))				\
-		    splnone();
-
-#define MAJOR_FUNCTION_WRAPPER_BH()					\
-	rtdm_context_unlock(context);					\
-									\
-err_out:								\
-	trace_mark(xn_rtdm, operation##_done, "result %d", ret);	\
-	return ret;							\
-} while (0)
-
-#define MAJOR_FUNCTION_WRAPPER(operation, args...)			\
-do {									\
-	MAJOR_FUNCTION_WRAPPER_TH(operation, args);			\
-	MAJOR_FUNCTION_WRAPPER_BH();					\
-} while (0)
-
-int __rt_dev_ioctl(rtdm_user_info_t *user_info, int fd, int request, ...)
-{
-	va_list args;
-	void __user *arg;
-
-	va_start(args, request);
-	arg = va_arg(args, void __user *);
-	va_end(args);
-
-	trace_mark(xn_rtdm, ioctl, "user_info %p fd %d request %d arg %p",
-		   user_info, fd, request, arg);
-
-	MAJOR_FUNCTION_WRAPPER_TH(ioctl, (unsigned int)request, arg);
-
-	if (unlikely(ret < 0) && (unsigned int)request == RTIOC_DEVICE_INFO) {
-		struct rtdm_device *dev = context->device;
-		struct rtdm_device_info dev_info;
-
-		dev_info.device_flags = dev->device_flags;
-		dev_info.device_class = dev->device_class;
-		dev_info.device_sub_class = dev->device_sub_class;
-		dev_info.profile_version = dev->profile_version;
-
-		ret = rtdm_safe_copy_to_user(user_info, arg, &dev_info,
-					     sizeof(dev_info));
-	}
-
-	MAJOR_FUNCTION_WRAPPER_BH();
-}
-
-EXPORT_SYMBOL_GPL(__rt_dev_ioctl);
-
-ssize_t __rt_dev_read(rtdm_user_info_t *user_info, int fd, void *buf,
-		      size_t nbyte)
-{
-	trace_mark(xn_rtdm, read, "user_info %p fd %d buf %p nbyte %zu",
-		   user_info, fd, buf, nbyte);
-	MAJOR_FUNCTION_WRAPPER(read, buf, nbyte);
-}
-
-EXPORT_SYMBOL_GPL(__rt_dev_read);
-
-ssize_t __rt_dev_write(rtdm_user_info_t *user_info, int fd, const void *buf,
-		       size_t nbyte)
-{
-	trace_mark(xn_rtdm, write, "user_info %p fd %d buf %p nbyte %zu",
-		   user_info, fd, buf, nbyte);
-	MAJOR_FUNCTION_WRAPPER(write, buf, nbyte);
-}
-
-EXPORT_SYMBOL_GPL(__rt_dev_write);
-
-ssize_t __rt_dev_recvmsg(rtdm_user_info_t *user_info, int fd,
-			 struct msghdr *msg, int flags)
-{
-	trace_mark(xn_rtdm, recvmsg, "user_info %p fd %d msg_name %p "
-		   "msg_namelen %u msg_iov %p msg_iovlen %zu "
-		   "msg_control %p msg_controllen %zu msg_flags %d",
-		   user_info, fd, msg->msg_name, msg->msg_namelen,
-		   msg->msg_iov, msg->msg_iovlen, msg->msg_control,
-		   msg->msg_controllen, msg->msg_flags);
-	MAJOR_FUNCTION_WRAPPER(recvmsg, msg, flags);
-}
-
-EXPORT_SYMBOL_GPL(__rt_dev_recvmsg);
-
-ssize_t __rt_dev_sendmsg(rtdm_user_info_t *user_info, int fd,
-			 const struct msghdr *msg, int flags)
-{
-	trace_mark(xn_rtdm, sendmsg, "user_info %p fd %d msg_name %p "
-		   "msg_namelen %u msg_iov %p msg_iovlen %zu "
-		   "msg_control %p msg_controllen %zu msg_flags %d",
-		   user_info, fd, msg->msg_name, msg->msg_namelen,
-		   msg->msg_iov, msg->msg_iovlen, msg->msg_control,
-		   msg->msg_controllen, msg->msg_flags);
-	MAJOR_FUNCTION_WRAPPER(sendmsg, msg, flags);
-}
-
-EXPORT_SYMBOL_GPL(__rt_dev_sendmsg);
-
-/**
- * @brief Bind a selector to specified event types of a given file descriptor
- * @internal
- *
- * This function is invoked by higher RTOS layers implementing select-like
- * services. It shall not be called directly by RTDM drivers.
- *
- * @param[in] fd File descriptor to bind to
- * @param[in,out] selector Selector object that shall be bound to the given
- * event
- * @param[in] type Event type the caller is interested in
- * @param[in] fd_index Index in the file descriptor set of the caller
- *
- * @return 0 on success, otherwise:
- *
- * - -EBADF is returned if the file descriptor @a fd cannot be resolved.
- *
- * - -EINVAL is returned if @a type or @a fd_index are invalid.
- *
- * Environments:
- *
- * This service can be called from:
- *
- * - Kernel module initialization/cleanup code
- * - Kernel-based task
- * - User-space task (RT, non-RT)
- *
- * Rescheduling: never.
- */
-int rtdm_select_bind(int fd, rtdm_selector_t *selector,
-		     enum rtdm_selecttype type, unsigned fd_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, fd_index);
-
-	if (!XENO_ASSERT(RTDM, !spltest()))
-		    splnone();
-
-	rtdm_context_unlock(context);
-
-  err_out:
-	return ret;
-}
-
-EXPORT_SYMBOL_GPL(rtdm_select_bind);
-
 #ifdef DOXYGEN_CPP /* Only used for doxygen doc generation */
 
 /**
diff --git a/kernel/cobalt/rtdm/device.c b/kernel/cobalt/rtdm/device.c
index aca34f7..d04f427 100644
--- a/kernel/cobalt/rtdm/device.c
+++ b/kernel/cobalt/rtdm/device.c
@@ -49,23 +49,21 @@
 struct list_head rtdm_named_devices;	/* hash table */
 struct rb_root rtdm_protocol_devices;
 
-int rtdm_apc;
-EXPORT_SYMBOL_GPL(rtdm_apc);
-
 struct semaphore nrt_dev_lock;
 DEFINE_XNLOCK(rt_dev_lock);
 
 int rtdm_initialised = 0;
 
+extern void __rt_dev_close(struct xnfd *fd);
+
 int rtdm_no_support(void)
 {
 	return -ENOSYS;
 }
 
-int rtdm_select_bind_no_support(struct rtdm_dev_context *context,
+int rtdm_select_bind_no_support(struct xnfd *fd,
 				struct xnselector *selector,
-				unsigned type,
-				unsigned index)
+				unsigned type)
 {
 	return -EBADF;
 }
@@ -190,30 +188,20 @@ int rtdm_dev_register(struct rtdm_device *device)
 	switch (device->device_flags & RTDM_DEVICE_TYPE_MASK) {
 	case RTDM_NAMED_DEVICE:
 		/* Sanity check: any open handler? */
-		if (!XENO_ASSERT(RTDM, ANY_HANDLER(*device, open))) {
+		if (device->open == NULL) {
 			printk(XENO_ERR "missing open handler for RTDM device\n");
 			return -EINVAL;
 		}
-		if (device->open_rt &&
-		    device->socket_rt != (void *)rtdm_no_support)
-			printk(XENO_ERR "RT open handler is deprecated, "
-			       "RTDM driver requires update\n");
-		SET_DEFAULT_OP_IF_NULL(*device, open);
-		SET_DEFAULT_OP(*device, socket);
+		device->socket = (typeof(device->socket))rtdm_no_support;
 		break;
 
 	case RTDM_PROTOCOL_DEVICE:
 		/* Sanity check: any socket handler? */
-		if (!XENO_ASSERT(RTDM, ANY_HANDLER(*device, socket))) {
+		if (device->socket == NULL) {
 			printk(XENO_ERR "missing socket handler for RTDM device\n");
 			return -EINVAL;
 		}
-		if (device->socket_rt &&
-		    device->socket_rt != (void *)rtdm_no_support)
-			printk(XENO_ERR "RT socket creation handler is "
-			       "deprecated, RTDM driver requires update\n");
-		SET_DEFAULT_OP_IF_NULL(*device, socket);
-		SET_DEFAULT_OP(*device, open);
+		device->open = (typeof(device->open))rtdm_no_support;
 		break;
 
 	default:
@@ -222,16 +210,12 @@ int rtdm_dev_register(struct rtdm_device *device)
 
 	/* Sanity check: non-RT close handler?
 	 * (Always required for forced cleanup) */
-	if (!device->ops.close_nrt) {
-		printk(XENO_ERR "missing non-RT close handler for RTDM device\n");
+	if (!device->ops.close) {
+		printk(XENO_ERR "missing close handler for RTDM device\n");
 		return -EINVAL;
 	}
-	if (device->ops.close_rt &&
-	    device->ops.close_rt != (void *)rtdm_no_support)
-		printk(XENO_ERR "RT close handler is deprecated, RTDM driver "
-		       "requires update\n");
-	else
-		device->ops.close_rt = (void *)rtdm_no_support;
+	device->reserved.close = device->ops.close;
+	device->ops.close = __rt_dev_close;
 
 	SET_DEFAULT_OP_IF_NULL(device->ops, ioctl);
 	SET_DEFAULT_OP_IF_NULL(device->ops, read);
@@ -423,11 +407,6 @@ int __init rtdm_dev_init(void)
 {
 	sema_init(&nrt_dev_lock, 1);
 
-	rtdm_apc = xnapc_alloc("deferred RTDM close", rtdm_apc_handler,
-				   NULL);
-	if (rtdm_apc < 0)
-		return rtdm_apc;
-
 	INIT_LIST_HEAD(&rtdm_named_devices);
 	xntree_init(&rtdm_protocol_devices);
 
@@ -440,7 +419,6 @@ void rtdm_dev_cleanup(void)
 	 * Note: no need to flush the cleanup_queue as no device is allowed
 	 * to deregister as long as there are references.
 	 */
-	xnapc_free(rtdm_apc);
 }
 
 /*@}*/
diff --git a/kernel/cobalt/rtdm/drvlib.c b/kernel/cobalt/rtdm/drvlib.c
index 17178ee..3f16507 100644
--- a/kernel/cobalt/rtdm/drvlib.c
+++ b/kernel/cobalt/rtdm/drvlib.c
@@ -1884,7 +1884,7 @@ static struct file_operations rtdm_mmap_fops = {
 	.get_unmapped_area = rtdm_unmapped_area
 };
 
-static int rtdm_do_mmap(rtdm_user_info_t *user_info,
+static int rtdm_do_mmap(struct xnfd *fd,
 			struct rtdm_mmap_data *mmap_data,
 			size_t len, int prot, void **pptr)
 {
@@ -1912,7 +1912,7 @@ static int rtdm_do_mmap(rtdm_user_info_t *user_info,
 	filp->f_op = (typeof(filp->f_op))old_fops;
 	filp->private_data = old_priv_data;
 
-	filp_close(filp, user_info->files);
+	filp_close(filp, current->files);
 
 	if (IS_ERR_VALUE(u_addr))
 		return (int)u_addr;
@@ -1976,7 +1976,7 @@ static int rtdm_do_mmap(rtdm_user_info_t *user_info,
  *
  * Rescheduling: possible.
  */
-int rtdm_mmap_to_user(rtdm_user_info_t *user_info,
+int rtdm_mmap_to_user(struct xnfd *fd,
 		      void *src_addr, size_t len,
 		      int prot, void **pptr,
 		      struct vm_operations_struct *vm_ops,
@@ -1989,7 +1989,7 @@ int rtdm_mmap_to_user(rtdm_user_info_t *user_info,
 		.vm_private_data = vm_private_data
 	};
 
-	return rtdm_do_mmap(user_info, &mmap_data, len, prot, pptr);
+	return rtdm_do_mmap(fd, &mmap_data, len, prot, pptr);
 }
 
 EXPORT_SYMBOL_GPL(rtdm_mmap_to_user);
@@ -2044,7 +2044,7 @@ EXPORT_SYMBOL_GPL(rtdm_mmap_to_user);
  *
  * Rescheduling: possible.
  */
-int rtdm_iomap_to_user(rtdm_user_info_t *user_info,
+int rtdm_iomap_to_user(struct xnfd *fd,
 		       phys_addr_t src_addr, size_t len,
 		       int prot, void **pptr,
 		       struct vm_operations_struct *vm_ops,
@@ -2057,7 +2057,7 @@ int rtdm_iomap_to_user(rtdm_user_info_t *user_info,
 		.vm_private_data = vm_private_data
 	};
 
-	return rtdm_do_mmap(user_info, &mmap_data, len, prot, pptr);
+	return rtdm_do_mmap(fd, &mmap_data, len, prot, pptr);
 }
 
 EXPORT_SYMBOL_GPL(rtdm_iomap_to_user);
@@ -2086,16 +2086,16 @@ EXPORT_SYMBOL_GPL(rtdm_iomap_to_user);
  *
  * Rescheduling: possible.
  */
-int rtdm_munmap(rtdm_user_info_t *user_info, void *ptr, size_t len)
+int rtdm_munmap(struct xnfd *fd, void *ptr, size_t len)
 {
 	int err;
 
 	if (!XENO_ASSERT(RTDM, xnsched_root_p()))
 		return -EPERM;
 
-	down_write(&user_info->mm->mmap_sem);
-	err = do_munmap(user_info->mm, (unsigned long)ptr, len);
-	up_write(&user_info->mm->mmap_sem);
+	down_write(&current->mm->mmap_sem);
+	err = do_munmap(current->mm, (unsigned long)ptr, len);
+	up_write(&current->mm->mmap_sem);
 
 	return err;
 }
@@ -2263,7 +2263,7 @@ void rtdm_free(void *ptr);
  *
  * Rescheduling: never.
  */
-int rtdm_read_user_ok(rtdm_user_info_t *user_info, const void __user *ptr,
+int rtdm_read_user_ok(struct xnfd *fd, const void __user *ptr,
 		      size_t size);
 
 /**
@@ -2287,7 +2287,7 @@ int rtdm_read_user_ok(rtdm_user_info_t *user_info, const void __user *ptr,
  *
  * Rescheduling: never.
  */
-int rtdm_rw_user_ok(rtdm_user_info_t *user_info, const void __user *ptr,
+int rtdm_rw_user_ok(struct xnfd *fd, const void __user *ptr,
 		    size_t size);
 
 /**
@@ -2316,7 +2316,7 @@ int rtdm_rw_user_ok(rtdm_user_info_t *user_info, const void __user *ptr,
  *
  * Rescheduling: never.
  */
-int rtdm_copy_from_user(rtdm_user_info_t *user_info, void *dst,
+int rtdm_copy_from_user(struct xnfd *fd, void *dst,
 			const void __user *src, size_t size);
 
 /**
@@ -2346,7 +2346,7 @@ int rtdm_copy_from_user(rtdm_user_info_t *user_info, void *dst,
  *
  * Rescheduling: never.
  */
-int rtdm_safe_copy_from_user(rtdm_user_info_t *user_info, void *dst,
+int rtdm_safe_copy_from_user(struct xnfd *fd, void *dst,
 			     const void __user *src, size_t size);
 
 /**
@@ -2375,7 +2375,7 @@ int rtdm_safe_copy_from_user(rtdm_user_info_t *user_info, void *dst,
  *
  * Rescheduling: never.
  */
-int rtdm_copy_to_user(rtdm_user_info_t *user_info, void __user *dst,
+int rtdm_copy_to_user(struct xnfd *fd, void __user *dst,
 		      const void *src, size_t size);
 
 /**
@@ -2405,7 +2405,7 @@ int rtdm_copy_to_user(rtdm_user_info_t *user_info, void __user *dst,
  *
  * Rescheduling: never.
  */
-int rtdm_safe_copy_to_user(rtdm_user_info_t *user_info, void __user *dst,
+int rtdm_safe_copy_to_user(struct xnfd *fd, void __user *dst,
 			   const void *src, size_t size);
 
 /**
@@ -2436,7 +2436,7 @@ int rtdm_safe_copy_to_user(rtdm_user_info_t *user_info, void __user *dst,
  *
  * Rescheduling: never.
  */
-int rtdm_strncpy_from_user(rtdm_user_info_t *user_info, char *dst,
+int rtdm_strncpy_from_user(struct xnfd *fd, char *dst,
 			   const char __user *src, size_t count);
 
 /**
@@ -2482,7 +2482,7 @@ int rtdm_in_rt_context(void);
  *
  * Rescheduling: never.
  */
-int rtdm_rt_capable(rtdm_user_info_t *user_info);
+int rtdm_rt_capable(struct xnfd *fd);
 
 #endif /* DOXYGEN_CPP */
 
diff --git a/kernel/cobalt/rtdm/internal.h b/kernel/cobalt/rtdm/internal.h
index 3288068..6db80a6 100644
--- a/kernel/cobalt/rtdm/internal.h
+++ b/kernel/cobalt/rtdm/internal.h
@@ -31,10 +31,6 @@
 #define DEF_DEVNAME_HASHTAB_SIZE	256	/* entries in name hash table */
 #define DEF_PROTO_HASHTAB_SIZE		256	/* entries in protocol hash table */
 
-struct rtdm_fildes {
-	struct rtdm_dev_context *context;
-};
-
 struct rtdm_process {
 #ifdef CONFIG_XENO_OPT_VFILE
 	char name[32];
@@ -46,10 +42,8 @@ DECLARE_EXTERN_XNLOCK(rt_fildes_lock);
 DECLARE_EXTERN_XNLOCK(rt_dev_lock);
 
 extern int __rtdm_muxid;
-extern struct rtdm_fildes fildes_table[];
 extern int open_fildes;
 extern struct semaphore nrt_dev_lock;
-extern unsigned int devname_hashtab_size;
 extern struct list_head rtdm_named_devices;
 extern struct rb_root rtdm_protocol_devices;
 extern struct xnpersonality rtdm_personality;
diff --git a/kernel/cobalt/rtdm/proc.c b/kernel/cobalt/rtdm/proc.c
index 28ec6ab..0b8cafa 100644
--- a/kernel/cobalt/rtdm/proc.c
+++ b/kernel/cobalt/rtdm/proc.c
@@ -184,40 +184,35 @@ static int openfd_show(struct xnvfile_regular_iterator *it, void *data)
 	struct rtdm_dev_context *context;
 	struct rtdm_device *device;
 	struct rtdm_process owner;
-	int close_lock_count, fd;
-	spl_t s;
+	int close_lock_count, i;
+	struct xnfd *fd;
 
 	if (data == NULL) {
 		xnvfile_puts(it, "Index\tLocked\tDevice\t\t\t\tOwner [PID]\n");
 		return 0;
 	}
 
-	fd = (int)it->pos - 1;
+	i = (int)it->pos - 1;
 
-	xnlock_get_irqsave(&rt_fildes_lock, s);
-
-	context = fildes_table[fd].context;
-	if (context == NULL) {
-		xnlock_put_irqrestore(&rt_fildes_lock, s);
+	fd = xnfd_get(&__xnsys_global_ppd, i, RTDM_MAGIC);
+	if (fd == NULL)
 		return VFILE_SEQ_SKIP;
-	}
 
-	close_lock_count = atomic_read(&context->close_lock_count);
+	context = rtdm_context(fd);
+	close_lock_count = fd->refs;
 	device = context->device;
-	if (context->reserved.owner)
-		memcpy(&owner, context->reserved.owner, sizeof(owner));
-	else {
-		strcpy(owner.name, "<kernel>");
-		owner.pid = -1;
-	}
 
-	xnlock_put_irqrestore(&rt_fildes_lock, s);
+	strcpy(owner.name, "<kernel>");
+	owner.pid = -1;
 
-	xnvfile_printf(it, "%d\t%d\t%-31s %s [%d]\n", fd,
+	xnvfile_printf(it, "%d\t%d\t%-31s %s [%d]\n", i,
 		       close_lock_count,
 		       (device->device_flags & RTDM_NAMED_DEVICE) ?
 		       device->device_name : device->proc_name,
 		       owner.name, owner.pid);
+
+	xnfd_put(fd);
+
 	return 0;
 }
 
@@ -230,7 +225,7 @@ static ssize_t openfd_store(struct xnvfile_input *input)
 	if (ret < 0)
 		return ret;
 
-	cret = __rt_dev_close(current, (int)val);
+	cret = xnfd_close(&__xnsys_global_ppd, (int)val, RTDM_MAGIC);
 	if (cret < 0)
 		return cret;
 
diff --git a/kernel/cobalt/rtdm/syscall.c b/kernel/cobalt/rtdm/syscall.c
index 24edd3a..42f8c06 100644
--- a/kernel/cobalt/rtdm/syscall.c
+++ b/kernel/cobalt/rtdm/syscall.c
@@ -24,83 +24,23 @@
 
 int __rtdm_muxid;
 
-static int sys_rtdm_fdcount(void)
-{
-	return RTDM_FD_MAX;
-}
-
-static int sys_rtdm_open(const char __user *u_path, int oflag)
+static int sys_rtdm_open(int fd, const char __user *u_path, int oflag)
 {
 	char krnl_path[RTDM_MAX_DEVNAME_LEN + 1];
-	struct task_struct *p = current;
 
 	if (unlikely(__xn_safe_strncpy_from_user(krnl_path, u_path,
 						 sizeof(krnl_path) - 1) < 0))
 		return -EFAULT;
 	krnl_path[sizeof(krnl_path) - 1] = '\0';
 
-	return __rt_dev_open(p, krnl_path, oflag);
-}
-
-static int sys_rtdm_socket(int protocol_family, int socket_type, int protocol)
-{
-	return __rt_dev_socket(current,
-			       protocol_family, socket_type, protocol);
-}
-
-static int sys_rtdm_close(int fd)
-{
-	return __rt_dev_close(current, fd);
-}
-
-static int sys_rtdm_ioctl(int fd, int request, void *arglist)
-{
-	return __rt_dev_ioctl(current, fd, request, arglist);
-}
-
-static int sys_rtdm_read(int fd, void __user *u_buf, size_t nbytes)
-{
-	return __rt_dev_read(current, fd, u_buf, nbytes);
-}
-
-static int sys_rtdm_write(int fd, const void __user *u_buf, size_t nbytes)
-{
-	return __rt_dev_write(current, fd, u_buf, nbytes);
+	return __rt_dev_open(xnsys_ppd_get(0), fd, krnl_path, oflag);
 }
 
-static int sys_rtdm_recvmsg(int fd, struct msghdr __user *u_msg, int flags)
+static int 
+sys_rtdm_socket(int fd, int protocol_family, int socket_type, int protocol)
 {
-	struct task_struct *p = current;
-	struct msghdr krnl_msg;
-	int ret;
-
-	if (unlikely(!access_wok(u_msg, sizeof(krnl_msg)) ||
-		     __xn_copy_from_user(&krnl_msg, u_msg,
-					 sizeof(krnl_msg))))
-		return -EFAULT;
-
-	ret = __rt_dev_recvmsg(p, fd, &krnl_msg, flags);
-	if (unlikely(ret < 0))
-		return ret;
-
-	if (unlikely(__xn_copy_to_user(u_msg, &krnl_msg, sizeof(krnl_msg))))
-		return -EFAULT;
-
-	return ret;
-}
-
-static int sys_rtdm_sendmsg(int fd, const struct msghdr __user *u_msg,
-			    int flags)
-{
-	struct task_struct *p = current;
-	struct msghdr krnl_msg;
-
-	if (unlikely(!access_rok(u_msg, sizeof(krnl_msg)) ||
-		     __xn_copy_from_user(&krnl_msg, u_msg,
-					 sizeof(krnl_msg))))
-		return -EFAULT;
-
-	return __rt_dev_sendmsg(p, fd, &krnl_msg, flags);
+	return __rt_dev_socket(xnsys_ppd_get(0), fd, 
+			protocol_family, socket_type, protocol);
 }
 
 static void *rtdm_process_attach(void)
@@ -123,20 +63,12 @@ static void rtdm_process_detach(void *arg)
 {
 	struct rtdm_process *process = arg;
 
-	cleanup_process_files(process);
 	kfree(process);
 }
 
 static struct xnsyscall rtdm_syscalls[] = {
-	SKINCALL_DEF(sc_rtdm_fdcount, sys_rtdm_fdcount, any),
 	SKINCALL_DEF(sc_rtdm_open, sys_rtdm_open, probing),
 	SKINCALL_DEF(sc_rtdm_socket, sys_rtdm_socket, probing),
-	SKINCALL_DEF(sc_rtdm_close, sys_rtdm_close, probing),
-	SKINCALL_DEF(sc_rtdm_ioctl, sys_rtdm_ioctl, probing),
-	SKINCALL_DEF(sc_rtdm_read, sys_rtdm_read, probing),
-	SKINCALL_DEF(sc_rtdm_write, sys_rtdm_write, probing),
-	SKINCALL_DEF(sc_rtdm_recvmsg, sys_rtdm_recvmsg, probing),
-	SKINCALL_DEF(sc_rtdm_sendmsg, sys_rtdm_sendmsg, probing),
 };
 
 struct xnpersonality rtdm_personality = {
diff --git a/lib/cobalt/rtdm.c b/lib/cobalt/rtdm.c
index d253bb1..21d5411 100644
--- a/lib/cobalt/rtdm.c
+++ b/lib/cobalt/rtdm.c
@@ -31,7 +31,6 @@
 
 extern int __rtdm_muxid;
 extern int __cobalt_muxid;
-extern int __rtdm_fd_start;
 
 static inline int set_errno(int ret)
 {
@@ -44,8 +43,13 @@ static inline int set_errno(int ret)
 
 COBALT_IMPL(int, open, (const char *path, int oflag, ...))
 {
-	int ret, oldtype;
+	int ret, fd, oldtype;
 	const char *rtdm_path = path;
+	va_list ap;
+
+	fd = open("/dev/null", O_RDONLY);
+	if (fd < 0)
+		return fd;
 
 	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
 
@@ -53,85 +57,78 @@ COBALT_IMPL(int, open, (const char *path, int oflag, ...))
 	if (strncmp(path, "/dev/", 5) == 0)
 		rtdm_path += 5;
 
-	ret = XENOMAI_SKINCALL2(__rtdm_muxid, sc_rtdm_open, rtdm_path, oflag);
+	ret = XENOMAI_SKINCALL3(__rtdm_muxid, 
+				sc_rtdm_open, 
+				fd, rtdm_path, oflag);
 
 	pthread_setcanceltype(oldtype, NULL);
 
-	if (ret >= 0)
-		ret += __rtdm_fd_start;
-	else if (ret == -ENODEV || ret == -ENOSYS) {
-		va_list ap;
-
-		va_start(ap, oflag);
-
-		ret = __STD(open(path, oflag, va_arg(ap, mode_t)));
+	if (ret == fd)
+		return fd;
+	close(fd);
 
-		va_end(ap);
+	if (ret != -ENODEV && ret != -ENOSYS)
+		return set_errno(ret);
 
-		if (ret >= __rtdm_fd_start) {
-			__STD(close(ret));
-			errno = EMFILE;
-			ret = -1;
-		}
-	} else {
-		errno = -ret;
-		ret = -1;
-	}
+	va_start(ap, oflag);
+	ret = __STD(open(path, oflag, va_arg(ap, mode_t)));
+	va_end(ap);
 
 	return ret;
 }
 
 COBALT_IMPL(int, socket, (int protocol_family, int socket_type, int protocol))
 {
-	int ret;
+	int ret, fd;
+
+	fd = open("/dev/null", O_RDONLY);
+	if (fd < 0)
+		return fd;
 
-	ret = XENOMAI_SKINCALL3(__rtdm_muxid,
+	ret = XENOMAI_SKINCALL4(__rtdm_muxid,
 				sc_rtdm_socket,
-				protocol_family, socket_type, protocol);
-	if (ret >= 0)
-		ret += __rtdm_fd_start;
-	else if (ret == -EAFNOSUPPORT || ret == -EPROTONOSUPPORT || 
-		 ret == -ENOSYS) {
-		ret = __STD(socket(protocol_family, socket_type, protocol));
-
-		if (ret >= __rtdm_fd_start) {
-			__STD(close(ret));
-			errno = -EMFILE;
-			ret = -1;
-		}
-	} else {
-		errno = -ret;
-		ret = -1;
-	}
+				fd, protocol_family, socket_type, protocol);
+	if (ret == fd)
+		return fd;
+	close(fd);
 
-	return ret;
+	if (ret != -EAFNOSUPPORT && ret != -EPROTONOSUPPORT && ret != -ENOSYS)
+		return set_errno(ret);
+	
+	return __STD(socket(protocol_family, socket_type, protocol));
 }
 
 COBALT_IMPL(int, close, (int fd))
 {
+	int oldtype;
 	int ret;
+	
+	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
 
 	ret = XENOMAI_SKINCALL1(__cobalt_muxid, sc_cobalt_close, fd);
-	if (ret != -EBADF) {
+
+	pthread_setcanceltype(oldtype, NULL);
+
+	if (ret != -EBADF && ret != -ENOSYS) {
 		if (ret == 0)
 			__STD(close(fd));
 		return set_errno(ret);
 	}
 
-	if (fd >= __rtdm_fd_start) {
-		int oldtype;
+	return __STD(close(fd));
+}
 
-		pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
+static int __xn_ioctl(int fd, unsigned long request, void *arg)
+{
+	int ret, oldtype;
 
-		ret = set_errno(XENOMAI_SKINCALL1(__rtdm_muxid,
-						  sc_rtdm_close,
-						  fd - __rtdm_fd_start));
+	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
 
-		pthread_setcanceltype(oldtype, NULL);
+	ret = XENOMAI_SKINCALL3(__cobalt_muxid,
+				sc_cobalt_ioctl, 
+				fd, request, arg);
 
-		return ret;
-	} else
-		return __STD(close(fd));
+	pthread_setcanceltype(oldtype, NULL);
 
 	return ret;
 }
@@ -140,24 +137,17 @@ COBALT_IMPL(int, ioctl, (int fd, unsigned long int request, ...))
 {
 	va_list ap;
 	void *arg;
-	int err;
+	int ret;
 
 	va_start(ap, request);
 	arg = va_arg(ap, void *);
 	va_end(ap);
 
-	err = XENOMAI_SKINCALL3(__cobalt_muxid,
-				sc_cobalt_ioctl, fd, request, arg);
-	if (err != -EBADF)
-		return set_errno(err);
-
-	if (fd >= __rtdm_fd_start)
-		return set_errno(XENOMAI_SKINCALL3(__rtdm_muxid,
-						   sc_rtdm_ioctl,
-						   fd - __rtdm_fd_start,
-						   request, arg));
-	else
-		return __STD(ioctl(fd, request, arg));
+	ret = __xn_ioctl(fd, request, arg);
+	if (ret != -EBADF && ret != -ENOSYS)
+		return set_errno(ret);
+
+	return __STD(ioctl(fd, request, arg));
 }
 
 COBALT_IMPL(ssize_t, read, (int fd, void *buf, size_t nbyte))
@@ -166,26 +156,14 @@ COBALT_IMPL(ssize_t, read, (int fd, void *buf, size_t nbyte))
 	
 	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
 
-	ret = XENOMAI_SKINCALL3(__cobalt_muxid, sc_cobalt_read, 
+	ret = XENOMAI_SKINCALL3(__cobalt_muxid, 
+				sc_cobalt_read, 
 				fd, buf, nbyte);
 
-	if (ret != -EBADF) {
-		pthread_setcanceltype(oldtype, NULL);
-		return set_errno(ret);
-	}
-
-	if (fd >= __rtdm_fd_start) {
-		ret = set_errno(XENOMAI_SKINCALL3(__rtdm_muxid,
-						  sc_rtdm_read,
-						  fd - __rtdm_fd_start,
-						  buf, nbyte));
-
-		pthread_setcanceltype(oldtype, NULL);
-
-		return ret;
-	}
-
 	pthread_setcanceltype(oldtype, NULL);
+
+	if (ret != -EBADF && ret != -ENOSYS)
+		return set_errno(ret);
 		
 	return __STD(read(fd, buf, nbyte));
 }
@@ -196,299 +174,232 @@ COBALT_IMPL(ssize_t, write, (int fd, const void *buf, size_t nbyte))
 
 	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
 
-	ret = XENOMAI_SKINCALL3(__cobalt_muxid, sc_cobalt_write,
+	ret = XENOMAI_SKINCALL3(__cobalt_muxid, 
+				sc_cobalt_write,
 				fd, buf, nbyte);
 
-	if (ret != -EBADF) {
-		pthread_setcanceltype(oldtype, NULL);
-		return set_errno(ret);
-	}
-	
-	if (fd >= __rtdm_fd_start) {
-		ret = set_errno(XENOMAI_SKINCALL3(__rtdm_muxid,
-						  sc_rtdm_write,
-						  fd - __rtdm_fd_start,
-						  buf, nbyte));
-
-		pthread_setcanceltype(oldtype, NULL);
-
-		return ret;
-	}
-
 	pthread_setcanceltype(oldtype, NULL);
 
+	if (ret != -EBADF && ret != -ENOSYS)
+		return set_errno(ret);
+
 	return __STD(write(fd, buf, nbyte));
 }
 
-COBALT_IMPL(ssize_t, recvmsg, (int fd, struct msghdr * msg, int flags))
+static ssize_t __xn_recvmsg(int fd, struct msghdr *msg, int flags)
 {
-	if (fd >= __rtdm_fd_start) {
-		int ret, oldtype;
+	int ret, oldtype;
 
-		pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
+	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
 
-		ret = set_errno(XENOMAI_SKINCALL3(__rtdm_muxid,
-						  sc_rtdm_recvmsg,
-						  fd - __rtdm_fd_start,
-						  msg, flags));
+	ret = XENOMAI_SKINCALL3(__cobalt_muxid, 
+				sc_cobalt_recvmsg, 
+				fd, msg, flags);
 
-		pthread_setcanceltype(oldtype, NULL);
+	pthread_setcanceltype(oldtype, NULL);
 
-		return ret;
-	} else
-		return __STD(recvmsg(fd, msg, flags));
+	return ret;
 }
 
-COBALT_IMPL(ssize_t, sendmsg, (int fd, const struct msghdr * msg, int flags))
+COBALT_IMPL(ssize_t, recvmsg, (int fd, struct msghdr *msg, int flags))
 {
-	if (fd >= __rtdm_fd_start) {
-		int ret, oldtype;
-
-		pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
-
-		ret = set_errno(XENOMAI_SKINCALL3(__rtdm_muxid,
-						  sc_rtdm_sendmsg,
-						  fd - __rtdm_fd_start,
-						  msg, flags));
+	int ret;
 
-		pthread_setcanceltype(oldtype, NULL);
+	ret = __xn_recvmsg(fd, msg, flags);
+	if (ret != -EBADF && ret != -ENOSYS)
+		return set_errno(ret);
 
-		return ret;
-	} else
-		return __STD(sendmsg(fd, msg, flags));
+	return __STD(recvmsg(fd, msg, flags));
 }
 
-COBALT_IMPL(ssize_t, recvfrom, (int fd, void *buf, size_t len, int flags,
-				struct sockaddr * from, socklen_t * fromlen))
+static ssize_t __xn_sendmsg(int fd, const struct msghdr *msg, int flags)
 {
-	if (fd >= __rtdm_fd_start) {
-		struct iovec iov = { buf, len };
-		struct msghdr msg =
-		    { from, (from != NULL) ? *fromlen : 0, &iov, 1, NULL, 0 };
-		int ret, oldtype;
+	int ret, oldtype;
 
-		pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
+	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
 
-		ret = XENOMAI_SKINCALL3(__rtdm_muxid,
-					sc_rtdm_recvmsg,
-					fd - __rtdm_fd_start, &msg, flags);
+	ret = XENOMAI_SKINCALL3(__cobalt_muxid, 
+				sc_rtdm_sendmsg,
+				fd, msg, flags);
 
-		pthread_setcanceltype(oldtype, NULL);
+	pthread_setcanceltype(oldtype, NULL);
 
-		if (ret < 0) {
-			errno = -ret;
-			ret = -1;
-		} else if (from != NULL)
-			*fromlen = msg.msg_namelen;
-		return ret;
-	} else
-		return __STD(recvfrom(fd, buf, len, flags, from, fromlen));
+	return ret;
 }
 
-COBALT_IMPL(ssize_t, sendto, (int fd, const void *buf, size_t len, int flags,
-			      const struct sockaddr * to, socklen_t tolen))
+COBALT_IMPL(ssize_t, sendmsg, (int fd, const struct msghdr *msg, int flags))
 {
-	if (fd >= __rtdm_fd_start) {
-		struct iovec iov = { (void *)buf, len };
-		struct msghdr msg =
-		    { (struct sockaddr *)to, tolen, &iov, 1, NULL, 0 };
-		int ret, oldtype;
+	int ret;
+	
+	ret = __xn_sendmsg(fd, msg, flags);
+	if (ret != -EBADF && ret != -ENOSYS)
+		return set_errno(ret);
 
-		pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
+	return __STD(sendmsg(fd, msg, flags));
+}
 
-		ret = set_errno(XENOMAI_SKINCALL3(__rtdm_muxid,
-						  sc_rtdm_sendmsg,
-						  fd - __rtdm_fd_start,
-						  &msg, flags));
+COBALT_IMPL(ssize_t, recvfrom, (int fd, void *buf, size_t len, int flags,
+				struct sockaddr *from, socklen_t *fromlen))
+{
+	struct iovec iov = { buf, len };
+	struct msghdr msg =
+		{ from, (from != NULL) ? *fromlen : 0, &iov, 1, NULL, 0 };
+	int ret;
 
-		pthread_setcanceltype(oldtype, NULL);
+	ret = __xn_recvmsg(fd, &msg, flags);
+	if (ret != -EBADF && ret != -ENOSYS)
+		return set_errno(ret);
 
-		return ret;
-	} else
-		return __STD(sendto(fd, buf, len, flags, to, tolen));
+	return __STD(recvfrom(fd, buf, len, flags, from, fromlen));
 }
 
-COBALT_IMPL(ssize_t, recv, (int fd, void *buf, size_t len, int flags))
+COBALT_IMPL(ssize_t, sendto, (int fd, const void *buf, size_t len, int flags,
+			      const struct sockaddr *to, socklen_t tolen))
 {
-	if (fd >= __rtdm_fd_start) {
-		struct iovec iov = { buf, len };
-		struct msghdr msg = { NULL, 0, &iov, 1, NULL, 0 };
-		int ret, oldtype;
-
-		pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
+	struct iovec iov = { (void *)buf, len };
+	struct msghdr msg =
+		{ (struct sockaddr *)to, tolen, &iov, 1, NULL, 0 };
+	int ret;
+	
+	ret = __xn_sendmsg(fd, &msg, flags);
+	if (ret != -EBADF && ret != -ENOSYS)
+		return set_errno(ret);
 
-		ret = set_errno(XENOMAI_SKINCALL3(__rtdm_muxid,
-						  sc_rtdm_recvmsg,
-						  fd - __rtdm_fd_start,
-						  &msg, flags));
+	return __STD(sendto(fd, buf, len, flags, to, tolen));
+}
 
-		pthread_setcanceltype(oldtype, NULL);
+COBALT_IMPL(ssize_t, recv, (int fd, void *buf, size_t len, int flags))
+{
+	struct iovec iov = { buf, len };
+	struct msghdr msg = { NULL, 0, &iov, 1, NULL, 0 };
+	int ret;
+	
+	ret = __xn_recvmsg(fd, &msg, flags);
+	if (ret != -EBADF && ret != -ENOSYS)
+		return set_errno(ret);	
 
-		return ret;
-	} else
-		return __STD(recv(fd, buf, len, flags));
+	return __STD(recv(fd, buf, len, flags));
 }
 
 COBALT_IMPL(ssize_t, send, (int fd, const void *buf, size_t len, int flags))
 {
-	if (fd >= __rtdm_fd_start) {
-		struct iovec iov = { (void *)buf, len };
-		struct msghdr msg = { NULL, 0, &iov, 1, NULL, 0 };
-		int ret, oldtype;
-
-		pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
-
-		ret = set_errno(XENOMAI_SKINCALL3(__rtdm_muxid,
-						  sc_rtdm_sendmsg,
-						  fd - __rtdm_fd_start,
-						  &msg, flags));
+	struct iovec iov = { (void *)buf, len };
+	struct msghdr msg = { NULL, 0, &iov, 1, NULL, 0 };
+	int ret;
 
-		pthread_setcanceltype(oldtype, NULL);
+	ret = __xn_sendmsg(fd, &msg, flags);
+	if (ret != -EBADF && ret != -ENOSYS)
+		return set_errno(ret);	
 
-		return ret;
-	} else
-		return __STD(send(fd, buf, len, flags));
+	return __STD(send(fd, buf, len, flags));
 }
 
 COBALT_IMPL(int, getsockopt, (int fd, int level, int optname, void *optval,
-			      socklen_t * optlen))
+			      socklen_t *optlen))
 {
-	if (fd >= __rtdm_fd_start) {
-		struct _rtdm_getsockopt_args args =
-		    { level, optname, optval, optlen };
-
-		return set_errno(XENOMAI_SKINCALL3(__rtdm_muxid,
-						   sc_rtdm_ioctl,
-						   fd - __rtdm_fd_start,
-						   _RTIOC_GETSOCKOPT, &args));
-	} else
-		return __STD(getsockopt(fd, level, optname, optval, optlen));
+	struct _rtdm_getsockopt_args args = { level, optname, optval, optlen };
+	int ret;
+	
+	ret = __xn_ioctl(fd, _RTIOC_GETSOCKOPT, &args);
+	if (ret != -EBADF && ret != -ENOSYS)
+		return set_errno(ret);
+
+	return __STD(getsockopt(fd, level, optname, optval, optlen));
 }
 
 COBALT_IMPL(int, setsockopt, (int fd, int level, int optname, const void *optval,
 			      socklen_t optlen))
 {
-	if (fd >= __rtdm_fd_start) {
-		struct _rtdm_setsockopt_args args =
-		    { level, optname, (void *)optval, optlen };
-
-		return set_errno(XENOMAI_SKINCALL3(__rtdm_muxid,
-						   sc_rtdm_ioctl,
-						   fd - __rtdm_fd_start,
-						   _RTIOC_SETSOCKOPT, &args));
-	} else
-		return __STD(setsockopt(fd, level, optname, optval, optlen));
+	struct _rtdm_setsockopt_args args = { 
+		level, optname, (void *)optval, optlen 
+	};
+	int ret;
+	
+	ret = __xn_ioctl(fd, _RTIOC_SETSOCKOPT, &args);
+	if (ret != -EBADF && ret != -ENOSYS)
+		return set_errno(ret);
+
+	return __STD(setsockopt(fd, level, optname, optval, optlen));
 }
 
 COBALT_IMPL(int, bind, (int fd, const struct sockaddr *my_addr, socklen_t addrlen))
 {
-	if (fd >= __rtdm_fd_start) {
-		struct _rtdm_setsockaddr_args args = { my_addr, addrlen };
-
-		return set_errno(XENOMAI_SKINCALL3(__rtdm_muxid,
-						   sc_rtdm_ioctl,
-						   fd - __rtdm_fd_start,
-						   _RTIOC_BIND, &args));
-	} else
-		return __STD(bind(fd, my_addr, addrlen));
+	struct _rtdm_setsockaddr_args args = { my_addr, addrlen };
+	int ret;
+	
+	ret = __xn_ioctl(fd, _RTIOC_BIND, &args);
+	if (ret != -EBADF && ret != -ENOSYS)
+		return set_errno(ret);
+
+	return __STD(bind(fd, my_addr, addrlen));
 }
 
 COBALT_IMPL(int, connect, (int fd, const struct sockaddr *serv_addr, socklen_t addrlen))
 {
-	if (fd >= __rtdm_fd_start) {
-		struct _rtdm_setsockaddr_args args = { serv_addr, addrlen };
-		int ret, oldtype;
-
-		pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
-
-		ret = set_errno(XENOMAI_SKINCALL3(__rtdm_muxid,
-						  sc_rtdm_ioctl,
-						  fd - __rtdm_fd_start,
-						  _RTIOC_CONNECT, &args));
-
-		pthread_setcanceltype(oldtype, NULL);
+	struct _rtdm_setsockaddr_args args = { serv_addr, addrlen };
+	int ret;
+	
+	ret = __xn_ioctl(fd, _RTIOC_CONNECT, &args);
+	if (ret != -EBADF && ret != -ENOSYS)
+		return set_errno(ret);
 
-		return ret;
-	} else
-		return __STD(connect(fd, serv_addr, addrlen));
+	return __STD(connect(fd, serv_addr, addrlen));
 }
 
 COBALT_IMPL(int, listen, (int fd, int backlog))
 {
-	if (fd >= __rtdm_fd_start) {
-		return set_errno(XENOMAI_SKINCALL3(__rtdm_muxid,
-						   sc_rtdm_ioctl,
-						   fd - __rtdm_fd_start,
-						   _RTIOC_LISTEN, backlog));
-	} else
-		return __STD(listen(fd, backlog));
-}
-
-COBALT_IMPL(int, accept, (int fd, struct sockaddr *addr, socklen_t * addrlen))
-{
-	if (fd >= __rtdm_fd_start) {
-		struct _rtdm_getsockaddr_args args = { addr, addrlen };
-		int oldtype;
-
-		pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
-
-		fd = XENOMAI_SKINCALL3(__rtdm_muxid,
-				       sc_rtdm_ioctl,
-				       fd - __rtdm_fd_start,
-				       _RTIOC_ACCEPT, &args);
-
-		pthread_setcanceltype(oldtype, NULL);
+	int ret;
 
-		if (fd < 0)
-			return set_errno(fd);
+	ret = __xn_ioctl(fd, _RTIOC_LISTEN, (void *)(long)backlog);
+	if (ret != -EBADF && ret != -ENOSYS)
+		return set_errno(ret);
 
-		return fd + __rtdm_fd_start;
-	} else {
-		fd = __STD(accept(fd, addr, addrlen));
+	return __STD(listen(fd, backlog));
+}
 
-		if (fd >= __rtdm_fd_start) {
-			__STD(close(fd));
-			errno = EMFILE;
-			fd = -1;
-		}
+COBALT_IMPL(int, accept, (int fd, struct sockaddr *addr, socklen_t *addrlen))
+{
+	struct _rtdm_getsockaddr_args args = { addr, addrlen };
+	int ret;
+	
+	ret = __xn_ioctl(fd, _RTIOC_ACCEPT, &args);
+	if (ret != -EBADF && ret != -ENOSYS)
+		return set_errno(ret);
 
-		return fd;
-	}
+	return __STD(accept(fd, addr, addrlen));
 }
 
 COBALT_IMPL(int, getsockname, (int fd, struct sockaddr *name, socklen_t *namelen))
 {
-	if (fd >= __rtdm_fd_start) {
-		struct _rtdm_getsockaddr_args args = { name, namelen };
-
-		return set_errno(XENOMAI_SKINCALL3(__rtdm_muxid,
-						   sc_rtdm_ioctl,
-						   fd - __rtdm_fd_start,
-						   _RTIOC_GETSOCKNAME, &args));
-	} else
-		return __STD(getsockname(fd, name, namelen));
+	struct _rtdm_getsockaddr_args args = { name, namelen };
+	int ret;
+	
+	ret = __xn_ioctl(fd, _RTIOC_GETSOCKNAME, &args);
+	if (ret != -EBADF && ret != -ENOSYS)
+		return set_errno(ret);
+
+	return __STD(getsockname(fd, name, namelen));
 }
 
 COBALT_IMPL(int, getpeername, (int fd, struct sockaddr *name, socklen_t *namelen))
 {
-	if (fd >= __rtdm_fd_start) {
-		struct _rtdm_getsockaddr_args args = { name, namelen };
-
-		return set_errno(XENOMAI_SKINCALL3(__rtdm_muxid,
-						   sc_rtdm_ioctl,
-						   fd - __rtdm_fd_start,
-						   _RTIOC_GETPEERNAME, &args));
-	} else
-		return __STD(getpeername(fd, name, namelen));
+	struct _rtdm_getsockaddr_args args = { name, namelen };
+	int ret;
+	
+	ret = __xn_ioctl(fd, _RTIOC_GETPEERNAME, &args);
+	if (ret != -EBADF && ret != -ENOSYS)
+		return set_errno(ret);
+
+	return __STD(getpeername(fd, name, namelen));
 }
 
 COBALT_IMPL(int, shutdown, (int fd, int how))
 {
-	if (fd >= __rtdm_fd_start) {
-		return set_errno(XENOMAI_SKINCALL3(__rtdm_muxid,
-						   sc_rtdm_ioctl,
-						   fd - __rtdm_fd_start,
-						   _RTIOC_SHUTDOWN, how));
-	} else
-		return __STD(shutdown(fd, how));
+	int ret;
+
+	ret = __xn_ioctl(fd, _RTIOC_SHUTDOWN, (void *)(long)how);
+	if (ret != -EBADF && ret != -ENOSYS)
+		return set_errno(ret);
+
+	return __STD(shutdown(fd, how));
 }
-- 
1.7.10.4



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

* Re: [Xenomai] RTDM rework
  2014-02-01 18:23 [Xenomai] RTDM rework Gilles Chanteperdrix
  2014-02-01 18:27 ` [Xenomai] [PATCH 1/3] cobalt/rtdm: base protocol devices on xnid Gilles Chanteperdrix
@ 2014-02-02  0:21 ` Gilles Chanteperdrix
  2014-02-04 20:49   ` Gilles Chanteperdrix
  1 sibling, 1 reply; 7+ messages in thread
From: Gilles Chanteperdrix @ 2014-02-02  0:21 UTC (permalink / raw)
  To: Jan Kiszka, Philippe Gerum; +Cc: Xenomai

On 02/01/2014 07:23 PM, Gilles Chanteperdrix wrote:
> 
> Hi Jan, Philippe,
> 
> I have started working on rebasing RTDM on the common fd implementation
> (xnfd). Before I start changing the drivers, the current state of the
> changes follow as patches. These patches are based on the commits in the
> "for-forge" branch in xenomai-gch repository. Please do not pull from
> this branch just yet, it is probably going to be rebased.
> 
> The thing which I know we will discuss, even before you read the patches:
> - struct xnfd appears instead of struct rtdm_dev_context in callbacks,
> we already discussed that, you prefer rtdm typedefs, the thing is, in
> forge, the habit to typedef structs seems gone, and typedef struct xnfd
> rtdm_dev_contex_t would be confusing since struct rtdm_dev_context still
> exists, albeit is no longer exported to drivers;

The simple solution is:
#define rtdm_dev_context xnfd, and rename the real struct
rtdm_dev_context to __rtdm_dev_context, since it is internal anyway.

> - the xnfd structure is defined in cobalt, and not cobalt/posix, this
> was made so that both rtdm and posix can use it, but maybe it makes more
> sense to move it to posix (after all, file descriptors are a posix
> thing), and get rtdm to use it anyway;
> - doc is probably out of sync, this will be arranged in later commits
> - maybe select should be moved to fd.c now, posix/select.c contains 3
> functions, and it now supports xnfds exclusively;
> - context_flags are gone, since the two flags it used are no longer
> used, since driver have a private structure, drivers can move their
> flags to their private structure if they want;
> - handling -EAGAIN in the close callback is gone, the close callback now
> returns void, it is possible to delay file descriptor destruction by
> using rtdm_lock/rtdm_unlock, so the -EAGAIN return value was IMO redundant.

Having read the rtdm test, I noticed that the semantics of "close" has
more changed than that: it is no longer possible to delay the close
while already in the close callback by calling rtdm_context_lock.
rtdm_context_lock should be called before that, to prevent the close
callback from even be called. This, I hope, should be more in line with
Linux drivers and follow the principle of least surprise.


-- 
                                                                Gilles.


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

* Re: [Xenomai] RTDM rework
  2014-02-02  0:21 ` [Xenomai] RTDM rework Gilles Chanteperdrix
@ 2014-02-04 20:49   ` Gilles Chanteperdrix
       [not found]     ` <52FE14E1.8040303@siemens.com>
  0 siblings, 1 reply; 7+ messages in thread
From: Gilles Chanteperdrix @ 2014-02-04 20:49 UTC (permalink / raw)
  To: Jan Kiszka, Philippe Gerum; +Cc: Xenomai

On 02/02/2014 01:21 AM, Gilles Chanteperdrix wrote:
> On 02/01/2014 07:23 PM, Gilles Chanteperdrix wrote:
>>
>> Hi Jan, Philippe,
>>
>> I have started working on rebasing RTDM on the common fd implementation
>> (xnfd). Before I start changing the drivers, the current state of the
>> changes follow as patches. These patches are based on the commits in the
>> "for-forge" branch in xenomai-gch repository. Please do not pull from
>> this branch just yet, it is probably going to be rebased.
>>
>> The thing which I know we will discuss, even before you read the patches:
>> - struct xnfd appears instead of struct rtdm_dev_context in callbacks,
>> we already discussed that, you prefer rtdm typedefs, the thing is, in
>> forge, the habit to typedef structs seems gone, and typedef struct xnfd
>> rtdm_dev_contex_t would be confusing since struct rtdm_dev_context still
>> exists, albeit is no longer exported to drivers;
> 
> The simple solution is:
> #define rtdm_dev_context xnfd, and rename the real struct
> rtdm_dev_context to __rtdm_dev_context, since it is internal anyway.
> 
>> - the xnfd structure is defined in cobalt, and not cobalt/posix, this
>> was made so that both rtdm and posix can use it, but maybe it makes more
>> sense to move it to posix (after all, file descriptors are a posix
>> thing), and get rtdm to use it anyway;
>> - doc is probably out of sync, this will be arranged in later commits
>> - maybe select should be moved to fd.c now, posix/select.c contains 3
>> functions, and it now supports xnfds exclusively;
>> - context_flags are gone, since the two flags it used are no longer
>> used, since driver have a private structure, drivers can move their
>> flags to their private structure if they want;
>> - handling -EAGAIN in the close callback is gone, the close callback now
>> returns void, it is possible to delay file descriptor destruction by
>> using rtdm_lock/rtdm_unlock, so the -EAGAIN return value was IMO redundant.
> 
> Having read the rtdm test, I noticed that the semantics of "close" has
> more changed than that: it is no longer possible to delay the close
> while already in the close callback by calling rtdm_context_lock.
> rtdm_context_lock should be called before that, to prevent the close
> callback from even be called. This, I hope, should be more in line with
> Linux drivers and follow the principle of least surprise.
> 
> 

In order to try and tart the discussion on this subject, I pushed my
working branch, where switchtest, timerbench, rtdmtest and the rtdm ipc
modules have been adapted to the modified RTDM, so that you can see what
work this will entail for drivers.

-- 
                                                                Gilles.


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

* Re: [Xenomai] RTDM rework
       [not found]                 ` <52FE4D84.90006@siemens.com>
@ 2014-02-28 11:27                   ` Philippe Gerum
  0 siblings, 0 replies; 7+ messages in thread
From: Philippe Gerum @ 2014-02-28 11:27 UTC (permalink / raw)
  To: Jan Kiszka, Gilles Chanteperdrix; +Cc: Xenomai

On 02/14/2014 06:08 PM, Jan Kiszka wrote:
> On 2014-02-14 17:28, Philippe Gerum wrote:
>> On 02/14/2014 04:52 PM, Jan Kiszka wrote:
>>> On 2014-02-14 15:08, Gilles Chanteperdrix wrote:
>>>> On 02/14/2014 02:35 PM, Jan Kiszka wrote:
>>>>>>> I started to read through your patches. The general direction remains
>>>>>>> valid and beneficial, but I have a few formal issues with some API
>>>>>>> changes. In a nutshell: We really need to avoid layering
>>>>>>> violations by
>>>>>>> expressing public RTDM interfaces via Xenomai data structures
>>>>>>> directly.
>>>>>>>
>>>>>>> Sometimes it's just a cosmetic thing like wrapping the opaque struct
>>>>>>> xnfd into something like rtdm_fd. But rtdm_operations cannot
>>>>>>> simply be
>>>>>>> replaced with xnfd_ops. We loose RTDM documentation this way (yes,
>>>>>>> fixable), but we also now logically depend on the internals of
>>>>>>> Xenomai
>>>>>>> Cobalt in the abstract RTDM driver API. rtdm_operations is not
>>>>>>> opaque to
>>>>>>> driver developers!
>>>>>>
>>>>>> #define rtdm_dev_context xnfd
>>>>>> #define rtdm_operations xnfd_ops
>>>>>> should do the trick. Note that I told you about this change in
>>>>>> advance,
>>>>>> and proposed to cascade the callbacks.
>>>>>
>>>>> Not for rtdm_operations as its content is part of the RTDM API. It is
>>>>> _not_ an opaque type, in contrast to xnfd.
>>>>
>>>> With #define rtdm_operations xnfd_ops
>>>>
>>>> The user can do:
>>>>
>>>> struct rtdm_operations foo = { /* ... */ };
>>>>
>>>> Without knowing that he is in fact defining an xnfd_ops structure.
>>>>
>>>> I am sorry, but I do not see the problem, if we keep rtdm_operations
>>>> documented. But if you prefer we can, as I said, cascade the callbacks.
>>>> Or even arrange to define rtdm_operations with members with the same
>>>> signature as xnfd_ops, and fill an xnfd_ops structure with the
>>>> rtdm_operations members.
>>>
>>> I'd like to avoid that a change to xnfd_ops for whatever internal reason
>>> breaks the RTDM API subtly. Keep in mind that we will also have to map
>>> it on native Linux in a not-too-far future. Probably it is even a good
>>> idea to try this mapping right now, at least conceptually, to avoid
>>> having to change too much at that point again.
>>>
>>
>> Talking about conceptual issues, we may have a problem with supporting
>> RTDM_EXECUTE_ATOMICALLY() over native. I don't expect to see this sorted
>> shortly, but this should be part of the API discussion at some point.
>
> I think there are two types of RTDM_EXECUTE_ATOMICALLY users:
>
> 1. Testcases and other Xenomai-internal users that could also use
>     platform specific mechanisms, ie. do not depend on a portable
>     solution.
>
> 2. Drivers that require this semantic:
>
>     RTDM_EXECUTE_ATOMICALLY(
>         register_with_something();
>         sleep();
>         unregister_again();
>     )
>
>     vs.
>
>     RTDM_EXECUTE_ATOMICALLY(
>         for_each_registered_thing()
>             rtdm_task_unblock()
>     )
>
> The need for RTDM_EXECUTE_ATOMICALLY in the second case arises from the
> fact that we cannot wake up a specific task waiting on a shared sync
> object in advance, i.e. before it is already blocked on that object,
> without destroying that object for everyone. If we find an alternative
> unlocked pattern for this scenario, we can drop the nasty macro, I think.
>

The semantics in this case looks similar to wait_event_* and friends, 
maybe with an implicit condition on being asleep/awake, although this 
construct is likely to be used along with an explicit condition to test 
before going to sleep.

What about introducing rtdm_waitqueue_t and the related helpers? Over a 
native kernel, we could just map them over the regular kernel/wait 
interface, and getting the same constructs working over Cobalt does not 
look like a big issue.

The bonus would be to get rid of the "single lock" semantics which 
taints RTDM_EXECUTE_ATOMICALLY in the same move, so that we don't kill 
scalability over single image kernels.

-- 
Philippe.


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

end of thread, other threads:[~2014-02-28 11:27 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-01 18:23 [Xenomai] RTDM rework Gilles Chanteperdrix
2014-02-01 18:27 ` [Xenomai] [PATCH 1/3] cobalt/rtdm: base protocol devices on xnid Gilles Chanteperdrix
2014-02-01 18:27   ` [Xenomai] [PATCH 2/3] cobalt/rtdm: base named devices on nucleus registry Gilles Chanteperdrix
2014-02-01 18:27   ` [Xenomai] [PATCH 3/3] cobalt/rtdm: base on common fd implementation Gilles Chanteperdrix
2014-02-02  0:21 ` [Xenomai] RTDM rework Gilles Chanteperdrix
2014-02-04 20:49   ` Gilles Chanteperdrix
     [not found]     ` <52FE14E1.8040303@siemens.com>
     [not found]       ` <52FE18CE.4020702@xenomai.org>
     [not found]         ` <52FE1B85.3070402@siemens.com>
     [not found]           ` <52FE2364.6060608@xenomai.org>
     [not found]             ` <52FE3BCD.3000608@siemens.com>
     [not found]               ` <52FE443D.9060806@xenomai.org>
     [not found]                 ` <52FE4D84.90006@siemens.com>
2014-02-28 11:27                   ` Philippe Gerum

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.