All of lore.kernel.org
 help / color / mirror / Atom feed
* [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks
@ 2010-04-19 10:28 Jan Kiszka
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 01/25] RTDM: Fix potential NULL pointer dereference Jan Kiszka
                   ` (25 more replies)
  0 siblings, 26 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:28 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

The following changes since commit 2bed24477882dd7937d59f4e33a0811981c7362c:
  Gilles Chanteperdrix (1):
        arm: declare the VFP inline asm snippets as volatile.

are available in the git repository at:

  git://git.xenomai.org/xenomai-jki.git for-upstream

Changes in v4:
 - fixed rtdm_rt_capable()
 - renamed rttesting subclasses to switchtest and timerbench
 - added non-atomic used_fildes patch
 - fixed false-positive deprecated warnings for open_rt
 - fixed test device name regressions of v3

Changes in v3:
 - extended RTDM unit test to check for returned file descriptor number

Changes in v2:
 - compat support for rttest device names
 - documented RTDM close procedure
 - internal rework of the close procedure
 - basic RTDM unit test, so far targeting at the close rework
 - some additional small cleanup patches

Jan Kiszka (24):
  RTDM: Add rtdm_rt_capable() service
  RTDM: Bump API version and document changes
  Revert "rtdm: tag syscalls as conforming"
  RTDM: Deprecate open_rt, socket_rt, and close_rt
  RTIPC: Fix memory leak on failing socket creation
  RTIPC: Drop support for RT socket creation/deletion
  RTCAN: Drop support for socket creation/deletion in real-time
  16550A: Drop support for device opening/closing in real-time
  Analogy: Drop support for opening/closing in real-time
  RTDM: Instrument rtdm_context_lock/unlock to detect misuses
  RTDM: Add rtdm_context_put()
  Fix historic msleep wrapping
  irqbench: Fix x86-64 build
  irqbench: Refactor user space helpers
  irqbench: Auto-detect bases of port address and IRQ values
  rttest: Resolved test device conflicts via separate name spaces
  testing: Clean up Kconfig rules
  RTIPC: Drop unused wrapper around close_lock_count
  RTDM: Document device close procedure
  Add list_first_entry wrapper for older kernels
  Add legacy kernel support for delayed_work
  RTDM: Early fd release with poll-free context reference tracking
  RTDM: Add basic unit test
  RTDM: Use non-atomic bitops for used_fildes

Wolfgang Mauerer (1):
  RTDM: Fix potential NULL pointer dereference

 configure.in                          |    2 +-
 include/asm-generic/wrappers.h        |   10 +-
 include/compat/linux/workqueue.h      |   13 +
 include/rtdm/rtdm.h                   |    4 +-
 include/rtdm/rtdm_driver.h            |   50 +++-
 include/rtdm/rttesting.h              |   19 ++-
 ksrc/drivers/analogy/rtdm_interface.c |    2 -
 ksrc/drivers/can/rtcan_raw.c          |    2 -
 ksrc/drivers/ipc/internal.h           |    5 -
 ksrc/drivers/ipc/rtipc.c              |   13 +-
 ksrc/drivers/serial/16550A.c          |   51 +---
 ksrc/drivers/testing/Config.in        |    6 +-
 ksrc/drivers/testing/Kconfig          |   27 ++-
 ksrc/drivers/testing/Makefile         |   12 +-
 ksrc/drivers/testing/irqbench.c       |    9 +-
 ksrc/drivers/testing/klat.c           |    8 +-
 ksrc/drivers/testing/rtdmtest.c       |  191 +++++++++++++
 ksrc/drivers/testing/switchtest.c     |    7 +-
 ksrc/drivers/testing/timerbench.c     |    7 +-
 ksrc/skins/rtdm/API.CHANGES           |    9 +
 ksrc/skins/rtdm/core.c                |  209 ++++++++++----
 ksrc/skins/rtdm/device.c              |   59 ++++-
 ksrc/skins/rtdm/drvlib.c              |   25 ++
 ksrc/skins/rtdm/internal.h            |    8 +-
 ksrc/skins/rtdm/syscall.c             |   10 +-
 src/testsuite/irqbench/Makefile.am    |    2 +-
 src/testsuite/irqbench/irqbench.c     |  480 ++++++++++++++++-----------------
 src/testsuite/irqbench/irqloop.c      |  312 +++++++++++----------
 src/testsuite/latency/latency.c       |   12 +-
 src/testsuite/switchtest/switchtest.c |   15 +-
 src/testsuite/unit/Makefile.am        |   17 ++-
 src/testsuite/unit/rtdm.c             |  114 ++++++++
 32 files changed, 1158 insertions(+), 552 deletions(-)
 create mode 100644 ksrc/drivers/testing/rtdmtest.c
 create mode 100644 src/testsuite/unit/rtdm.c



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

* [Xenomai-core] [PATCH v4 01/25] RTDM: Fix potential NULL pointer dereference
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
@ 2010-04-19 10:28 ` Jan Kiszka
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 02/25] RTDM: Add rtdm_rt_capable() service Jan Kiszka
                   ` (24 subsequent siblings)
  25 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:28 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: Wolfgang Mauerer, xenomai-core

From: Wolfgang Mauerer <wolfgang.mauerer@domain.hid>

The rework in 95278926edc559d4 misses the case that context can be NULL,
which can (and has) triggered a kernel oops. Take care of this case.

Signed-off-by: Wolfgang Mauerer <wolfgang.mauerer@domain.hid>
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 ksrc/skins/rtdm/core.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/ksrc/skins/rtdm/core.c b/ksrc/skins/rtdm/core.c
index 8677c47..8cccf52 100644
--- a/ksrc/skins/rtdm/core.c
+++ b/ksrc/skins/rtdm/core.c
@@ -175,7 +175,7 @@ static int cleanup_instance(struct rtdm_device *device,
 
 	xnlock_get_irqsave(&rt_fildes_lock, s);
 
-	if (unlikely(atomic_read(&context->close_lock_count) > 1)) {
+	if (context && unlikely(atomic_read(&context->close_lock_count) > 1)) {
 		xnlock_put_irqrestore(&rt_fildes_lock, s);
 		return -EAGAIN;
 	}
-- 
1.6.0.2



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

* [Xenomai-core] [PATCH v4 02/25] RTDM: Add rtdm_rt_capable() service
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 01/25] RTDM: Fix potential NULL pointer dereference Jan Kiszka
@ 2010-04-19 10:28 ` Jan Kiszka
  2010-04-19 22:15   ` Philippe Gerum
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 03/25] RTDM: Bump API version and document changes Jan Kiszka
                   ` (23 subsequent siblings)
  25 siblings, 1 reply; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:28 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: Alexis Berlemont, xenomai-core

This adds rtdm_rt_capable(), a function that can be used by drivers to
detect callers that could issue a service request also from the
(typically preferred) real-time context. If that is the case, the driver
can trigger a restart of the request if the current context is not
real-time.

CC: Philippe Gerum <rpm@xenomai.org>
CC: Alexis Berlemont <berlemont.hauw@domain.hid>
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 include/rtdm/rtdm_driver.h |    6 ++++++
 ksrc/skins/rtdm/drvlib.c   |   25 +++++++++++++++++++++++++
 2 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/include/rtdm/rtdm_driver.h b/include/rtdm/rtdm_driver.h
index 0fc1496..d124157 100644
--- a/include/rtdm/rtdm_driver.h
+++ b/include/rtdm/rtdm_driver.h
@@ -1296,6 +1296,12 @@ static inline int rtdm_in_rt_context(void)
 {
 	return (rthal_current_domain != rthal_root_domain);
 }
+
+static inline int rtdm_rt_capable(void)
+{
+	return (!xnpod_root_p() || xnshadow_thread(current) != NULL);
+}
+
 #endif /* !DOXYGEN_CPP */
 
 int rtdm_exec_in_rt(struct rtdm_dev_context *context,
diff --git a/ksrc/skins/rtdm/drvlib.c b/ksrc/skins/rtdm/drvlib.c
index 3b04493..6e26501 100644
--- a/ksrc/skins/rtdm/drvlib.c
+++ b/ksrc/skins/rtdm/drvlib.c
@@ -2341,6 +2341,31 @@ int rtdm_strncpy_from_user(rtdm_user_info_t *user_info, char *dst,
  */
 int rtdm_in_rt_context(void);
 
+/**
+ * Test if the caller is capable of running in real-time context
+ *
+ * @return Non-zero is returned if the caller is able to execute in real-time
+ * context (independent of its current execution mode), 0 otherwise.
+ *
+ * @note This function can be used by drivers that provide different
+ * implementations for the same service depending on the execution mode of
+ * the caller. If a caller requests such a service in non-real-time context
+ * but is capable of running in real-time as well, it might be appropriate
+ * for the driver to reject the request via -ENOSYS so that RTDM can switch
+ * the caller and restart the request in real-time context.
+ *
+ * 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_rt_capable(void);
+
 #endif /* DOXYGEN_CPP */
 
 /** @} Utility Services */
-- 
1.6.0.2



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

* [Xenomai-core] [PATCH v4 03/25] RTDM: Bump API version and document changes
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 01/25] RTDM: Fix potential NULL pointer dereference Jan Kiszka
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 02/25] RTDM: Add rtdm_rt_capable() service Jan Kiszka
@ 2010-04-19 10:28 ` Jan Kiszka
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 04/25] Revert "rtdm: tag syscalls as conforming" Jan Kiszka
                   ` (22 subsequent siblings)
  25 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:28 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 include/rtdm/rtdm.h         |    4 ++--
 ksrc/skins/rtdm/API.CHANGES |    6 ++++++
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/include/rtdm/rtdm.h b/include/rtdm/rtdm.h
index 6e02083..1e6e41e 100644
--- a/include/rtdm/rtdm.h
+++ b/include/rtdm/rtdm.h
@@ -31,7 +31,7 @@
  * RT/non-RT systems like Xenomai. RTDM conforms to POSIX
  * semantics (IEEE Std 1003.1) where available and applicable.
  *
- * @b API @b Revision: 7
+ * @b API @b Revision: 8
  */
 
 /*!
@@ -76,7 +76,7 @@ typedef struct task_struct rtdm_user_info_t;
  * @anchor api_versioning @name API Versioning
  * @{ */
 /** Common user and driver API version */
-#define RTDM_API_VER			7
+#define RTDM_API_VER			8
 
 /** Minimum API revision compatible with the current release */
 #define RTDM_API_MIN_COMPAT_VER		6
diff --git a/ksrc/skins/rtdm/API.CHANGES b/ksrc/skins/rtdm/API.CHANGES
index ca9012b..84487f7 100644
--- a/ksrc/skins/rtdm/API.CHANGES
+++ b/ksrc/skins/rtdm/API.CHANGES
@@ -5,6 +5,12 @@ Scheduled modifications (unsorted):
  o Support for deferring IRQ line re-enabling from handler to thread context.
  o Support for user-space drivers.
 
+Revision 8:
+ o Added rtdm_rt_capable.
+
+Revision 7:
+ o Added callbacks and services to enable select support.
+
 Revision 6:
  o Added profile_version field to rtdm_device.
  o Requested IRQ lines are now enabled on return of rtdm_irq_request.
-- 
1.6.0.2



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

* [Xenomai-core] [PATCH v4 04/25] Revert "rtdm: tag syscalls as conforming"
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
                   ` (2 preceding siblings ...)
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 03/25] RTDM: Bump API version and document changes Jan Kiszka
@ 2010-04-19 10:28 ` Jan Kiszka
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 05/25] RTDM: Deprecate open_rt, socket_rt, and close_rt Jan Kiszka
                   ` (21 subsequent siblings)
  25 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:28 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: Alexis Berlemont, xenomai-core

This reverts commit 13bfdd477ab880499d2e8f3b82c49ef4d2cccff0. We better
let the driver trigger the confoming switch once it detects such a case
by using the new service rtdm_rt_capable(). Always being comforming
caused regressions for existing designs.

CC: Philippe Gerum <rpm@xenomai.org>
CC: Alexis Berlemont <berlemont.hauw@domain.hid>
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 ksrc/skins/rtdm/syscall.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/ksrc/skins/rtdm/syscall.c b/ksrc/skins/rtdm/syscall.c
index d869887..80785ab 100644
--- a/ksrc/skins/rtdm/syscall.c
+++ b/ksrc/skins/rtdm/syscall.c
@@ -154,14 +154,14 @@ static xnsysent_t __systab[] = {
 	[__rtdm_close] =
 	    {sys_rtdm_close, __xn_exec_current | __xn_exec_adaptive},
 	[__rtdm_ioctl] =
-	    {sys_rtdm_ioctl, __xn_exec_conforming | __xn_exec_adaptive},
-	[__rtdm_read] = {sys_rtdm_read, __xn_exec_conforming | __xn_exec_adaptive},
+	    {sys_rtdm_ioctl, __xn_exec_current | __xn_exec_adaptive},
+	[__rtdm_read] = {sys_rtdm_read, __xn_exec_current | __xn_exec_adaptive},
 	[__rtdm_write] =
-	    {sys_rtdm_write, __xn_exec_conforming | __xn_exec_adaptive},
+	    {sys_rtdm_write, __xn_exec_current | __xn_exec_adaptive},
 	[__rtdm_recvmsg] =
-	    {sys_rtdm_recvmsg, __xn_exec_conforming | __xn_exec_adaptive},
+	    {sys_rtdm_recvmsg, __xn_exec_current | __xn_exec_adaptive},
 	[__rtdm_sendmsg] =
-	    {sys_rtdm_sendmsg, __xn_exec_conforming | __xn_exec_adaptive},
+	    {sys_rtdm_sendmsg, __xn_exec_current | __xn_exec_adaptive},
 };
 
 static struct xnskin_props __props = {
-- 
1.6.0.2



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

* [Xenomai-core] [PATCH v4 05/25] RTDM: Deprecate open_rt, socket_rt, and close_rt
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
                   ` (3 preceding siblings ...)
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 04/25] Revert "rtdm: tag syscalls as conforming" Jan Kiszka
@ 2010-04-19 10:28 ` Jan Kiszka
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 06/25] RTIPC: Fix memory leak on failing socket creation Jan Kiszka
                   ` (20 subsequent siblings)
  25 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:28 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

Support for RTDM device creation and destruction in RT context will be
removed in the future. Start warning the users about this when loading
a driver that makes use of it.

CC: Philippe Gerum <rpm@xenomai.org>
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 include/rtdm/rtdm_driver.h  |   12 +++++++++---
 ksrc/skins/rtdm/API.CHANGES |    2 ++
 ksrc/skins/rtdm/device.c    |   14 +++++++++++++-
 3 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/include/rtdm/rtdm_driver.h b/include/rtdm/rtdm_driver.h
index d124157..d68f542 100644
--- a/include/rtdm/rtdm_driver.h
+++ b/include/rtdm/rtdm_driver.h
@@ -328,7 +328,8 @@ typedef int (*rtdm_rt_handler_t)(struct rtdm_dev_context *context,
 struct rtdm_operations {
 	/*! @name Common Operations
 	 * @{ */
-	/** Close handler for real-time contexts (optional) */
+	/** 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;
@@ -468,14 +469,19 @@ struct rtdm_device {
 	int socket_type;
 
 	/** Named device instance creation for real-time contexts,
-	 *  optional if open_nrt is non-NULL, ignored for protocol devices */
+	 *  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;
 
 	/** Protocol socket creation for real-time contexts,
-	 *  optional if socket_nrt is non-NULL, ignored for named devices */
+	 *  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 */
diff --git a/ksrc/skins/rtdm/API.CHANGES b/ksrc/skins/rtdm/API.CHANGES
index 84487f7..64a4b38 100644
--- a/ksrc/skins/rtdm/API.CHANGES
+++ b/ksrc/skins/rtdm/API.CHANGES
@@ -4,6 +4,8 @@ Scheduled modifications (unsorted):
  o Threaded IRQ handlers.
  o Support for deferring IRQ line re-enabling from handler to thread context.
  o Support for user-space drivers.
+ o Removal of open_rt, socket_rt, and close_rt, ie. support for device
+   creation and destruction in RT context.
 
 Revision 8:
  o Added rtdm_rt_capable.
diff --git a/ksrc/skins/rtdm/device.c b/ksrc/skins/rtdm/device.c
index e927ce7..e229932 100644
--- a/ksrc/skins/rtdm/device.c
+++ b/ksrc/skins/rtdm/device.c
@@ -219,6 +219,10 @@ int rtdm_dev_register(struct rtdm_device *device)
 		XENO_ASSERT(RTDM, ANY_HANDLER(*device, open),
 			    xnlogerr("RTDM: missing open handler\n");
 			    return -EINVAL;);
+		if (device->open_rt &&
+		    device->socket_rt != (void *)rtdm_no_support)
+			xnlogerr("RTDM: RT open handler is deprecated, "
+				 "driver requires update.\n");
 		SET_DEFAULT_OP_IF_NULL(*device, open);
 		SET_DEFAULT_OP(*device, socket);
 		break;
@@ -228,6 +232,10 @@ int rtdm_dev_register(struct rtdm_device *device)
 		XENO_ASSERT(RTDM, ANY_HANDLER(*device, socket),
 			    xnlogerr("RTDM: missing socket handler\n");
 			    return -EINVAL;);
+		if (device->socket_rt &&
+		    device->socket_rt != (void *)rtdm_no_support)
+			xnlogerr("RTDM: RT socket creation handler is "
+				 "deprecated, driver requires update.\n");
 		SET_DEFAULT_OP_IF_NULL(*device, socket);
 		SET_DEFAULT_OP(*device, open);
 		break;
@@ -242,7 +250,11 @@ int rtdm_dev_register(struct rtdm_device *device)
 		xnlogerr("RTDM: missing non-RT close handler\n");
 		return -EINVAL;
 	}
-	if (!device->ops.close_rt)
+	if (device->ops.close_rt &&
+	    device->ops.close_rt != (void *)rtdm_no_support)
+		xnlogerr("RTDM: RT close handler is deprecated, driver "
+			 "requires update.\n");
+	else
 		device->ops.close_rt = (void *)rtdm_no_support;
 
 	SET_DEFAULT_OP_IF_NULL(device->ops, ioctl);
-- 
1.6.0.2



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

* [Xenomai-core] [PATCH v4 06/25] RTIPC: Fix memory leak on failing socket creation
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
                   ` (4 preceding siblings ...)
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 05/25] RTDM: Deprecate open_rt, socket_rt, and close_rt Jan Kiszka
@ 2010-04-19 10:28 ` Jan Kiszka
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 07/25] RTIPC: Drop support for RT socket creation/deletion Jan Kiszka
                   ` (19 subsequent siblings)
  25 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:28 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

CC: Philippe Gerum <rpm@xenomai.org>
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 ksrc/drivers/ipc/rtipc.c |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/ksrc/drivers/ipc/rtipc.c b/ksrc/drivers/ipc/rtipc.c
index d529912..563cc4e 100644
--- a/ksrc/drivers/ipc/rtipc.c
+++ b/ksrc/drivers/ipc/rtipc.c
@@ -143,6 +143,7 @@ static int rtipc_socket(struct rtdm_dev_context *context,
 {
 	struct rtipc_protocol *proto;
 	struct rtipc_private *p;
+	int ret;
 
 	if (protocol < 0 || protocol >= IPCPROTO_MAX)
 		return -EPROTONOSUPPORT;
@@ -161,7 +162,11 @@ static int rtipc_socket(struct rtdm_dev_context *context,
 	if (p->state == NULL)
 		return -ENOMEM;
 
-	return proto->proto_ops.socket(p, user_info);
+	ret = proto->proto_ops.socket(p, user_info);
+	if (ret)
+		xnfree(p->state);
+
+	return ret;
 }
 
 static int rtipc_close(struct rtdm_dev_context *context,
-- 
1.6.0.2



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

* [Xenomai-core] [PATCH v4 07/25] RTIPC: Drop support for RT socket creation/deletion
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
                   ` (5 preceding siblings ...)
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 06/25] RTIPC: Fix memory leak on failing socket creation Jan Kiszka
@ 2010-04-19 10:28 ` Jan Kiszka
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 08/25] RTCAN: Drop support for socket creation/deletion in real-time Jan Kiszka
                   ` (18 subsequent siblings)
  25 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:28 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

