[Xenomai-git] Jan Kiszka : RTDM: Early fd release with poll-free context reference tracking
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
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
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
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
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
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_