[Xenomai-git] Jan Kiszka : RTDM: Early fd release with poll-free context reference tracking

2010-04-17 Thread GIT version control
Module: xenomai-jki
Branch: for-upstream
Commit: c628ba4a3dad4273e15591b8bc78f7629fe4658e
URL:
http://git.xenomai.org/?p=xenomai-jki.git;a=commit;h=c628ba4a3dad4273e15591b8bc78f7629fe4658e

Author: Jan Kiszka 
Date:   Tue Apr  6 17:03:30 2010 +0200

RTDM: Early fd release with poll-free context reference tracking

---

 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 bd8a9d0..c856568 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 
+#include 
 
 #include 
 #include 
@@ -35,7 +35,7 @@
 
 #include "rtdm/internal.h"
 
-#define CLOSURE_RETRY_PERIOD   100 /* ms */
+#define CLOSURE_RETRY_PERIOD_MS100
 
 #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->

[Xenomai-git] Jan Kiszka : RTDM: Early fd release with poll-free context reference tracking

2010-04-17 Thread GIT version control
Module: xenomai-jki
Branch: queues/proc
Commit: c628ba4a3dad4273e15591b8bc78f7629fe4658e
URL:
http://git.xenomai.org/?p=xenomai-jki.git;a=commit;h=c628ba4a3dad4273e15591b8bc78f7629fe4658e

Author: Jan Kiszka 
Date:   Tue Apr  6 17:03:30 2010 +0200

RTDM: Early fd release with poll-free context reference tracking

---

 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 bd8a9d0..c856568 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 
+#include 
 
 #include 
 #include 
@@ -35,7 +35,7 @@
 
 #include "rtdm/internal.h"
 
-#define CLOSURE_RETRY_PERIOD   100 /* ms */
+#define CLOSURE_RETRY_PERIOD_MS100
 
 #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->c

[Xenomai-git] Jan Kiszka : RTDM: Early fd release with poll-free context reference tracking

2010-04-17 Thread GIT version control
Module: xenomai-jki
Branch: for-upstream
Commit: 8ce08a6c18b08a9286a966c461dbefb5b07e942d
URL:
http://git.xenomai.org/?p=xenomai-jki.git;a=commit;h=8ce08a6c18b08a9286a966c461dbefb5b07e942d

Author: Jan Kiszka 
Date:   Tue Apr  6 17:03:30 2010 +0200

RTDM: Early fd release with poll-free context reference tracking

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.

Signed-off-by: Jan Kiszka 

---

 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 bd8a9d0..c856568 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 
+#include 
 
 #include 
 #include 
@@ -35,7 +35,7 @@
 
 #include "rtdm/internal.h"
 
-#define CLOSURE_RETRY_PERIOD   100 /* ms */
+#define CLOSURE_RETRY_PERIOD_MS100
 
 #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

[Xenomai-git] Jan Kiszka : RTDM: Early fd release with poll-free context reference tracking

2010-04-18 Thread GIT version control
Module: xenomai-jki
Branch: for-upstream
Commit: ef0950a3fd1a8df178c2cf683187895ec74c45b7
URL:
http://git.xenomai.org/?p=xenomai-jki.git;a=commit;h=ef0950a3fd1a8df178c2cf683187895ec74c45b7

Author: Jan Kiszka 
Date:   Tue Apr  6 17:03:30 2010 +0200

RTDM: Early fd release with poll-free context reference tracking

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 
Signed-off-by: Jan Kiszka 

---

 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 bd8a9d0..c856568 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 
+#include 
 
 #include 
 #include 
@@ -35,7 +35,7 @@
 
 #include "rtdm/internal.h"
 
-#define CLOSURE_RETRY_PERIOD   100 /* ms */
+#define CLOSURE_RETRY_PERIOD_MS100
 
 #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

[Xenomai-git] Jan Kiszka : RTDM: Early fd release with poll-free context reference tracking

2010-04-19 Thread GIT version control
Module: xenomai-jki
Branch: for-upstream
Commit: fbbeec611f8f5ed9a8e9652894b150a02ca62c7b
URL:
http://git.xenomai.org/?p=xenomai-jki.git;a=commit;h=fbbeec611f8f5ed9a8e9652894b150a02ca62c7b

Author: Jan Kiszka 
Date:   Tue Apr  6 17:03:30 2010 +0200

RTDM: Early fd release with poll-free context reference tracking

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 
Signed-off-by: Jan Kiszka 

---

 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 
+#include 
 
 #include 
 #include 
@@ -35,7 +35,7 @@
 
 #include "rtdm/internal.h"
 
-#define CLOSURE_RETRY_PERIOD   100 /* ms */
+#define CLOSURE_RETRY_PERIOD_MS100
 
 #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

[Xenomai-git] Jan Kiszka : RTDM: Early fd release with poll-free context reference tracking

2010-04-19 Thread GIT version control
Module: xenomai-2.5
Branch: master
Commit: fbbeec611f8f5ed9a8e9652894b150a02ca62c7b
URL:
http://git.xenomai.org/?p=xenomai-2.5.git;a=commit;h=fbbeec611f8f5ed9a8e9652894b150a02ca62c7b

Author: Jan Kiszka 
Date:   Tue Apr  6 17:03:30 2010 +0200

RTDM: Early fd release with poll-free context reference tracking

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 
Signed-off-by: Jan Kiszka 

---

 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 
+#include 
 
 #include 
 #include 
@@ -35,7 +35,7 @@
 
 #include "rtdm/internal.h"
 
-#define CLOSURE_RETRY_PERIOD   100 /* ms */
+#define CLOSURE_RETRY_PERIOD_MS100
 
 #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_