This is deprecated now, RT callers will automatically be migrated to
NRT to perform the requests. Moreover, dropping it allows us to allocate
resources from Linux instead of using the precious system heap.

CC: Philippe Gerum <rpm@xenomai.org>
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 ksrc/drivers/ipc/rtipc.c |    8 +++-----
 1 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/ksrc/drivers/ipc/rtipc.c b/ksrc/drivers/ipc/rtipc.c
index 563cc4e..71629cb 100644
--- a/ksrc/drivers/ipc/rtipc.c
+++ b/ksrc/drivers/ipc/rtipc.c
@@ -158,13 +158,13 @@ static int rtipc_socket(struct rtdm_dev_context *context,
 
 	p = rtdm_context_to_private(context);
 	p->proto = proto;
-	p->state = xnmalloc(proto->proto_statesz);
+	p->state = kmalloc(proto->proto_statesz, GFP_KERNEL);
 	if (p->state == NULL)
 		return -ENOMEM;
 
 	ret = proto->proto_ops.socket(p, user_info);
 	if (ret)
-		xnfree(p->state);
+		kfree(p->state);
 
 	return ret;
 }
@@ -180,7 +180,7 @@ static int rtipc_close(struct rtdm_dev_context *context,
 	if (ret)
 		return ret;
 
-	xnfree(p->state);
+	kfree(p->state);
 
 	return 0;
 }
@@ -232,10 +232,8 @@ static struct rtdm_device device = {
 	.device_name	=	"rtipc",
 	.protocol_family=	PF_RTIPC,
 	.socket_type	=	SOCK_DGRAM,
-	.socket_rt	=	rtipc_socket,
 	.socket_nrt	=	rtipc_socket,
 	.ops = {
-		.close_rt	=	NULL,
 		.close_nrt	=	rtipc_close,
 		.recvmsg_rt	=	rtipc_recvmsg,
 		.recvmsg_nrt	=	NULL,
-- 
1.6.0.2



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

* [Xenomai-core] [PATCH v4 08/25] RTCAN: Drop support for socket creation/deletion in real-time
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
                   ` (6 preceding siblings ...)
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 07/25] RTIPC: Drop support for RT socket creation/deletion Jan Kiszka
@ 2010-04-19 10:28 ` Jan Kiszka
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 09/25] 16550A: Drop support for device opening/closing " Jan Kiszka
                   ` (17 subsequent siblings)
  25 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:28 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

This is deprecated now, RT callers will automatically be migrated to
NRT to perform the requests.

CC: Wolfgang Grandegger <wg@domain.hid>
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 ksrc/drivers/can/rtcan_raw.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/ksrc/drivers/can/rtcan_raw.c b/ksrc/drivers/can/rtcan_raw.c
index 0cf0bb9..9ee0950 100644
--- a/ksrc/drivers/can/rtcan_raw.c
+++ b/ksrc/drivers/can/rtcan_raw.c
@@ -999,11 +999,9 @@ static struct rtdm_device rtcan_proto_raw_dev = {
     protocol_family:    PF_CAN,
     socket_type:        SOCK_RAW,
 
-    socket_rt:          rtcan_raw_socket,
     socket_nrt:         rtcan_raw_socket,
 
     ops: {
-        close_rt:       rtcan_raw_close,
         close_nrt:      rtcan_raw_close,
 
         ioctl_rt:       rtcan_raw_ioctl,
-- 
1.6.0.2



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

* [Xenomai-core] [PATCH v4 09/25] 16550A: Drop support for device opening/closing in real-time
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
                   ` (7 preceding siblings ...)
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 08/25] RTCAN: Drop support for socket creation/deletion in real-time Jan Kiszka
@ 2010-04-19 10:28 ` Jan Kiszka
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 10/25] Analogy: Drop support for " Jan Kiszka
                   ` (16 subsequent siblings)
  25 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:28 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

This is deprected now, RT callers will automatically be switched to
non-RT. Along this, simplify the allocation logic for the RX timestamp
history buffer. We only support allocations from non-RT now and migrate
RT callers as required.

Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 ksrc/drivers/serial/16550A.c |   51 +++++++++++------------------------------
 1 files changed, 14 insertions(+), 37 deletions(-)

diff --git a/ksrc/drivers/serial/16550A.c b/ksrc/drivers/serial/16550A.c
index db8a515..4c46d86 100644
--- a/ksrc/drivers/serial/16550A.c
+++ b/ksrc/drivers/serial/16550A.c
@@ -297,7 +297,7 @@ static int rt_16550_interrupt(rtdm_irq_t * irq_context)
 
 static int rt_16550_set_config(struct rt_16550_context *ctx,
 			       const struct rtser_config *config,
-			       uint64_t ** in_history_ptr)
+			       uint64_t **in_history_ptr)
 {
 	rtdm_lockctx_t lock_ctx;
 	unsigned long base = ctx->base_addr;
@@ -537,12 +537,7 @@ int rt_16550_close(struct rtdm_dev_context *context,
 
 	rt_16550_cleanup_ctx(ctx);
 
-	if (in_history) {
-		if (test_bit(RTDM_CREATED_IN_NRT, &context->context_flags))
-			kfree(in_history);
-		else
-			rtdm_free(in_history);
-	}
+	kfree(in_history);
 
 	return 0;
 }
@@ -602,40 +597,24 @@ int rt_16550_ioctl(struct rtdm_dev_context *context,
 
 		if (testbits(config->config_mask,
 			     RTSER_SET_TIMESTAMP_HISTORY)) {
-			if (test_bit(RTDM_CREATED_IN_NRT,
-				     &context->context_flags)
-			    && rtdm_in_rt_context()) {
-				/* Already fail here if we MAY allocate or
-				   release a non-RT buffer in RT context. */
-				return -EPERM;
-			}
+			/*
+			 * Reflect the call to non-RT as we will likely
+			 * allocate or free the buffer.
+			 */
+			if (rtdm_in_rt_context())
+				return -ENOSYS;
 
 			if (testbits(config->timestamp_history,
-				     RTSER_RX_TIMESTAMP_HISTORY)) {
-				if (test_bit(RTDM_CREATED_IN_NRT,
-					     &context->context_flags))
-					hist_buf =
-					    kmalloc(IN_BUFFER_SIZE *
-						    sizeof(nanosecs_abs_t),
-						    GFP_KERNEL);
-				else
-					hist_buf =
-					    rtdm_malloc(IN_BUFFER_SIZE *
-						sizeof(nanosecs_abs_t));
-					if (!hist_buf)
-						return -ENOMEM;
-			}
+				     RTSER_RX_TIMESTAMP_HISTORY))
+				hist_buf = kmalloc(IN_BUFFER_SIZE *
+						   sizeof(nanosecs_abs_t),
+						   GFP_KERNEL);
 		}
 
 		rt_16550_set_config(ctx, config, &hist_buf);
 
-		if (hist_buf) {
-			if (test_bit(RTDM_CREATED_IN_NRT,
-				     &context->context_flags))
-				kfree(hist_buf);
-			else
-				rtdm_free(hist_buf);
-		}
+		if (hist_buf)
+			kfree(hist_buf);
 
 		break;
 	}
@@ -1107,11 +1086,9 @@ static const struct rtdm_device __initdata device_tmpl = {
 	.context_size		= sizeof(struct rt_16550_context),
 	.device_name		= "",
 
-	.open_rt		= rt_16550_open,
 	.open_nrt		= rt_16550_open,
 
 	.ops = {
-		.close_rt	= rt_16550_close,
 		.close_nrt	= rt_16550_close,
 
 		.ioctl_rt	= rt_16550_ioctl,
-- 
1.6.0.2



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

* [Xenomai-core] [PATCH v4 10/25] Analogy: Drop support for opening/closing in real-time
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
                   ` (8 preceding siblings ...)
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 09/25] 16550A: Drop support for device opening/closing " Jan Kiszka
@ 2010-04-19 10:28 ` Jan Kiszka
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 11/25] RTDM: Instrument rtdm_context_lock/unlock to detect misuses Jan Kiszka
                   ` (15 subsequent siblings)
  25 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:28 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: Alexis Berlemont, xenomai-core

This is deprected now, RT callers will automatically be switched to
non-RT.

CC: Alexis Berlemont <berlemont.hauw@domain.hid>
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 ksrc/drivers/analogy/rtdm_interface.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/ksrc/drivers/analogy/rtdm_interface.c b/ksrc/drivers/analogy/rtdm_interface.c
index f769e4a..99abf2f 100644
--- a/ksrc/drivers/analogy/rtdm_interface.c
+++ b/ksrc/drivers/analogy/rtdm_interface.c
@@ -227,11 +227,9 @@ static struct rtdm_device rtdm_devs[A4L_NB_DEVICES] =
 		.context_size =		sizeof(struct a4l_dummy_context),
 		.device_name = 		"",
 
-		.open_rt =		a4l_rt_open,
 		.open_nrt =		a4l_rt_open,
 
 		.ops = {
-			.close_rt =	a4l_rt_close,
 			.ioctl_rt =	a4l_rt_ioctl,
 			.read_rt =	a4l_rt_read,
 			.write_rt =	a4l_rt_write,
-- 
1.6.0.2



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

* [Xenomai-core] [PATCH v4 11/25] RTDM: Instrument rtdm_context_lock/unlock to detect misuses
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
                   ` (9 preceding siblings ...)
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 10/25] Analogy: Drop support for " Jan Kiszka
@ 2010-04-19 10:28 ` Jan Kiszka
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 12/25] RTDM: Add rtdm_context_put() Jan Kiszka
                   ` (14 subsequent siblings)
  25 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:28 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

rtdm_context_lock must only be called on context structures that are
already locked, and rtdm_context_unlock must be kept in balance with
rtdm_context_get/rtdm_context_lock. Try to check for mistakes by
requiring non-null clock_lock_count on entry of both services.

Also fix a typo and clarify the use cases and restrictions of
rtdm_context_lock.

CC: Philippe Gerum <rpm@xenomai.org>
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 include/rtdm/rtdm_driver.h |    4 ++++
 ksrc/skins/rtdm/core.c     |   10 +++++++---
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/include/rtdm/rtdm_driver.h b/include/rtdm/rtdm_driver.h
index d68f542..3fc9071 100644
--- a/include/rtdm/rtdm_driver.h
+++ b/include/rtdm/rtdm_driver.h
@@ -555,11 +555,15 @@ struct rtdm_dev_context *rtdm_context_get(int fd);
 #ifndef DOXYGEN_CPP /* Avoid static inline tags for RTDM in doxygen */
 static inline void rtdm_context_lock(struct rtdm_dev_context *context)
 {
+	XENO_ASSERT(RTDM, atomic_read(&context->close_lock_count) > 0,
+		    /* just warn if context was a dangling pointer */);
 	atomic_inc(&context->close_lock_count);
 }
 
 static inline void rtdm_context_unlock(struct rtdm_dev_context *context)
 {
+	XENO_ASSERT(RTDM, atomic_read(&context->close_lock_count) > 0,
+		    /* just warn if context was a dangling pointer */);
 	smp_mb__before_atomic_dec();
 	atomic_dec(&context->close_lock_count);
 }
diff --git a/ksrc/skins/rtdm/core.c b/ksrc/skins/rtdm/core.c
index 8cccf52..ba4dc63 100644
--- a/ksrc/skins/rtdm/core.c
+++ b/ksrc/skins/rtdm/core.c
@@ -87,7 +87,7 @@ struct rtdm_dev_context *rtdm_context_get(int fd)
 		return NULL;
 	}
 
-	rtdm_context_lock(context);
+	atomic_inc(&context->close_lock_count);
 
 	xnlock_put_irqrestore(&rt_fildes_lock, s);
 
@@ -328,7 +328,7 @@ again:
 	}
 
 	set_bit(RTDM_CLOSING, &context->context_flags);
-	rtdm_context_lock(context);
+	atomic_inc(&context->close_lock_count);
 
 	xnlock_put_irqrestore(&rt_fildes_lock, s);
 
@@ -588,7 +588,11 @@ EXPORT_SYMBOL(rtdm_select_bind);
  * @param[in] context Device context
  *
  * @note rtdm_context_get() automatically increments the lock counter. You
- * only need to call this function in special scenrios.
+ * only need to call this function in special scenarios, e.g. when keeping
+ * additional references to the context structure that have different
+ * lifetimes. Only use rtdm_context_lock() on contexts that are currently
+ * locked via an earlier rtdm_context_get()/rtdm_contex_lock() or while
+ * running a device operation handler.
  *
  * Environments:
  *
-- 
1.6.0.2



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

* [Xenomai-core] [PATCH v4 12/25] RTDM: Add rtdm_context_put()
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
                   ` (10 preceding siblings ...)
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 11/25] RTDM: Instrument rtdm_context_lock/unlock to detect misuses Jan Kiszka
@ 2010-04-19 10:28 ` Jan Kiszka
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 13/25] Fix historic msleep wrapping Jan Kiszka
                   ` (13 subsequent siblings)
  25 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:28 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

As suggested by Philippe: This is an alias of rtdm_context_unlock(), but
it is more intuitive to match it with rtdm_context_get() calls.

CC: Philippe Gerum <rpm@xenomai.org>
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 include/rtdm/rtdm_driver.h  |    5 +++++
 ksrc/skins/rtdm/API.CHANGES |    1 +
 ksrc/skins/rtdm/core.c      |   29 +++++++++++++++++++++++++----
 3 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/include/rtdm/rtdm_driver.h b/include/rtdm/rtdm_driver.h
index 3fc9071..07b73a3 100644
--- a/include/rtdm/rtdm_driver.h
+++ b/include/rtdm/rtdm_driver.h
@@ -568,6 +568,11 @@ static inline void rtdm_context_unlock(struct rtdm_dev_context *context)
 	atomic_dec(&context->close_lock_count);
 }
 
+static inline void rtdm_context_put(struct rtdm_dev_context *context)
+{
+	rtdm_context_unlock(context);
+}
+
 /* --- clock services --- */
 struct xntbase;
 extern struct xntbase *rtdm_tbase;
diff --git a/ksrc/skins/rtdm/API.CHANGES b/ksrc/skins/rtdm/API.CHANGES
index 64a4b38..73c1850 100644
--- a/ksrc/skins/rtdm/API.CHANGES
+++ b/ksrc/skins/rtdm/API.CHANGES
@@ -9,6 +9,7 @@ Scheduled modifications (unsorted):
 
 Revision 8:
  o Added rtdm_rt_capable.
+ o Added rtdm_context_put as logic match to rtdm_context_get
 
 Revision 7:
  o Added callbacks and services to enable select support.
diff --git a/ksrc/skins/rtdm/core.c b/ksrc/skins/rtdm/core.c
index ba4dc63..e04b3f6 100644
--- a/ksrc/skins/rtdm/core.c
+++ b/ksrc/skins/rtdm/core.c
@@ -50,14 +50,14 @@ EXPORT_SYMBOL(rtdm_tbase);
 DEFINE_XNLOCK(rt_fildes_lock);
 
 /**
- * @brief Resolve file descriptor to device context
+ * @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_unlock()
- * when it is no longer referenced.
+ * @note The device context has to be unlocked using rtdm_context_put() when
+ * it is no longer referenced.
  *
  * Environments:
  *
@@ -612,7 +612,7 @@ void rtdm_context_lock(struct rtdm_dev_context *context);
  *
  * @param[in] context Device context
  *
- * @note Every successful call to rtdm_context_get() must be matched by a
+ * @note Every call to rtdm_context_locked() must be matched by a
  * rtdm_context_unlock() invocation.
  *
  * Environments:
@@ -629,6 +629,27 @@ void rtdm_context_lock(struct rtdm_dev_context *context);
 void rtdm_context_unlock(struct rtdm_dev_context *context);
 
 /**
+ * @brief Release a device context obtained via rtdm_context_get()
+ *
+ * @param[in] context Device context
+ *
+ * @note Every successful call to rtdm_context_get() must be matched by a
+ * rtdm_context_put() invocation.
+ *
+ * Environments:
+ *
+ * This service can be called from:
+ *
+ * - Kernel module initialization/cleanup code
+ * - Interrupt service routine
+ * - Kernel-based task
+ * - User-space task (RT, non-RT)
+ *
+ * Rescheduling: never.
+ */
+void rtdm_context_put(struct rtdm_dev_context *context);
+
+/**
  * @brief Open a device
  *
  * Refer to rt_dev_open() for parameters and return values
-- 
1.6.0.2



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

* [Xenomai-core] [PATCH v4 13/25] Fix historic msleep wrapping
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
                   ` (11 preceding siblings ...)
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 12/25] RTDM: Add rtdm_context_put() Jan Kiszka
@ 2010-04-19 10:28 ` Jan Kiszka
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 14/25] irqbench: Fix x86-64 build Jan Kiszka
                   ` (12 subsequent siblings)
  25 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:28 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

