Skip to contentSkip to conversation

Posix skin user-space mutexes, second take.

PATCH In review Gilles Chanteperdrix 3 participants 34 messages May 2, 2008 – May 20, 2008

lore
Share & tools
lore
#0 lore raw

cover Posix skin user-space mutexes, second take.

Hi,

here comes a second attempt of implementing user-space mutexes for the posix skin.

Only differences with the first implementation are explained in the following mails.

Thanks in advance for your review.

Signature · 1 line
					    Gilles.
#1 lore raw

PATCH 1/7 Support for non cached memory mappings

In addition to support for non cached memory mappings, this patch implements xnheap_init_mapped and xnheap_destroy_mapped in the !CONFIG_XENO_OPT_PERVASIVE case. This avoids a lot of #ifdefs for users of these functions without user-space support (posix skin shared memories, and the new semaphore heaps, heaps where is allocated the memory used for storing semaphores counters and mutexes owner fields).

---
 include/asm-generic/wrappers.h |   12 +++++---
 include/native/heap.h          |    1
 include/nucleus/heap.h         |    2 +
 ksrc/nucleus/heap.c            |   55 +++++++++++++++++++++++++++++++++++------
 ksrc/skins/native/heap.c       |    8 +++++
 5 files changed, 66 insertions(+), 12 deletions(-)
native/heap.h +1 -0
Index: include/native/heap.h
===================================================================
@@ -33,6 +33,7 @@
 #define H_MAPPABLE 0x200	/* Memory is mappable to user-space. */
 #define H_SINGLE   0x400	/* Manage as single-block area. */
 #define H_SHARED   (H_MAPPABLE|H_SINGLE) /* I.e. shared memory segment. */
+#define H_NONCACHED 0x800
 
 /** Structure containing heap-information useful to users.
  *
asm-generic/wrappers.h +8 -4
Index: include/asm-generic/wrappers.h
===================================================================
@@ -62,7 +62,7 @@ unsigned long __va_to_kva(unsigned long 
 
 #define wrap_remap_vm_page(vma,from,to) ({ \
     vma->vm_flags |= VM_RESERVED; \
-    remap_page_range(from,virt_to_phys((void *)__va_to_kva(to)),PAGE_SIZE,PAGE_SHARED); \
+    remap_page_range(from,virt_to_phys((void *)__va_to_kva(to)),PAGE_SIZE,vma->vm_page_prot); \
 })
 #define wrap_remap_io_page_range(vma,from,to,size,prot) ({ \
     vma->vm_flags |= VM_RESERVED; \
@@ -223,7 +223,7 @@ unsigned long __va_to_kva(unsigned long 
  * memory. Anyway, this legacy would only hit setups using pre-2.6.11
  * kernel revisions. */
 #define wrap_remap_vm_page(vma,from,to) \
-    remap_pfn_range(vma,from,virt_to_phys((void *)__va_to_kva(to)) >> PAGE_SHIFT,PAGE_SHIFT,PAGE_SHARED)
+    remap_pfn_range(vma,from,virt_to_phys((void *)__va_to_kva(to)) >> PAGE_SHIFT,PAGE_SHIFT,vma->vm_page_prot)
 #define wrap_remap_io_page_range(vma,from,to,size,prot)  ({		\
     (vma)->vm_page_prot = pgprot_noncached((vma)->vm_page_prot);	\
     /* Sets VM_RESERVED | VM_IO | VM_PFNMAP on the vma. */		\
@@ -236,7 +236,7 @@ unsigned long __va_to_kva(unsigned long 
 #else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) */
 #define wrap_remap_vm_page(vma,from,to) ({ \
     vma->vm_flags |= VM_RESERVED; \
-    remap_page_range(from,virt_to_phys((void *)__va_to_kva(to)),PAGE_SIZE,PAGE_SHARED); \
+    remap_page_range(from,virt_to_phys((void *)__va_to_kva(to)),PAGE_SIZE,vma->vm_page_prot); \
 })
 #define wrap_remap_io_page_range(vma,from,to,size,prot) ({	\
       vma->vm_flags |= VM_RESERVED;				\
@@ -248,7 +248,11 @@ unsigned long __va_to_kva(unsigned long 
     })
 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) */
 
-#define wrap_switch_mm(prev,next,task)	\
+#ifndef __GFP_BITS_SHIFT
+#define __GFP_BITS_SHIFT 20
+#endif
+
+#define wrap_switch_mm(prev,next,task)		\
     switch_mm(prev,next,task)
 #define wrap_enter_lazy_tlb(mm,task)	\
     enter_lazy_tlb(mm,task)
nucleus/heap.h +2 -0
Index: include/nucleus/heap.h
===================================================================
@@ -57,6 +57,8 @@
 #define XNHEAP_PCONT   1
 #define XNHEAP_PLIST   2
 
+#define XNHEAP_GFP_NONCACHED (1 << __GFP_BITS_SHIFT)
+
 typedef struct xnextent {
 
 	xnholder_t link;
skins/native/heap.c +7 -1
Index: ksrc/skins/native/heap.c
===================================================================
@@ -205,6 +205,10 @@ static void __heap_flush_private(xnheap_
  * operations with I/O devices. The physical address of the
  * heap can be obtained by a call to rt_heap_inquire().
  *
+ * - H_NONCACHED causes the heap not to be cached. This is necessary on
+ * platforms such as ARM to share a heap between kernel and user-space.
+ * Note that this flag is not compatible with the H_DMA flag.
+ *
  * @return 0 is returned upon success. Otherwise:
  *
  * - -EEXIST is returned if the @a name is already in use by some
@@ -260,7 +264,9 @@ int rt_heap_create(RT_HEAP *heap, const 
 
 		err = xnheap_init_mapped(&heap->heap_base,
 					 heapsize,
-					 (mode & H_DMA) ? GFP_DMA : 0);
+					 ((mode & H_DMA) ? GFP_DMA : 0)
+					 | ((mode & H_NONCACHED) ?
+					    XNHEAP_GFP_NONCACHED : 0));
 		if (err)
 			return err;
 
nucleus/heap.c +48 -7

90 lines not on this page · raw message

Signature · 1 line
					    Gilles.
#2 lore raw

PATCH 2/7 Define XNARCH_SHARED_HEAP_FLAGS

No comment.

---
 asm-arm/hal.h        |    7 ++++++-
 asm-generic/system.h |    6 ++++++
 2 files changed, 12 insertions(+), 1 deletion(-)
asm-generic/system.h +6 -0
Index: include/asm-generic/system.h
===================================================================
@@ -238,6 +238,12 @@ static inline int xnlock_dbg_release(xnl
 #define xnarch_logerr(fmt, args...)	printk(KERN_ERR XNARCH_PROMPT fmt, ##args)
 #define xnarch_printf(fmt, args...)	printk(KERN_INFO XNARCH_PROMPT fmt, ##args)
 
+#ifndef RTHAL_SHARED_HEAP_FLAGS
+#define XNARCH_SHARED_HEAP_FLAGS 0
+#else /* !RTHAL_SHARED_HEAP_FLAGS */
+#define XNARCH_SHARED_HEAP_FLAGS RTHAL_SHARED_HEAP_FLAGS
+#endif /* !RTHAL_SHARED_HEAP_FLAGS */
+
 typedef cpumask_t xnarch_cpumask_t;
 
 #ifdef CONFIG_SMP
asm-arm/hal.h +6 -1
Index: include/asm-arm/hal.h
===================================================================
@@ -108,10 +108,15 @@ static inline __attribute_const__ unsign
 #include <asm/processor.h>
 #include <asm/ipipe.h>
 #include <asm/mach/irq.h>
+#include <asm/cacheflush.h>
 
 #define RTHAL_TIMER_IRQ   __ipipe_mach_timerint
 
-#define RTHAL_SHARED_HEAP_FLAGS XNHEAP_GFP_NONCACHED
+#ifdef CONFIG_XENO_OPT_PERVASIVE
+#define RTHAL_SHARED_HEAP_FLAGS (cache_is_vivt() ? XNHEAP_GFP_NONCACHED : 0)
+#else /* !CONFIG_XENO_OPT_PERVASIVE */
+#define RTHAL_SHARED_HEAP_FLAGS 0
+#endif /* !CONFIG_XENO_OPT_PERVASIVE */
 
 #define rthal_grab_control()     do { } while(0)
 #define rthal_release_control()  do { } while(0)
Signature · 1 line
					    Gilles.
#3 lore raw

PATCH 3/7 Define more atomic operations in user-space

This patch now only implement the _get, _set and _cmpxchg operations for the new xnarch_atomic_intptr_t type. Since xnarch_atomic_t is now a long type, the atomic_long_t is no longer needed.

---
 Makefile.am |    2 +-
 atomic.h    |   24 ++++++++++++++++++++++++
 2 files changed, 25 insertions(+), 1 deletion(-)
asm-generic/atomic.h +24 -0
Index: include/asm-generic/atomic.h
===================================================================
@@ -0,0 +1,24 @@
+#ifndef _XENO_ASM_GENERIC_ATOMIC_H
+#define _XENO_ASM_GENERIC_ATOMIC_H
+
+typedef xnarch_atomic_t xnarch_atomic_intptr_t;
+
+static inline void *xnarch_atomic_intptr_get(xnarch_atomic_intptr_t *l)
+{
+        xnarch_atomic_t *v = (xnarch_atomic_t *)l;
+
+        return (void *)xnarch_atomic_get(v);
+}
+
+static inline void xnarch_atomic_intptr_set(xnarch_atomic_intptr_t *l, void *i)
+{
+        xnarch_atomic_t *v = (xnarch_atomic_t *)l;
+
+        xnarch_atomic_set(v, (long)i);
+}
+
+#define xnarch_atomic_intptr_cmpxchg(l, old, new) \
+        (void *)(xnarch_atomic_cmpxchg((xnarch_atomic_t *)(l), \
+				       (long)(old), (long)(new)))
+
+#endif /* _XENO_ASM_GENERIC_ATOMIC_H */
asm-generic/Makefile.am +1 -1
Index: include/asm-generic/Makefile.am
===================================================================
@@ -1,5 +1,5 @@
 includesubdir = $(includedir)/asm-generic
 
-includesub_HEADERS = arith.h features.h hal.h syscall.h system.h wrappers.h
+includesub_HEADERS = arith.h atomic.h features.h hal.h syscall.h system.h wrappers.h
 
 SUBDIRS = bits
Signature · 1 line
					    Gilles.
#4 lore raw

PATCH 4/7 Define ARM atomic operations in user-space

The include/asm-arm/atomic.h header now defines the xnarch_memory_barrier in addition to user-space atomic operations. The pxa3xx deserves a special treatment since it uses the ARMv6 memory barrier operation whereas being an ARMv5 for other operations, hence a special --enable-arm-mach=pxa3xx option in configure.in.

---
 configure.in             |   13 ++
 include/asm-arm/atomic.h |  238 +++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 222 insertions(+), 29 deletions(-)
configure.in +12 -1
Index: configure.in
===================================================================
@@ -166,6 +166,7 @@ if test $XENO_TARGET_ARCH = arm ; then
   CONFIX_XENO_ARM_EABI=
 
   unset CONFIG_XENO_ARM_SA1100
+  unset CONFIG_XENO_CPU_XSC3
   unset tsc_type
   unset CONFIG_XENO_ARM_HW_DIRECT_TSC
 
@@ -173,7 +174,7 @@ if test $XENO_TARGET_ARCH = arm ; then
   AC_ARG_ENABLE(arm-mach,
 	AS_HELP_STRING([--enable-arm-mach], [Select for which machine we are
 compiling. Valid machines are at91rm9200, at91sam926x, imx, imx21, integrator, 
-ixp4xx, pxa, s3c2410, sa1100.]),
+ixp4xx, pxa, pxa3xx, s3c2410, sa1100.]),
 	[case "$enableval" in
 	at91rm9200)   	arch=4
 	        	tsc_type=__XN_TSC_TYPE_FREERUNNING;;
@@ -193,6 +194,9 @@ ixp4xx, pxa, s3c2410, sa1100.]),
 	ixp4xx|pxa) 	arch=5
 	      		tsc_type=__XN_TSC_TYPE_FREERUNNING;;
 
+	pxa3xx)	        arch=xscale3
+			tsc_type=__XN_TSC_TYPE_FREERUNNING;;
+
 	s3c2410) 	arch=4
 			tsc_type=__XN_TSC_TYPE_DECREMENTER;;
 
@@ -218,6 +222,9 @@ ixp4xx, pxa, s3c2410, sa1100.]),
 		esac
 		CONFIG_XENO_ARM_ARCH="$enableval"
     	])
+  elif test $arch = xscale3; then
+	CONFIG_XENO_ARM_ARCH=5
+	CONFIG_XENO_CPU_XSC3=y
   else
 	CONFIG_XENO_ARM_ARCH=$arch
   fi
@@ -226,6 +233,9 @@ ixp4xx, pxa, s3c2410, sa1100.]),
   AC_MSG_CHECKING(for ARM SA1100 architecture)
   AC_MSG_RESULT(${CONFIG_XENO_ARM_SA1100:-no})
 