Probably only an academic exercise: Fix the rounding bug in msleep
wrapper for kernels < 2.4.28.

Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 include/asm-generic/wrappers.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/include/asm-generic/wrappers.h b/include/asm-generic/wrappers.h
index 15d9837..64ec43f 100644
--- a/include/asm-generic/wrappers.h
+++ b/include/asm-generic/wrappers.h
@@ -197,7 +197,7 @@ do {									\
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,28)
 #define msleep(x) do {				 \
 	set_current_state(TASK_UNINTERRUPTIBLE); \
-	schedule_timeout((x)*(HZ/1000));         \
+	schedule_timeout(((x)*HZ)/1000);         \
 } while(0)
 #endif
 
-- 
1.6.0.2



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

* [Xenomai-core] [PATCH v4 14/25] irqbench: Fix x86-64 build
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
                   ` (12 preceding siblings ...)
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 13/25] Fix historic msleep wrapping Jan Kiszka
@ 2010-04-19 10:28 ` Jan Kiszka
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 15/25] irqbench: Refactor user space helpers Jan Kiszka
                   ` (11 subsequent siblings)
  25 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:28 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 configure.in                       |    2 +-
 src/testsuite/irqbench/Makefile.am |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/configure.in b/configure.in
index 0228f51..9d6fe35 100644
--- a/configure.in
+++ b/configure.in
@@ -127,7 +127,7 @@ case "$build_for" in
 esac
 
 AC_MSG_RESULT([$XENO_TARGET_ARCH])
-AM_CONDITIONAL(XENO_LINUX_ARCH_I386,[test $XENO_LINUX_ARCH = i386])
+AM_CONDITIONAL(XENO_TARGET_ARCH_X86,[test $XENO_TARGET_ARCH = x86])
 
 case "$XENO_TARGET_ARCH" in
  nios2)
diff --git a/src/testsuite/irqbench/Makefile.am b/src/testsuite/irqbench/Makefile.am
index 27c5ddb..3e531c7 100644
--- a/src/testsuite/irqbench/Makefile.am
+++ b/src/testsuite/irqbench/Makefile.am
@@ -5,7 +5,7 @@ CCLD = $(top_srcdir)/scripts/wrap-link.sh $(CC)
 
 test_PROGRAMS = irqloop
 
-if XENO_LINUX_ARCH_I386
+if XENO_TARGET_ARCH_X86
 test_PROGRAMS += irqbench
 endif
 
-- 
1.6.0.2



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

* [Xenomai-core] [PATCH v4 15/25] irqbench: Refactor user space helpers
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
                   ` (13 preceding siblings ...)
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 14/25] irqbench: Fix x86-64 build Jan Kiszka
@ 2010-04-19 10:28 ` Jan Kiszka
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 16/25] irqbench: Auto-detect bases of port address and IRQ values Jan Kiszka
                   ` (10 subsequent siblings)
  25 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:28 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

Indent according to our style, push irqbench's inner loop into separate
function. No functional changes.

Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 src/testsuite/irqbench/irqbench.c |  480 ++++++++++++++++++-------------------
 src/testsuite/irqbench/irqloop.c  |  303 ++++++++++++------------
 2 files changed, 393 insertions(+), 390 deletions(-)

diff --git a/src/testsuite/irqbench/irqbench.c b/src/testsuite/irqbench/irqbench.c
index 6b22711..844f187 100644
--- a/src/testsuite/irqbench/irqbench.c
+++ b/src/testsuite/irqbench/irqbench.c
@@ -51,268 +51,266 @@
 #define STAT(base) (base + 1) /* Status register */
 #define CTRL(base) (base + 2) /* Control register */
 
-double tsc2ns_scale;
-long long min_lat = LONG_MAX;
-long long max_lat = LONG_MIN;
-long long avg_lat = 0;
-long outer_loops = 0;
-int warmup = 1;
-int terminate = 0;
+static double tsc2ns_scale;
+static long long min_lat = LONG_MAX;
+static long long max_lat = LONG_MIN;
+static long long avg_lat;
+static long outer_loops;
+static int warmup = 1;
+static int terminate;
+static unsigned long port_ioaddr = 0x3F8;
+static int port_type = SERPORT;
+static unsigned int toggle;
+static long loop_avg;
+static long long period = 100000;
+static int trigger_trace;
 
 static inline long long rdtsc(void)
 {
-    unsigned long long tsc;
+	unsigned long long tsc;
 
-    __asm__ __volatile__("rdtsc" : "=A" (tsc));
-    return tsc;
+	__asm__ __volatile__("rdtsc" : "=A" (tsc));
+	return tsc;
 }
 
-
 static long tsc2ns(long long tsc)
 {
-    if ((tsc > LONG_MAX) || (tsc < LONG_MIN)) {
-        fprintf(stderr, "irqbench: overflow (%lld ns)!\n",
-                (long long)(tsc2ns_scale * (double)tsc));
-        exit(2);
-    }
-    return (long)(tsc2ns_scale * (double)tsc);
+	if (tsc > LONG_MAX || tsc < LONG_MIN) {
+		fprintf(stderr, "irqbench: overflow (%lld ns)!\n",
+			(long long)(tsc2ns_scale * (double)tsc));
+		exit(2);
+	}
+	return (long)(tsc2ns_scale * (double)tsc);
 }
 
-
 static inline long long ns2tsc(long long ns)
 {
-    return (long long)(((double)ns) / tsc2ns_scale);
+	return (long long)(((double)ns) / tsc2ns_scale);
 }
 
-
-void calibrate_tsc(void)
+static void calibrate_tsc(void)
 {
-    FILE *proc;
-    char *lineptr = NULL;
-    size_t len;
-    double cpu_mhz;
-
-    proc = fopen("/proc/cpuinfo", "r");
-    if (proc == NULL) {
-        perror("irqbench: Unable to open /proc/cpuinfo");
-        exit(1);
-    }
-
-    while (getline(&lineptr, &len, proc) != -1)
-        if (strncmp(lineptr, "cpu MHz", 7) == 0) {
-            sscanf(strchr(lineptr, ':') + 1, "%lf", &cpu_mhz);
-            break;
-        }
-
-    if (lineptr)
-        free(lineptr);
-    fclose(proc);
-
-    printf("CPU frequency: %.3lf MHz\n", cpu_mhz);
-
-    tsc2ns_scale = 1000.0 / cpu_mhz;
+	FILE *proc;
+	char *lineptr = NULL;
+	size_t len;
+	double cpu_mhz;
+
+	proc = fopen("/proc/cpuinfo", "r");
+	if (proc == NULL) {
+		perror("irqbench: Unable to open /proc/cpuinfo");
+		exit(1);
+	}
+
+	while (getline(&lineptr, &len, proc) != -1)
+		if (strncmp(lineptr, "cpu MHz", 7) == 0) {
+			sscanf(strchr(lineptr, ':') + 1, "%lf", &cpu_mhz);
+			break;
+		}
+
+	if (lineptr)
+		free(lineptr);
+	fclose(proc);
+
+	printf("CPU frequency: %.3lf MHz\n", cpu_mhz);
+
+	tsc2ns_scale = 1000.0 / cpu_mhz;
 }
 
-
-void sighand(int signal)
+static void sighand(int signal)
 {
-    if (warmup)
-        exit(0);
-    else
-        terminate = 1;
+	if (warmup)
+		exit(0);
+	else
+		terminate = 1;
 }
 
+static void do_inner_loop(void)
+{
+	long long start, delay, timeout;
+	long lat;
+
+	__asm__ __volatile__("cli");
+
+	if (port_type ==  SERPORT) {
+		start = rdtsc();
+
+		toggle ^= MCR_RTS;
+		outb(toggle, MCR(port_ioaddr));
+
+		timeout = start + period * 100;
+		while ((inb(MSR(port_ioaddr)) & MSR_DELTA) == 0 &&
+		       rdtsc() < timeout);
+
+		delay = rdtsc() - start;
+	} else {
+		int status = inb(STAT(port_ioaddr));
+
+		outb(0x08, DATA(port_ioaddr));
+
+		start = rdtsc();
+
+		outb(0x00, DATA(port_ioaddr));
+
+		timeout = start + period * 100;
+		while (inb(STAT(port_ioaddr)) == status &&
+		       rdtsc() < timeout);
+
+		delay = rdtsc() - start;
+	}
+
+	if (!warmup) {
+		lat = tsc2ns(delay);
+
+		loop_avg += lat;
+		if (lat < min_lat)
+			min_lat = lat;
+		if (lat > max_lat) {
+			max_lat = lat;
+			if (trigger_trace) {
+				if (port_type == SERPORT) {
+					toggle ^= MCR_DTR;
+					outb(toggle, MCR(port_ioaddr));
+				} else {
+					outb(0x18, DATA(port_ioaddr));
+					outb(0x10, DATA(port_ioaddr));
+				}
+			}
+		}
+	}
+
+	__asm__ __volatile__("sti");
+
+	while (rdtsc() < start + period);
+}
 
 int main(int argc, char *argv[])
 {
-    int                 port_type   = SERPORT;
-    unsigned long       port_ioaddr = 0x3F8;
-    int                 ioaddr_set = 0;
-    long long           period = 100000;
-    long long           timeout;
-    long long           start, delay;
-    unsigned long long  count = 1;
-    unsigned int        toggle = 0;
-    int                 trigger_trace = 0;
-    int                 c;
-
-
-    signal(SIGINT, sighand);
-    signal(SIGTERM, sighand);
-    signal(SIGHUP, sighand);
-    signal(SIGALRM, sighand);
-
-    calibrate_tsc();
-
-    while ((c = getopt(argc,argv,"p:T:o:a:f")) != EOF)
-        switch (c) {
-            case 'p':
-                period = atoi(optarg) * 1000;
-                break;
-
-            case 'T':
-                alarm(atoi(optarg));
-                break;
-
-            case 'o':
-                port_type = atoi(optarg);
-                break;
-
-            case 'a':
-                port_ioaddr = strtol(optarg, NULL,
-                    (strncmp(optarg, "0x", 2) == 0) ? 16 : 10);
-                ioaddr_set = 1;
-                break;
-
-            case 'f':
-                trigger_trace = 1;
-                break;
-
-            default:
-                fprintf(stderr, "usage: irqbench [options]\n"
-                        "  [-p <period_us>]             # signal period, default=100 us\n"
-                        "  [-T <test_duration_seconds>] # default=0, so ^C to end\n"
-                        "  [-o <port_type>]             # 0=serial (default), 1=parallel\n"
-                        "  [-a <port_io_address>]       # default=0x3f8/0x378\n"
-                        "  [-f]                         # freeze trace for each new max latency\n");
-                exit(2);
-        }
-
-    /* set defaults for parallel port */
-    if (port_type == 1 && !ioaddr_set)
-        port_ioaddr = 0x378;
-
-    if (iopl(3) < 0) {
-        fprintf(stderr, "irqbench: superuser permissions required\n");
-        exit(1);
-    }
-    mlockall(MCL_CURRENT | MCL_FUTURE);
-
-    switch (port_type) {
-        case SERPORT:
-            toggle = MCR_OUT2;
-            inb(MSR(port_ioaddr));
-            break;
-
-        case PARPORT:
-            outb(CTRL_INIT, CTRL(port_ioaddr));
-            break;
-
-        default:
-            fprintf(stderr, "irqbench: invalid port type\n");
-            exit(1);
-    }
-
-    period = ns2tsc(period);
-
-    printf("Port type:     %s\n"
-           "Port address:  0x%lx\n\n",
-           (port_type == SERPORT) ? "serial" : "parallel", port_ioaddr);
-
-    printf("Waiting on target...\n");
-
-    while (1)
-        if (port_type ==  SERPORT) {
-            toggle ^= MCR_RTS;
-            outb(toggle, MCR(port_ioaddr));
-            usleep(100000);
-            if ((inb(MSR(port_ioaddr)) & MSR_DELTA) != 0)
-                break;
-        } else {
-            int status = inb(STAT(port_ioaddr));
-
-            outb(0x08, DATA(port_ioaddr));
-            outb(0x00, DATA(port_ioaddr));
-            usleep(100000);
-            if (inb(STAT(port_ioaddr)) != status)
-                break;
-        }
-
-    printf("Warming up...\n");
-
-    while (!terminate) {
-        long long loop_timeout = rdtsc() + ns2tsc(1000000000LL);
-        long loop_avg = 0;
-        int inner_loops = 0;
-
-        while (rdtsc() < loop_timeout) {
-            long lat;
-
-            __asm__ __volatile__("cli");
-
-            if (port_type ==  SERPORT) {
-                start = rdtsc();
-
-                toggle ^= MCR_RTS;
-                outb(toggle, MCR(port_ioaddr));
-
-                timeout = start + period * 100;
-                while (((inb(MSR(port_ioaddr)) & MSR_DELTA) == 0) &&
-                       (rdtsc() < timeout));
-
-                delay = rdtsc() - start;
-            } else {
-                int status = inb(STAT(port_ioaddr));
-
-                outb(0x08, DATA(port_ioaddr));
-
-                start = rdtsc();
-
-                outb(0x00, DATA(port_ioaddr));
-
-                timeout = start + period * 100;
-                while ((inb(STAT(port_ioaddr)) == status) &&
-                       (rdtsc() < timeout));
-
-                delay = rdtsc() - start;
-            }
-
-            if (!warmup) {
-                lat = tsc2ns(delay);
-
-                loop_avg += lat;
-                if (lat < min_lat)
-                    min_lat = lat;
-                if (lat > max_lat) {
-                    max_lat = lat;
-                    if (trigger_trace) {
-                        if (port_type == SERPORT) {
-                            toggle ^= MCR_DTR;
-                            outb(toggle, MCR(port_ioaddr));
-                        } else {
-                            outb(0x18, DATA(port_ioaddr));
-                            outb(0x10, DATA(port_ioaddr));
-                        }
-                    }
-                }
-            }
-
-            __asm__ __volatile__("sti");
-
-            inner_loops++;
-
-            while (rdtsc() < start + period);
-        }
-
-        count += inner_loops;
-
-        if (!warmup && !terminate) {
-            loop_avg /= inner_loops;
-
-            printf("%llu: %.3f / %.3f / %.3f us\n", count,
-                ((double)min_lat) / 1000.0, ((double)loop_avg) / 1000.0,
-                ((double)max_lat) / 1000.0);
-
-            avg_lat += loop_avg;
-            outer_loops++;
-        } else
-            warmup = 0;
-    }
-
-    avg_lat /= outer_loops;
-    printf("---\n%llu: %.3f / %.3f / %.3f us\n", count,
-           ((double)min_lat) / 1000.0, ((double)avg_lat) / 1000.0,
-           ((double)max_lat) / 1000.0);
-
-    return 0;
+	int ioaddr_set = 0;
+	unsigned long long count = 1;
+	int c;
+
+	signal(SIGINT, sighand);
+	signal(SIGTERM, sighand);
+	signal(SIGHUP, sighand);
+	signal(SIGALRM, sighand);
+
+	calibrate_tsc();
+
+	while ((c = getopt(argc, argv, "p:T:o:a:f")) != EOF)
+		switch (c) {
+		case 'p':
+			period = atoi(optarg) * 1000;
+			break;
+
+		case 'T':
+			alarm(atoi(optarg));
+			break;
+
+		case 'o':
+			port_type = atoi(optarg);
+			break;
+
+		case 'a':
+			port_ioaddr = strtol(optarg, NULL, (strncmp(optarg, "0x", 2) == 0) ? 16 : 10);
+			ioaddr_set = 1;
+			break;
+
+		case 'f':
+			trigger_trace = 1;
+			break;
+
+		default:
+			fprintf(stderr, "usage: irqbench [options]\n"
+				"  [-p <period_us>]             # signal period, default=100 us\n"
+				"  [-T <test_duration_seconds>] # default=0, so ^C to end\n"
+				"  [-o <port_type>]             # 0=serial (default), 1=parallel\n"
+				"  [-a <port_io_address>]       # default=0x3f8/0x378\n"
+				"  [-f]                         # freeze trace for each new max latency\n");
+			exit(2);
+		}
+
+	/* set defaults for parallel port */
+	if (port_type == 1 && !ioaddr_set)
+		port_ioaddr = 0x378;
+
+	if (iopl(3) < 0) {
+		fprintf(stderr, "irqbench: superuser permissions required\n");
+		exit(1);
+	}
+	mlockall(MCL_CURRENT | MCL_FUTURE);
+
+	switch (port_type) {
+	case SERPORT:
+		toggle = MCR_OUT2;
+		inb(MSR(port_ioaddr));
+		break;
+
+	case PARPORT:
+		outb(CTRL_INIT, CTRL(port_ioaddr));
+		break;
+
+	default:
+		fprintf(stderr, "irqbench: invalid port type\n");
+		exit(1);
+	}
+
+	period = ns2tsc(period);
+
+	printf("Port type:     %s\n"
+	       "Port address:  0x%lx\n\n",
+	       (port_type == SERPORT) ? "serial" : "parallel", port_ioaddr);
+
+	printf("Waiting on target...\n");
+
+	while (1)
+		if (port_type ==  SERPORT) {
+			toggle ^= MCR_RTS;
+			outb(toggle, MCR(port_ioaddr));
+			usleep(100000);
+			if ((inb(MSR(port_ioaddr)) & MSR_DELTA) != 0)
+				break;
+		} else {
+			int status = inb(STAT(port_ioaddr));
+
+			outb(0x08, DATA(port_ioaddr));
+			outb(0x00, DATA(port_ioaddr));
+			usleep(100000);
+			if (inb(STAT(port_ioaddr)) != status)
+				break;
+		}
+
+	printf("Warming up...\n");
+
+	while (!terminate) {
+		long long loop_timeout = rdtsc() + ns2tsc(1000000000LL);
+		int inner_loops = 0;
+
+		loop_avg = 0;
+		while (rdtsc() < loop_timeout) {
+			do_inner_loop();
+			inner_loops++;
+		}
+
+		count += inner_loops;
+
+		if (!warmup && !terminate) {
+			loop_avg /= inner_loops;
+
+			printf("%llu: %.3f / %.3f / %.3f us\n", count,
+			       ((double)min_lat) / 1000.0,
+			       ((double)loop_avg) / 1000.0,
+			       ((double)max_lat) / 1000.0);
+
+			avg_lat += loop_avg;
+			outer_loops++;
+		} else
+			warmup = 0;
+	}
+
+	avg_lat /= outer_loops;
+	printf("---\n%llu: %.3f / %.3f / %.3f us\n", count,
+	       ((double)min_lat) / 1000.0, ((double)avg_lat) / 1000.0,
+	       ((double)max_lat) / 1000.0);
+
+	return 0;
 }
diff --git a/src/testsuite/irqbench/irqloop.c b/src/testsuite/irqbench/irqloop.c
index e97123f..3b4de4f 100644
--- a/src/testsuite/irqbench/irqloop.c
+++ b/src/testsuite/irqbench/irqloop.c
@@ -29,165 +29,170 @@
 static int benchdev;
 static int terminate;
 
-void *irq_thread(void *arg)
+static void *irq_thread(void *arg)
 {
-    struct sched_param param = { .sched_priority = (long)arg };
+	struct sched_param param = { .sched_priority = (long)arg };
 
-    pthread_setschedparam(pthread_self(), SCHED_FIFO, &param);
+	pthread_setschedparam(pthread_self(), SCHED_FIFO, &param);
 
-    while (1) {
-        if (ioctl(benchdev, RTTST_RTIOC_IRQBENCH_WAIT_IRQ) ||
-            ioctl(benchdev, RTTST_RTIOC_IRQBENCH_REPLY_IRQ))
-            break;
-    }
+	while (1) {
+		if (ioctl(benchdev, RTTST_RTIOC_IRQBENCH_WAIT_IRQ) ||
+		    ioctl(benchdev, RTTST_RTIOC_IRQBENCH_REPLY_IRQ))
+			break;
+	}
 
-    param.sched_priority = 0;
-    pthread_setschedparam(pthread_self(), SCHED_OTHER, &param);
+	param.sched_priority = 0;
+	pthread_setschedparam(pthread_self(), SCHED_OTHER, &param);
 
-    return NULL;
+	return NULL;
 }
 
-
-void sighand(int sig)
+static void sighand(int sig)
 {
-    terminate = 1;
+	terminate = 1;
 }
 
-
 int main(int argc, char *argv[])
 {
-    const char *mode_name[] =
-        { "user-space task", "kernel-space task",
-          "IRQ handler", "hard-IRQ handler" };
-    const char *port_type_name[] = { "serial", "parallel" };
-    char devname[RTDM_MAX_DEVNAME_LEN];
-    int benchdev_no = 0;
-    struct rttst_irqbench_config config = {
-        mode:               RTTST_IRQBENCH_USER_TASK,
-        priority:           sched_get_priority_max(SCHED_FIFO),
-        calibration_loops:  0,
-        port_type:          RTTST_IRQBENCH_SERPORT,
-        port_ioaddr:        0x3f8,
-        port_irq:           4
-    };
-    struct rttst_irqbench_stats stats;
-    unsigned long long last_received = 0;
-    pthread_t thr;
-    int ioaddr_set = 0;
-    int irq_set = 0;
-    int c;
-    int timeout = 10;
-
-
-    while ((c = getopt(argc,argv,"D:t:P:o:a:i:")) != EOF)
-        switch (c) {
-            case 'D':
-                benchdev_no = atoi(optarg);
-                break;
-
-            case 't':
-                config.mode = atoi(optarg);
-                break;
-
-            case 'P':
-                config.priority = atoi(optarg);
-                break;
-
-            case 'o':
-                config.port_type = atoi(optarg);
-                break;
-
-            case 'a':
-                config.port_ioaddr = strtol(optarg, NULL,
-                    (strncmp(optarg, "0x", 2) == 0) ? 16 : 10);
-                ioaddr_set = 1;
-                break;
-
-            case 'i':
-                config.port_irq = atoi(optarg);
-                irq_set = 1;
-                break;
-
-            default:
-                fprintf(stderr, "usage: irqloop [options]\n"
-                        "  [-D <testing_device_no>] # number of testing device, default=0\n"
-                        "  [-t <test_mode>]         # 0=user task (default), 1=kernel task,\n"
-                        "                           # 2=IRQ handler, 3=hard-IRQ handler\n"
-                        "  [-P <priority>]          # task priority (test mode 0 and 1 only)\n"
-                        "  [-o <port_type>]         # 0=serial (default), 1=parallel\n"
-                        "  [-a <port_io_address>]   # default=0x3f8/0x378\n"
-                        "  [-i <port_irq>]          # default=4/7\n");
-                exit(2);
-        }
-
-    /* set defaults for parallel port */
-    if (config.port_type == 1) {
-        if (!ioaddr_set)
-            config.port_ioaddr = 0x378;
-        if (!irq_set)
-            config.port_irq = 0x7;
-    }
-
-    signal(SIGINT, sighand);
-    signal(SIGTERM, sighand);
-    signal(SIGHUP, sighand);
-
-    mlockall(MCL_CURRENT|MCL_FUTURE);
-
-    snprintf(devname, RTDM_MAX_DEVNAME_LEN, "/dev/rttest%d", benchdev_no);
-    benchdev = open(devname, O_RDWR);
-    if (benchdev < 0) {
-        perror("irqloop: failed to open benchmark device");
-        fprintf(stderr, "(modprobe xeno_irqbench?)\n");
-        return 1;
-    }
-
-    if (config.mode == RTTST_IRQBENCH_USER_TASK) {
-        pthread_attr_t attr;
-
-        pthread_attr_init(&attr);
-        pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);
-
-        pthread_create(&thr, &attr, irq_thread, (void *)(long)config.priority);
-    }
-
-    if (ioctl(benchdev, RTTST_RTIOC_IRQBENCH_START, &config)) {
-        perror("irqloop: error starting test");
-        goto cleanup;
-    }
-
-    printf("Test mode:    %s\n"
-           "Port type:    %s\n"
-           "Port address: 0x%lx\n"
-           "Port IRQ:     %d\n\n\n\n",
-           mode_name[config.mode], port_type_name[config.port_type],
-           config.port_ioaddr, config.port_irq);
-
-    while (!terminate) {
-        if (ioctl(benchdev, RTTST_RTIOC_IRQBENCH_GET_STATS, &stats) < 0) {
-            perror("irqloop: error reading stats");
-            break;
-        }
-
-        if ((last_received > 0) && (stats.irqs_received == last_received)) {
-            if (--timeout == 0)
-                break; /* timed out */
-        } else
-            timeout = 10;
-        last_received = stats.irqs_received;
-
-        printf("\033[2AReceived IRQs:     %lld\nAcknowledged IRQs: %lld\n",
-                stats.irqs_received, stats.irqs_acknowledged);
-        usleep(250000);
-    }
-
-    ioctl(benchdev, RTTST_RTIOC_IRQBENCH_STOP);
-
-  cleanup:
-    close(benchdev);
-    if (config.mode == RTTST_IRQBENCH_USER_TASK) {
-        pthread_cancel(thr);
-        pthread_join(thr, NULL);
-    }
-    return 0;
+	const char *mode_name[] = {
+		[RTTST_IRQBENCH_USER_TASK]	= "user-space task",
+		[RTTST_IRQBENCH_KERNEL_TASK]	= "kernel-space task",
+		[RTTST_IRQBENCH_HANDLER]	= "IRQ handler",
+		[RTTST_IRQBENCH_HARD_IRQ]	= "hard-IRQ handler",
+	};
+	const char *port_type_name[] = {
+		[RTTST_IRQBENCH_SERPORT]	= "serial",
+		[RTTST_IRQBENCH_PARPORT]	= "parallel",
+	};
+	char devname[RTDM_MAX_DEVNAME_LEN];
+	int benchdev_no = 0;
+	struct rttst_irqbench_config config = {
+		.mode			= RTTST_IRQBENCH_USER_TASK,
+		.priority		= sched_get_priority_max(SCHED_FIFO),
+		.calibration_loops	= 0,
+		.port_type		= RTTST_IRQBENCH_SERPORT,
+		.port_ioaddr		= 0x3f8,
+		.port_irq		= 4
+	};
+	struct rttst_irqbench_stats stats;
+	unsigned long long last_received = 0;
+	pthread_t thr;
+	int ioaddr_set = 0;
+	int irq_set = 0;
+	int c;
+	int timeout = 10;
+
+	while ((c = getopt(argc, argv, "D:t:P:o:a:i:")) != EOF)
+		switch (c) {
+		case 'D':
+			benchdev_no = atoi(optarg);
+			break;
+
+		case 't':
+			config.mode = atoi(optarg);
+			break;
+
+		case 'P':
+			config.priority = atoi(optarg);
+			break;
+
+		case 'o':
+			config.port_type = atoi(optarg);
+			break;
+
+		case 'a':
+			config.port_ioaddr = strtol(optarg, NULL, (strncmp(optarg, "0x", 2) == 0) ? 16 : 10);
+			ioaddr_set = 1;
+			break;
+
+		case 'i':
+			config.port_irq = atoi(optarg);
+			irq_set = 1;
+			break;
+
+		default:
+			fprintf(stderr, "usage: irqloop [options]\n"
+				"  [-D <testing_device_no>] # number of testing device, default=0\n"
+				"  [-t <test_mode>]         # 0=user task (default), 1=kernel task,\n"
+				"                           # 2=IRQ handler, 3=hard-IRQ handler\n"
+				"  [-P <priority>]          # task priority (test mode 0 and 1 only)\n"
+				"  [-o <port_type>]         # 0=serial (default), 1=parallel\n"
+				"  [-a <port_io_address>]   # default=0x3f8/0x378\n"
+				"  [-i <port_irq>]          # default=4/7\n");
+			exit(2);
+		}
+
+	/* set defaults for parallel port */
+	if (config.port_type == 1) {
+		if (!ioaddr_set)
+			config.port_ioaddr = 0x378;
+		if (!irq_set)
+			config.port_irq = 0x7;
+	}
+
+	signal(SIGINT, sighand);
+	signal(SIGTERM, sighand);
+	signal(SIGHUP, sighand);
+
+	mlockall(MCL_CURRENT|MCL_FUTURE);
+
+	snprintf(devname, RTDM_MAX_DEVNAME_LEN, "/dev/rttest%d", benchdev_no);
+	benchdev = open(devname, O_RDWR);
+	if (benchdev < 0) {
+		perror("irqloop: failed to open benchmark device");
+		fprintf(stderr, "(modprobe xeno_irqbench?)\n");
+		return 1;
+	}
+
+	if (config.mode == RTTST_IRQBENCH_USER_TASK) {
+		pthread_attr_t attr;
+
+		pthread_attr_init(&attr);
+		pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);
+
+		pthread_create(&thr, &attr, irq_thread, (void *)(long)config.priority);
+	}
+
+	if (ioctl(benchdev, RTTST_RTIOC_IRQBENCH_START, &config)) {
+		perror("irqloop: error starting test");
+		goto cleanup;
+	}
+
+	printf("Test mode:    %s\n"
+	       "Port type:    %s\n"
+	       "Port address: 0x%lx\n"
+	       "Port IRQ:     %d\n\n\n\n",
+	       mode_name[config.mode], port_type_name[config.port_type],
+	       config.port_ioaddr, config.port_irq);
+
+	while (!terminate) {
+		if (ioctl(benchdev, RTTST_RTIOC_IRQBENCH_GET_STATS,
+			  &stats) < 0) {
+			perror("irqloop: error reading stats");
+			break;
+		}
+
+		if ((last_received > 0) &&
+		    (stats.irqs_received == last_received)) {
+			if (--timeout == 0)
+				break; /* timed out */
+		} else
+			timeout = 10;
+		last_received = stats.irqs_received;
+
+		printf("\033[2AReceived IRQs:     %lld\n"
+		       "Acknowledged IRQs: %lld\n",
+		       stats.irqs_received, stats.irqs_acknowledged);
+		usleep(250000);
+	}
+
+	ioctl(benchdev, RTTST_RTIOC_IRQBENCH_STOP);
+
+cleanup:
+	close(benchdev);
+	if (config.mode == RTTST_IRQBENCH_USER_TASK) {
+		pthread_cancel(thr);
+		pthread_join(thr, NULL);
+	}
+	return 0;
 }
-- 
1.6.0.2



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

* [Xenomai-core] [PATCH v4 16/25] irqbench: Auto-detect bases of port address and IRQ values
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
                   ` (14 preceding siblings ...)
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 15/25] irqbench: Refactor user space helpers Jan Kiszka
@ 2010-04-19 10:28 ` Jan Kiszka
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 17/25] rttest: Resolved test device conflicts via separate name spaces Jan Kiszka
                   ` (9 subsequent siblings)
  25 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:28 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 src/testsuite/irqbench/irqbench.c |    2 +-
 src/testsuite/irqbench/irqloop.c  |    4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/testsuite/irqbench/irqbench.c b/src/testsuite/irqbench/irqbench.c
index 844f187..ca7a313 100644
--- a/src/testsuite/irqbench/irqbench.c
+++ b/src/testsuite/irqbench/irqbench.c
@@ -211,7 +211,7 @@ int main(int argc, char *argv[])
 			break;
 
 		case 'a':
-			port_ioaddr = strtol(optarg, NULL, (strncmp(optarg, "0x", 2) == 0) ? 16 : 10);
+			port_ioaddr = strtol(optarg, NULL, 0);
 			ioaddr_set = 1;
 			break;
 
diff --git a/src/testsuite/irqbench/irqloop.c b/src/testsuite/irqbench/irqloop.c
index 3b4de4f..d4623b4 100644
--- a/src/testsuite/irqbench/irqloop.c
+++ b/src/testsuite/irqbench/irqloop.c
@@ -101,12 +101,12 @@ int main(int argc, char *argv[])
 			break;
 
 		case 'a':
-			config.port_ioaddr = strtol(optarg, NULL, (strncmp(optarg, "0x", 2) == 0) ? 16 : 10);
+			config.port_ioaddr = strtol(optarg, NULL, 0);
 			ioaddr_set = 1;
 			break;
 
 		case 'i':
-			config.port_irq = atoi(optarg);
+			config.port_irq = strtol(optarg, NULL, 0);
 			irq_set = 1;
 			break;
 
-- 
1.6.0.2



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

* [Xenomai-core] [PATCH v4 17/25] rttest: Resolved test device conflicts via separate name spaces
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
                   ` (15 preceding siblings ...)
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 16/25] irqbench: Auto-detect bases of port address and IRQ values Jan Kiszka
@ 2010-04-19 10:28 ` Jan Kiszka
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 18/25] testing: Clean up Kconfig rules Jan Kiszka
                   ` (8 subsequent siblings)
  25 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:28 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

Usually, all devices of some RTDM class use the same naming scheme. But
as test devices are different as they do not provide compatible APIs,
let's give them separate name space for their device names. That finally
resolves all the detection troubles that showed up once more than one
test device was registered.

To allow addressing old drivers with new user space and vice versa, a
config switch is added to the former to select the naming scheme, and
the latter will try to open under both names.

Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 include/rtdm/rttesting.h              |   10 +++++++---
 ksrc/drivers/testing/Config.in        |    2 ++
 ksrc/drivers/testing/Kconfig          |    9 +++++++++
 ksrc/drivers/testing/irqbench.c       |    9 +++++++--
 ksrc/drivers/testing/klat.c           |    8 +++++++-
 ksrc/drivers/testing/switchtest.c     |    7 ++++++-
 ksrc/drivers/testing/timerbench.c     |    7 ++++++-
 src/testsuite/irqbench/irqloop.c      |   11 ++++++++++-
 src/testsuite/latency/latency.c       |   12 +++++++++++-
 src/testsuite/switchtest/switchtest.c |   15 +++++++++++++--
 10 files changed, 78 insertions(+), 12 deletions(-)

diff --git a/include/rtdm/rttesting.h b/include/rtdm/rttesting.h
index ce0418e..a660139 100644
--- a/include/rtdm/rttesting.h
+++ b/include/rtdm/rttesting.h
@@ -29,13 +29,14 @@
  * Feel free to comment on this profile via the Xenomai mailing list
  * (xenomai@xenomai.org) or directly to the author (jan.kiszka@domain.hid).
  *
- * @b Profile @b Revision: 1
+ * @b Profile @b Revision: 2
  * @n
  * @n
  * @par Device Characteristics
  * @ref rtdm_device.device_flags "Device Flags": @c RTDM_NAMED_DEVICE @n
  * @n
- * @ref rtdm_device.device_name "Device Name": @c "rttest<N>", N >= 0 @n
+ * @ref rtdm_device.device_name "Device Name": @c "rttest[-<subclass>]<N>",
+ * N >= 0, optional subclass name to simplify device discovery @n
  * @n
  * @ref rtdm_device.device_class "Device Class": @c RTDM_CLASS_TESTING @n
  * @n
@@ -61,7 +62,7 @@
 
 #include <rtdm/rtdm.h>
 