+  AC_MSG_CHECKING(for ARM Xscale3 architecture)
+  AC_MSG_RESULT(${CONFIG_XENO_CPU_XSC3:-no})
+
   AC_MSG_CHECKING(for TSC emulation in user-space.)
   if test $tsc_type; then
 	AC_ARG_ENABLE(arm-tsc,
@@ -527,6 +537,7 @@ test x$CONFIG_X86_TSC = xy && AC_DEFINE(
 test -n "$CONFIG_XENO_ARM_ARCH" && AC_DEFINE_UNQUOTED(CONFIG_XENO_ARM_ARCH,$CONFIG_XENO_ARM_ARCH,[config])
 
 test x$CONFIG_XENO_ARM_SA1100 = xy && AC_DEFINE(CONFIG_XENO_ARM_SA1100,1,[config])
+test x$CONFIG_XENO_CPU_XSC3 = xy && AC_DEFINE(CONFIG_XENO_CPU_XSC3,1,[config])
 test $CONFIG_XENO_ARM_HW_DIRECT_TSC && AC_DEFINE_UNQUOTED(CONFIG_XENO_ARM_HW_DIRECT_TSC,$CONFIG_XENO_ARM_HW_DIRECT_TSC,[config])
 test x$CONFIG_XENO_ARM_EABI = xy && AC_DEFINE(CONFIG_XENO_ARM_EABI,1,[config])
 
asm-arm/atomic.h +210 -28

352 lines not on this page · raw message

Signature · 1 line
					    Gilles.
#5 lore raw

PATCH 5/7 Define new syscalls for the system skin

The two syscalls defined in the posix skin now moved to the sys skin, they are used in user-space by include/asm-generic/bits/bind.h and the new header include/asm-generic/bits/current.h. The global and process-specific shared heaps are now part of this patch.

---
 include/asm-generic/bits/Makefile.am |    1
 include/asm-generic/bits/bind.h      |  121 +++++++++++++++++++++++++++++++++++
 include/asm-generic/bits/current.h   |   14 ++++
 include/asm-generic/syscall.h        |    2
 include/nucleus/Makefile.am          |    1
 include/nucleus/sys_ppd.h            |   37 ++++++++++
 include/posix/syscall.h              |    1
 ksrc/nucleus/Kconfig                 |   25 +++++++
 ksrc/nucleus/module.c                |   19 ++++-
 ksrc/nucleus/shadow.c                |  103 ++++++++++++++++++++++++++++-
 src/skins/posix/thread.c             |    4 +
 11 files changed, 323 insertions(+), 5 deletions(-)
asm-generic/syscall.h +2 -0
Index: include/asm-generic/syscall.h
===================================================================
@@ -30,6 +30,8 @@
 #define __xn_sys_info       4	/* xnshadow_get_info(muxid,&info) */
 #define __xn_sys_arch       5	/* r = xnarch_local_syscall(args) */
 #define __xn_sys_trace      6	/* r = xntrace_xxx(...) */
+#define __xn_sys_sem_heap   7
+#define __xn_sys_current    8
 
 #define XENOMAI_LINUX_DOMAIN  0
 #define XENOMAI_XENO_DOMAIN   1
nucleus/Kconfig +25 -0
Index: ksrc/nucleus/Kconfig
===================================================================
@@ -158,6 +158,31 @@ config XENO_OPT_SYS_STACKPOOLSZ
 	default 0
 endif	
 
+config XENO_OPT_SEM_HEAPSZ
+	int "Size of private semaphores heap (Kb)"
+	default 12
+	help
+
+	Xenomai implementation of user-space semaphores relies on heaps 
+	shared between kernel and user-space. This configuration entry
+	allow to set the size of the heap used for private semaphores.
+
+	Note that each semaphore will allocate 4 or 8 bytes of memory,
+	so, the default of 12 Kb allows creating many semaphores.
+
+config XENO_OPT_GLOBAL_SEM_HEAPSZ
+	int "Size of global semaphores heap (Kb)"
+	default 12
+	help
+
+	Xenomai implementation of user-space semaphores relies on heaps 
+	shared between kernel and user-space. This configuration entry
+	allow to set the size of the heap used for semaphores shared 
+	between several processes.
+
+	Note that each semaphore will allocate 4 or 8 bytes of memory,
+	so, the default of 12 Kb allows creating many semaphores.
+
 config XENO_OPT_STATS
 	bool "Statistics collection"
 	depends on PROC_FS
nucleus/module.c +17 -2
Index: ksrc/nucleus/module.c
===================================================================
@@ -28,6 +28,7 @@
 #include <nucleus/timer.h>
 #include <nucleus/heap.h>
 #include <nucleus/version.h>
+#include <nucleus/sys_ppd.h>
 #ifdef CONFIG_XENO_OPT_PIPE
 #include <nucleus/pipe.h>
 #endif /* CONFIG_XENO_OPT_PIPE */
@@ -50,6 +51,8 @@ u_long xnmod_sysheap_size;
 
 int xeno_nucleus_status = -EINVAL;
 
+struct xnsys_ppd __xnsys_global_ppd;
+
 void xnmod_alloc_glinks(xnqueue_t *freehq)
 {
 	xngholder_t *sholder, *eholder;
@@ -1156,6 +1159,14 @@ int __init __xeno_sys_init(void)
 	if (err)
 		goto fail;
 
+	err = xnheap_init_mapped(&__xnsys_global_ppd.sem_heap,
+				 CONFIG_XENO_OPT_GLOBAL_SEM_HEAPSZ * 1024,
+				 XNARCH_SHARED_HEAP_FLAGS ?:
+				 (CONFIG_XENO_OPT_GLOBAL_SEM_HEAPSZ <= 128
+				  ? GFP_USER : 0));
+	if (err)
+		goto cleanup_arch;
+	
 #ifdef __KERNEL__
 #ifdef CONFIG_PROC_FS
 	xnpod_init_proc();
@@ -1167,7 +1178,7 @@ int __init __xeno_sys_init(void)
 	err = xnpipe_mount();
 
 	if (err)
-		goto cleanup_arch;
+		goto cleanup_proc;
 #endif /* CONFIG_XENO_OPT_PIPE */
 
 #ifdef CONFIG_XENO_OPT_PERVASIVE
@@ -1207,7 +1218,7 @@ int __init __xeno_sys_init(void)
 #ifdef CONFIG_XENO_OPT_PIPE
 	xnpipe_umount();
 
-      cleanup_arch:
+      cleanup_proc:
 
 #endif /* CONFIG_XENO_OPT_PIPE */
 
@@ -1215,6 +1226,8 @@ int __init __xeno_sys_init(void)
 	xnpod_delete_proc();
 #endif /* CONFIG_PROC_FS */
 
+      cleanup_arch:
+
 	xnarch_exit();
 
 #endif /* __KERNEL__ */
@@ -1254,6 +1267,8 @@ void __exit __xeno_sys_exit(void)
 #endif /* CONFIG_XENO_OPT_PIPE */
 #endif /* __KERNEL__ */
 
+	xnheap_destroy_mapped(&__xnsys_global_ppd.sem_heap);
+
 	if (nkmsgbuf)
 		xnarch_free_host_mem(nkmsgbuf, XNPOD_FATAL_BUFSZ);
 
nucleus/shadow.c +100 -3

157 lines not on this page · raw message

posix/syscall.h +1 -0
Index: include/posix/syscall.h
===================================================================
@@ -46,6 +46,7 @@
 #define __pse51_mutex_lock            20
 #define __pse51_mutex_timedlock       21
 #define __pse51_mutex_trylock         22
+#define __pse51_check_init            __pse51_mutex_trylock
 #define __pse51_mutex_unlock          23
 #define __pse51_cond_init             24
 #define __pse51_cond_destroy          25
skins/posix/thread.c +4 -0
Index: src/skins/posix/thread.c
===================================================================
@@ -24,6 +24,7 @@
 #include <sys/types.h>
 #include <semaphore.h>
 #include <posix/syscall.h>
+#include <asm-generic/bits/current.h>
 
 extern int __pse51_muxid;
 
@@ -56,6 +57,7 @@ int __wrap_pthread_setschedparam(pthread
 
 	if (!err && promoted) {
 		old_sigharden_handler = signal(SIGHARDEN, &__pthread_sigharden_handler);
+		xeno_set_current();
 		if (policy != SCHED_OTHER)
 			XENOMAI_SYSCALL1(__xn_sys_migrate, XENOMAI_XENO_DOMAIN);
 	}
@@ -132,6 +134,8 @@ static void *__pthread_trampoline(void *
 	start = iargs->start;
 	cookie = iargs->arg;
 
+	xeno_set_current();
+
 	__real_sem_post(&iargs->sync);
 
 	if (!err) {
asm-generic/bits/current.h +14 -0
Index: include/asm-generic/bits/current.h
===================================================================
@@ -0,0 +1,14 @@
+#ifndef _XENO_ASM_GENERIC_CURRENT_H
+#define _XENO_ASM_GENERIC_CURRENT_H
+
+#include <pthread.h>
+
+extern pthread_key_t xeno_current_key;
+
+extern void xeno_set_current(void);
+
+static inline void *xeno_get_current(void)
+{
+	return pthread_getspecific(xeno_current_key);
+}
+#endif /* _XENO_ASM_GENERIC_CURRENT_H */
asm-generic/bits/Makefile.am +1 -0
Index: include/asm-generic/bits/Makefile.am
===================================================================
@@ -2,6 +2,7 @@ includesubdir = $(includedir)/asm-generi
 
 includesub_HEADERS = \
 	bind.h \
+	current.h \
 	heap.h \
 	intr.h \
 	mlock_alert.h \
nucleus/sys_ppd.h +37 -0
Index: include/nucleus/sys_ppd.h
===================================================================
@@ -0,0 +1,37 @@
+#ifndef _XENO_NUCLEUS_SYS_PPD_H
+#define _XENO_NUCLEUS_SYS_PPD_H
+
+#include <nucleus/ppd.h>
+#include <nucleus/heap.h>
+
+struct xnsys_ppd {
+	xnshadow_ppd_t ppd;
+	xnheap_t sem_heap;
+
+#define ppd2sys(addr) container_of(addr, struct xnsys_ppd, ppd)
+};
+
+extern struct xnsys_ppd __xnsys_global_ppd;
+
+#ifdef CONFIG_XENO_OPT_PERVASIVE
+
+static inline struct xnsys_ppd *xnsys_ppd_get(int global)
+{
+	xnshadow_ppd_t *ppd;
+
+	if (global || !(ppd = xnshadow_ppd_get(0)))
+		return &__xnsys_global_ppd;
+
+	return ppd2sys(ppd);
+}
+
+#else /* !CONFIG_XENO_OPT_PERVASIVE */
+
+static inline struct xnsys_ppd *xnsys_ppd_get(int global)
+{
+	return &__xnsys_global_ppd;
+}
+
+#endif /* !CONFIG_XENO_OPT_PERVASIVE */
+
+#endif /* _XENO_NUCLEUS_SYS_PPD_H */
nucleus/Makefile.am +1 -0
Index: include/nucleus/Makefile.am
===================================================================
@@ -20,6 +20,7 @@ includesub_HEADERS = \
 	stat.h \
 	synch.h \
 	system.h \
+	sys_ppd.h \
 	thread.h \
 	timebase.h \
 	timer.h \
asm-generic/bits/bind.h +121 -0

143 lines not on this page · raw message

Signature · 1 line
					    Gilles.
#6 lore raw

PATCH 6/7 Re-implementation of mutexes, kernel-space support.

No comment.

---
 include/posix/pthread.h    |   56 ++++----
 ksrc/skins/posix/cb_lock.h |   84 ++++++++++++
 ksrc/skins/posix/cond.c    |   41 ++++-
 ksrc/skins/posix/mutex.c   |  308 +++++++++++++++++++++++++++------------------
 ksrc/skins/posix/mutex.h   |  125 ++++++++++++++----
 ksrc/skins/posix/shm.c     |   40 -----
 ksrc/skins/posix/syscall.c |  300 ++++++++++++++++++++++++++++++++++++++++++-
 7 files changed, 725 insertions(+), 229 deletions(-)
skins/posix/shm.c +5 -35
Index: ksrc/skins/posix/shm.c
===================================================================
@@ -90,14 +90,6 @@ static void pse51_shm_init(pse51_shm_t *
 	appendq(&pse51_shmq, &shm->link);
 }
 
-#ifndef CONFIG_XENO_OPT_PERVASIVE
-static void pse51_free_heap_extent(xnheap_t *heap,
-				   void *extent, u_long size, void *cookie)
-{
-	xnarch_free_host_mem(extent, size);
-}
-#endif /* !CONFIG_XENO_OPT_PERVASIVE */
-
 /* Must be called nklock locked, irq off. */
 static void pse51_shm_destroy(pse51_shm_t * shm, int force)
 {
@@ -111,11 +103,7 @@ static void pse51_shm_destroy(pse51_shm_
 	if (shm->addr) {
 		xnheap_free(&shm->heapbase, shm->addr);
 
-#ifdef CONFIG_XENO_OPT_PERVASIVE
 		xnheap_destroy_mapped(&shm->heapbase);
-#else /* !CONFIG_XENO_OPT_PERVASIVE. */
-		xnheap_destroy(&shm->heapbase, &pse51_free_heap_extent, NULL);
-#endif /* !CONFIG_XENO_OPT_PERVASIVE. */
 
 		shm->addr = NULL;
 		shm->size = 0;
@@ -534,37 +522,19 @@ int ftruncate(int fd, off_t len)
 			memcpy(addr, shm->addr, size);
 
 			xnheap_free(&shm->heapbase, shm->addr);
-#ifdef CONFIG_XENO_OPT_PERVASIVE
 			xnheap_destroy_mapped(&shm->heapbase);
-#else /* !CONFIG_XENO_OPT_PERVASIVE. */
-			xnheap_destroy(&shm->heapbase, &pse51_free_heap_extent,
-				       NULL);
-#endif /* !CONFIG_XENO_OPT_PERVASIVE. */
 
 			shm->addr = NULL;
 			shm->size = 0;
 		}
 
 		if (len) {
-#ifdef CONFIG_XENO_OPT_PERVASIVE
-			int flags = len <= 128 * 1024 ? GFP_USER : 0;
-			err = -xnheap_init_mapped(&shm->heapbase, len, flags);
-#else /* !CONFIG_XENO_OPT_PERVASIVE. */
-			{
-				void *heapaddr = xnarch_alloc_host_mem(len);
-
-				if (heapaddr)
-					err =
-					    -xnheap_init(&shm->heapbase,
-							 heapaddr, len,
-							 XNCORE_PAGE_SIZE);
-				else
-					err = ENOMEM;
+			int flags = (XNARCH_SHARED_HEAP_FLAGS ?:
+				     len <= 128 * 1024 ? GFP_USER : 0);
 
-				if (err)
-					goto err_up;
-			}
-#endif /* !CONFIG_XENO_OPT_PERVASIVE. */
+			err = -xnheap_init_mapped(&shm->heapbase, len, flags);
+			if (err)
+				goto err_up;
 
 			shm->size = xnheap_max_contiguous(&shm->heapbase);
 			shm->addr = xnheap_alloc(&shm->heapbase, shm->size);
skins/posix/cb_lock.h +84 -0

84 lines not on this page · raw message

posix/pthread.h +33 -23

82 lines not on this page · raw message

skins/posix/mutex.h +96 -29

180 lines not on this page · raw message

skins/posix/mutex.c +188 -120

494 lines not on this page · raw message

skins/posix/cond.c +28 -13

91 lines not on this page · raw message

skins/posix/syscall.c +291 -9

379 lines not on this page · raw message

Signature · 1 line
					    Gilles.
#7 lore raw

PATCH 7/7 Re-implementation of mutexes, user-space support.

Since binding of the semaphore heaps is now made by xeno_skin_bind, there is much less modifications in src/skins/posix/init.c. However, I had to do something really ugly: since binding the semaphore heaps by xeno_skin_bind requires calls to open, ioctl, mmap, close and munmap, I redefined these symbols to be the __real_ variants before including bind.h.
Another solution would have been to use __open (which would not have been wrapped) instead of open in bind.h and rely on the fact that the posix skin wrapped syscalls fall back to the __real variants when called for non real-time file descriptors. I do not know however, if this solution would have been portable. In particular, does uclibc also defines __open ?

---
 Makefile.am |    2
 cond.c      |   21 ++++
 init.c      |   26 +++++
 mutex.c     |  265 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------
 4 files changed, 287 insertions(+), 27 deletions(-)
skins/posix/init.c +25 -1
Index: src/skins/posix/init.c
===================================================================
@@ -26,9 +26,23 @@
 #include <posix/posix.h>
 #include <posix/syscall.h>
 #include <rtdm/syscall.h>
-#include <asm-generic/bits/bind.h>
 #include <asm-generic/bits/mlock_alert.h>
 
+/* asm-generic/bits/bind.h uses the following functions, so we redefine them to
+   be the __real variants */
+#undef open
+#undef ioctl
+#undef mmap
+#undef close
+#undef munmap
+#define open __real_open
+#define ioctl __real_ioctl
+#define mmap __real_mmap
+#define close __real_close
+#define munmap __real_munmap
+
+#include <asm-generic/bits/bind.h>
+
 int __pse51_muxid = -1;
 int __rtdm_muxid = -1;
 int __rtdm_fd_start = INT_MAX;
@@ -91,5 +105,15 @@ void __init_posix_interface(void)
 			exit(EXIT_FAILURE);
 		}
 		fork_handler_registered = 1;
+
+		if (sizeof(struct __shadow_mutex) > sizeof(pthread_mutex_t)) {
+			fprintf(stderr, "sizeof(pthread_mutex_t): %d,"
+				" sizeof(shadow_mutex): %d\n",
+				sizeof(pthread_mutex_t),
+				sizeof(struct __shadow_mutex));
+			exit(EXIT_FAILURE);
+		}
+
 	}
 }
+
skins/posix/mutex.c +242 -23

318 lines not on this page · raw message

skins/posix/cond.c +18 -3
Index: src/skins/posix/cond.c
===================================================================
@@ -19,6 +19,7 @@
 #include <errno.h>
 #include <posix/syscall.h>
 #include <pthread.h>
+#include <posix/cb_lock.h>
 
 extern int __pse51_muxid;
 
@@ -95,7 +96,7 @@ static void __pthread_cond_cleanup(void 
 			  c->count);
 }
 
-int __wrap_pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex)
+int __wrap_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
 {
 	struct pse51_cond_cleanup_t c = {
 		.cond = (union __xeno_cond *)cond,
@@ -103,6 +104,9 @@ int __wrap_pthread_cond_wait(pthread_con
 	};
 	int err, oldtype;
 
+	if (cb_try_read_lock(&c.mutex->shadow_mutex.lock, s))
+		return EINVAL;
+
 	pthread_cleanup_push(&__pthread_cond_cleanup, &c);
 
 	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
@@ -118,11 +122,15 @@ int __wrap_pthread_cond_wait(pthread_con
 
 	pthread_cleanup_pop(0);
 
-	if (err)
+	if (err) {
+		cb_read_unlock(&c.mutex->shadow_mutex.lock, s);
 		return err;
+	}
 
 	__pthread_cond_cleanup(&c);
 
+	cb_read_unlock(&c.mutex->shadow_mutex.lock, s);
+
 	pthread_testcancel();
 
 	return 0;
@@ -138,6 +146,9 @@ int __wrap_pthread_cond_timedwait(pthrea
 	};
 	int err, oldtype;
 
+	if (cb_try_read_lock(&c.mutex->shadow_mutex.lock, s))
+		return EINVAL;
+
 	pthread_cleanup_push(&__pthread_cond_cleanup, &c);
 
 	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
@@ -153,11 +164,15 @@ int __wrap_pthread_cond_timedwait(pthrea
 
 	pthread_cleanup_pop(0);
 
-	if (err && err != ETIMEDOUT)
+	if (err && err != ETIMEDOUT) {
+		cb_read_unlock(&c.mutex->shadow_mutex.lock, s);		
 		return err;
+	}
 
 	__pthread_cond_cleanup(&c);
 
+	cb_read_unlock(&c.mutex->shadow_mutex.lock, s);
+
 	pthread_testcancel();
 
 	return err;
skins/posix/Makefile.am +2 -0
Index: src/skins/posix/Makefile.am
===================================================================
@@ -2,6 +2,8 @@ includedir = $(prefix)/include/posix
 
 lib_LTLIBRARIES = libpthread_rt.la
 
+CPPFLAGS+=-I$(top_srcdir)/ksrc/skins
+
 libpthread_rt_la_LDFLAGS = -version-info 1:0:0 -lpthread
 
 libpthread_rt_la_SOURCES = \
Signature · 1 line
					    Gilles.
#8 lore raw

Re: [Xenomai-core] [Patch 7/7] Re-implementation of mutexes, user-space support.

Quoted 5 lines · Gilles Chanteperdrix

Since binding of the semaphore heaps is now made by xeno_skin_bind, there is much less modifications in src/skins/posix/init.c. However, I had to do something really ugly: since binding the semaphore heaps by xeno_skin_bind requires calls to open, ioctl, mmap, close and munmap, I redefined these symbols to be the __real_ variants before including bind.h.

Is there any upside to do this instead of simply calling the __real_* placeholders, since we do already provide weak wrappers for those when the linker's wrapping magic is not invoked?

Quoted 472 lines

Another solution would have been to use __open (which would not have been wrapped) instead of open in bind.h and rely on the fact that the posix skin wrapped syscalls fall back to the __real variants when called for non real-time file descriptors. I do not know however, if this solution would have been portable. In particular, does uclibc also defines __open ?

---
 Makefile.am |    2
 cond.c      |   21 ++++
 init.c      |   26 +++++
 mutex.c     |  265 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------
 4 files changed, 287 insertions(+), 27 deletions(-)

Index: src/skins/posix/init.c
===================================================================

skins/posix/init.c +25 -1
@@ -26,9 +26,23 @@
 #include <posix/posix.h>
 #include <posix/syscall.h>
 #include <rtdm/syscall.h>
-#include <asm-generic/bits/bind.h>
 #include <asm-generic/bits/mlock_alert.h>
 
+/* asm-generic/bits/bind.h uses the following functions, so we redefine them to
+   be the __real variants */
+#undef open
+#undef ioctl
+#undef mmap
+#undef close
+#undef munmap
+#define open __real_open
+#define ioctl __real_ioctl
+#define mmap __real_mmap
+#define close __real_close
+#define munmap __real_munmap
+
+#include <asm-generic/bits/bind.h>
+
 int __pse51_muxid = -1;
 int __rtdm_muxid = -1;
 int __rtdm_fd_start = INT_MAX;
@@ -91,5 +105,15 @@ void __init_posix_interface(void)
 			exit(EXIT_FAILURE);
 		}
 		fork_handler_registered = 1;
+
+		if (sizeof(struct __shadow_mutex) > sizeof(pthread_mutex_t)) {
+			fprintf(stderr, "sizeof(pthread_mutex_t): %d,"
+				" sizeof(shadow_mutex): %d\n",
+				sizeof(pthread_mutex_t),
+				sizeof(struct __shadow_mutex));
+			exit(EXIT_FAILURE);
+		}
+
 	}
 }
+

Index: src/skins/posix/mutex.c
===================================================================

skins/posix/mutex.c +242 -23
@@ -17,10 +17,15 @@
  */
 
 #include <errno.h>
-#include <posix/syscall.h>
 #include <pthread.h>
+#include <posix/syscall.h>
+#include <posix/cb_lock.h>
+#include <asm-generic/bits/current.h>
+
+#define PSE51_MUTEX_MAGIC (0x86860303)
 
 extern int __pse51_muxid;
+extern unsigned long xeno_sem_heap[2];
 
 int __wrap_pthread_mutexattr_init(pthread_mutexattr_t *attr)
 {
@@ -73,66 +78,280 @@ int __wrap_pthread_mutexattr_setpshared(
 				  __pse51_mutexattr_setpshared, attr, pshared);
 }
 
-int __wrap_pthread_mutex_init(pthread_mutex_t * mutex,
-			      const pthread_mutexattr_t * attr)
+static xnarch_atomic_intptr_t *get_ownerp(struct __shadow_mutex *shadow)
+{
+	if (likely(!shadow->attr.pshared))
+		return shadow->owner;
+	
+	return (xnarch_atomic_intptr_t *) (xeno_sem_heap[1] + shadow->owner_offset);
+}
+
+int __wrap_pthread_mutex_init(pthread_mutex_t *mutex,
+			      const pthread_mutexattr_t *attr)
 {
 	union __xeno_mutex *_mutex = (union __xeno_mutex *)mutex;
+	struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
 	int err;
 
-	err = -XENOMAI_SKINCALL2(__pse51_muxid,
-				 __pse51_mutex_init,&_mutex->shadow_mutex,attr);
+#ifdef XNARCH_HAVE_US_ATOMIC_CMPXCHG
+	if (unlikely(cb_try_read_lock(&shadow->lock, s)))
+		goto checked;
+
+	err = -XENOMAI_SKINCALL2(__pse51_muxid,__pse51_check_init,shadow,attr);
+
+	if (err) {
+		cb_read_unlock(&shadow->lock, s);
+		return err;
+	}
+
+  checked:
+	cb_force_write_lock(&shadow->lock, s);
+#endif /* XNARCH_HAVE_US_ATOMIC_CMPXCHG */
+
+	err = -XENOMAI_SKINCALL2(__pse51_muxid,__pse51_mutex_init,shadow,attr);
+
+	if (!shadow->attr.pshared)
+		shadow->owner = (xnarch_atomic_intptr_t *)
+			(xeno_sem_heap[0] + shadow->owner_offset);
+	
+	cb_write_unlock(&shadow->lock, s);
+
 	return err;
 }
 
-int __wrap_pthread_mutex_destroy(pthread_mutex_t * mutex)
+int __wrap_pthread_mutex_destroy(pthread_mutex_t *mutex)
 {
 	union __xeno_mutex *_mutex = (union __xeno_mutex *)mutex;
+	struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
+	int err;
+
+	if (unlikely(cb_try_write_lock(&shadow->lock, s)))
+		return EINVAL;
 
-	return -XENOMAI_SKINCALL1(__pse51_muxid,
-				  __pse51_mutex_destroy, &_mutex->shadow_mutex);
+	err = -XENOMAI_SKINCALL1(__pse51_muxid, __pse51_mutex_destroy, shadow);
+
+	cb_write_unlock(&shadow->lock, s);
+
+	return err;
 }
 
-int __wrap_pthread_mutex_lock(pthread_mutex_t * mutex)
+int __wrap_pthread_mutex_lock(pthread_mutex_t *mutex)
 {
 	union __xeno_mutex *_mutex = (union __xeno_mutex *)mutex;
-	int err;
+	struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
+	xnthread_t *cur, *owner;
+	int err = 0;
+
+#ifdef XNARCH_HAVE_US_ATOMIC_CMPXCHG
+	cur = xeno_get_current();
+	if (!cur)
+		return EPERM;
+
+	if (unlikely(cb_try_read_lock(&shadow->lock, s)))
+		return EINVAL;
+
+	if (unlikely(shadow->magic != PSE51_MUTEX_MAGIC)) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	owner = xnarch_atomic_intptr_cmpxchg(get_ownerp(shadow), NULL, cur);
+	if (likely(!owner)) {
+		shadow->lockcnt = 1;
+		cb_read_unlock(&shadow->lock, s);
+		return 0;
+	}
+
+	if (clear_claimed(owner) == cur)
+		switch(shadow->attr.type) {
+		case PTHREAD_MUTEX_NORMAL:
+			break;
+
+		case PTHREAD_MUTEX_ERRORCHECK:
+			err = -EDEADLK;
+			goto out;
+
+		case PTHREAD_MUTEX_RECURSIVE:
+			if (shadow->lockcnt == UINT_MAX) {
+				err = -EAGAIN;
+				goto out;
+			}
+
+			++shadow->lockcnt;
+			goto out;
+		}
+#endif /* XNARCH_HAVE_US_ATOMIC_CMPXCHG */
 
 	do {
-		err = XENOMAI_SKINCALL1(__pse51_muxid,
-					__pse51_mutex_lock,
-					&_mutex->shadow_mutex);
+		err = XENOMAI_SKINCALL1(__pse51_muxid,__pse51_mutex_lock,shadow);
 	} while (err == -EINTR);
 
+#ifdef XNARCH_HAVE_US_ATOMIC_CMPXCHG
+  out:
+	cb_read_unlock(&shadow->lock, s);
+#endif /* XNARCH_HAVE_US_ATOMIC_CMPXCHG */
+
 	return -err;
 }
 
-int __wrap_pthread_mutex_timedlock(pthread_mutex_t * mutex,
+int __wrap_pthread_mutex_timedlock(pthread_mutex_t *mutex,
 				   const struct timespec *to)
 {
 	union __xeno_mutex *_mutex = (union __xeno_mutex *)mutex;
-	int err;
+	struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
+	xnthread_t *cur, *owner;
+	int err = 0;
+
+#ifdef XNARCH_HAVE_US_ATOMIC_CMPXCHG
+	cur = xeno_get_current();
+	if (!cur)
+		return EPERM;
+
+	if (unlikely(cb_try_read_lock(&shadow->lock, s)))
+		return EINVAL;
+
+	if (shadow->magic != PSE51_MUTEX_MAGIC) {
+		err = -EINVAL;
+		goto out;
+	}	
+
+	owner = xnarch_atomic_intptr_cmpxchg(get_ownerp(shadow), NULL, cur);
+	if (likely(!owner)) {
+		shadow->lockcnt = 1;
+		cb_read_unlock(&shadow->lock, s);
+		return 0;
+	}
+
+	if (clear_claimed(owner) == cur)
+		switch(shadow->attr.type) {
+		case PTHREAD_MUTEX_NORMAL:
+			break;
+
+		case PTHREAD_MUTEX_ERRORCHECK:
+			err = -EDEADLK;
+			goto out;
+
+		case PTHREAD_MUTEX_RECURSIVE:
+			if (shadow->lockcnt == UINT_MAX) {
+				err = -EAGAIN;
+				goto out;
+			}
+
+			++shadow->lockcnt;
+			goto out;
+		}
+#endif /* XNARCH_HAVE_US_ATOMIC_CMPXCHG */
 
 	do {
 		err = XENOMAI_SKINCALL2(__pse51_muxid,
-					__pse51_mutex_timedlock,
-					&_mutex->shadow_mutex, to);
+					__pse51_mutex_timedlock, shadow, to);
 	} while (err == -EINTR);
 
+#ifdef XNARCH_HAVE_US_ATOMIC_CMPXCHG
+  out:
+	cb_read_unlock(&shadow->lock, s);
+#endif /* XNARCH_HAVE_US_ATOMIC_CMPXCHG */
+
 	return -err;
 }
 
-int __wrap_pthread_mutex_trylock(pthread_mutex_t * mutex)
+int __wrap_pthread_mutex_trylock(pthread_mutex_t *mutex)
 {
 	union __xeno_mutex *_mutex = (union __xeno_mutex *)mutex;
+	struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
+	xnthread_t *cur, *owner;
+	int err = 0;
+
+#ifdef XNARCH_HAVE_US_ATOMIC_CMPXCHG
+	cur = xeno_get_current();
+	if (!cur)
+		return EPERM;
+
+	if (unlikely(cb_try_read_lock(&shadow->lock, s)))
+		return EINVAL;
+
+	if (unlikely(shadow->magic != PSE51_MUTEX_MAGIC)) {
+		err = -EINVAL;
+		goto out;
+	}	
+
+	owner = xnarch_atomic_intptr_cmpxchg(get_ownerp(shadow), NULL, cur);
+	if (likely(!owner)) {
+		shadow->lockcnt = 1;
+		cb_read_unlock(&shadow->lock, s);
+		return 0;
+	}
+
+	err = -EBUSY;
+	if (clear_claimed(owner) == cur
+	    && shadow->attr.type == PTHREAD_MUTEX_RECURSIVE) {
+		if (shadow->lockcnt == UINT_MAX)
+			err = -EAGAIN;
+		else {
+			++shadow->lockcnt;
+			err = 0;
+		}
+	}
+
+  out:
+	cb_read_unlock(&shadow->lock, s);
 
-	return -XENOMAI_SKINCALL1(__pse51_muxid,
-				  __pse51_mutex_trylock, &_mutex->shadow_mutex);
+	return -err;
+
+#else /* !XNARCH_HAVE_US_ATOMIC_CMPXCHG */
+
+	return -XENOMAI_SKINCALL1(__pse51_muxid, __pse51_mutex_trylock, shadow);
+
+#endif /* !XNARCH_HAVE_US_ATOMIC_CMPXCHG */
 }
 
-int __wrap_pthread_mutex_unlock(pthread_mutex_t * mutex)
+int __wrap_pthread_mutex_unlock(pthread_mutex_t *mutex)
 {
 	union __xeno_mutex *_mutex = (union __xeno_mutex *)mutex;
+	struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
 
-	return -XENOMAI_SKINCALL1(__pse51_muxid,
-				  __pse51_mutex_unlock, &_mutex->shadow_mutex);
+#ifdef XNARCH_HAVE_US_ATOMIC_CMPXCHG
+	xnarch_atomic_intptr_t *ownerp;
+	xnthread_t *cur;
+	int err = 0;
+
+	cur = xeno_get_current();
+	if (!cur)
+		return EPERM;
+
+	if (unlikely(cb_try_read_lock(&shadow->lock, s)))
+		return EINVAL;
+
+	if (unlikely(shadow->magic != PSE51_MUTEX_MAGIC)) {
+		err = -EINVAL;
+		goto out_err;
+	}
+
+	ownerp = get_ownerp(shadow);
+	if (unlikely(clear_claimed(xnarch_atomic_intptr_get(ownerp)) != cur)) {
+		err = -EPERM;
+		goto out_err;
+	}
+
+	err = 0;
+	if (shadow->lockcnt > 1) {
+		--shadow->lockcnt;
+		goto out;
+	}
+
+	if (likely(xnarch_atomic_intptr_cmpxchg(ownerp, cur, NULL) == cur)) {
+	  out:
+		cb_read_unlock(&shadow->lock, s);
+		return 0;
+	}
+#endif /* XNARCH_HAVE_US_ATOMIC_CMPXCHG */
+
+	err = XENOMAI_SKINCALL1(__pse51_muxid, __pse51_mutex_unlock, shadow);
+
+#ifdef XNARCH_HAVE_US_ATOMIC_CMPXCHG
+  out_err:
+	cb_read_unlock(&shadow->lock, s);
+#endif /* XNARCH_HAVE_US_ATOMIC_CMPXCHG */
+
+	return -err;
 }

Index: src/skins/posix/cond.c
===================================================================

skins/posix/cond.c +18 -3
@@ -19,6 +19,7 @@
 #include <errno.h>
 #include <posix/syscall.h>
 #include <pthread.h>
+#include <posix/cb_lock.h>
 
 extern int __pse51_muxid;
 
@@ -95,7 +96,7 @@ static void __pthread_cond_cleanup(void 
 			  c->count);
 }
 
-int __wrap_pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex)
+int __wrap_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
 {
 	struct pse51_cond_cleanup_t c = {
 		.cond = (union __xeno_cond *)cond,
@@ -103,6 +104,9 @@ int __wrap_pthread_cond_wait(pthread_con
 	};
 	int err, oldtype;
 
+	if (cb_try_read_lock(&c.mutex->shadow_mutex.lock, s))
+		return EINVAL;
+
 	pthread_cleanup_push(&__pthread_cond_cleanup, &c);
 
 	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
@@ -118,11 +122,15 @@ int __wrap_pthread_cond_wait(pthread_con
 
 	pthread_cleanup_pop(0);
 
-	if (err)
+	if (err) {
+		cb_read_unlock(&c.mutex->shadow_mutex.lock, s);
 		return err;
+	}
 
 	__pthread_cond_cleanup(&c);
 
+	cb_read_unlock(&c.mutex->shadow_mutex.lock, s);
+
 	pthread_testcancel();
 
 	return 0;
@@ -138,6 +146,9 @@ int __wrap_pthread_cond_timedwait(pthrea
 	};
 	int err, oldtype;
 
+	if (cb_try_read_lock(&c.mutex->shadow_mutex.lock, s))
+		return EINVAL;
+
 	pthread_cleanup_push(&__pthread_cond_cleanup, &c);
 
 	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
@@ -153,11 +164,15 @@ int __wrap_pthread_cond_timedwait(pthrea
 
 	pthread_cleanup_pop(0);
 
-	if (err && err != ETIMEDOUT)
+	if (err && err != ETIMEDOUT) {
+		cb_read_unlock(&c.mutex->shadow_mutex.lock, s);		
 		return err;
+	}
 
 	__pthread_cond_cleanup(&c);
 
+	cb_read_unlock(&c.mutex->shadow_mutex.lock, s);
+
 	pthread_testcancel();
 
 	return err;

Index: src/skins/posix/Makefile.am
===================================================================

skins/posix/Makefile.am +2 -0
@@ -2,6 +2,8 @@ includedir = $(prefix)/include/posix
 
 lib_LTLIBRARIES = libpthread_rt.la
 
+CPPFLAGS+=-I$(top_srcdir)/ksrc/skins
+
 libpthread_rt_la_LDFLAGS = -version-info 1:0:0 -lpthread
 
 libpthread_rt_la_SOURCES = \
Signature · 1 line
Philippe.
#9 lore raw

Re: [Xenomai-core] [Patch 7/7] Re-implementation of mutexes, user-space support.

Quoted 10 lines · Philippe Gerum
Quoted 5 lines · Gilles Chanteperdrix

Since binding of the semaphore heaps is now made by xeno_skin_bind, there is much less modifications in src/skins/posix/init.c. However, I had to do something really ugly: since binding the semaphore heaps by xeno_skin_bind requires calls to open, ioctl, mmap, close and munmap, I redefined these symbols to be the __real_ variants before including bind.h.

Is there any upside to do this instead of simply calling the __real_* placeholders, since we do already provide weak wrappers for those when the linker's wrapping magic is not invoked?

The point is that the wrappers and linker magic only take place for POSIX skins. Other skins have to call the genuine open, ioctl, mmap, close and munmap services.

Signature · 1 line
					    Gilles.
#10 lore raw

Re: [Xenomai-core] [Patch 7/7] Re-implementation of mutexes, user-space support.

Quoted 8 lines · Gilles Chanteperdrix
Quoted 7 lines · Philippe Gerum
Quoted 5 lines · Gilles Chanteperdrix

Since binding of the semaphore heaps is now made by xeno_skin_bind, there is much less modifications in src/skins/posix/init.c. However, I had to do something really ugly: since binding the semaphore heaps by xeno_skin_bind requires calls to open, ioctl, mmap, close and munmap, I redefined these symbols to be the __real_ variants before including bind.h.

Quoted 7 lines
Quoted 3 lines

Is there any upside to do this instead of simply calling the __real_* placeholders, since we do already provide weak wrappers for those when the linker's wrapping magic is not invoked?

The point is that the wrappers and linker magic only take place for POSIX skins. Other skins have to call the genuine open, ioctl, mmap, close and munmap services.

What about controlling the desired prefix for generic functions in bind.h via some #define that the caller has to/can set before including the header:

#define POSIX_PREFIX __real_
#include <asm-generic/bits/bind.h>

and there we would have:

POSIX_PREFIX##open(...);

Looks a bit cleaner to me.

Jan

#11 lore raw

Re: [Xenomai-core] [Patch 7/7] Re-implementation of mutexes, user-space support.

Quoted 21 lines · Jan Kiszka
Quoted 8 lines · Gilles Chanteperdrix
Quoted 7 lines · Philippe Gerum
Quoted 5 lines · Gilles Chanteperdrix

Since binding of the semaphore heaps is now made by xeno_skin_bind, there is much less modifications in src/skins/posix/init.c. However, I had to do something really ugly: since binding the semaphore heaps by xeno_skin_bind requires calls to open, ioctl, mmap, close and munmap, I redefined these symbols to be the __real_ variants before including bind.h.

Quoted 7 lines
Quoted 3 lines

Is there any upside to do this instead of simply calling the __real_* placeholders, since we do already provide weak wrappers for those when the linker's wrapping magic is not invoked?

The point is that the wrappers and linker magic only take place for POSIX skins. Other skins have to call the genuine open, ioctl, mmap, close and munmap services.

What about controlling the desired prefix for generic functions in bind.h via some #define that the caller has to/can set before including the header:

Quoted 8 lines

#define POSIX_PREFIX __real_
#include <asm-generic/bits/bind.h>

and there we would have:

POSIX_PREFIX##open(...);

Looks a bit cleaner to me.

Well, in this case we end up cluttering the code with the POSIX_PREFIX macro, even in the non posix case where no prefix is needed.

Signature · 1 line
					    Gilles.
#12 lore raw

Re: [Xenomai-core] [Patch 7/7] Re-implementation of mutexes, user-space support.

Quoted 25 lines · Gilles Chanteperdrix
Quoted 24 lines · Jan Kiszka
Quoted 8 lines · Gilles Chanteperdrix
Quoted 7 lines · Philippe Gerum
Quoted 5 lines · Gilles Chanteperdrix

Since binding of the semaphore heaps is now made by xeno_skin_bind, there is much less modifications in src/skins/posix/init.c. However, I had to do something really ugly: since binding the semaphore heaps by xeno_skin_bind requires calls to open, ioctl, mmap, close and munmap, I redefined these symbols to be the __real_ variants before including bind.h.

Quoted 7 lines
Quoted 3 lines

Is there any upside to do this instead of simply calling the __real_* placeholders, since we do already provide weak wrappers for those when the linker's wrapping magic is not invoked?

The point is that the wrappers and linker magic only take place for POSIX skins. Other skins have to call the genuine open, ioctl, mmap, close and munmap services.

What about controlling the desired prefix for generic functions in bind.h via some #define that the caller has to/can set before including the header:

#define POSIX_PREFIX __real_
#include <asm-generic/bits/bind.h>

Quoted 8 lines
Quoted 5 lines

and there we would have:

POSIX_PREFIX##open(...);

Looks a bit cleaner to me.

Well, in this case we end up cluttering the code with the POSIX_PREFIX macro, even in the non posix case where no prefix is needed.

Yes, but there are only few spots. The advantage of this strategy is that it is explicit in-place (ie. inside bind.h). That avoids potential collateral damage in the future when other services are added to that helper which shall not be wrapped.

Jan

#13 lore raw

Re: [Xenomai-core] [Patch 7/7] Re-implementation of mutexes, user-space support.

Quoted 32 lines · Jan Kiszka
Quoted 31 lines · Gilles Chanteperdrix
Quoted 29 lines · Jan Kiszka
Quoted 8 lines · Gilles Chanteperdrix
Quoted 7 lines · Philippe Gerum
Quoted 5 lines · Gilles Chanteperdrix

Since binding of the semaphore heaps is now made by xeno_skin_bind, there is much less modifications in src/skins/posix/init.c. However, I had to do something really ugly: since binding the semaphore heaps by xeno_skin_bind requires calls to open, ioctl, mmap, close and munmap, I redefined these symbols to be the __real_ variants before including bind.h.

Quoted 7 lines
Quoted 3 lines

Is there any upside to do this instead of simply calling the __real_* placeholders, since we do already provide weak wrappers for those when the linker's wrapping magic is not invoked?

The point is that the wrappers and linker magic only take place for POSIX skins. Other skins have to call the genuine open, ioctl, mmap, close and munmap services.

What about controlling the desired prefix for generic functions in bind.h via some #define that the caller has to/can set before including the header:

#define POSIX_PREFIX __real_
#include <asm-generic/bits/bind.h>

and there we would have:

POSIX_PREFIX##open(...);

Looks a bit cleaner to me.

Quoted 7 lines
Quoted 2 lines

Well, in this case we end up cluttering the code with the POSIX_PREFIX macro, even in the non posix case where no prefix is needed.

Yes, but there are only few spots. The advantage of this strategy is that it is explicit in-place (ie. inside bind.h). That avoids potential collateral damage in the future when other services are added to that helper which shall not be wrapped.

Actually, the only important call is open. Since once the file descriptor has been created with __real_open, all syscall wrappers will automatically fall back to the __real syscall variants.

Signature · 1 line
					    Gilles.
#14 lore raw

Re: [Xenomai-core] [Patch 7/7] Re-implementation of mutexes, user-space support.

Quoted 36 lines · Gilles Chanteperdrix
Quoted 35 lines · Jan Kiszka
Quoted 33 lines · Gilles Chanteperdrix
Quoted 21 lines · Jan Kiszka
Quoted 8 lines · Gilles Chanteperdrix
Quoted 7 lines · Philippe Gerum
Quoted 5 lines · Gilles Chanteperdrix

Since binding of the semaphore heaps is now made by xeno_skin_bind, there is much less modifications in src/skins/posix/init.c. However, I had to do something really ugly: since binding the semaphore heaps by xeno_skin_bind requires calls to open, ioctl, mmap, close and munmap, I redefined these symbols to be the __real_ variants before including bind.h.

Quoted 7 lines
Quoted 3 lines

Is there any upside to do this instead of simply calling the __real_* placeholders, since we do already provide weak wrappers for those when the linker's wrapping magic is not invoked?

The point is that the wrappers and linker magic only take place for POSIX skins. Other skins have to call the genuine open, ioctl, mmap, close and munmap services.

What about controlling the desired prefix for generic functions in bind.h via some #define that the caller has to/can set before including the header:

Quoted 8 lines

#define POSIX_PREFIX __real_
#include <asm-generic/bits/bind.h>

and there we would have:

POSIX_PREFIX##open(...);

Looks a bit cleaner to me.

Well, in this case we end up cluttering the code with the POSIX_PREFIX macro, even in the non posix case where no prefix is needed.

Quoted 9 lines
Quoted 4 lines

Yes, but there are only few spots. The advantage of this strategy is that it is explicit in-place (ie. inside bind.h). That avoids potential collateral damage in the future when other services are added to that helper which shall not be wrapped.

Actually, the only important call is open. Since once the file descriptor has been created with __real_open, all syscall wrappers will automatically fall back to the __real syscall variants.

Then let's just provide __real_open() as a weak symbol in all libs; that's less error-prone that fiddling with the preprocessor.

Signature · 1 line
Philippe.
#15 lore raw

Re: [Xenomai-core] [Patch 7/7] Re-implementation of mutexes, user-space support.

Quoted 42 lines · Philippe Gerum
Quoted 41 lines · Gilles Chanteperdrix
Quoted 39 lines · Jan Kiszka
Quoted 25 lines · Gilles Chanteperdrix
Quoted 24 lines · Jan Kiszka
Quoted 8 lines · Gilles Chanteperdrix
Quoted 7 lines · Philippe Gerum
Quoted 5 lines · Gilles Chanteperdrix

Since binding of the semaphore heaps is now made by xeno_skin_bind, there is much less modifications in src/skins/posix/init.c. However, I had to do something really ugly: since binding the semaphore heaps by xeno_skin_bind requires calls to open, ioctl, mmap, close and munmap, I redefined these symbols to be the __real_ variants before including bind.h.

Quoted 7 lines
Quoted 3 lines

Is there any upside to do this instead of simply calling the __real_* placeholders, since we do already provide weak wrappers for those when the linker's wrapping magic is not invoked?

The point is that the wrappers and linker magic only take place for POSIX skins. Other skins have to call the genuine open, ioctl, mmap, close and munmap services.

What about controlling the desired prefix for generic functions in bind.h via some #define that the caller has to/can set before including the header:

#define POSIX_PREFIX __real_
#include <asm-generic/bits/bind.h>

Quoted 8 lines
Quoted 5 lines

and there we would have:

POSIX_PREFIX##open(...);

Looks a bit cleaner to me.

Well, in this case we end up cluttering the code with the POSIX_PREFIX macro, even in the non posix case where no prefix is needed.

Yes, but there are only few spots. The advantage of this strategy is that it is explicit in-place (ie. inside bind.h). That avoids potential collateral damage in the future when other services are added to that helper which shall not be wrapped.

Quoted 7 lines
Quoted 4 lines

Actually, the only important call is open. Since once the file descriptor has been created with __real_open, all syscall wrappers will automatically fall back to the __real syscall variants.

Then let's just provide __real_open() as a weak symbol in all libs; that's less error-prone that fiddling with the preprocessor.

For now, I kept a solution based on the preprocessor. If I remember correctly, the __real stuff needs to be in a separate object, this means that we cannot put __real_open definition in bind.h, we have to generate an open_wrapper.lo object and link every library with this object. Is this really what we want ?

Signature · 1 line
					    Gilles.
#16 lore raw

Re: [Xenomai-core] [Patch 7/7] Re-implementation of mutexes, user-space support.

Quoted 48 lines · Gilles Chanteperdrix
Quoted 47 lines · Philippe Gerum
Quoted 45 lines · Gilles Chanteperdrix
Quoted 32 lines · Jan Kiszka
Quoted 31 lines · Gilles Chanteperdrix
Quoted 29 lines · Jan Kiszka
Quoted 8 lines · Gilles Chanteperdrix
Quoted 7 lines · Philippe Gerum
Quoted 5 lines · Gilles Chanteperdrix

Since binding of the semaphore heaps is now made by xeno_skin_bind, there is much less modifications in src/skins/posix/init.c. However, I had to do something really ugly: since binding the semaphore heaps by xeno_skin_bind requires calls to open, ioctl, mmap, close and munmap, I redefined these symbols to be the __real_ variants before including bind.h.

Quoted 7 lines
Quoted 3 lines

Is there any upside to do this instead of simply calling the __real_* placeholders, since we do already provide weak wrappers for those when the linker's wrapping magic is not invoked?

The point is that the wrappers and linker magic only take place for POSIX skins. Other skins have to call the genuine open, ioctl, mmap, close and munmap services.

What about controlling the desired prefix for generic functions in bind.h via some #define that the caller has to/can set before including the header:

#define POSIX_PREFIX __real_
#include <asm-generic/bits/bind.h>

and there we would have:

POSIX_PREFIX##open(...);

Looks a bit cleaner to me.

Quoted 7 lines
Quoted 2 lines

Well, in this case we end up cluttering the code with the POSIX_PREFIX macro, even in the non posix case where no prefix is needed.

Yes, but there are only few spots. The advantage of this strategy is that it is explicit in-place (ie. inside bind.h). That avoids potential collateral damage in the future when other services are added to that helper which shall not be wrapped.

Actually, the only important call is open. Since once the file descriptor has been created with __real_open, all syscall wrappers will automatically fall back to the __real syscall variants.

Quoted 9 lines
Quoted 2 lines

Then let's just provide __real_open() as a weak symbol in all libs; that's less error-prone that fiddling with the preprocessor.

For now, I kept a solution based on the preprocessor. If I remember correctly, the __real stuff needs to be in a separate object, this means that we cannot put __real_open definition in bind.h, we have to generate an open_wrapper.lo object and link every library with this object. Is this really what we want ?

bind.h is meant to be included exclusively from init.c files. So yes, as far as possible, we don't want to mess with the preprocessor.

Signature · 1 line
Philippe.
#17 lore raw

Re: [Xenomai-core] [Patch 7/7] Re-implementation of mutexes, user-space support.

Quoted 59 lines · Philippe Gerum
Quoted 48 lines · Gilles Chanteperdrix
Quoted 47 lines · Philippe Gerum
Quoted 45 lines · Gilles Chanteperdrix
Quoted 32 lines · Jan Kiszka
Quoted 31 lines · Gilles Chanteperdrix
Quoted 29 lines · Jan Kiszka
Quoted 8 lines · Gilles Chanteperdrix
Quoted 7 lines · Philippe Gerum
Quoted 5 lines · Gilles Chanteperdrix

Since binding of the semaphore heaps is now made by xeno_skin_bind, there is much less modifications in src/skins/posix/init.c. However, I had to do something really ugly: since binding the semaphore heaps by xeno_skin_bind requires calls to open, ioctl, mmap, close and munmap, I redefined these symbols to be the __real_ variants before including bind.h.

Quoted 7 lines
Quoted 3 lines

Is there any upside to do this instead of simply calling the __real_* placeholders, since we do already provide weak wrappers for those when the linker's wrapping magic is not invoked?

The point is that the wrappers and linker magic only take place for POSIX skins. Other skins have to call the genuine open, ioctl, mmap, close and munmap services.

What about controlling the desired prefix for generic functions in bind.h via some #define that the caller has to/can set before including the header:

#define POSIX_PREFIX __real_
#include <asm-generic/bits/bind.h>

and there we would have:

POSIX_PREFIX##open(...);

Looks a bit cleaner to me.

Quoted 7 lines
Quoted 2 lines

Well, in this case we end up cluttering the code with the POSIX_PREFIX macro, even in the non posix case where no prefix is needed.

Yes, but there are only few spots. The advantage of this strategy is that it is explicit in-place (ie. inside bind.h). That avoids potential collateral damage in the future when other services are added to that helper which shall not be wrapped.

Actually, the only important call is open. Since once the file descriptor has been created with __real_open, all syscall wrappers will automatically fall back to the __real syscall variants.

Quoted 9 lines
Quoted 2 lines

Then let's just provide __real_open() as a weak symbol in all libs; that's less error-prone that fiddling with the preprocessor.

For now, I kept a solution based on the preprocessor. If I remember correctly, the __real stuff needs to be in a separate object, this means that we cannot put __real_open definition in bind.h, we have to generate an open_wrapper.lo object and link every library with this object. Is this really what we want ?

Quoted 2 lines

bind.h is meant to be included exclusively from init.c files. So yes, as far as possible, we don't want to mess with the preprocessor.

Then better let the caller decide which version to call. A simple argument to xeno_bind_skin can be passed through to map_sem_heap and define there if open or __real_open is used. As the functions are inlined, we shouldn't see the other symbol after the compilation.

Jan

#18 lore raw

Re: [Xenomai-core] [Patch 7/7] Re-implementation of mutexes, user-space support.

Quoted 60 lines · Jan Kiszka
Quoted 59 lines · Philippe Gerum
Quoted 57 lines · Gilles Chanteperdrix
Quoted 42 lines · Philippe Gerum
Quoted 41 lines · Gilles Chanteperdrix
Quoted 39 lines · Jan Kiszka
Quoted 25 lines · Gilles Chanteperdrix
Quoted 24 lines · Jan Kiszka
Quoted 8 lines · Gilles Chanteperdrix
Quoted 7 lines · Philippe Gerum
Quoted 5 lines · Gilles Chanteperdrix

Since binding of the semaphore heaps is now made by xeno_skin_bind, there is much less modifications in src/skins/posix/init.c. However, I had to do something really ugly: since binding the semaphore heaps by xeno_skin_bind requires calls to open, ioctl, mmap, close and munmap, I redefined these symbols to be the __real_ variants before including bind.h.

Quoted 7 lines
Quoted 3 lines

Is there any upside to do this instead of simply calling the __real_* placeholders, since we do already provide weak wrappers for those when the linker's wrapping magic is not invoked?

The point is that the wrappers and linker magic only take place for POSIX skins. Other skins have to call the genuine open, ioctl, mmap, close and munmap services.

What about controlling the desired prefix for generic functions in bind.h via some #define that the caller has to/can set before including the header:

#define POSIX_PREFIX __real_
#include <asm-generic/bits/bind.h>

Quoted 8 lines
Quoted 5 lines

and there we would have:

POSIX_PREFIX##open(...);

Looks a bit cleaner to me.

Well, in this case we end up cluttering the code with the POSIX_PREFIX macro, even in the non posix case where no prefix is needed.

Yes, but there are only few spots. The advantage of this strategy is that it is explicit in-place (ie. inside bind.h). That avoids potential collateral damage in the future when other services are added to that helper which shall not be wrapped.

Quoted 7 lines
Quoted 4 lines

Actually, the only important call is open. Since once the file descriptor has been created with __real_open, all syscall wrappers will automatically fall back to the __real syscall variants.

Then let's just provide __real_open() as a weak symbol in all libs; that's less error-prone that fiddling with the preprocessor.

For now, I kept a solution based on the preprocessor. If I remember correctly, the __real stuff needs to be in a separate object, this means that we cannot put __real_open definition in bind.h, we have to generate an open_wrapper.lo object and link every library with this object. Is this really what we want ?

Quoted 7 lines
Quoted 2 lines

bind.h is meant to be included exclusively from init.c files. So yes, as far as possible, we don't want to mess with the preprocessor.

Then better let the caller decide which version to call. A simple argument to xeno_bind_skin can be passed through to map_sem_heap and define there if open or __real_open is used. As the functions are inlined, we shouldn't see the other symbol after the compilation.

Except the day when would compile without optimization... I will implement the open_wrapper.lo solution.

Signature · 1 line
 Gilles
#19 lore raw

Re: [Xenomai-core] [Patch 5/7] Define new syscalls for the system skin

In reply to Gilles Chanteperdrix
Quoted 5 lines · Gilles Chanteperdrix

The two syscalls defined in the posix skin now moved to the sys skin, they are used in user-space by include/asm-generic/bits/bind.h and the new header include/asm-generic/bits/current.h. The global and process-specific shared heaps are now part of this patch.

Is there any reason why the nucleus should not implement a full-fledged "RT futex" support, instead of a toolbox to build them? I'm concerned by skins reinventing their own wheel uselessly to get to the same point at the end of the day; e.g. cb_lock ops seem to me fairly generic when it comes to handling futexes, so I would move them upstream one level more.

In that respect, talking about "semaphore heaps" at nucleus level looks a bit of a misnomer: if we mostly bring a service to map non-cacheable memory to user-space, then we don't actually provide semaphore support.

Quoted 35 lines
---
 include/asm-generic/bits/Makefile.am |    1
 include/asm-generic/bits/bind.h      |  121 +++++++++++++++++++++++++++++++++++
 include/asm-generic/bits/current.h   |   14 ++++
 include/asm-generic/syscall.h        |    2
 include/nucleus/Makefile.am          |    1
 include/nucleus/sys_ppd.h            |   37 ++++++++++
 include/posix/syscall.h              |    1
 ksrc/nucleus/Kconfig                 |   25 +++++++
 ksrc/nucleus/module.c                |   19 ++++-
 ksrc/nucleus/shadow.c                |  103 ++++++++++++++++++++++++++++-
 src/skins/posix/thread.c             |    4 +
 11 files changed, 323 insertions(+), 5 deletions(-)

Index: include/asm-generic/syscall.h
===================================================================

asm-generic/syscall.h +2 -0
@@ -30,6 +30,8 @@
 #define __xn_sys_info       4	/* xnshadow_get_info(muxid,&info) */
 #define __xn_sys_arch       5	/* r = xnarch_local_syscall(args) */
 #define __xn_sys_trace      6	/* r = xntrace_xxx(...) */
+#define __xn_sys_sem_heap   7
+#define __xn_sys_current    8
 
 #define XENOMAI_LINUX_DOMAIN  0
 #define XENOMAI_XENO_DOMAIN   1

Index: ksrc/nucleus/Kconfig
===================================================================

nucleus/Kconfig +0 -0
@@ -158,6 +158,31 @@ config XENO_OPT_SYS_STACKPOOLSZ
 	default 0
 endif	
 

nucleus/Kconfig config XENO_OPT_SYS_STACKPOOLSZ · line 170

Quoted 10 lines
nucleus/Kconfig +10 -0
+config XENO_OPT_SEM_HEAPSZ
+	int "Size of private semaphores heap (Kb)"
+	default 12
+	help
+
+	Xenomai implementation of user-space semaphores relies on heaps 
+	shared between kernel and user-space. This configuration entry
+	allow to set the size of the heap used for private semaphores.
+
+	Note that each semaphore will allocate 4 or 8 bytes of memory,

It would be nice to tell the folks why such difference (32/64bit arch?)

Quoted 535 lines
nucleus/Kconfig +15 -0
+	so, the default of 12 Kb allows creating many semaphores.
+
+config XENO_OPT_GLOBAL_SEM_HEAPSZ
+	int "Size of global semaphores heap (Kb)"
+	default 12
+	help
+
+	Xenomai implementation of user-space semaphores relies on heaps 
+	shared between kernel and user-space. This configuration entry
+	allow to set the size of the heap used for semaphores shared 
+	between several processes.
+
+	Note that each semaphore will allocate 4 or 8 bytes of memory,
+	so, the default of 12 Kb allows creating many semaphores.
+
 config XENO_OPT_STATS
 	bool "Statistics collection"
 	depends on PROC_FS

Index: ksrc/nucleus/module.c
===================================================================

nucleus/module.c +17 -2
@@ -28,6 +28,7 @@
 #include <nucleus/timer.h>
 #include <nucleus/heap.h>
 #include <nucleus/version.h>
+#include <nucleus/sys_ppd.h>
 #ifdef CONFIG_XENO_OPT_PIPE
 #include <nucleus/pipe.h>
 #endif /* CONFIG_XENO_OPT_PIPE */
@@ -50,6 +51,8 @@ u_long xnmod_sysheap_size;
 
 int xeno_nucleus_status = -EINVAL;
 
+struct xnsys_ppd __xnsys_global_ppd;
+
 void xnmod_alloc_glinks(xnqueue_t *freehq)
 {
 	xngholder_t *sholder, *eholder;
@@ -1156,6 +1159,14 @@ int __init __xeno_sys_init(void)
 	if (err)
 		goto fail;
 
+	err = xnheap_init_mapped(&__xnsys_global_ppd.sem_heap,
+				 CONFIG_XENO_OPT_GLOBAL_SEM_HEAPSZ * 1024,
+				 XNARCH_SHARED_HEAP_FLAGS ?:
+				 (CONFIG_XENO_OPT_GLOBAL_SEM_HEAPSZ <= 128
+				  ? GFP_USER : 0));
+	if (err)
+		goto cleanup_arch;
+	
 #ifdef __KERNEL__
 #ifdef CONFIG_PROC_FS
 	xnpod_init_proc();
@@ -1167,7 +1178,7 @@ int __init __xeno_sys_init(void)
 	err = xnpipe_mount();
 
 	if (err)
-		goto cleanup_arch;
+		goto cleanup_proc;
 #endif /* CONFIG_XENO_OPT_PIPE */
 
 #ifdef CONFIG_XENO_OPT_PERVASIVE
@@ -1207,7 +1218,7 @@ int __init __xeno_sys_init(void)
 #ifdef CONFIG_XENO_OPT_PIPE
 	xnpipe_umount();
 
-      cleanup_arch:
+      cleanup_proc:
 
 #endif /* CONFIG_XENO_OPT_PIPE */
 
@@ -1215,6 +1226,8 @@ int __init __xeno_sys_init(void)
 	xnpod_delete_proc();
 #endif /* CONFIG_PROC_FS */
 
+      cleanup_arch:
+
 	xnarch_exit();
 
 #endif /* __KERNEL__ */
@@ -1254,6 +1267,8 @@ void __exit __xeno_sys_exit(void)
 #endif /* CONFIG_XENO_OPT_PIPE */
 #endif /* __KERNEL__ */
 
+	xnheap_destroy_mapped(&__xnsys_global_ppd.sem_heap);
+
 	if (nkmsgbuf)
 		xnarch_free_host_mem(nkmsgbuf, XNPOD_FATAL_BUFSZ);
 

Index: ksrc/nucleus/shadow.c
===================================================================

nucleus/shadow.c +100 -3
@@ -51,6 +51,7 @@
 #include <nucleus/ppd.h>
 #include <nucleus/trace.h>
 #include <nucleus/stat.h>
+#include <nucleus/sys_ppd.h>
 #include <asm/xenomai/features.h>
 #include <asm/xenomai/syscall.h>
 #include <asm/xenomai/bits/shadow.h>
@@ -1558,11 +1559,11 @@ static void stringify_feature_set(u_long
 
 static int xnshadow_sys_bind(struct pt_regs *regs)
 {
+	xnshadow_ppd_t *ppd = NULL, *sys_ppd = NULL;
 	unsigned magic = __xn_reg_arg1(regs);
 	u_long featdep = __xn_reg_arg2(regs);
 	u_long abirev = __xn_reg_arg3(regs);
 	u_long infarg = __xn_reg_arg4(regs);
-	xnshadow_ppd_t *ppd = NULL;
 	xnfeatinfo_t finfo;
 	u_long featmis;
 	int muxid, err;
@@ -1636,6 +1637,36 @@ static int xnshadow_sys_bind(struct pt_r
 	   earlier than that, do not refer to nkpod until the latter had a
 	   chance to call xnpod_init(). */
 
+	xnlock_get_irqsave(&nklock, s);
+	sys_ppd = ppd_lookup(0, current->mm);
+	xnlock_put_irqrestore(&nklock, s);
+
+	if (sys_ppd)
+		goto muxid_eventcb;
+
+	sys_ppd = (xnshadow_ppd_t *) muxtable[0].props->eventcb(XNSHADOW_CLIENT_ATTACH,
+								 current);
+
+	if (IS_ERR(sys_ppd)) {
+		err = PTR_ERR(sys_ppd);
+		goto fail;
+	}
+
+	if (!sys_ppd)
+		goto muxid_eventcb;
+
+
+	sys_ppd->key.muxid = 0;
+	sys_ppd->key.mm = current->mm;
+
+	if (ppd_insert(sys_ppd) == -EBUSY) {
+		/* In case of concurrent binding (which can not happen with
+		   Xenomai libraries), detach right away the second ppd. */
+		muxtable[0].props->eventcb(XNSHADOW_CLIENT_DETACH, sys_ppd);
+		sys_ppd = NULL;
+	}
+
+  muxid_eventcb:
 	if (!muxtable[muxid].props->eventcb)
 		goto eventcb_done;
 
@@ -1652,7 +1683,7 @@ static int xnshadow_sys_bind(struct pt_r
 
 	if (IS_ERR(ppd)) {
 		err = PTR_ERR(ppd);
-		goto fail;
+		goto fail_destroy_sys_ppd;
 	}
 
 	if (!ppd)
@@ -1689,6 +1720,11 @@ static int xnshadow_sys_bind(struct pt_r
 
 		err = -ENOSYS;
 
+	  fail_destroy_sys_ppd:
+		if (sys_ppd) {
+			ppd_remove(sys_ppd);
+			muxtable[0].props->eventcb(XNSHADOW_CLIENT_DETACH, sys_ppd);
+		}
 	      fail:
 		if (!xnarch_atomic_get(&muxtable[muxid].refcnt))
 			xnarch_atomic_dec(&muxtable[muxid].refcnt);
@@ -1856,6 +1892,32 @@ static int xnshadow_sys_trace(struct pt_
 	return err;
 }
 
+struct heap_info {
+	xnheap_t *addr;
+	unsigned size;
+};
+
+static int xnshadow_sys_sem_heap(struct pt_regs *regs)
+{
+	struct heap_info hinfo, __user *us_hinfo;
+	unsigned global;
+
+	global = __xn_reg_arg2(regs);
+	us_hinfo = (struct heap_info __user *) __xn_reg_arg1(regs);
+	hinfo.addr = &xnsys_ppd_get(global)->sem_heap;
+	hinfo.size = xnheap_extentsize(hinfo.addr);
+
+	return __xn_safe_copy_to_user(us_hinfo, &hinfo, sizeof(*us_hinfo));
+}
+
+static int xnshadow_sys_current(struct pt_regs *regs)
+{
+	xnthread_t * __user *us_current, *cur = xnshadow_thread(current);
+	us_current = (xnthread_t *__user *) __xn_reg_arg1(regs);
+
+	return __xn_safe_copy_to_user(us_current, &cur, sizeof(*us_current));
+}
+
 static xnsysent_t __systab[] = {
 	[__xn_sys_migrate] = {&xnshadow_sys_migrate, __xn_exec_current},
 	[__xn_sys_arch] = {&xnshadow_sys_arch, __xn_exec_any},
@@ -1864,15 +1926,50 @@ static xnsysent_t __systab[] = {
 	[__xn_sys_completion] = {&xnshadow_sys_completion, __xn_exec_lostage},
 	[__xn_sys_barrier] = {&xnshadow_sys_barrier, __xn_exec_lostage},
 	[__xn_sys_trace] = {&xnshadow_sys_trace, __xn_exec_any},
+	[__xn_sys_sem_heap] = {&xnshadow_sys_sem_heap, __xn_exec_any},
+	[__xn_sys_current] = {&xnshadow_sys_current, __xn_exec_any},
 };
 
+static void *xnshadow_sys_event(int event, void *data)
+{
+	struct xnsys_ppd *p;
+	int err;
+
+	switch(event) {
+	case XNSHADOW_CLIENT_ATTACH:
+		p = (struct xnsys_ppd *) xnarch_alloc_host_mem(sizeof(*p));
+		if (!p)
+			return ERR_PTR(-ENOMEM);
+
+		err = xnheap_init_mapped(&p->sem_heap,
+					 CONFIG_XENO_OPT_SEM_HEAPSZ * 1024,
+					 XNARCH_SHARED_HEAP_FLAGS ?:
+					 (CONFIG_XENO_OPT_SEM_HEAPSZ <= 128
+					  ? GFP_USER : 0));
+		if (err) {
+			xnarch_free_host_mem(p, sizeof(*p));
+			return ERR_PTR(err);
+		}
+
+		return &p->ppd;
+
+	case XNSHADOW_CLIENT_DETACH:
+		p = ppd2sys((xnshadow_ppd_t *) data);
+
+		xnheap_destroy_mapped(&p->sem_heap);
+
+		return NULL;
+	}
+
+	return ERR_PTR(-EINVAL);
+}
 
 static struct xnskin_props __props = {
 	.name = "sys",
 	.magic = 0x434F5245,
 	.nrcalls = sizeof(__systab) / sizeof(__systab[0]),
 	.systab = __systab,
-	.eventcb = NULL,
+	.eventcb = xnshadow_sys_event,
 	.timebasep = NULL,
 	.module = NULL
 };

Index: include/posix/syscall.h
===================================================================

posix/syscall.h +1 -0
@@ -46,6 +46,7 @@
 #define __pse51_mutex_lock            20
 #define __pse51_mutex_timedlock       21
 #define __pse51_mutex_trylock         22
+#define __pse51_check_init            __pse51_mutex_trylock
 #define __pse51_mutex_unlock          23
 #define __pse51_cond_init             24
 #define __pse51_cond_destroy          25

Index: src/skins/posix/thread.c
===================================================================

skins/posix/thread.c +4 -0
@@ -24,6 +24,7 @@
 #include <sys/types.h>
 #include <semaphore.h>
 #include <posix/syscall.h>
+#include <asm-generic/bits/current.h>
 
 extern int __pse51_muxid;
 
@@ -56,6 +57,7 @@ int __wrap_pthread_setschedparam(pthread
 
 	if (!err && promoted) {
 		old_sigharden_handler = signal(SIGHARDEN, &__pthread_sigharden_handler);
+		xeno_set_current();
 		if (policy != SCHED_OTHER)
 			XENOMAI_SYSCALL1(__xn_sys_migrate, XENOMAI_XENO_DOMAIN);
 	}
@@ -132,6 +134,8 @@ static void *__pthread_trampoline(void *
 	start = iargs->start;
 	cookie = iargs->arg;
 
+	xeno_set_current();
+
 	__real_sem_post(&iargs->sync);
 
 	if (!err) {

Index: include/asm-generic/bits/current.h
===================================================================

asm-generic/bits/current.h +14 -0
@@ -0,0 +1,14 @@
+#ifndef _XENO_ASM_GENERIC_CURRENT_H
+#define _XENO_ASM_GENERIC_CURRENT_H
+
+#include <pthread.h>
+
+extern pthread_key_t xeno_current_key;
+
+extern void xeno_set_current(void);
+
+static inline void *xeno_get_current(void)
+{
+	return pthread_getspecific(xeno_current_key);
+}
+#endif /* _XENO_ASM_GENERIC_CURRENT_H */

Index: include/asm-generic/bits/Makefile.am
===================================================================

asm-generic/bits/Makefile.am +1 -0
@@ -2,6 +2,7 @@ includesubdir = $(includedir)/asm-generi
 
 includesub_HEADERS = \
 	bind.h \
+	current.h \
 	heap.h \
 	intr.h \
 	mlock_alert.h \

Index: include/nucleus/sys_ppd.h
===================================================================

nucleus/sys_ppd.h +37 -0
@@ -0,0 +1,37 @@
+#ifndef _XENO_NUCLEUS_SYS_PPD_H
+#define _XENO_NUCLEUS_SYS_PPD_H
+
+#include <nucleus/ppd.h>
+#include <nucleus/heap.h>
+
+struct xnsys_ppd {
+	xnshadow_ppd_t ppd;
+	xnheap_t sem_heap;
+
+#define ppd2sys(addr) container_of(addr, struct xnsys_ppd, ppd)
+};
+
+extern struct xnsys_ppd __xnsys_global_ppd;
+
+#ifdef CONFIG_XENO_OPT_PERVASIVE
+
+static inline struct xnsys_ppd *xnsys_ppd_get(int global)
+{
+	xnshadow_ppd_t *ppd;
+
+	if (global || !(ppd = xnshadow_ppd_get(0)))
+		return &__xnsys_global_ppd;
+
+	return ppd2sys(ppd);
+}
+
+#else /* !CONFIG_XENO_OPT_PERVASIVE */
+
+static inline struct xnsys_ppd *xnsys_ppd_get(int global)
+{
+	return &__xnsys_global_ppd;
+}
+
+#endif /* !CONFIG_XENO_OPT_PERVASIVE */
+
+#endif /* _XENO_NUCLEUS_SYS_PPD_H */

Index: include/nucleus/Makefile.am
===================================================================

nucleus/Makefile.am +1 -0
@@ -20,6 +20,7 @@ includesub_HEADERS = \
 	stat.h \
 	synch.h \
 	system.h \
+	sys_ppd.h \
 	thread.h \
 	timebase.h \
 	timer.h \

Index: include/asm-generic/bits/bind.h
===================================================================

asm-generic/bits/bind.h +121 -0
@@ -6,10 +6,89 @@
 #include <string.h>
 #include <errno.h>
 #include <signal.h>
+#include <pthread.h>
+#include <sys/ioctl.h>
 #include <asm/xenomai/syscall.h>
 
+__attribute__ ((weak))
+pthread_key_t xeno_current_key;
+__attribute__ ((weak))
+pthread_once_t xeno_init_current_key_once = PTHREAD_ONCE_INIT;
+
+__attribute__ ((weak))
+void xeno_set_current(void)
+{
+	void *kthread_cb;
+	XENOMAI_SYSCALL1(__xn_sys_current, &kthread_cb);
+	pthread_setspecific(xeno_current_key, kthread_cb);
+}
+
+static void init_current_key(void)
+{
+	int err = pthread_key_create(&xeno_current_key, NULL);
+	if (err) {
+		fprintf(stderr, "Xenomai: error creating TSD key: %s\n",
+			strerror(err));
+		exit(1);
+	}
+}
+
+__attribute__ ((weak))
+unsigned long xeno_sem_heap[2] = { 0, 0 };
+
 void xeno_handle_mlock_alert(int sig);
 
+static void *map_sem_heap(unsigned shared)
+{
+	struct heap_info {
+		void *addr;
+		unsigned size;
+	} hinfo;
+	int fd, err;
+
+	fd = open("/dev/rtheap", O_RDWR, 0);
+	if (fd < 0) {
+		fprintf(stderr, "Xenomai: open: %m\n");
+		return MAP_FAILED;
+	}
+
+	err = XENOMAI_SYSCALL2(__xn_sys_sem_heap, &hinfo, shared);
+	if (err < 0) {
+		fprintf(stderr, "Xenomai: sys_sem_heap: %m\n");
+		return MAP_FAILED;
+	}
+
+	err = ioctl(fd, 0, hinfo.addr);
+	if (err < 0) {
+		fprintf(stderr, "Xenomai: ioctl: %m\n");
+		return MAP_FAILED;
+	}
+
+	hinfo.addr = mmap(NULL, hinfo.size,
+			  PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+	close(fd);
+
+	return hinfo.addr;
+}
+
+static void unmap_sem_heap(unsigned long heap_addr, unsigned shared)
+{
+	struct heap_info {
+		void *addr;
+		unsigned size;
+	} hinfo;
+	int err;
+
+	err = XENOMAI_SYSCALL2(__xn_sys_sem_heap, &hinfo, shared);
+	if (err < 0) {
+		fprintf(stderr, "Xenomai: sys_sem_heap: %m\n");
+		return;
+	}
+
+	munmap((void *) heap_addr, hinfo.size);
+}
+
+
 static inline int
 xeno_bind_skin(unsigned skin_magic, const char *skin, const char *module)
 {
@@ -62,6 +141,27 @@ xeno_bind_skin(unsigned skin_magic, cons
 	sa.sa_flags = 0;
 	sigaction(SIGXCPU, &sa, NULL);
 
+	pthread_once(&xeno_init_current_key_once, &init_current_key);
+
+	/* In case we forked, we need to map the new local semaphore heap */
+	if (xeno_sem_heap[0])
+		unmap_sem_heap(xeno_sem_heap[0], 0);
+	xeno_sem_heap[0] = (unsigned long) map_sem_heap(0);
+	if (xeno_sem_heap[0] == (unsigned long) MAP_FAILED) {
+		perror("Xenomai: mmap(local sem heap)");
+		exit(EXIT_FAILURE);
+	}
+
+	/* Even if we forked the global semaphore heap did not change, no need
+	  to map it anew */
+	if (!xeno_sem_heap[1]) {
+		xeno_sem_heap[1] = (unsigned long) map_sem_heap(1);
+		if (xeno_sem_heap[1] == (unsigned long) MAP_FAILED) {
+			perror("Xenomai: mmap(global sem heap)");
+			exit(EXIT_FAILURE);
+		}
+	}
+
 	return muxid;
 }
 
@@ -105,6 +205,27 @@ xeno_bind_skin_opt(unsigned skin_magic, 
 	xeno_arch_features_check();
 #endif /* xeno_arch_features_check */
 
+	pthread_once(&xeno_init_current_key_once, &init_current_key);
+
+	/* In case we forked, we need to map the new local semaphore heap */
+	if (xeno_sem_heap[0])
+		unmap_sem_heap(xeno_sem_heap[0], 0);
+	xeno_sem_heap[0] = (unsigned long) map_sem_heap(0);
+	if (xeno_sem_heap[0] == (unsigned long) MAP_FAILED) {
+		perror("Xenomai: mmap(local sem heap)");
+		exit(EXIT_FAILURE);
+	}
+
+	/* Even if we forked the global semaphore heap did not change, no need
+	  to map it anew */
+	if (!xeno_sem_heap[1]) {
+		xeno_sem_heap[1] = (unsigned long) map_sem_heap(1);
+		if (xeno_sem_heap[1] == (unsigned long) MAP_FAILED) {
+			perror("Xenomai: mmap(global sem heap)");
+			exit(EXIT_FAILURE);
+		}
+	}
+
 	return muxid;
 }
 
Signature · 1 line
Philippe.
#20 lore raw

Re: [Xenomai-core] [Patch 5/7] Define new syscalls for the system skin

Quoted 7 lines · Philippe Gerum
Quoted 5 lines · Gilles Chanteperdrix

The two syscalls defined in the posix skin now moved to the sys skin, they are used in user-space by include/asm-generic/bits/bind.h and the new header include/asm-generic/bits/current.h. The global and process-specific shared heaps are now part of this patch.

Quoted 6 lines

Is there any reason why the nucleus should not implement a full-fledged "RT futex" support, instead of a toolbox to build them? I'm concerned by skins reinventing their own wheel uselessly to get to the same point at the end of the day; e.g. cb_lock ops seem to me fairly generic when it comes to handling futexes, so I would move them upstream one level more.

First of all, because I do not know much what a futex is, but from my point of view it has very much to do with making threads wait in kernel-space for a user-space change. By using kernel/user shared heaps, we seem to be far from these considerations.

Now for the implementation of user-space mutexes per-se, apart from the xnarch_atomic_ operations, I think every skin will have its own tradeoffs. For instance, the "cb_lock" thing is itself a tradeoff, it sacrifices a bit of performance by making a mutex lock operation use three atomic operations instead of only one for the sake of safely getting a correct value of the mapped memory pointer. Besides, it works well with the posix skin, because the posix specification allows pthread_mutex_destroy to return an error if a mutex is currently in use. Currently, the native skin mutex destruction operation is successful even if the mutex is currently in use (the owner does not get any notification, simply its unlock operation will fail, and waiters receive an -EIDRM error). So, I would guess the native skin will have to use something else than cb_lock.

Quoted 3 lines

In that respect, talking about "semaphore heaps" at nucleus level looks a bit of a misnomer: if we mostly bring a service to map non-cacheable memory to user-space, then we don't actually provide semaphore support.

It was only a name making clear to the user what the heaps will be used for... I imagine people having to configure yet another heap size in kernel configuration and wondering what this heap will be used for.

Signature · 1 line
					    Gilles.
#21 lore raw

Re: [Xenomai-core] [Patch 5/7] Define new syscalls for the system skin

In reply to Philippe Gerum
Quoted 13 lines · Philippe Gerum
Quoted 5 lines · Gilles Chanteperdrix

The two syscalls defined in the posix skin now moved to the sys skin, they are used in user-space by include/asm-generic/bits/bind.h and the new header include/asm-generic/bits/current.h. The global and process-specific shared heaps are now part of this patch.

Is there any reason why the nucleus should not implement a full-fledged "RT futex" support, instead of a toolbox to build them? I'm concerned by skins reinventing their own wheel uselessly to get to the same point at the end of the day; e.g. cb_lock ops seem to me fairly generic when it comes to handling futexes, so I would move them upstream one level more.

Quoted 3 lines

In that respect, talking about "semaphore heaps" at nucleus level looks a bit of a misnomer: if we mostly bring a service to map non-cacheable memory to user-space, then we don't actually provide semaphore support.

If I understand correctly, a futex is, in xenomai terms, a way to associate a user-space address, with an xnsynch object. I feel this would complicate things: currently, the way I implemented user-space mutexes for the posix skin kept the old association between the user-space mutex, and its kernel-space companion, also used by kernel-space operations.

Signature · 1 line
					    Gilles.
#22 lore raw

Re: [Xenomai-core] [Patch 5/7] Define new syscalls for the system skin

Quoted 14 lines · Gilles Chanteperdrix
Quoted 13 lines · Philippe Gerum
Quoted 5 lines · Gilles Chanteperdrix

The two syscalls defined in the posix skin now moved to the sys skin, they are used in user-space by include/asm-generic/bits/bind.h and the new header include/asm-generic/bits/current.h. The global and process-specific shared heaps are now part of this patch.

Is there any reason why the nucleus should not implement a full-fledged "RT futex" support, instead of a toolbox to build them? I'm concerned by skins reinventing their own wheel uselessly to get to the same point at the end of the day; e.g. cb_lock ops seem to me fairly generic when it comes to handling futexes, so I would move them upstream one level more.

Quoted 6 lines
Quoted 3 lines

In that respect, talking about "semaphore heaps" at nucleus level looks a bit of a misnomer: if we mostly bring a service to map non-cacheable memory to user-space, then we don't actually provide semaphore support.

If I understand correctly, a futex is, in xenomai terms, a way to associate a user-space address, with an xnsynch object.

I would specialize it more actually so that it really resembles the vanilla futex support, i.e. a basic object implementing the required operations to provide mutually exclusive access, working on a pinned memory area shared between kernel and userland. AFAICS, the current patchset implements the pinned memory support in the nucleus, but not the operations, which remain a per-skin issue.

I feel this

Quoted 5 lines

would complicate things: currently, the way I implemented user-space mutexes for the posix skin kept the old association between the user-space mutex, and its kernel-space companion, also used by kernel-space operations.

My concern boils down to: how much of the POSIX implementation, beyond the cb_lock stuff, would have to be duplicated to get the same support ported to, say the VxWorks semM services?

Signature · 1 line
Philippe.
#23 lore raw

Re: [Xenomai-core] [Patch 5/7] Define new syscalls for the system skin

Quoted 22 lines · Philippe Gerum
Quoted 14 lines · Gilles Chanteperdrix
Quoted 13 lines · Philippe Gerum
Quoted 5 lines · Gilles Chanteperdrix

The two syscalls defined in the posix skin now moved to the sys skin, they are used in user-space by include/asm-generic/bits/bind.h and the new header include/asm-generic/bits/current.h. The global and process-specific shared heaps are now part of this patch.

Is there any reason why the nucleus should not implement a full-fledged "RT futex" support, instead of a toolbox to build them? I'm concerned by skins reinventing their own wheel uselessly to get to the same point at the end of the day; e.g. cb_lock ops seem to me fairly generic when it comes to handling futexes, so I would move them upstream one level more.

Quoted 6 lines
Quoted 3 lines

In that respect, talking about "semaphore heaps" at nucleus level looks a bit of a misnomer: if we mostly bring a service to map non-cacheable memory to user-space, then we don't actually provide semaphore support.

If I understand correctly, a futex is, in xenomai terms, a way to associate a user-space address, with an xnsynch object.

Quoted 6 lines

I would specialize it more actually so that it really resembles the vanilla futex support, i.e. a basic object implementing the required operations to provide mutually exclusive access, working on a pinned memory area shared between kernel and userland. AFAICS, the current patchset implements the pinned memory support in the nucleus, but not the operations, which remain a per-skin issue.

As far as I understood, the user-space atomic operations, used to acquire a free mutex in user-space, are not part of the futex API. In our case, we are using xnarch_atomic_* operations to implement portably this user-space locking stuff. I think that even setting the bit saying that the mutex is currently owned is done in pthread_mutexes implementation, not in the Futex API. Now, what remains is sys_futex(FUTEX_WAIT) and sys_futex(FUTEX_WAKE), this terribly looks like xnsync_sleep_on and xnsynch_wakeup_one_sleeper.

Quoted 11 lines

I feel this

Quoted 5 lines

would complicate things: currently, the way I implemented user-space mutexes for the posix skin kept the old association between the user-space mutex, and its kernel-space companion, also used by kernel-space operations.

My concern boils down to: how much of the POSIX implementation, beyond the cb_lock stuff, would have to be duplicated to get the same support ported to, say the VxWorks semM services?

The initialization code, and the additional calls to xnarch_atomic_cmpxchg in user-space. If xnarch_atomic_cmpxchg fails we call kernel-space, which is mostly unchanged.

Because of the cb_lock stuff, I also needed to implement the kernel-space syscalls in two versions: one if user-space has xnarch_atomic_cmpxchg and could lock the mutex control block, the other if the mutex control block needs to be locked by kernel-space.

Signature · 1 line
					    Gilles.
#24 lore raw

Re: [Xenomai-core] [Patch 5/7] Define new syscalls for the system skin

Quoted 30 lines · Gilles Chanteperdrix
Quoted 22 lines · Philippe Gerum
Quoted 14 lines · Gilles Chanteperdrix
Quoted 13 lines · Philippe Gerum
Quoted 5 lines · Gilles Chanteperdrix

The two syscalls defined in the posix skin now moved to the sys skin, they are used in user-space by include/asm-generic/bits/bind.h and the new header include/asm-generic/bits/current.h. The global and process-specific shared heaps are now part of this patch.

Is there any reason why the nucleus should not implement a full-fledged "RT futex" support, instead of a toolbox to build them? I'm concerned by skins reinventing their own wheel uselessly to get to the same point at the end of the day; e.g. cb_lock ops seem to me fairly generic when it comes to handling futexes, so I would move them upstream one level more.

Quoted 6 lines
Quoted 3 lines

In that respect, talking about "semaphore heaps" at nucleus level looks a bit of a misnomer: if we mostly bring a service to map non-cacheable memory to user-space, then we don't actually provide semaphore support.

If I understand correctly, a futex is, in xenomai terms, a way to associate a user-space address, with an xnsynch object.

Quoted 6 lines

I would specialize it more actually so that it really resembles the vanilla futex support, i.e. a basic object implementing the required operations to provide mutually exclusive access, working on a pinned memory area shared between kernel and userland. AFAICS, the current patchset implements the pinned memory support in the nucleus, but not the operations, which remain a per-skin issue.

Quoted 6 lines

As far as I understood, the user-space atomic operations, used to acquire a free mutex in user-space, are not part of the futex API. In our case, we are using xnarch_atomic_* operations to implement portably this user-space locking stuff. I think that even setting the bit saying that the mutex is currently owned is done in pthread_mutexes implementation, not in the Futex API.

I would fully agree if the futex API did not define PI-based ops, which are needed for proper real-time operations from userland. You will certainly agree that PI implies that some kind of ownership exists; and because there can't be more than a single owner in that case, you end up with an object that can't be held by more than a single task. So you do have a mutex in disguise, whatever the way to keep its state is (a bit, an integer, whatever). So there is stronger semantics attached to that API than to simply manage an event notification scheme.

Now, what remains is

Quoted 3 lines

sys_futex(FUTEX_WAIT) and sys_futex(FUTEX_WAKE), this terribly looks like xnsync_sleep_on and xnsynch_wakeup_one_sleeper.

Yes, here again I partially agree, except for a significant issue: xnsynch is a stateless object (that's why we can use it for different syncobjs which are totally unrelated in their semantics - mutex, queue, region, counting sems, whatever). I was just wondering if we could make the *tex thingy a bit more stateful to ease the job for the skins, just in case we would use it for mutexes only. I have no immediate answer to this question, just asking -- this is my contribution as a senior member of the peanut gallery.

Quoted 12 lines
Quoted 11 lines

I feel this

Quoted 5 lines

would complicate things: currently, the way I implemented user-space mutexes for the posix skin kept the old association between the user-space mutex, and its kernel-space companion, also used by kernel-space operations.

My concern boils down to: how much of the POSIX implementation, beyond the cb_lock stuff, would have to be duplicated to get the same support ported to, say the VxWorks semM services?

Quoted 9 lines

The initialization code, and the additional calls to xnarch_atomic_cmpxchg in user-space. If xnarch_atomic_cmpxchg fails we call kernel-space, which is mostly unchanged.

Because of the cb_lock stuff, I also needed to implement the kernel-space syscalls in two versions: one if user-space has xnarch_atomic_cmpxchg and could lock the mutex control block, the other if the mutex control block needs to be locked by kernel-space.

This is the part my laziness would very much like to factor as much as possible. If ever possible.

Signature · 1 line
Philippe.
#25 lore raw

Re: [Xenomai-core] [Patch 5/7] Define new syscalls for the system skin

Quoted 21 lines · Philippe Gerum
Quoted 6 lines · Gilles Chanteperdrix

As far as I understood, the user-space atomic operations, used to acquire a free mutex in user-space, are not part of the futex API. In our case, we are using xnarch_atomic_* operations to implement portably this user-space locking stuff. I think that even setting the bit saying that the mutex is currently owned is done in pthread_mutexes implementation, not in the Futex API.

I would fully agree if the futex API did not define PI-based ops, which are needed for proper real-time operations from userland. You will certainly agree that PI implies that some kind of ownership exists; and because there can't be more than a single owner in that case, you end up with an object that can't be held by more than a single task. So you do have a mutex in disguise, whatever the way to keep its state is (a bit, an integer, whatever). So there is stronger semantics attached to that API than to simply manage an event notification scheme.

Now, what remains is

Quoted 3 lines

sys_futex(FUTEX_WAIT) and sys_futex(FUTEX_WAKE), this terribly looks like xnsync_sleep_on and xnsynch_wakeup_one_sleeper.

Quoted 7 lines

Yes, here again I partially agree, except for a significant issue: xnsynch is a stateless object (that's why we can use it for different syncobjs which are totally unrelated in their semantics - mutex, queue, region, counting sems, whatever). I was just wondering if we could make the *tex thingy a bit more stateful to ease the job for the skins, just in case we would use it for mutexes only. I have no immediate answer to this question, just asking -- this is my contribution as a senior member of the peanut gallery.

We can certainly implement an abstraction managing xnarch_atomic_t + xnsynch_t, however, it seems that we would have to re-factor all mutex/semaphores implementations to use this new abstraction. The current approach is to add an xnarch_atomic_cmpxchg in user-space, and fall back to an almost unchanged kernel-space support when it fails.

Quoted 17 lines
Quoted 17 lines
Quoted 9 lines

I feel this

Quoted 5 lines

would complicate things: currently, the way I implemented user-space mutexes for the posix skin kept the old association between the user-space mutex, and its kernel-space companion, also used by kernel-space operations.

Quoted 3 lines

My concern boils down to: how much of the POSIX implementation, beyond the cb_lock stuff, would have to be duplicated to get the same support ported to, say the VxWorks semM services?

The initialization code, and the additional calls to xnarch_atomic_cmpxchg in user-space. If xnarch_atomic_cmpxchg fails we call kernel-space, which is mostly unchanged.

Quoted 8 lines
Quoted 5 lines

Because of the cb_lock stuff, I also needed to implement the kernel-space syscalls in two versions: one if user-space has xnarch_atomic_cmpxchg and could lock the mutex control block, the other if the mutex control block needs to be locked by kernel-space.

This is the part my laziness would very much like to factor as much as possible. If ever possible.

The current implementation is more or less:

/* Common generic function */
pse51_mutex_thing_inner(mutex)

{
    /*... Assume mutex cb is locked ... */
}

/* Kernel-space operation */
pthread_mutex_thing(mutex)

{
     cb_trylock(mutex->lock);
  
     pse51_mutex_thing_inner(mutex);

     cb_unlock(mutex->lock);
}

/* syscall wrapper */
#ifdef XNARCH_HAVE_US_ATOMIC_CMPXCHG
__pthread_mutex_thing()

{
     copy_from_user();

     pse51_mutex_thing_inner(mutex)

     copy_to_user();
}
#else
__pthread_mutex_thing()
{
     copy_from_user();

     pthread_mutex_thing(mutex)

     copy_to_user();
}

#endif

Signature · 1 line
					    Gilles.
#26 lore raw

Re: [Xenomai-core] [Patch 5/7] Define new syscalls for the system skin

Quoted 30 lines · Gilles Chanteperdrix
Quoted 21 lines · Philippe Gerum
Quoted 6 lines · Gilles Chanteperdrix

As far as I understood, the user-space atomic operations, used to acquire a free mutex in user-space, are not part of the futex API. In our case, we are using xnarch_atomic_* operations to implement portably this user-space locking stuff. I think that even setting the bit saying that the mutex is currently owned is done in pthread_mutexes implementation, not in the Futex API.

I would fully agree if the futex API did not define PI-based ops, which are needed for proper real-time operations from userland. You will certainly agree that PI implies that some kind of ownership exists; and because there can't be more than a single owner in that case, you end up with an object that can't be held by more than a single task. So you do have a mutex in disguise, whatever the way to keep its state is (a bit, an integer, whatever). So there is stronger semantics attached to that API than to simply manage an event notification scheme.

Now, what remains is

Quoted 3 lines

sys_futex(FUTEX_WAIT) and sys_futex(FUTEX_WAKE), this terribly looks like xnsync_sleep_on and xnsynch_wakeup_one_sleeper.

Quoted 7 lines

Yes, here again I partially agree, except for a significant issue: xnsynch is a stateless object (that's why we can use it for different syncobjs which are totally unrelated in their semantics - mutex, queue, region, counting sems, whatever). I was just wondering if we could make the *tex thingy a bit more stateful to ease the job for the skins, just in case we would use it for mutexes only. I have no immediate answer to this question, just asking -- this is my contribution as a senior member of the peanut gallery.

Quoted 6 lines

We can certainly implement an abstraction managing xnarch_atomic_t + xnsynch_t, however, it seems that we would have to re-factor all mutex/semaphores implementations to use this new abstraction. The current approach is to add an xnarch_atomic_cmpxchg in user-space, and fall back to an almost unchanged kernel-space support when it fails.

Ok. Let's merge this as it is. Common code will emerge eventually if it happens to make sense when plugging the feature into the native and VxWorks mutex support.

Quoted 66 lines
Quoted 17 lines
Quoted 17 lines
Quoted 9 lines

I feel this

Quoted 5 lines

would complicate things: currently, the way I implemented user-space mutexes for the posix skin kept the old association between the user-space mutex, and its kernel-space companion, also used by kernel-space operations.

Quoted 3 lines

My concern boils down to: how much of the POSIX implementation, beyond the cb_lock stuff, would have to be duplicated to get the same support ported to, say the VxWorks semM services?

The initialization code, and the additional calls to xnarch_atomic_cmpxchg in user-space. If xnarch_atomic_cmpxchg fails we call kernel-space, which is mostly unchanged.

Quoted 8 lines
Quoted 5 lines

Because of the cb_lock stuff, I also needed to implement the kernel-space syscalls in two versions: one if user-space has xnarch_atomic_cmpxchg and could lock the mutex control block, the other if the mutex control block needs to be locked by kernel-space.

This is the part my laziness would very much like to factor as much as possible. If ever possible.

The current implementation is more or less:

/* Common generic function */
pse51_mutex_thing_inner(mutex)

{
    /*... Assume mutex cb is locked ... */
}

/* Kernel-space operation */
pthread_mutex_thing(mutex)

{
     cb_trylock(mutex->lock);
  
     pse51_mutex_thing_inner(mutex);

     cb_unlock(mutex->lock);
}

/* syscall wrapper */
#ifdef XNARCH_HAVE_US_ATOMIC_CMPXCHG
__pthread_mutex_thing()

{
     copy_from_user();

     pse51_mutex_thing_inner(mutex)

     copy_to_user();
}
#else
__pthread_mutex_thing()
{
     copy_from_user();

     pthread_mutex_thing(mutex)

     copy_to_user();
}

#endif

Signature · 1 line
Philippe.
#27 lore raw

Re: [Xenomai-core] [Patch 5/7] Define new syscalls for the system skin

Quoted 38 lines · Philippe Gerum
Quoted 30 lines · Gilles Chanteperdrix
Quoted 21 lines · Philippe Gerum
Quoted 6 lines · Gilles Chanteperdrix

As far as I understood, the user-space atomic operations, used to acquire a free mutex in user-space, are not part of the futex API. In our case, we are using xnarch_atomic_* operations to implement portably this user-space locking stuff. I think that even setting the bit saying that the mutex is currently owned is done in pthread_mutexes implementation, not in the Futex API.

I would fully agree if the futex API did not define PI-based ops, which are needed for proper real-time operations from userland. You will certainly agree that PI implies that some kind of ownership exists; and because there can't be more than a single owner in that case, you end up with an object that can't be held by more than a single task. So you do have a mutex in disguise, whatever the way to keep its state is (a bit, an integer, whatever). So there is stronger semantics attached to that API than to simply manage an event notification scheme.

Now, what remains is

Quoted 3 lines

sys_futex(FUTEX_WAIT) and sys_futex(FUTEX_WAKE), this terribly looks like xnsync_sleep_on and xnsynch_wakeup_one_sleeper.

Quoted 7 lines

Yes, here again I partially agree, except for a significant issue: xnsynch is a stateless object (that's why we can use it for different syncobjs which are totally unrelated in their semantics - mutex, queue, region, counting sems, whatever). I was just wondering if we could make the *tex thingy a bit more stateful to ease the job for the skins, just in case we would use it for mutexes only. I have no immediate answer to this question, just asking -- this is my contribution as a senior member of the peanut gallery.

Quoted 6 lines

We can certainly implement an abstraction managing xnarch_atomic_t + xnsynch_t, however, it seems that we would have to re-factor all mutex/semaphores implementations to use this new abstraction. The current approach is to add an xnarch_atomic_cmpxchg in user-space, and fall back to an almost unchanged kernel-space support when it fails.

Quoted 2 lines

Ok. Let's merge this as it is. Common code will emerge eventually if it happens to make sense when plugging the feature into the native and VxWorks mutex support.

Ok. I need a few more days though, to adapt it to other architectures than arm.

Signature · 1 line
 Gilles
#28 lore raw

Re: [Xenomai-core] [Patch 5/7] Define new syscalls for the system skin

Quoted 39 lines · Gilles Chanteperdrix
Quoted 38 lines · Philippe Gerum
Quoted 36 lines · Gilles Chanteperdrix
Quoted 21 lines · Philippe Gerum
Quoted 6 lines · Gilles Chanteperdrix

As far as I understood, the user-space atomic operations, used to acquire a free mutex in user-space, are not part of the futex API. In our case, we are using xnarch_atomic_* operations to implement portably this user-space locking stuff. I think that even setting the bit saying that the mutex is currently owned is done in pthread_mutexes implementation, not in the Futex API.

I would fully agree if the futex API did not define PI-based ops, which are needed for proper real-time operations from userland. You will certainly agree that PI implies that some kind of ownership exists; and because there can't be more than a single owner in that case, you end up with an object that can't be held by more than a single task. So you do have a mutex in disguise, whatever the way to keep its state is (a bit, an integer, whatever). So there is stronger semantics attached to that API than to simply manage an event notification scheme.

Now, what remains is

Quoted 3 lines

sys_futex(FUTEX_WAIT) and sys_futex(FUTEX_WAKE), this terribly looks like xnsync_sleep_on and xnsynch_wakeup_one_sleeper.

Quoted 7 lines

Yes, here again I partially agree, except for a significant issue: xnsynch is a stateless object (that's why we can use it for different syncobjs which are totally unrelated in their semantics - mutex, queue, region, counting sems, whatever). I was just wondering if we could make the *tex thingy a bit more stateful to ease the job for the skins, just in case we would use it for mutexes only. I have no immediate answer to this question, just asking -- this is my contribution as a senior member of the peanut gallery.

We can certainly implement an abstraction managing xnarch_atomic_t + xnsynch_t, however, it seems that we would have to re-factor all mutex/semaphores implementations to use this new abstraction. The current approach is to add an xnarch_atomic_cmpxchg in user-space, and fall back to an almost unchanged kernel-space support when it fails.

Quoted 4 lines
Quoted 2 lines

Ok. Let's merge this as it is. Common code will emerge eventually if it happens to make sense when plugging the feature into the native and VxWorks mutex support.

Ok. I need a few more days though, to adapt it to other architectures than arm.

I changed my mind and commited the whole stuff. Instead of implementing full atomic operations in user-space for other platforms than ARM, I have left this work for others.

Signature · 1 line
					    Gilles.
#29 lore raw

Re: [Xenomai-core] [Patch 4/7] Define ARM atomic operations in user-space

In reply to Gilles Chanteperdrix
Quoted 6 lines · Gilles Chanteperdrix

The include/asm-arm/atomic.h header now defines the xnarch_memory_barrier in addition to user-space atomic operations. The pxa3xx deserves a special treatment since it uses the ARMv6 memory barrier operation whereas being an ARMv5 for other operations, hence a special --enable-arm-mach=pxa3xx option in configure.in.

After a quick look at all architectures xenomai supports, it seems that we can implement atomic_cmpxchg for most of them in user-space. The only one for which I have a doubt is blackfin. Since linux for blackfin is uclinux, can we call cli/sti from user-space ?

Signature · 1 line
 Gilles
#30 lore raw

Re: [Xenomai-core] [Patch 4/7] Define ARM atomic operations in user-space

Quoted 8 lines · Gilles Chanteperdrix
Quoted 5 lines · Gilles Chanteperdrix

The include/asm-arm/atomic.h header now defines the xnarch_memory_barrier in addition to user-space atomic operations. The pxa3xx deserves a special treatment since it uses the ARMv6 memory barrier operation whereas being an ARMv5 for other operations, hence a special --enable-arm-mach=pxa3xx option in configure.in.

Quoted 5 lines

After a quick look at all architectures xenomai supports, it seems that we can implement atomic_cmpxchg for most of them in user-space. The only one for which I have a doubt is blackfin. Since linux for blackfin is uclinux, can we call cli/sti from user-space ?

Nope, these are supervisor's toys on this arch. IIRC, recent Blackfin releases should be providing fast atomic ops from userland despite this, by using protected jumps to kernel space for that purpose. I need to check that in the kernel code, this was a discussion running on the Blackfin dev-list months ago. Anyway, I would suggest to exclude Blackfin from the mutex optimization set right now, then go back to it when we support their latest kernel.

Signature · 1 line
Philippe.
#31 lore raw

Re: [Xenomai-core] [Patch 4/7] Define ARM atomic operations in user-space

Quoted 16 lines · Philippe Gerum
Quoted 8 lines · Gilles Chanteperdrix
Quoted 5 lines · Gilles Chanteperdrix

The include/asm-arm/atomic.h header now defines the xnarch_memory_barrier in addition to user-space atomic operations. The pxa3xx deserves a special treatment since it uses the ARMv6 memory barrier operation whereas being an ARMv5 for other operations, hence a special --enable-arm-mach=pxa3xx option in configure.in.

Quoted 5 lines

After a quick look at all architectures xenomai supports, it seems that we can implement atomic_cmpxchg for most of them in user-space. The only one for which I have a doubt is blackfin. Since linux for blackfin is uclinux, can we call cli/sti from user-space ?

Quoted 4 lines

Nope, these are supervisor's toys on this arch. IIRC, recent Blackfin releases should be providing fast atomic ops from userland despite this, by using protected jumps to kernel space for that purpose. I need to check that in the kernel code, this was a discussion running on the Blackfin dev-list months ago.

It looks like the same technique as used on pre-v6 ARM.

Quoted 2 lines

Anyway, I would suggest to exclude Blackfin from the mutex optimization set right now, then go back to it when we support their latest kernel.

Ok. I was dreaming about removing all the #ifdef XNARCH_HAVE_US_ATOMIC_CMPXCHG. But it is probably better to leave it after all. If for anything, it will help people doing ports to new architectures gradually.

Signature · 1 line
 Gilles
#32 lore raw

Re: [Xenomai-core] [Patch 1/7] Support for non cached memory mappings

In reply to Gilles Chanteperdrix
Quoted 7 lines · Gilles Chanteperdrix

In addition to support for non cached memory mappings, this patch implements xnheap_init_mapped and xnheap_destroy_mapped in the !CONFIG_XENO_OPT_PERVASIVE case. This avoids a lot of #ifdefs for users of these functions without user-space support (posix skin shared memories, and the new semaphore heaps, heaps where is allocated the memory used for storing semaphores counters and mutexes owner fields).

Looks good. I would suggest to make xnheap_init_mapped() whine and bail out when non-cached DMA memory is requested though.

Quoted 203 lines
---
 include/asm-generic/wrappers.h |   12 +++++---
 include/native/heap.h          |    1
 include/nucleus/heap.h         |    2 +
 ksrc/nucleus/heap.c            |   55 +++++++++++++++++++++++++++++++++++------
 ksrc/skins/native/heap.c       |    8 +++++
 5 files changed, 66 insertions(+), 12 deletions(-)

Index: include/native/heap.h
===================================================================

native/heap.h +1 -0
@@ -33,6 +33,7 @@
 #define H_MAPPABLE 0x200	/* Memory is mappable to user-space. */
 #define H_SINGLE   0x400	/* Manage as single-block area. */
 #define H_SHARED   (H_MAPPABLE|H_SINGLE) /* I.e. shared memory segment. */
+#define H_NONCACHED 0x800
 
 /** Structure containing heap-information useful to users.
  *

Index: include/asm-generic/wrappers.h
===================================================================

asm-generic/wrappers.h +8 -4
@@ -62,7 +62,7 @@ unsigned long __va_to_kva(unsigned long 
 
 #define wrap_remap_vm_page(vma,from,to) ({ \
     vma->vm_flags |= VM_RESERVED; \
-    remap_page_range(from,virt_to_phys((void *)__va_to_kva(to)),PAGE_SIZE,PAGE_SHARED); \
+    remap_page_range(from,virt_to_phys((void *)__va_to_kva(to)),PAGE_SIZE,vma->vm_page_prot); \
 })
 #define wrap_remap_io_page_range(vma,from,to,size,prot) ({ \
     vma->vm_flags |= VM_RESERVED; \
@@ -223,7 +223,7 @@ unsigned long __va_to_kva(unsigned long 
  * memory. Anyway, this legacy would only hit setups using pre-2.6.11
  * kernel revisions. */
 #define wrap_remap_vm_page(vma,from,to) \
-    remap_pfn_range(vma,from,virt_to_phys((void *)__va_to_kva(to)) >> PAGE_SHIFT,PAGE_SHIFT,PAGE_SHARED)
+    remap_pfn_range(vma,from,virt_to_phys((void *)__va_to_kva(to)) >> PAGE_SHIFT,PAGE_SHIFT,vma->vm_page_prot)
 #define wrap_remap_io_page_range(vma,from,to,size,prot)  ({		\
     (vma)->vm_page_prot = pgprot_noncached((vma)->vm_page_prot);	\
     /* Sets VM_RESERVED | VM_IO | VM_PFNMAP on the vma. */		\
@@ -236,7 +236,7 @@ unsigned long __va_to_kva(unsigned long 
 #else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) */
 #define wrap_remap_vm_page(vma,from,to) ({ \
     vma->vm_flags |= VM_RESERVED; \
-    remap_page_range(from,virt_to_phys((void *)__va_to_kva(to)),PAGE_SIZE,PAGE_SHARED); \
+    remap_page_range(from,virt_to_phys((void *)__va_to_kva(to)),PAGE_SIZE,vma->vm_page_prot); \
 })
 #define wrap_remap_io_page_range(vma,from,to,size,prot) ({	\
       vma->vm_flags |= VM_RESERVED;				\
@@ -248,7 +248,11 @@ unsigned long __va_to_kva(unsigned long 
     })
 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) */
 
-#define wrap_switch_mm(prev,next,task)	\
+#ifndef __GFP_BITS_SHIFT
+#define __GFP_BITS_SHIFT 20
+#endif
+
+#define wrap_switch_mm(prev,next,task)		\
     switch_mm(prev,next,task)
 #define wrap_enter_lazy_tlb(mm,task)	\
     enter_lazy_tlb(mm,task)

Index: include/nucleus/heap.h
===================================================================

nucleus/heap.h +2 -0
@@ -57,6 +57,8 @@
 #define XNHEAP_PCONT   1
 #define XNHEAP_PLIST   2
 
+#define XNHEAP_GFP_NONCACHED (1 << __GFP_BITS_SHIFT)
+
 typedef struct xnextent {
 
 	xnholder_t link;

Index: ksrc/skins/native/heap.c
===================================================================

skins/native/heap.c +7 -1
@@ -205,6 +205,10 @@ static void __heap_flush_private(xnheap_
  * operations with I/O devices. The physical address of the
  * heap can be obtained by a call to rt_heap_inquire().
  *
+ * - H_NONCACHED causes the heap not to be cached. This is necessary on
+ * platforms such as ARM to share a heap between kernel and user-space.
+ * Note that this flag is not compatible with the H_DMA flag.
+ *
  * @return 0 is returned upon success. Otherwise:
  *
  * - -EEXIST is returned if the @a name is already in use by some
@@ -260,7 +264,9 @@ int rt_heap_create(RT_HEAP *heap, const 
 
 		err = xnheap_init_mapped(&heap->heap_base,
 					 heapsize,
-					 (mode & H_DMA) ? GFP_DMA : 0);
+					 ((mode & H_DMA) ? GFP_DMA : 0)
+					 | ((mode & H_NONCACHED) ?
+					    XNHEAP_GFP_NONCACHED : 0));
 		if (err)
 			return err;
 

Index: ksrc/nucleus/heap.c
===================================================================

nucleus/heap.c +48 -7
@@ -1097,9 +1097,13 @@ static int xnheap_mmap(struct file *file
 
 	vaddr = (unsigned long)heap->archdep.heapbase;
 
-	if (!heap->archdep.kmflags) {
+	if (!heap->archdep.kmflags
+	    || heap->archdep.kmflags == XNHEAP_GFP_NONCACHED) {
 		unsigned long maddr = vma->vm_start;
 
+		if (heap->archdep.kmflags == XNHEAP_GFP_NONCACHED)
+			vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
 		while (size > 0) {
 			if (xnarch_remap_vm_page(vma, maddr, vaddr))
 				return -EAGAIN;
@@ -1174,9 +1178,13 @@ static inline void *__alloc_and_reserve_
 
 	/* Size must be page-aligned. */
 
-	if (!kmflags) {
-		ptr = vmalloc(size);
-
+	if (!kmflags || kmflags == XNHEAP_GFP_NONCACHED) {
+		if (!kmflags)
+			ptr = vmalloc(size);
+		else
+			ptr = __vmalloc(size,
+					GFP_KERNEL | __GFP_HIGHMEM,
+					pgprot_noncached(PAGE_KERNEL));
 		if (!ptr)
 			return NULL;
 
@@ -1217,7 +1225,7 @@ static inline void __unreserve_and_free_
 
 	vabase = (unsigned long)ptr;
 
-	if (!kmflags) {
+	if (!kmflags  || kmflags == XNHEAP_GFP_NONCACHED) {
 		for (vaddr = vabase; vaddr < vabase + size; vaddr += PAGE_SIZE)
 			ClearPageReserved(virt_to_page(__va_to_kva(vaddr)));
 
@@ -1241,6 +1249,11 @@ int xnheap_init_mapped(xnheap_t *heap, u
 
 	/* Caller must have accounted for internal overhead. */
 	heapsize = xnheap_align(heapsize, PAGE_SIZE);
+
+	if ((memflags & XNHEAP_GFP_NONCACHED)
+	    && memflags != XNHEAP_GFP_NONCACHED)
+		return -EINVAL;
+
 	heapbase = __alloc_and_reserve_heap(heapsize, memflags);
 
 	if (!heapbase)
@@ -1284,11 +1297,39 @@ int xnheap_destroy_mapped(xnheap_t *heap
 	return 0;
 }
 
-EXPORT_SYMBOL(xnheap_init_mapped);
-EXPORT_SYMBOL(xnheap_destroy_mapped);
+#else /* !CONFIG_XENO_OPT_PERVASIVE */
+static void xnheap_free_extent(xnheap_t *heap,
+			       void *extent, u_long size, void *cookie)
+{
+	xnarch_free_host_mem(extent, size);
+}
+
+int xnheap_init_mapped(xnheap_t *heap, unsigned len, int flags)
+{
+	void *heapaddr = xnarch_alloc_host_mem(len);
+	int err;
 
+	if (heapaddr) {
+		err = xnheap_init(&shm->heapbase,
+				  heapaddr, len, XNCORE_PAGE_SIZE);
+		if (err)
+			xnarch_free_host_mem(heapaddr, len);
+
+		return err;
+	}
+
+	return -ENOMEM;
+}
+
+void xnheap_destroy_mapped(xnheap_t *heap)
+{
+	xnheap_destroy(heap, &xnheap_free_extent, NULL);
+}
 #endif /* CONFIG_XENO_OPT_PERVASIVE */
 
+EXPORT_SYMBOL(xnheap_init_mapped);
+EXPORT_SYMBOL(xnheap_destroy_mapped);
+
 /*@}*/
 
 EXPORT_SYMBOL(xnheap_alloc);
Signature · 1 line
Philippe.
#33 lore raw
In reply to Gilles Chanteperdrix
Quoted 10 lines · Gilles Chanteperdrix

Hi,

here comes a second attempt of implementing user-space mutexes for the posix skin.

Only differences with the first implementation are explained in the following mails.

Thanks in advance for your review.

After extensive testing, except for bugs in condition variables system calls, the new implementation seems to work fine.

Of course, it is well known that the one who makes the test should not be the same as the one who makes the code...

Signature · 1 line
					    Gilles.