-#define RTTST_PROFILE_VER		1
+#define RTTST_PROFILE_VER		2
 
 typedef struct rttst_bench_res {
 	long long avg;
@@ -145,8 +146,11 @@ struct rttst_swtest_error {
 /*!
  * @name Sub-Classes of RTDM_CLASS_TESTING
  * @{ */
+/** subclass name: "timerbench" */
 #define RTDM_SUBCLASS_TIMERBENCH	0
+/** subclass name: "irqbench" */
 #define RTDM_SUBCLASS_IRQBENCH		1
+/** subclass name: "switchtest" */
 #define RTDM_SUBCLASS_SWITCHTEST	2
 /** @} */
 
diff --git a/ksrc/drivers/testing/Config.in b/ksrc/drivers/testing/Config.in
index 07bd900..3552670 100644
--- a/ksrc/drivers/testing/Config.in
+++ b/ksrc/drivers/testing/Config.in
@@ -5,6 +5,8 @@
 mainmenu_option next_comment
 comment 'Testing drivers'
 
+bool 'Use legacy names for testing drivers' CONFIG_XENO_DRIVERS_TESTING_LEGACY_NAMES $CONFIG_XENO_SKIN_RTDM
+
 dep_tristate 'Timer benchmark driver' CONFIG_XENO_DRIVERS_TIMERBENCH $CONFIG_XENO_SKIN_RTDM
 
 dep_tristate 'IRQ benchmark driver' CONFIG_XENO_DRIVERS_IRQBENCH $CONFIG_XENO_SKIN_RTDM
diff --git a/ksrc/drivers/testing/Kconfig b/ksrc/drivers/testing/Kconfig
index 7ca2eb1..05d6a49 100644
--- a/ksrc/drivers/testing/Kconfig
+++ b/ksrc/drivers/testing/Kconfig
@@ -4,6 +4,15 @@ config XENO_TESTING_MODULE
         depends on MODULES
 	def_tristate m
 
+config XENO_DRIVERS_TESTING_LEGACY_NAMES
+	depends on XENO_SKIN_RTDM
+	bool "Use legacy names for testing drivers"
+	help
+	This lets the testing drivers register under legacy names
+	("rttest<N>") instead of the new scheme ("rttest-<subclass><N>").
+	Only enable this if you plan to use old userspace tools with the
+	drivers.
+
 config XENO_DRIVERS_TIMERBENCH
 	depends on XENO_SKIN_RTDM
 	tristate "Timer benchmark driver"
diff --git a/ksrc/drivers/testing/irqbench.c b/ksrc/drivers/testing/irqbench.c
index 3dfb646..ab9686a 100644
--- a/ksrc/drivers/testing/irqbench.c
+++ b/ksrc/drivers/testing/irqbench.c
@@ -515,8 +515,13 @@ static int __init __irqbench_init(void)
 	int err;
 
 	do {
-		snprintf(device.device_name, RTDM_MAX_DEVNAME_LEN, "rttest%d",
-			 start_index);
+		snprintf(device.device_name, RTDM_MAX_DEVNAME_LEN,
+#ifdef CONFIG_XENO_DRIVERS_TESTING_LEGACY_NAMES
+			 "rttest%d",
+#else
+			 "rttest-irqbench%d",
+#endif
+			  start_index);
 		err = rtdm_dev_register(&device);
 
 		start_index++;
diff --git a/ksrc/drivers/testing/klat.c b/ksrc/drivers/testing/klat.c
index 6070c26..9e3613e 100644
--- a/ksrc/drivers/testing/klat.c
+++ b/ksrc/drivers/testing/klat.c
@@ -99,7 +99,13 @@ static int __init klat_mod_init(void)
 	pkt.config.freeze_max = freeze_max;
 
 	for (dev_nr = 0; dev_nr < DEV_NR_MAX; dev_nr++) {
-		snprintf(devname, sizeof(devname), "rttest%d", dev_nr);
+		snprintf(devname, sizeof(devname),
+#ifdef CONFIG_XENO_DRIVERS_TESTING_LEGACY_NAMES
+			 "rttest%d",
+#else
+			 "rttest-timerbench%d",
+#endif
+			 dev_nr);
 		fd = rt_dev_open(devname, O_RDONLY);
 		if (fd < 0)
 			continue;
diff --git a/ksrc/drivers/testing/switchtest.c b/ksrc/drivers/testing/switchtest.c
index 057094b..e335bfb 100644
--- a/ksrc/drivers/testing/switchtest.c
+++ b/ksrc/drivers/testing/switchtest.c
@@ -750,7 +750,12 @@ int __init __switchtest_init(void)
 	int err;
 
 	do {
-		snprintf(device.device_name, RTDM_MAX_DEVNAME_LEN, "rttest%d",
+		snprintf(device.device_name, RTDM_MAX_DEVNAME_LEN,
+#ifdef CONFIG_XENO_DRIVERS_TESTING_LEGACY_NAMES
+			 "rttest%d",
+#else
+			 "rttest-switchtest%d",
+#endif
 			 start_index);
 		err = rtdm_dev_register(&device);
 
diff --git a/ksrc/drivers/testing/timerbench.c b/ksrc/drivers/testing/timerbench.c
index 0946a04..fcd040d 100644
--- a/ksrc/drivers/testing/timerbench.c
+++ b/ksrc/drivers/testing/timerbench.c
@@ -508,7 +508,12 @@ static int __init __timerbench_init(void)
 	int err;
 
 	do {
-		snprintf(device.device_name, RTDM_MAX_DEVNAME_LEN, "rttest%d",
+		snprintf(device.device_name, RTDM_MAX_DEVNAME_LEN,
+#ifdef CONFIG_XENO_DRIVERS_TESTING_LEGACY_NAMES
+			 "rttest%d",
+#else
+			 "rttest-timerbench%d",
+#endif
 			 start_index);
 		err = rtdm_dev_register(&device);
 
diff --git a/src/testsuite/irqbench/irqloop.c b/src/testsuite/irqbench/irqloop.c
index d4623b4..9298575 100644
--- a/src/testsuite/irqbench/irqloop.c
+++ b/src/testsuite/irqbench/irqloop.c
@@ -26,6 +26,11 @@
 #include <sys/mman.h>
 #include <rtdm/rttesting.h>
 
+static const char *devname_fmt[] = {
+	"/dev/rttest-irqbench%d",
+	"/dev/rttest%d",
+};
+
 static int benchdev;
 static int terminate;
 
@@ -81,6 +86,7 @@ int main(int argc, char *argv[])
 	int irq_set = 0;
 	int c;
 	int timeout = 10;
+	int fmt = 0;
 
 	while ((c = getopt(argc, argv, "D:t:P:o:a:i:")) != EOF)
 		switch (c) {
@@ -136,9 +142,12 @@ int main(int argc, char *argv[])
 
 	mlockall(MCL_CURRENT|MCL_FUTURE);
 
-	snprintf(devname, RTDM_MAX_DEVNAME_LEN, "/dev/rttest%d", benchdev_no);
+retry:
+	snprintf(devname, RTDM_MAX_DEVNAME_LEN, devname_fmt[fmt], benchdev_no);
 	benchdev = open(devname, O_RDWR);
 	if (benchdev < 0) {
+		if (fmt++ == 0)
+			goto retry;
 		perror("irqloop: failed to open benchmark device");
 		fprintf(stderr, "(modprobe xeno_irqbench?)\n");
 		return 1;
diff --git a/src/testsuite/latency/latency.c b/src/testsuite/latency/latency.c
index e9e741e..8c3ca87 100644
--- a/src/testsuite/latency/latency.c
+++ b/src/testsuite/latency/latency.c
@@ -67,6 +67,11 @@ long *histogram_avg = NULL, *histogram_max = NULL, *histogram_min = NULL;
 int do_histogram = 0, do_stats = 0, finished = 0;
 int bucketsize = 1000;		/* default = 1000ns, -B <size> to override */
 
+static const char *devname_fmt[] = {
+	"rttest-timerbench%d",
+	"rttest%d",
+};
+
 static inline void add_histogram(long *histogram, long addval)
 {
 	/* bucketsize steps */
@@ -473,6 +478,7 @@ int main(int argc, char **argv)
 	int cpu = 0, c, err, sig;
 	char task_name[16];
 	sigset_t mask;
+	int fmt = 0;
 
 	while ((c = getopt(argc, argv, "hp:l:T:qH:B:sD:t:fc:P:b")) != EOF)
 		switch (c) {
@@ -622,11 +628,15 @@ int main(int argc, char **argv)
 	if (test_mode != USER_TASK) {
 		char devname[RTDM_MAX_DEVNAME_LEN];
 
-		snprintf(devname, RTDM_MAX_DEVNAME_LEN, "rttest%d",
+retry:
+		snprintf(devname, RTDM_MAX_DEVNAME_LEN, devname_fmt[fmt],
 			 benchdev_no);
 		benchdev = rt_dev_open(devname, O_RDWR);
 
 		if (benchdev < 0) {
+			if (fmt++ == 0)
+				goto retry;
+
 			fprintf(stderr,
 				"latency: failed to open benchmark device, code %d\n"
 				"(modprobe xeno_timerbench?)\n", benchdev);
diff --git a/src/testsuite/switchtest/switchtest.c b/src/testsuite/switchtest/switchtest.c
index 9e4df10..7114a9f 100644
--- a/src/testsuite/switchtest/switchtest.c
+++ b/src/testsuite/switchtest/switchtest.c
@@ -888,13 +888,19 @@ static int task_create(struct cpu_tasks *cpu,
 
 #define DEV_NR_MAX 256
 
+static const char *devname_fmt[] = {
+	"/dev/rttest-switchtest%d",
+	"/dev/rttest%d",
+};
+
 static int open_rttest(char *buf, size_t size, unsigned count)
 {
 	static unsigned dev_nr = 0;
 	int fd, status;
+	int fmt = 0;
 
 	do {
-		snprintf(buf, size, "/dev/rttest%u", dev_nr);
+		snprintf(buf, size, devname_fmt[fmt], dev_nr);
 
 		status = fd = open(buf, O_RDWR);
 
@@ -913,6 +919,11 @@ static int open_rttest(char *buf, size_t size, unsigned count)
 		if (++dev_nr != DEV_NR_MAX)
 			continue;
 
+		if (fmt++ == 0) {
+			dev_nr = 0;
+			continue;
+		}
+
 		fprintf(stderr, "switchtest: Unable to open switchtest device.\n"
 			"(modprobe xeno_switchtest ?)\n");
 
@@ -1110,7 +1121,7 @@ int main(int argc, const char *argv[])
 	const char *progname = argv[0];
 	struct cpu_tasks *cpus;
 	struct sched_param sp;
-	char devname[21];
+	char devname[RTDM_MAX_DEVNAME_LEN+1];
 	sigset_t mask;
 	int sig;
 
-- 
1.6.0.2



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

* [Xenomai-core] [PATCH v4 18/25] testing: Clean up Kconfig rules
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
                   ` (16 preceding siblings ...)
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 17/25] rttest: Resolved test device conflicts via separate name spaces Jan Kiszka
@ 2010-04-19 10:28 ` Jan Kiszka
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 19/25] RTIPC: Drop unused wrapper around close_lock_count Jan Kiszka
                   ` (7 subsequent siblings)
  25 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:28 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

To exclude modules from built-in, make them depend on 'm' is sufficient.

Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 ksrc/drivers/testing/Config.in |    2 +-
 ksrc/drivers/testing/Kconfig   |   14 +++++---------
 2 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/ksrc/drivers/testing/Config.in b/ksrc/drivers/testing/Config.in
index 3552670..215c38d 100644
--- a/ksrc/drivers/testing/Config.in
+++ b/ksrc/drivers/testing/Config.in
@@ -15,6 +15,6 @@ dep_tristate 'Context switches test driver' CONFIG_XENO_DRIVERS_SWITCHTEST $CONF
 
 dep_tristate 'Kernel-only latency measurement module' CONFIG_XENO_DRIVERS_KLATENCY $CONFIG_XENO_DRIVERS_TIMERBENCH m
 
-dep_tristate 'User-space real-time signals testing module' CONFIG_XENO_DRIVERS_SIGTEST $CONFIG_MODULES m
+dep_tristate 'User-space real-time signals testing module' CONFIG_XENO_DRIVERS_SIGTEST m
 
 endmenu
diff --git a/ksrc/drivers/testing/Kconfig b/ksrc/drivers/testing/Kconfig
index 05d6a49..883ede1 100644
--- a/ksrc/drivers/testing/Kconfig
+++ b/ksrc/drivers/testing/Kconfig
@@ -1,9 +1,5 @@
 menu "Testing drivers"
 
-config XENO_TESTING_MODULE
-        depends on MODULES
-	def_tristate m
-
 config XENO_DRIVERS_TESTING_LEGACY_NAMES
 	depends on XENO_SKIN_RTDM
 	bool "Use legacy names for testing drivers"
@@ -22,7 +18,7 @@ config XENO_DRIVERS_TIMERBENCH
 	See testsuite/latency for a possible front-end.
 
 config XENO_DRIVERS_KLATENCY
-	depends on XENO_DRIVERS_TIMERBENCH && XENO_TESTING_MODULE
+	depends on XENO_DRIVERS_TIMERBENCH && m
 	tristate "Kernel-only latency measurement module"
 	help
 	Kernel module for kernel-only latency measurement.
@@ -44,9 +40,9 @@ config XENO_DRIVERS_SWITCHTEST
 	FPU switches.
 
 config XENO_DRIVERS_SIGTEST
-       depends on XENO_TESTING_MODULE
-       tristate "User-space real-time signals testing module"
-       help
-       Elementary skin for unit testing user-space real-time signals.
+	depends on m
+	tristate "User-space real-time signals testing module"
+	help
+	Elementary skin for unit testing user-space real-time signals.
 
 endmenu
-- 
1.6.0.2



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

* [Xenomai-core] [PATCH v4 19/25] RTIPC: Drop unused wrapper around close_lock_count
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
                   ` (17 preceding siblings ...)
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 18/25] testing: Clean up Kconfig rules Jan Kiszka
@ 2010-04-19 10:28 ` Jan Kiszka
  2010-04-19 10:29 ` [Xenomai-core] [PATCH v4 20/25] RTDM: Document device close procedure Jan Kiszka
                   ` (6 subsequent siblings)
  25 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:28 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

CC: Philippe Gerum <rpm@xenomai.org>
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 ksrc/drivers/ipc/internal.h |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/ksrc/drivers/ipc/internal.h b/ksrc/drivers/ipc/internal.h
index 296a988..ed8c103 100644
--- a/ksrc/drivers/ipc/internal.h
+++ b/ksrc/drivers/ipc/internal.h
@@ -127,9 +127,4 @@ extern struct xnptree rtipc_ptree;
 #define rtipc_enter_atomic(lockctx)	xnlock_get_irqsave(&nklock, (lockctx))
 #define rtipc_leave_atomic(lockctx)	xnlock_put_irqrestore(&nklock, (lockctx))
 
-static inline int rtipc_socket_locked(struct rtdm_dev_context *context)
-{
-	return atomic_read(&context->close_lock_count);
-}
-
 #endif /* !_RTIPC_INTERNAL_H */
-- 
1.6.0.2



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

* [Xenomai-core] [PATCH v4 20/25] RTDM: Document device close procedure
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
                   ` (18 preceding siblings ...)
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 19/25] RTIPC: Drop unused wrapper around close_lock_count Jan Kiszka
@ 2010-04-19 10:29 ` Jan Kiszka
  2010-04-19 10:29 ` [Xenomai-core] [PATCH v4 21/25] Add list_first_entry wrapper for older kernels Jan Kiszka
                   ` (5 subsequent siblings)
  25 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:29 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

Interating over the close handler when it returns -EAGAIN or in case a
pending reference to the device context exists is RTDM practice since
day one. Documenting this is seriously overdue.

CC: Philippe Gerum <rpm@xenomai.org>
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 include/rtdm/rtdm_driver.h |   11 +++++++++--
 1 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/include/rtdm/rtdm_driver.h b/include/rtdm/rtdm_driver.h
index 07b73a3..380d752 100644
--- a/include/rtdm/rtdm_driver.h
+++ b/include/rtdm/rtdm_driver.h
@@ -193,11 +193,18 @@ typedef int (*rtdm_socket_handler_t)(struct rtdm_dev_context *context,
  *
  * @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
+ * 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, or another negative error code.
+ * 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 */
-- 
1.6.0.2



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

* [Xenomai-core] [PATCH v4 21/25] Add list_first_entry wrapper for older kernels
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
                   ` (19 preceding siblings ...)
  2010-04-19 10:29 ` [Xenomai-core] [PATCH v4 20/25] RTDM: Document device close procedure Jan Kiszka
@ 2010-04-19 10:29 ` Jan Kiszka
  2010-04-19 10:29 ` [Xenomai-core] [PATCH v4 22/25] Add legacy kernel support for delayed_work Jan Kiszka
                   ` (4 subsequent siblings)
  25 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:29 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

CC: Philippe Gerum <rpm@xenomai.org>
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 include/asm-generic/wrappers.h |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/include/asm-generic/wrappers.h b/include/asm-generic/wrappers.h
index 64ec43f..d864397 100644
--- a/include/asm-generic/wrappers.h
+++ b/include/asm-generic/wrappers.h
@@ -559,6 +559,11 @@ static inline void wrap_proc_dir_entry_owner(struct proc_dir_entry *entry)
 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) */
 #endif /* CONFIG_PROC_FS */
 
+#ifndef list_first_entry
+#define list_first_entry(ptr, type, member) \
+	list_entry((ptr)->next, type, member)
+#endif
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
 #define rthal_irq_descp(irq)	(irq_desc + (irq))
 #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) */
-- 
1.6.0.2



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

* [Xenomai-core] [PATCH v4 22/25] Add legacy kernel support for delayed_work
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
                   ` (20 preceding siblings ...)
  2010-04-19 10:29 ` [Xenomai-core] [PATCH v4 21/25] Add list_first_entry wrapper for older kernels Jan Kiszka
@ 2010-04-19 10:29 ` Jan Kiszka
  2010-04-19 10:29 ` [Xenomai-core] [PATCH v4 23/25] RTDM: Early fd release with poll-free context reference tracking Jan Kiszka
                   ` (3 subsequent siblings)
  25 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:29 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

Note that the kernel 2.4 version of schedule_delayed_work is not
universally usable.

CC: Philippe Gerum <rpm@xenomai.org>
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 include/asm-generic/wrappers.h   |    3 +++
 include/compat/linux/workqueue.h |   13 +++++++++++++
 2 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/include/asm-generic/wrappers.h b/include/asm-generic/wrappers.h
index d864397..7513781 100644
--- a/include/asm-generic/wrappers.h
+++ b/include/asm-generic/wrappers.h
@@ -192,6 +192,7 @@ do {									\
 #define DECLARE_WORK(n,f,d)      	struct tq_struct n = __WORK_INITIALIZER(n, f, d)
 #define DECLARE_WORK_NODATA(n, f)	DECLARE_WORK(n, f, NULL)
 #define DECLARE_WORK_FUNC(f)		void f(void *cookie)
+#define DECLARE_DELAYED_WORK_NODATA(n, f) DECLARE_WORK(n, f, NULL)
 
 /* Msleep is unknown before 2.4.28 */
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,28)
@@ -436,9 +437,11 @@ unsigned long find_next_bit(const unsigned long *addr,
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
 #define DECLARE_WORK_NODATA(f, n)	DECLARE_WORK(f, n, NULL)
 #define DECLARE_WORK_FUNC(f)		void f(void *cookie)
+#define DECLARE_DELAYED_WORK_NODATA(n, f) DECLARE_DELAYED_WORK(n, f, NULL)
 #else /* >= 2.6.20 */
 #define DECLARE_WORK_NODATA(f, n)	DECLARE_WORK(f, n)
 #define DECLARE_WORK_FUNC(f)		void f(struct work_struct *work)
+#define DECLARE_DELAYED_WORK_NODATA(n, f) DECLARE_DELAYED_WORK(n, f)
 #endif /* >= 2.6.20 */
 
 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) */
diff --git a/include/compat/linux/workqueue.h b/include/compat/linux/workqueue.h
index 3ac37aa..6fad03c 100644
--- a/include/compat/linux/workqueue.h
+++ b/include/compat/linux/workqueue.h
@@ -28,4 +28,17 @@
 #define schedule_work(x)         schedule_task(x)
 #define flush_scheduled_work()   flush_scheduled_tasks()
 
+/*
+ * WARNING: This is not identical to 2.6 schedule_delayed_work as it delayes
+ * the caller to schedule the task after the specified delay. That's fine for
+ * our current use cases, though.
+ */
+#define schedule_delayed_work(work, delay) do {			\
+	if (delay) {						\
+		set_current_state(TASK_UNINTERRUPTIBLE);	\
+		schedule_timeout(delay);			\
+	}							\
+	schedule_task(work);					\
+} while (0)
+
 #endif /* _XENO_COMPAT_LINUX_WORKQUEUE_H */
-- 
1.6.0.2



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

* [Xenomai-core] [PATCH v4 23/25] RTDM: Early fd release with poll-free context reference tracking
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
                   ` (21 preceding siblings ...)
  2010-04-19 10:29 ` [Xenomai-core] [PATCH v4 22/25] Add legacy kernel support for delayed_work Jan Kiszka
@ 2010-04-19 10:29 ` Jan Kiszka
  2010-04-19 10:29 ` [Xenomai-core] [PATCH v4 24/25] RTDM: Add basic unit test Jan Kiszka
                   ` (2 subsequent siblings)
  25 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:29 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

Two changes in one as they are tightly related: Once close is called,
remove the file descriptor from open table, allowing its reuse while
close for the previous user proceeds.

The second and major part of the patch avoids time-based polling while
waiting for context references to be dropped. This specifically helps in
scenarios where references can be held for a longer time beyond the
first close.

CC: Philippe Gerum <rpm@xenomai.org>
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 include/rtdm/rtdm_driver.h |   16 ++++-
 ksrc/skins/rtdm/core.c     |  168 ++++++++++++++++++++++++++++++-------------
 ksrc/skins/rtdm/device.c   |   45 ++++++++++--
 ksrc/skins/rtdm/internal.h |    8 +--
 4 files changed, 170 insertions(+), 67 deletions(-)

diff --git a/include/rtdm/rtdm_driver.h b/include/rtdm/rtdm_driver.h
index 380d752..1a4097b 100644
--- a/include/rtdm/rtdm_driver.h
+++ b/include/rtdm/rtdm_driver.h
@@ -379,6 +379,7 @@ struct rtdm_operations {
 
 struct rtdm_devctx_reserved {
 	void *owner;
+	struct list_head cleanup;
 };
 
 /**
@@ -560,19 +561,28 @@ int rtdm_dev_unregister(struct rtdm_device *device, unsigned int poll_delay);
 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)
 {
-	XENO_ASSERT(RTDM, atomic_read(&context->close_lock_count) > 0,
+	XENO_ASSERT(RTDM, CONTEXT_IS_LOCKED(context),
 		    /* just warn if context was a dangling pointer */);
 	atomic_inc(&context->close_lock_count);
 }
 
+extern int rtdm_apc;
+
 static inline void rtdm_context_unlock(struct rtdm_dev_context *context)
 {
-	XENO_ASSERT(RTDM, atomic_read(&context->close_lock_count) > 0,
+	XENO_ASSERT(RTDM, CONTEXT_IS_LOCKED(context),
 		    /* just warn if context was a dangling pointer */);
 	smp_mb__before_atomic_dec();
-	atomic_dec(&context->close_lock_count);
+	if (unlikely(atomic_dec_and_test(&context->close_lock_count)))
+		rthal_apc_schedule(rtdm_apc);
 }
 
 static inline void rtdm_context_put(struct rtdm_dev_context *context)
diff --git a/ksrc/skins/rtdm/core.c b/ksrc/skins/rtdm/core.c
index e04b3f6..bf905df 100644
--- a/ksrc/skins/rtdm/core.c
+++ b/ksrc/skins/rtdm/core.c
@@ -26,7 +26,7 @@
  * @{
  */
 
-#include <linux/delay.h>
+#include <linux/workqueue.h>
 
 #include <nucleus/pod.h>
 #include <nucleus/ppd.h>
@@ -35,7 +35,7 @@
 
 #include "rtdm/internal.h"
 
-#define CLOSURE_RETRY_PERIOD	100	/* ms */
+#define CLOSURE_RETRY_PERIOD_MS	100
 
 #define FD_BITMAP_SIZE  ((RTDM_FD_MAX + BITS_PER_LONG-1) / BITS_PER_LONG)
 
@@ -44,6 +44,10 @@ struct rtdm_fildes fildes_table[RTDM_FD_MAX] =
 static unsigned long used_fildes[FD_BITMAP_SIZE];
 int open_fildes;	/* number of used descriptors */
 
+static DECLARE_WORK_FUNC(close_callback);
+static DECLARE_DELAYED_WORK_NODATA(close_work, close_callback);
+static LIST_HEAD(cleanup_queue);
+
 xntbase_t *rtdm_tbase;
 EXPORT_SYMBOL(rtdm_tbase);
 
@@ -81,8 +85,7 @@ struct rtdm_dev_context *rtdm_context_get(int fd)
 	xnlock_get_irqsave(&rt_fildes_lock, s);
 
 	context = fildes_table[fd].context;
-	if (unlikely(!context ||
-		     test_bit(RTDM_CLOSING, &context->context_flags))) {
+	if (unlikely(!context)) {
 		xnlock_put_irqrestore(&rt_fildes_lock, s);
 		return NULL;
 	}
@@ -106,8 +109,10 @@ static int create_instance(struct rtdm_device *device,
 	int fd;
 	spl_t s;
 
-	/* Reset to NULL so that we can always use cleanup_instance to revert
-	   also partially successful allocations */
+	/*
+	 * Reset to NULL so that we can always use cleanup_files/instance to
+	 * revert also partially successful allocations.
+	 */
 	*context_ptr = NULL;
 	*fildes_ptr = NULL;
 
@@ -155,7 +160,7 @@ static int create_instance(struct rtdm_device *device,
 
 	context->fd = fd;
 	context->ops = &device->ops;
-	atomic_set(&context->close_lock_count, 0);
+	atomic_set(&context->close_lock_count, 1);
 
 #ifdef CONFIG_XENO_OPT_PERVASIVE
 	ppd = xnshadow_ppd_get(__rtdm_muxid);
@@ -163,31 +168,34 @@ static int create_instance(struct rtdm_device *device,
 
 	context->reserved.owner =
 	    ppd ? container_of(ppd, struct rtdm_process, ppd) : NULL;
+	INIT_LIST_HEAD(&context->reserved.cleanup);
 
 	return 0;
 }
 
-static int cleanup_instance(struct rtdm_device *device,
-			    struct rtdm_dev_context *context,
-			    struct rtdm_fildes *fildes, int nrt_mem)
+static void __cleanup_fildes(struct rtdm_fildes *fildes)
 {
-	spl_t s;
-
-	xnlock_get_irqsave(&rt_fildes_lock, s);
+	clear_bit((fildes - fildes_table), used_fildes);
+	fildes->context = NULL;
+	open_fildes--;
+}
 
-	if (context && unlikely(atomic_read(&context->close_lock_count) > 1)) {
-		xnlock_put_irqrestore(&rt_fildes_lock, s);
-		return -EAGAIN;
-	}
+static void cleanup_fildes(struct rtdm_fildes *fildes)
+{
+	spl_t s;
 
-	if (fildes) {
-		clear_bit((fildes - fildes_table), used_fildes);
-		fildes->context = NULL;
-		open_fildes--;
-	}
+	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)
 			context->device = NULL;
@@ -200,10 +208,62 @@ static int cleanup_instance(struct rtdm_device *device,
 	}
 
 	rtdm_dereference_device(device);
+}
 
-	return 0;
+static DECLARE_WORK_FUNC(close_callback)
+{
+	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);
+	}
+
+	list_splice(&deferred_list, &cleanup_queue);
+
+	xnlock_put_irqrestore(&rt_fildes_lock, s);
+
+	if (reschedule)
+		schedule_delayed_work(&close_work,
+				      (HZ * CLOSURE_RETRY_PERIOD_MS) / 1000);
 }
 
+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)
 {
 	struct rtdm_device *device;
@@ -245,7 +305,8 @@ int __rt_dev_open(rtdm_user_info_t *user_info, const char *path, int oflag)
 	return context->fd;
 
 cleanup_out:
-	cleanup_instance(device, context, fildes, nrt_mode);
+	cleanup_fildes(fildes);
+	cleanup_instance(device, context, nrt_mode);
 
 err_out:
 	return ret;
@@ -296,7 +357,8 @@ int __rt_dev_socket(rtdm_user_info_t *user_info, int protocol_family,
 	return context->fd;
 
 cleanup_out:
-	cleanup_instance(device, context, fildes, nrt_mode);
+	cleanup_fildes(fildes);
+	cleanup_instance(device, context, nrt_mode);
 
 err_out:
 	return ret;
@@ -317,7 +379,6 @@ int __rt_dev_close(rtdm_user_info_t *user_info, int fd)
 	if (unlikely((unsigned int)fd >= RTDM_FD_MAX))
 		goto err_out;
 
-again:
 	xnlock_get_irqsave(&rt_fildes_lock, s);
 
 	context = fildes_table[fd].context;
@@ -327,47 +388,52 @@ again:
 		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 {
-		/* Avoid asymmetric close context by switching to nrt. */
-		if (unlikely(
-		    test_bit(RTDM_CREATED_IN_NRT, &context->context_flags))) {
-			ret = -ENOSYS;
-			goto unlock_out;
-		}
+	else
 		ret = context->ops->close_rt(context, user_info);
-	}
 
 	XENO_ASSERT(RTDM, !rthal_local_irq_disabled(),
 		    rthal_local_irq_enable(););
 
-	if (unlikely(ret == -EAGAIN) && nrt_mode) {
-		rtdm_context_unlock(context);
-		msleep(CLOSURE_RETRY_PERIOD);
-		goto again;
-	} else if (unlikely(ret < 0))
-		goto unlock_out;
+	xnlock_get_irqsave(&rt_fildes_lock, s);
 
-	ret = cleanup_instance(context->device, context, &fildes_table[fd],
-			       test_bit(RTDM_CREATED_IN_NRT,
-			       &context->context_flags));
-	if (ret < 0) {
-		rtdm_context_unlock(context);
+	if (ret == -EAGAIN || atomic_read(&context->close_lock_count) > 2) {
+		atomic_dec(&context->close_lock_count);
+		list_add(&context->reserved.cleanup, &cleanup_queue);
 
-		if (!nrt_mode)
-			goto err_out;
+		xnlock_put_irqrestore(&rt_fildes_lock, s);
 
-		msleep(CLOSURE_RETRY_PERIOD);
-		goto again;
+		if (ret == -EAGAIN) {
+			rthal_apc_schedule(rtdm_apc);
+			ret = 0;
+		}
+		goto unlock_out;
 	}
 
-	trace_mark(xn_rtdm, fd_closed, "fd %d", fd);
+	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;
 
@@ -402,7 +468,7 @@ void cleanup_owned_contexts(void *owner)
 					 fd);
 
 			ret = __rt_dev_close(NULL, fd);
-			XENO_ASSERT(RTDM, ret >= 0 || ret == -EBADF,
+			XENO_ASSERT(RTDM, ret == 0 || ret == -EBADF,
 				    /* only warn here */;);
 		}
 	}
diff --git a/ksrc/skins/rtdm/device.c b/ksrc/skins/rtdm/device.c
index e229932..6eb2975 100644
--- a/ksrc/skins/rtdm/device.c
+++ b/ksrc/skins/rtdm/device.c
@@ -58,6 +58,9 @@ struct list_head *rtdm_protocol_devices;	/* hash table */
 static int name_hashkey_mask;
 static int proto_hashkey_mask;
 
+int rtdm_apc;
+EXPORT_SYMBOL(rtdm_apc);
+
 DECLARE_MUTEX(nrt_dev_lock);
 DEFINE_XNLOCK(rt_dev_lock);
 
@@ -458,19 +461,28 @@ EXPORT_SYMBOL(rtdm_dev_unregister);
 
 int __init rtdm_dev_init(void)
 {
-	int i;
+	int err, i;
+
+	rtdm_apc = rthal_apc_alloc("deferred RTDM close", rtdm_apc_handler,
+				   NULL);
+	if (rtdm_apc < 0)
+		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))
-		return -EINVAL;
+	    ((protocol_hashtab_size & proto_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)
-		return -ENOMEM;
+	if (!rtdm_named_devices) {
+		err = -ENOMEM;
+		goto err_out1;
+	}
 
 	for (i = 0; i < devname_hashtab_size; i++)
 		INIT_LIST_HEAD(&rtdm_named_devices[i]);
@@ -479,14 +491,33 @@ int __init rtdm_dev_init(void)
 	    kmalloc(protocol_hashtab_size * sizeof(struct list_head),
 		    GFP_KERNEL);
 	if (!rtdm_protocol_devices) {
-		kfree(rtdm_named_devices);
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto err_out2;
 	}
 
 	for (i = 0; i < protocol_hashtab_size; i++)
 		INIT_LIST_HEAD(&rtdm_protocol_devices[i]);
 
 	return 0;
+
+err_out2:
+	kfree(rtdm_named_devices);
+
+err_out1:
+	rthal_apc_free(rtdm_apc);
+
+	return err;
+}
+
+void __exit 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.
+	 */
+	rthal_apc_free(rtdm_apc);
+	kfree(rtdm_named_devices);
+	kfree(rtdm_protocol_devices);
 }
 
 /*@}*/
diff --git a/ksrc/skins/rtdm/internal.h b/ksrc/skins/rtdm/internal.h
index 69299f8..3d39def 100644
--- a/ksrc/skins/rtdm/internal.h
+++ b/ksrc/skins/rtdm/internal.h
@@ -80,15 +80,11 @@ static inline void rtdm_dereference_device(struct rtdm_device *device)
 }
 
 int __init rtdm_dev_init(void);
-
-static inline void rtdm_dev_cleanup(void)
-{
-	kfree(rtdm_named_devices);
-	kfree(rtdm_protocol_devices);
-}
+void __exit rtdm_dev_cleanup(void);
 
 int rtdm_proc_register_device(struct rtdm_device *device);
 int __init rtdm_proc_init(void);
 void rtdm_proc_cleanup(void);
+void rtdm_apc_handler(void *cookie);
 
 #endif /* _RTDM_INTERNAL_H */
-- 
1.6.0.2



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

* [Xenomai-core] [PATCH v4 24/25] RTDM: Add basic unit test
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
                   ` (22 preceding siblings ...)
  2010-04-19 10:29 ` [Xenomai-core] [PATCH v4 23/25] RTDM: Early fd release with poll-free context reference tracking Jan Kiszka
@ 2010-04-19 10:29 ` Jan Kiszka
  2010-04-19 10:29 ` [Xenomai-core] [PATCH v4 25/25] RTDM: Use non-atomic bitops for used_fildes Jan Kiszka
  2010-04-19 16:19 ` [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Gilles Chanteperdrix
  25 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:29 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

This unit test for RTDM validates deferred device closing and driver
deregistration due to pending references. Further tests can be added in
the future.

CC: Philippe Gerum <rpm@xenomai.org>
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 include/rtdm/rttesting.h        |    9 ++
 ksrc/drivers/testing/Config.in  |    2 +
 ksrc/drivers/testing/Kconfig    |    6 ++
 ksrc/drivers/testing/Makefile   |   12 +++-
 ksrc/drivers/testing/rtdmtest.c |  191 +++++++++++++++++++++++++++++++++++++++
 src/testsuite/unit/Makefile.am  |   17 ++++-
 src/testsuite/unit/rtdm.c       |  114 +++++++++++++++++++++++
 7 files changed, 349 insertions(+), 2 deletions(-)
 create mode 100644 ksrc/drivers/testing/rtdmtest.c
 create mode 100644 src/testsuite/unit/rtdm.c

diff --git a/include/rtdm/rttesting.h b/include/rtdm/rttesting.h
index a660139..e936630 100644
--- a/include/rtdm/rttesting.h
+++ b/include/rtdm/rttesting.h
@@ -141,6 +141,10 @@ struct rttst_swtest_error {
 	unsigned fp_val;
 };
 
+#define RTTST_RTDM_NORMAL_CLOSE		0
+#define RTTST_RTDM_DEFER_CLOSE_HANDLER	1
+#define RTTST_RTDM_DEFER_CLOSE_CONTEXT	2
+
 #define RTIOC_TYPE_TESTING		RTDM_CLASS_TESTING
 
 /*!
@@ -152,6 +156,8 @@ struct rttst_swtest_error {
 #define RTDM_SUBCLASS_IRQBENCH		1
 /** subclass name: "switchtest" */
 #define RTDM_SUBCLASS_SWITCHTEST	2
+/** subclase name: "rtdm" */
+#define RTDM_SUBCLASS_RTDMTEST		3
 /** @} */
 
 /*!
@@ -208,6 +214,9 @@ struct rttst_swtest_error {
 
 #define RTTST_RTIOC_SWTEST_SET_PAUSE \
 	_IOW(RTIOC_TYPE_TESTING, 0x38, unsigned long)
+
+#define RTTST_RTIOC_RTDM_DEFER_CLOSE \
+	_IOW(RTIOC_TYPE_TESTING, 0x40, unsigned long)
 /** @} */
 
 /** @} */
diff --git a/ksrc/drivers/testing/Config.in b/ksrc/drivers/testing/Config.in
index 215c38d..4f81cf9 100644
--- a/ksrc/drivers/testing/Config.in
+++ b/ksrc/drivers/testing/Config.in
@@ -17,4 +17,6 @@ dep_tristate 'Kernel-only latency measurement module' CONFIG_XENO_DRIVERS_KLATEN
 
 dep_tristate 'User-space real-time signals testing module' CONFIG_XENO_DRIVERS_SIGTEST m
 
+dep_tristate 'RTDM unit tests driver' CONFIG_XENO_DRIVERS_RTDMTEST $CONFIG_XENO_SKIN_RTDM m
+
 endmenu
diff --git a/ksrc/drivers/testing/Kconfig b/ksrc/drivers/testing/Kconfig
index 883ede1..28504dc 100644
--- a/ksrc/drivers/testing/Kconfig
+++ b/ksrc/drivers/testing/Kconfig
@@ -45,4 +45,10 @@ config XENO_DRIVERS_SIGTEST
 	help
 	Elementary skin for unit testing user-space real-time signals.
 
+config XENO_DRIVERS_RTDMTEST
+	depends on XENO_SKIN_RTDM && m
+	tristate "RTDM unit tests driver"
+	help
+	Kernel driver for performing RTDM unit tests.
+
 endmenu
diff --git a/ksrc/drivers/testing/Makefile b/ksrc/drivers/testing/Makefile
index 7878cd5..17a6cf1 100644
--- a/ksrc/drivers/testing/Makefile
+++ b/ksrc/drivers/testing/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_XENO_DRIVERS_IRQBENCH)   += xeno_irqbench.o
 obj-$(CONFIG_XENO_DRIVERS_SWITCHTEST) += xeno_switchtest.o
 obj-$(CONFIG_XENO_DRIVERS_KLATENCY)   += xeno_klat.o
 obj-$(CONFIG_XENO_DRIVERS_SIGTEST)    += xeno_sigtest.o
+obj-$(CONFIG_XENO_DRIVERS_RTDMTEST)   += xeno_rtdmtest.o
 
 xeno_timerbench-y := timerbench.o
 
@@ -20,6 +21,8 @@ xeno_klat-y := klat.o
 
 xeno_sigtest-y := sigtest_module.o
 
+xeno_rtdmtest-y := rtdmtest.o
+
 EXTRA_CFLAGS += -D__IN_XENOMAI__ -Iinclude/xenomai
 
 else
@@ -33,6 +36,7 @@ obj-$(CONFIG_XENO_DRIVERS_IRQBENCH)   += xeno_irqbench.o
 obj-$(CONFIG_XENO_DRIVERS_SWITCHTEST) += xeno_switchtest.o
 obj-$(CONFIG_XENO_DRIVERS_KLATENCY)   += xeno_klat.o
 obj-$(CONFIG_XENO_DRIVERS_SIGTEST)    += xeno_sigtest.o
+obj-$(CONFIG_XENO_DRIVERS_RTDMTEST)   += xeno_rtdmtest.o
 
 xeno_timerbench-objs := timerbench.o
 
@@ -44,8 +48,11 @@ xeno_klat-objs := klat.o
 
 xeno_sigtest-objs := sigtest_module.o
 
+xeno_rtdmtest-objs := rtdmtest.o
+
 export-objs := $(xeno_timerbench-objs) $(xeno_irqbench-objs) \
-	$(xeno_switchtest-objs) $(xeno_klat-objs) $(xeno_sigtest-objs)
+	$(xeno_switchtest-objs) $(xeno_klat-objs) $(xeno_sigtest-objs) \
+	$(xeno_rtdmtest-objs)
 
 EXTRA_CFLAGS += -D__IN_XENOMAI__ -I$(TOPDIR)/include/xenomai -I$(TOPDIR)/include/xenomai/compat
 
@@ -66,4 +73,7 @@ xeno_klat.o: $(xeno_klat-objs)
 xeno_sigtest.o: $(xeno_sigtest-objs)
 	$(LD) -r -o $@ $(xeno_sigtest-objs)
 
+xeno_rtdmtest.o: $(xeno_rtdmtest-objs)
+	$(LD) -r -o $@ $(xeno_rtdmtest-objs)
+
 endif
diff --git a/ksrc/drivers/testing/rtdmtest.c b/ksrc/drivers/testing/rtdmtest.c
new file mode 100644
index 0000000..12540de
--- /dev/null
+++ b/ksrc/drivers/testing/rtdmtest.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2010 Jan Kiszka <jan.kiszka@domain.hid>.
+ *
+ * Xenomai is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Xenomai is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Xenomai; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+
+#include <rtdm/rtdm_driver.h>
+#include <rtdm/rttesting.h>
+
+static unsigned int start_index;
+
+module_param(start_index, uint, 0400);
+MODULE_PARM_DESC(start_index, "First device instance number to be used");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("jan.kiszka@domain.hid");
+
+struct rtdm_test_context {
+	rtdm_timer_t close_timer;
+	unsigned long close_counter;
+	unsigned long close_deferral;
+};
+
+static void close_timer_proc(rtdm_timer_t *timer)
+{
+	struct rtdm_test_context *ctx =
+		container_of(timer, struct rtdm_test_context, close_timer);
+
+	if (ctx->close_counter != 1)
+		printk(KERN_ERR
+		       "rtdmtest: %s: close_counter is %lu, should be 1!\n",
+		       __FUNCTION__, ctx->close_counter);
+
+	rtdm_context_unlock(rtdm_private_to_context(ctx));
+}
+
+static int rtdm_test_open(struct rtdm_dev_context *context,
+			  rtdm_user_info_t *user_info, int oflags)
+{
+	struct rtdm_test_context *ctx =
+		(struct rtdm_test_context *)context->dev_private;
+
+	rtdm_timer_init(&ctx->close_timer, close_timer_proc,
+			"rtdm close test");
+	ctx->close_counter = 0;
+	ctx->close_deferral = RTTST_RTDM_NORMAL_CLOSE;
+
+	return 0;
+}
+
+static int rtdm_test_close(struct rtdm_dev_context *context,
+			   rtdm_user_info_t *user_info)
+{
+	struct rtdm_test_context *ctx =
+		(struct rtdm_test_context *)context->dev_private;
+
+	ctx->close_counter++;
+
+	switch (ctx->close_deferral) {
+	case RTTST_RTDM_DEFER_CLOSE_HANDLER:
+		if (ctx->close_counter <= 3)
+			return -EAGAIN;
+		if (ctx->close_counter > 4) {
+			printk(KERN_ERR
+			       "rtdmtest: %s: close_counter is %lu, "
+			       "should be 2!\n",
+			       __FUNCTION__, ctx->close_counter);
+			return 0;
+		}
+		break;
+
+	case RTTST_RTDM_DEFER_CLOSE_CONTEXT:
+		if (ctx->close_counter == 1) {
+			rtdm_context_lock(context);
+			rtdm_timer_start(&ctx->close_timer, 300000000ULL, 0,
+					 RTDM_TIMERMODE_RELATIVE);
+			return 0;
+		}
+		if (ctx->close_counter > 2) {
+			printk(KERN_ERR
+			       "rtdmtest: %s: close_counter is %lu, "
+			       "should be 2!\n",
+			       __FUNCTION__, ctx->close_counter);
+			return 0;
+		}
+		break;
+	}
+
+	rtdm_timer_destroy(&ctx->close_timer);
+
+	return 0;
+}
+
+static int rtdm_test_ioctl(struct rtdm_dev_context *context,
+			   rtdm_user_info_t *user_info,
+			   unsigned int request, void __user *arg)
+{
+	struct rtdm_test_context *ctx =
+		(struct rtdm_test_context *)context->dev_private;
+	int err = 0;
+
+	switch (request) {
+	case RTTST_RTIOC_RTDM_DEFER_CLOSE:
+		ctx->close_deferral = (unsigned long)arg;
+		break;
+
+	default:
+		err = -ENOTTY;
+	}
+
+	return err;
+}
+
+static struct rtdm_device device[2] = { [0 ... 1] = {
+	.struct_version		= RTDM_DEVICE_STRUCT_VER,
+
+	.device_flags		= RTDM_NAMED_DEVICE | RTDM_EXCLUSIVE,
+	.context_size		= sizeof(struct rtdm_test_context),
+	.device_name		= "",
+
+	.open_nrt		= rtdm_test_open,
+
+	.ops = {
+		.close_nrt	= rtdm_test_close,
+
+		.ioctl_rt	= rtdm_test_ioctl,
+		.ioctl_nrt	= rtdm_test_ioctl,
+	},
+
+	.device_class		= RTDM_CLASS_TESTING,
+	.device_sub_class	= RTDM_SUBCLASS_RTDMTEST,
+	.profile_version	= RTTST_PROFILE_VER,
+	.driver_name		= "xeno_rtdmtest",
+	.driver_version		= RTDM_DRIVER_VER(0, 1, 0),
+	.peripheral_name	= "RTDM unit test",
+	.provider_name		= "Jan Kiszka",
+} };
+
+static int __init __rtdm_test_init(void)
+{
+	int dev = 0;
+	int err;
+
+	while (1) {
+		device[dev].proc_name = device[dev].device_name;
+
+		snprintf(device[dev].device_name, RTDM_MAX_DEVNAME_LEN,
+			 "rttest-rtdm%d",
+			 start_index);
+		err = rtdm_dev_register(&device[dev]);
+
+		start_index++;
+
+		if (!err) {
+			if (++dev >= ARRAY_SIZE(device))
+				break;
+		} else if (err != -EEXIST) {
+			while (dev > 0) {
+				dev--;
+				rtdm_dev_unregister(&device[dev], 1000);
+			}
+			return err;
+		}
+	}
+	return 0;
+}
+
+static void __exit __rtdm_test_exit(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(device); i++)
+		rtdm_dev_unregister(&device[i], 1000);
+}
+
+module_init(__rtdm_test_init);
+module_exit(__rtdm_test_exit);
diff --git a/src/testsuite/unit/Makefile.am b/src/testsuite/unit/Makefile.am
index 8966883..f37ec33 100644
--- a/src/testsuite/unit/Makefile.am
+++ b/src/testsuite/unit/Makefile.am
@@ -10,7 +10,8 @@ test_PROGRAMS = \
 	mutex-torture-native \
 	cond-torture-posix \
 	cond-torture-native \
-	check-vdso
+	check-vdso \
+	rtdm
 
 arith_SOURCES = arith.c arith-noinline.c arith-noinline.h
 
@@ -105,6 +106,20 @@ check_vdso_LDADD = \
 	../../skins/common/libxenomai.la \
 	-lpthread -lm
 
+rtdm_SOURCES = rtdm.c
+
+rtdm_CPPFLAGS = \
+	-I$(top_srcdir)/include/posix @XENO_USER_CFLAGS@ -g -DXENO_POSIX \
+	-I$(top_srcdir)/include
+
+rtdm_LDFLAGS = $(XENO_POSIX_WRAPPERS) @XENO_USER_LDFLAGS@
+
+rtdm_LDADD = \
+	../../skins/posix/libpthread_rt.la \
+	../../skins/native/libnative.la \
+	../../skins/common/libxenomai.la \
+	-lpthread -lrt -lm
+
 install-data-local:
 	$(mkinstalldirs) $(DESTDIR)$(rundir)
 	@sed -e's,@exec_prefix\@,$(exec_prefix),g' $(srcdir)/runinfo.in > $(DESTDIR)$(rundir)/.runinfo
diff --git a/src/testsuite/unit/rtdm.c b/src/testsuite/unit/rtdm.c
new file mode 100644
index 0000000..e472c9b
--- /dev/null
+++ b/src/testsuite/unit/rtdm.c
@@ -0,0 +1,114 @@
+/*
+ * Functional testing of RTDM services.
+ *
+ * Copyright (C) 2010 Jan Kiszka <jan.kiszka@domain.hid>.
+ *
+ * Released under the terms of GPLv2.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <native/timer.h>
+#include <rtdm/rttesting.h>
+
+#define NS_PER_MS (1000000)
+
+static void check_inner(const char *fn, int line, const char *msg,
+			int status, int expected)
+{
+	if (status == expected)
+		return;
+
+	fprintf(stderr, "FAILED %s:%d: %s returned %d instead of %d - %s\n",
+		fn, line, msg, status, expected, strerror(-status));
+	exit(EXIT_FAILURE);
+}
+
+#define check(msg, status, expected) ({					\
+	int __status = status;						\
+	check_inner(__FUNCTION__, __LINE__, msg,			\
+		    __status < 0 ? -errno : __status, expected);	\
+	__status;							\
+})
+
+#define check_no_error(msg, status) ({					\
+	int __status = status;						\
+	check_inner(__FUNCTION__, __LINE__, msg,			\
+		    __status < 0 ? -errno : 0, 0);			\
+	__status;							\
+})
+
+static void check_sleep_inner(const char *fn, int line,
+			      const char *msg, unsigned long long start)
+{
+	unsigned long long diff = rt_timer_tsc2ns(rt_timer_tsc() - start);
+
+	if (diff < 300 * NS_PER_MS) {
+		fprintf(stderr, "FAILED %s:%d: %s waited only %Ld.%06u ms\n",
+			fn, line, msg, diff / 1000000,
+			(unsigned)(diff % 1000000));
+		exit(EXIT_FAILURE);
+	}
+}
+#define check_sleep(msg, start) \
+	check_sleep_inner(__FUNCTION__, __LINE__, msg, start)
+
+static const char *devname = "/dev/rttest-rtdm0";
+static const char *devname2 = "/dev/rttest-rtdm1";
+
+int main(int argc, const char *argv[])
+{
+	unsigned long long start;
+	int dev, dev2;
+
+	printf("Setup\n");
+	check("modprobe", system("modprobe xeno_rtdmtest"), 0);
+	dev = check_no_error("open", open(devname, O_RDWR));
+
+	printf("Exclusive open\n");
+	check("open", open(devname, O_RDWR), -EBUSY);
+
+	printf("Successive open\n");
+	dev2 = check("open", open(devname2, O_RDWR), dev + 1);
+	check("close", close(dev2), 0);
+
+	printf("Defer close by driver handler\n");
+	check("ioctl", ioctl(dev, RTTST_RTIOC_RTDM_DEFER_CLOSE,
+			     RTTST_RTDM_DEFER_CLOSE_HANDLER), 0);
+	start = rt_timer_tsc();
+	check("close", close(dev), 0);
+	check("open", open(devname, O_RDWR), -EBUSY);
+	dev2 = check("open", open(devname2, O_RDWR), dev);
+	check("close", close(dev2), 0);
+	usleep(300000);
+	dev = check("open", open(devname, O_RDWR), dev);
+
+	printf("Defer close by pending reference\n");
+	check("ioctl", ioctl(dev, RTTST_RTIOC_RTDM_DEFER_CLOSE,
+			     RTTST_RTDM_DEFER_CLOSE_CONTEXT), 0);
+	start = rt_timer_tsc();
+	check("close", close(dev), 0);
+	check("open", open(devname, O_RDWR), -EBUSY);
+	dev2 = check("open", open(devname2, O_RDWR), dev);
+	check("close", close(dev2), 0);
+	usleep(300000);
+	dev = check("open", open(devname, O_RDWR), dev);
+
+	printf("Normal close\n");
+	check("ioctl", ioctl(dev, RTTST_RTIOC_RTDM_DEFER_CLOSE,
+			     RTTST_RTDM_NORMAL_CLOSE), 0);
+	check("close", close(dev), 0);
+	dev = check("open", open(devname, O_RDWR), dev);
+
+	printf("Deferred module unload\n");
+	check("ioctl", ioctl(dev, RTTST_RTIOC_RTDM_DEFER_CLOSE,
+			     RTTST_RTDM_DEFER_CLOSE_CONTEXT), 0);
+	start = rt_timer_tsc();
+	check("close", close(dev), 0);
+	check("rmmod", system("rmmod xeno_rtdmtest"), 0);
+	check_sleep("rmmod", start);
+
+	return 0;
+}
-- 
1.6.0.2



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

* [Xenomai-core] [PATCH v4 25/25] RTDM: Use non-atomic bitops for used_fildes
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
                   ` (23 preceding siblings ...)
  2010-04-19 10:29 ` [Xenomai-core] [PATCH v4 24/25] RTDM: Add basic unit test Jan Kiszka
@ 2010-04-19 10:29 ` Jan Kiszka
  2010-04-19 16:19 ` [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Gilles Chanteperdrix
  25 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 10:29 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

All bit manipulations happen under rt_fildes_lock, so there is no need
for atomic ops.

Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 ksrc/skins/rtdm/core.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/ksrc/skins/rtdm/core.c b/ksrc/skins/rtdm/core.c
index bf905df..11102e2 100644
--- a/ksrc/skins/rtdm/core.c
+++ b/ksrc/skins/rtdm/core.c
@@ -125,7 +125,7 @@ static int create_instance(struct rtdm_device *device,
 	}
 
 	fd = find_first_zero_bit(used_fildes, RTDM_FD_MAX);
-	set_bit(fd, used_fildes);
+	__set_bit(fd, used_fildes);
 	open_fildes++;
 
 	xnlock_put_irqrestore(&rt_fildes_lock, s);
@@ -175,7 +175,7 @@ static int create_instance(struct rtdm_device *device,
 
 static void __cleanup_fildes(struct rtdm_fildes *fildes)
 {
-	clear_bit((fildes - fildes_table), used_fildes);
+	__clear_bit((fildes - fildes_table), used_fildes);
 	fildes->context = NULL;
 	open_fildes--;
 }
-- 
1.6.0.2



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

* Re: [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks
  2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
                   ` (24 preceding siblings ...)
  2010-04-19 10:29 ` [Xenomai-core] [PATCH v4 25/25] RTDM: Use non-atomic bitops for used_fildes Jan Kiszka
@ 2010-04-19 16:19 ` Gilles Chanteperdrix
  2010-04-19 16:46   ` Jan Kiszka
  25 siblings, 1 reply; 33+ messages in thread
From: Gilles Chanteperdrix @ 2010-04-19 16:19 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai-core

Jan Kiszka wrote:
> The following changes since commit 2bed24477882dd7937d59f4e33a0811981c7362c:
>   Gilles Chanteperdrix (1):
>         arm: declare the VFP inline asm snippets as volatile.
> 
> are available in the git repository at:
> 
>   git://git.xenomai.org/xenomai-jki.git for-upstream

Ok, seems this merge broke the build test:
http://sisyphus.hd.free.fr/~gilles/bx/

Could you please have a look?

-- 
					    Gilles.


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

* Re: [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks
  2010-04-19 16:19 ` [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Gilles Chanteperdrix
@ 2010-04-19 16:46   ` Jan Kiszka
  2010-04-19 16:53     ` Gilles Chanteperdrix
  0 siblings, 1 reply; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 16:46 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

Gilles Chanteperdrix wrote:
> Jan Kiszka wrote:
>> The following changes since commit 2bed24477882dd7937d59f4e33a0811981c7362c:
>>   Gilles Chanteperdrix (1):
>>         arm: declare the VFP inline asm snippets as volatile.
>>
>> are available in the git repository at:
>>
>>   git://git.xenomai.org/xenomai-jki.git for-upstream
> 
> Ok, seems this merge broke the build test:
> http://sisyphus.hd.free.fr/~gilles/bx/
> 
> Could you please have a look?

The section mismatch should be resolved in my queue.

Regarding the other bug:

In file included from ./2.4.25-DENX-ppc_6xx-gcc-3.3.3/include/linux/workqueue.h:14,
                 from core.c:29:
./2.4.25-DENX-ppc_6xx-gcc-3.3.3/include/linux/tqueue.h: In function `queue_task':
./2.4.25-DENX-ppc_6xx-gcc-3.3.3/include/linux/tqueue.h:105: warning: implicit declaration of function `barrier'
core.c: In function `close_callback':
core.c:257: warning: implicit declaration of function `schedule_delayed_work'

Does that kernel come with a linux/workqueue.h? What does it include?
That's a custom patch, isn't it?

Jan

-- 
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux


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

* Re: [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks
  2010-04-19 16:46   ` Jan Kiszka
@ 2010-04-19 16:53     ` Gilles Chanteperdrix
  2010-04-19 17:04       ` Jan Kiszka
  0 siblings, 1 reply; 33+ messages in thread
From: Gilles Chanteperdrix @ 2010-04-19 16:53 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai-core

Jan Kiszka wrote:
> Gilles Chanteperdrix wrote:
>> Jan Kiszka wrote:
>>> The following changes since commit 2bed24477882dd7937d59f4e33a0811981c7362c:
>>>   Gilles Chanteperdrix (1):
>>>         arm: declare the VFP inline asm snippets as volatile.
>>>
>>> are available in the git repository at:
>>>
>>>   git://git.xenomai.org/xenomai-jki.git for-upstream
>> Ok, seems this merge broke the build test:
>> http://sisyphus.hd.free.fr/~gilles/bx/
>>
>> Could you please have a look?
> 
> The section mismatch should be resolved in my queue.
> 
> Regarding the other bug:
> 
> In file included from ./2.4.25-DENX-ppc_6xx-gcc-3.3.3/include/linux/workqueue.h:14,
>                  from core.c:29:
> ./2.4.25-DENX-ppc_6xx-gcc-3.3.3/include/linux/tqueue.h: In function `queue_task':
> ./2.4.25-DENX-ppc_6xx-gcc-3.3.3/include/linux/tqueue.h:105: warning: implicit declaration of function `barrier'
> core.c: In function `close_callback':
> core.c:257: warning: implicit declaration of function `schedule_delayed_work'
> 
> Does that kernel come with a linux/workqueue.h? What does it include?

I guess either this kernel containes a workqueue.h or it gets it via the
compat directory.

> That's a custom patch, isn't it?

This kernel is generated as explained in the README:
git clone git://www.denx.de/git/linuxppc_2_4_devel
git checkout 5bab6d641ff5ba139f9f41869502cb7c96d785bc
patch -p1 < adeos-ipipe-2.4.25-ppc-DENX-2.2-01.patch

Nothing custom about it,

-- 
					    Gilles.


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

* Re: [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks
  2010-04-19 16:53     ` Gilles Chanteperdrix
@ 2010-04-19 17:04       ` Jan Kiszka
  0 siblings, 0 replies; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 17:04 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

Gilles Chanteperdrix wrote:
> Jan Kiszka wrote:
>> Gilles Chanteperdrix wrote:
>>> Jan Kiszka wrote:
>>>> The following changes since commit 2bed24477882dd7937d59f4e33a0811981c7362c:
>>>>   Gilles Chanteperdrix (1):
>>>>         arm: declare the VFP inline asm snippets as volatile.
>>>>
>>>> are available in the git repository at:
>>>>
>>>>   git://git.xenomai.org/xenomai-jki.git for-upstream
>>> Ok, seems this merge broke the build test:
>>> http://sisyphus.hd.free.fr/~gilles/bx/
>>>
>>> Could you please have a look?
>> The section mismatch should be resolved in my queue.
>>
>> Regarding the other bug:
>>
>> In file included from ./2.4.25-DENX-ppc_6xx-gcc-3.3.3/include/linux/workqueue.h:14,
>>                  from core.c:29:
>> ./2.4.25-DENX-ppc_6xx-gcc-3.3.3/include/linux/tqueue.h: In function `queue_task':
>> ./2.4.25-DENX-ppc_6xx-gcc-3.3.3/include/linux/tqueue.h:105: warning: implicit declaration of function `barrier'
>> core.c: In function `close_callback':
>> core.c:257: warning: implicit declaration of function `schedule_delayed_work'
>>
>> Does that kernel come with a linux/workqueue.h? What does it include?
> 
> I guess either this kernel containes a workqueue.h or it gets it via the
> compat directory.

It has MTD compat workqueue under central include/linux/workqueue.h. I
tend to consider this a bug of that tree, but we can workaround it. See
for-upstream.

Jan

-- 
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux


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

* Re: [Xenomai-core] [PATCH v4 02/25] RTDM: Add rtdm_rt_capable() service
  2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 02/25] RTDM: Add rtdm_rt_capable() service Jan Kiszka
@ 2010-04-19 22:15   ` Philippe Gerum
  2010-04-19 23:43     ` Jan Kiszka
  0 siblings, 1 reply; 33+ messages in thread
From: Philippe Gerum @ 2010-04-19 22:15 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: Alexis Berlemont, xenomai-core

On Mon, 2010-04-19 at 12:28 +0200, Jan Kiszka wrote:
> This adds rtdm_rt_capable(), a function that can be used by drivers to
> detect callers that could issue a service request also from the
> (typically preferred) real-time context. If that is the case, the driver
> can trigger a restart of the request if the current context is not
> real-time.
> 
> CC: Philippe Gerum <rpm@xenomai.org>
> CC: Alexis Berlemont <berlemont.hauw@domain.hid>
> Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
> ---
>  include/rtdm/rtdm_driver.h |    6 ++++++
>  ksrc/skins/rtdm/drvlib.c   |   25 +++++++++++++++++++++++++
>  2 files changed, 31 insertions(+), 0 deletions(-)
> 
> diff --git a/include/rtdm/rtdm_driver.h b/include/rtdm/rtdm_driver.h
> index 0fc1496..d124157 100644
> --- a/include/rtdm/rtdm_driver.h
> +++ b/include/rtdm/rtdm_driver.h
> @@ -1296,6 +1296,12 @@ static inline int rtdm_in_rt_context(void)
>  {
>  	return (rthal_current_domain != rthal_root_domain);
>  }
> +
> +static inline int rtdm_rt_capable(void)
> +{
> +	return (!xnpod_root_p() || xnshadow_thread(current) != NULL);
> +}
> +

This patch still has fundamental flaw, the service would not work
correctly and would actually return the wrong value, in case it is used
deeply buried into some helper code, traversed by asynchronous Xenomai
contexts. At the very least, you should avoid this by binding that
service to a valid rtdm_dev_context, so that you know that it is called
from a context that is correct in the first place, where a
rtdm_dev_context reference is available.

I.e. 
static inline int rtdm_rt_capable(struct rtdm_dev_context *context), and
extract the information from that context structure. That would avoid a
lot of headaches down the road to your user base.

-- 
Philippe.




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

* Re: [Xenomai-core] [PATCH v4 02/25] RTDM: Add rtdm_rt_capable() service
  2010-04-19 22:15   ` Philippe Gerum
@ 2010-04-19 23:43     ` Jan Kiszka
  2010-04-20  8:19       ` Philippe Gerum
  0 siblings, 1 reply; 33+ messages in thread
From: Jan Kiszka @ 2010-04-19 23:43 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: Alexis Berlemont, xenomai-core

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

Philippe Gerum wrote:
> On Mon, 2010-04-19 at 12:28 +0200, Jan Kiszka wrote:
>> This adds rtdm_rt_capable(), a function that can be used by drivers to
>> detect callers that could issue a service request also from the
>> (typically preferred) real-time context. If that is the case, the driver
>> can trigger a restart of the request if the current context is not
>> real-time.
>>
>> CC: Philippe Gerum <rpm@xenomai.org>
>> CC: Alexis Berlemont <berlemont.hauw@domain.hid>
>> Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
>> ---
>>  include/rtdm/rtdm_driver.h |    6 ++++++
>>  ksrc/skins/rtdm/drvlib.c   |   25 +++++++++++++++++++++++++
>>  2 files changed, 31 insertions(+), 0 deletions(-)
>>
>> diff --git a/include/rtdm/rtdm_driver.h b/include/rtdm/rtdm_driver.h
>> index 0fc1496..d124157 100644
>> --- a/include/rtdm/rtdm_driver.h
>> +++ b/include/rtdm/rtdm_driver.h
>> @@ -1296,6 +1296,12 @@ static inline int rtdm_in_rt_context(void)
>>  {
>>  	return (rthal_current_domain != rthal_root_domain);
>>  }
>> +
>> +static inline int rtdm_rt_capable(void)
>> +{
>> +	return (!xnpod_root_p() || xnshadow_thread(current) != NULL);
>> +}
>> +
> 
> This patch still has fundamental flaw, the service would not work
> correctly and would actually return the wrong value, in case it is used
> deeply buried into some helper code, traversed by asynchronous Xenomai
> contexts.

Using it from that contexts would be the fundamental flaw. We can catch
this, though.

> At the very least, you should avoid this by binding that
> service to a valid rtdm_dev_context, so that you know that it is called
> from a context that is correct in the first place, where a
> rtdm_dev_context reference is available.
> 
> I.e. 
> static inline int rtdm_rt_capable(struct rtdm_dev_context *context), and
> extract the information from that context structure. That would avoid a
> lot of headaches down the road to your user base.

The context is not that helpful here.

But instead of using current, we can force the caller to pass the
user_info which is only available in helper context:

static inline int rtdm_rt_capable(rtdm_user_info_t *user_info)
{
	XENO_ASSERT(RTDM, !xnpod_asynch_p(), return 0;);

	return (!xnpod_root_p() ||
		(user_info && xnshadow_thread(user_info) != NULL));
}

Pushed a corresponding patch.

Jan


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

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

* Re: [Xenomai-core] [PATCH v4 02/25] RTDM: Add rtdm_rt_capable() service
  2010-04-19 23:43     ` Jan Kiszka
@ 2010-04-20  8:19       ` Philippe Gerum
  0 siblings, 0 replies; 33+ messages in thread
From: Philippe Gerum @ 2010-04-20  8:19 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: Alexis Berlemont, xenomai-core

On Tue, 2010-04-20 at 01:43 +0200, Jan Kiszka wrote:
> Philippe Gerum wrote:
> > On Mon, 2010-04-19 at 12:28 +0200, Jan Kiszka wrote:
> >> This adds rtdm_rt_capable(), a function that can be used by drivers to
> >> detect callers that could issue a service request also from the
> >> (typically preferred) real-time context. If that is the case, the driver
> >> can trigger a restart of the request if the current context is not
> >> real-time.
> >>
> >> CC: Philippe Gerum <rpm@xenomai.org>
> >> CC: Alexis Berlemont <berlemont.hauw@domain.hid>
> >> Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
> >> ---
> >>  include/rtdm/rtdm_driver.h |    6 ++++++
> >>  ksrc/skins/rtdm/drvlib.c   |   25 +++++++++++++++++++++++++
> >>  2 files changed, 31 insertions(+), 0 deletions(-)
> >>
> >> diff --git a/include/rtdm/rtdm_driver.h b/include/rtdm/rtdm_driver.h
> >> index 0fc1496..d124157 100644
> >> --- a/include/rtdm/rtdm_driver.h
> >> +++ b/include/rtdm/rtdm_driver.h
> >> @@ -1296,6 +1296,12 @@ static inline int rtdm_in_rt_context(void)
> >>  {
> >>  	return (rthal_current_domain != rthal_root_domain);
> >>  }
> >> +
> >> +static inline int rtdm_rt_capable(void)
> >> +{
> >> +	return (!xnpod_root_p() || xnshadow_thread(current) != NULL);
> >> +}
> >> +
> > 
> > This patch still has fundamental flaw, the service would not work
> > correctly and would actually return the wrong value, in case it is used
> > deeply buried into some helper code, traversed by asynchronous Xenomai
> > contexts.
> 
> Using it from that contexts would be the fundamental flaw. We can catch
> this, though.
> 

Sure, but this API is supposed to help people to deal with context
issues by providing unambiguous services.

> > At the very least, you should avoid this by binding that
> > service to a valid rtdm_dev_context, so that you know that it is called
> > from a context that is correct in the first place, where a
> > rtdm_dev_context reference is available.
> > 
> > I.e. 
> > static inline int rtdm_rt_capable(struct rtdm_dev_context *context), and
> > extract the information from that context structure. That would avoid a
> > lot of headaches down the road to your user base.
> 
> The context is not that helpful here.
> 
> But instead of using current, we can force the caller to pass the
> user_info which is only available in helper context:
> 
> static inline int rtdm_rt_capable(rtdm_user_info_t *user_info)
> {
> 	XENO_ASSERT(RTDM, !xnpod_asynch_p(), return 0;);
> 
> 	return (!xnpod_root_p() ||
> 		(user_info && xnshadow_thread(user_info) != NULL));
> }

This is now correct in a Xenomai context. Thanks.

> 
> Pushed a corresponding patch.
> 
> Jan
> 


-- 
Philippe.




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

end of thread, other threads:[~2010-04-20  8:19 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-04-19 10:28 [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Jan Kiszka
2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 01/25] RTDM: Fix potential NULL pointer dereference Jan Kiszka
2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 02/25] RTDM: Add rtdm_rt_capable() service Jan Kiszka
2010-04-19 22:15   ` Philippe Gerum
2010-04-19 23:43     ` Jan Kiszka
2010-04-20  8:19       ` Philippe Gerum
2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 03/25] RTDM: Bump API version and document changes Jan Kiszka
2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 04/25] Revert "rtdm: tag syscalls as conforming" Jan Kiszka
2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 05/25] RTDM: Deprecate open_rt, socket_rt, and close_rt Jan Kiszka
2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 06/25] RTIPC: Fix memory leak on failing socket creation Jan Kiszka
2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 07/25] RTIPC: Drop support for RT socket creation/deletion Jan Kiszka
2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 08/25] RTCAN: Drop support for socket creation/deletion in real-time Jan Kiszka
2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 09/25] 16550A: Drop support for device opening/closing " Jan Kiszka
2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 10/25] Analogy: Drop support for " Jan Kiszka
2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 11/25] RTDM: Instrument rtdm_context_lock/unlock to detect misuses Jan Kiszka
2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 12/25] RTDM: Add rtdm_context_put() Jan Kiszka
2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 13/25] Fix historic msleep wrapping Jan Kiszka
2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 14/25] irqbench: Fix x86-64 build Jan Kiszka
2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 15/25] irqbench: Refactor user space helpers Jan Kiszka
2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 16/25] irqbench: Auto-detect bases of port address and IRQ values Jan Kiszka
2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 17/25] rttest: Resolved test device conflicts via separate name spaces Jan Kiszka
2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 18/25] testing: Clean up Kconfig rules Jan Kiszka
2010-04-19 10:28 ` [Xenomai-core] [PATCH v4 19/25] RTIPC: Drop unused wrapper around close_lock_count Jan Kiszka
2010-04-19 10:29 ` [Xenomai-core] [PATCH v4 20/25] RTDM: Document device close procedure Jan Kiszka
2010-04-19 10:29 ` [Xenomai-core] [PATCH v4 21/25] Add list_first_entry wrapper for older kernels Jan Kiszka
2010-04-19 10:29 ` [Xenomai-core] [PATCH v4 22/25] Add legacy kernel support for delayed_work Jan Kiszka
2010-04-19 10:29 ` [Xenomai-core] [PATCH v4 23/25] RTDM: Early fd release with poll-free context reference tracking Jan Kiszka
2010-04-19 10:29 ` [Xenomai-core] [PATCH v4 24/25] RTDM: Add basic unit test Jan Kiszka
2010-04-19 10:29 ` [Xenomai-core] [PATCH v4 25/25] RTDM: Use non-atomic bitops for used_fildes Jan Kiszka
2010-04-19 16:19 ` [Xenomai-core] [PATCH v4 00/25] [git pull v4] RTDM fixes and reworks Gilles Chanteperdrix
2010-04-19 16:46   ` Jan Kiszka
2010-04-19 16:53     ` Gilles Chanteperdrix
2010-04-19 17:04       ` Jan Kiszka

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