[RFC/PATCH] RT-NPTL-2.1 5/5
Hu, Boris
boris.hu@intel.com
Mon Feb 2 03:18:00 GMT 2004
bits/posix_opt.h | 9 +
bits/pthreadtypes.h | 3
lowlevellock.h | 235
+++++++++++++++++++++++++++++++++++++++++++++++
lowlevelrtlock.c | 79 +++++++++++++++
pthread_cond_broadcast.c | 2
pthread_cond_signal.c | 2
pthread_cond_timedwait.c | 2
pthread_cond_wait.c | 2
8 files changed, 333 insertions(+), 1 deletion(-)
diff -urN src.cvs/nptl/sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h
src/nptl/sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h
--- src.cvs/nptl/sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h
2004-01-31 11:49:05.000000000 +0800
+++ src/nptl/sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h
2004-01-31 11:51:20.000000000 +0800
@@ -144,4 +144,13 @@
/* The clock selection interfaces are available. */
#define _POSIX_CLOCK_SELECTION 200112L
+/* The Priority Inheritence of thread is available. */
+#define _POSIX_THREAD_PRIO_INHERIT 1
+
+/* The Priority Protect of thread is available. */
+#define _POSIX_THREAD_PRIO_PROTECT 2
+
+/* The robust mutex is available. */
+#define _POSIX_THREAD_ROBUST_MUTEX_NP 1
+
#endif /* posix_opt.h */
diff -urN src.cvs/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h
src/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h
--- src.cvs/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h
2004-01-31 11:49:05.000000000 +0800
+++ src/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h
2004-01-31 11:51:20.000000000 +0800
@@ -52,10 +52,11 @@
int __lock;
unsigned int __count;
int __owner;
- unsigned int __nusers;
/* KIND must stay at this position in the structure to maintain
binary compatibility. */
int __kind;
+ unsigned int __nusers;
+ unsigned int __prioceiling;
} __data;
char __size[__SIZEOF_PTHREAD_MUTEX_T];
long int __align;
diff -urN src.cvs/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h
src/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h
--- src.cvs/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h
2004-01-31 11:49:05.000000000 +0800
+++ src/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h
2004-01-31 11:51:20.000000000 +0800
@@ -2,6 +2,10 @@
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+ Redirect lowlevellock to use Fast User SYNchronization(fusyn).
+ Based on implementation for i386 by Boris Hu (Intel).
+ Dave Howell <david.p.howell@intel.com>, 2003
+
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
@@ -111,6 +115,7 @@
#define lll_mutex_unlock(futex) \
__lll_mutex_unlock(&(futex))
+//#warning FIXME: requeue feature will be added when the fusyn is
ready.
#define __lll_mutex_unlock_force(futex) \
((void) ({ \
@@ -190,4 +195,234 @@
#define lll_cond_broadcast(cond) \
__lll_cond_broadcast (cond)
+// USE_FUSYN_ROBUST_MUTEX macro to enable/disable the RM features.
+#define USE_FUSYN_ROBUST_MUTEX 1
+
+#ifdef USE_FUSYN_ROBUST_MUTEX
+
+#include <linux/fulock.h>
+#include <sysdep.h>
+#include <errno.h>
+#include <pthread.h>
+
+#ifndef __set_errno
+#define __set_errno(e) (errno = (e))
+#endif
+
+//#define SEA_DEBUG 1 // To Enable the debug info
+
+#ifdef SEA_DEBUG
+int printf(const char *format, ...); /* To make GCC happy */
+
+/* Indicate location */
+# define SEA_L
\
+ do {
\
+ unsigned id = THREAD_GETMEM (THREAD_SELF, tid);
\
+ printf("[%d] %s:%s() %d line: \n", id, __FILE__,
\
+ __FUNCTION__, __LINE__);
\
+ } while (0)
+
+/* Location-aware printf */
+# define SEA_P(fmt, args...)
\
+ do {
\
+ unsigned id = THREAD_GETMEM (THREAD_SELF, tid);
\
+ printf("[%d] %s:%s() %d line: " fmt "\n",
\
+ id, __FILE__,__FUNCTION__,__LINE__,args);
\
+ } while (0)
+
+#else
+# define SEA_L
+# define SEA_P(fmt, args...)
+#endif
+
+/* Add lll_rtmutex_* to support fusyn */
+#define FUSYN_FL_RT_MASK 0x78000000
+#define MUTEX_OFF_KIND 3
+
+#define __LK_FL(mutex)
\
+ ({ unsigned k_flags;
\
+ unsigned flags =((pthread_mutex_t *)(mutex))->__data.__kind
\
+ & FUSYN_FL_RT_MASK;
\
+ k_flags = ((flags << 1) & FULOCK_FL_USER_MK);
\
+ k_flags;})
+
+static inline int
+__attribute__ ((always_inline))
+__lll_rtmutex_trylock (volatile unsigned *vfulock, unsigned flags,
unsigned tid)
+{
+ unsigned old_value;
+
+ restart:
+ old_value = atomic_compare_and_exchange_val_acq (vfulock, tid,
VFULOCK_UNLOCKED);
+ if (old_value == VFULOCK_UNLOCKED) /* If it was unlocked, fulock
acquired */
+ return 0;
+ else if (__builtin_expect (old_value == VFULOCK_NR, 0))
+ return ENOTRECOVERABLE;
+ else
+ {
+ if ((old_value == VFULOCK_KCO) || (flags & FULOCK_FL_RM))
+ {
+ int result = INLINE_SYSCALL (ufulock_lock, 3, vfulock, flags, 0);
+ if (__builtin_expect (result < 0, 0))
+ {
+ if (result == -EAGAIN || result == -EINTR)
+ goto restart;
+ result = -result;
+ }
+ return result;
+ }
+ }
+ return EBUSY;
+}
+#define lll_rtmutex_trylock(futex, tid) \
+ __lll_rtmutex_trylock(&(futex), __LK_FL(&(futex)), tid)
+
+
+extern int
+__lll_rtmutex_timedlock (volatile unsigned *vfulock, unsigned flags,
+ unsigned tid, const struct timespec *rel);
+#define lll_rtmutex_timedlock(futex, tid, timeout) \
+ __lll_rtmutex_timedlock(&(futex), __LK_FL(&(futex)), tid,
timeout)
+
+
+static inline int
+__attribute__ ((always_inline))
+__lll_rtmutex_lock (volatile unsigned *vfulock, unsigned flags,
unsigned tid)
+{
+ int result;
+ restart:
+ if (!atomic_compare_and_exchange_bool_acq (vfulock, tid,
VFULOCK_UNLOCKED))
+ return 0;
+ result = INLINE_SYSCALL (ufulock_lock, 3, vfulock, flags, (void
*)-1);
+ if (__builtin_expect (result < 0, 0))
+ {
+ if (result == -EAGAIN || result == -EINTR)
+ goto restart;
+ result = -result;
+ }
+ return result;
+}
+#define lll_rtmutex_lock(futex, tid) \
+ __lll_rtmutex_lock(&(futex), __LK_FL(&(futex)), tid)
+
+
+static inline int
+__attribute__ ((always_inline))
+__lll_rtmutex_unlock (volatile unsigned *vfulock, unsigned flags,
unsigned tid)
+{
+ unsigned old_value;
+
+ while (1)
+ {
+ old_value = *vfulock;
+ if (__builtin_expect (old_value == VFULOCK_NR, 0))
+ return ENOTRECOVERABLE;
+ else if (old_value >= VFULOCK_KCO)
+ {
+ int result;
+ result = INLINE_SYSCALL(ufulock_unlock, 3, vfulock, flags, 0);
+ return (result < 0) ? -result : 0;
+ }
+ else if (! atomic_compare_and_exchange_bool_acq (vfulock,
VFULOCK_UNLOCKED,
+ old_value))
+ return 0;
+ }
+}
+#define lll_rtmutex_unlock(futex, tid) \
+ __lll_rtmutex_unlock(&(futex), __LK_FL(&(futex)), tid)
+
+
+static inline int
+__attribute__ ((always_inline))
+__lll_rtmutex_unlock_nocheck (volatile unsigned *vfulock)
+{
+ int result = INLINE_SYSCALL (ufulock_unlock, 3, vfulock,
__LK_FL(vfulock), 0);
+ return result ? -result : 0;
+}
+#define lll_rtmutex_unlock_nocheck(futex) \
+ __lll_rtmutex_unlock_nocheck(&(futex))
+
+
+static inline int
+__attribute__ ((always_inline))
+__lll_rtmutex_set_consistency (volatile unsigned *vfulock,
+ enum fulock_con consistency)
+{
+ int result = INLINE_SYSCALL (ufulock_consistency, 3, vfulock,
+ __LK_FL(vfulock), consistency);
+ return result ? -result : 0;
+}
+#define lll_rtmutex_set_consistency(futex, state) \
+ __lll_rtmutex_set_consistency(&(futex), state)
+
+
+static inline int
+__attribute__ ((always_inline))
+__lll_rtmutex_get_consistency (volatile unsigned *vfulock, int *state)
+{
+ *state = INLINE_SYSCALL (ufulock_consistency, 3, vfulock,
+ __LK_FL(vfulock), 0);
+ return 0;
+}
+#define lll_rtmutex_get_consistency(futex, state) \
+ __lll_rtmutex_get_consistency(&(futex), state)
+
+
+static inline int
+__attribute__ ((always_inline))
+is_mutex_robust(pthread_mutex_t *mutex)
+{
+ return (mutex->__data.__kind & ((FULOCK_FL_RM | FULOCK_FL_RM_SUN) >>
1));
+}
+
+static inline int
+__attribute__ ((always_inline))
+is_mutex_healthy(pthread_mutex_t *mutex)
+{
+ int state;
+ pthread_mutex_getconsistency_np (mutex, &state);
+ return state == PTHREAD_MUTEX_ROBUST_CONSISTENT_NP;
+}
+
+#define CONDVAR_RM_FLAGS FULOCK_FL_RM
+
+#define lll_cmutex_lock(fulock, id) \
+ do {
\
+ while (__lll_rtmutex_lock(&(fulock), CONDVAR_RM_FLAGS, id))
\
+ lll_rtmutex_set_consistency(fulock,
\
+ PTHREAD_MUTEX_ROBUST_CONSISTENT_NP);
\
+ } while (0)
+
+#define lll_cmutex_unlock(fulock, id) \
+ __lll_rtmutex_unlock(&(fulock), CONDVAR_RM_FLAGS, id)
+
+#define LLL_CMUTEX_LOCK(mutex, tid) \
+ lll_cmutex_lock (mutex, tid)
+
+#define LLL_CMUTEX_UNLOCK(mutex, tid) \
+ lll_cmutex_unlock (mutex, tid)
+
+#else /* Normal NPTL */
+
+#define FUSYN_FL_RT_MASK 0
+
+#define LLL_CMUTEX_LOCK(mutex, tid) \
+ lll_mutex_lock(mutex)
+
+#define LLL_CMUTEX_UNLOCK(mutex, tid) \
+ lll_mutex_unlock (mutex)
+
+#define lll_rtmutex_get_consistency(futex, state) 0
+
+#define lll_rtmutex_set_consistency(futex, state) 0
+
+#define lll_rtmutex_unlock_nocheck(futex) 0
+
+#define __LK_FL(fulock) 0
+
+#define FUSYN_FL_RT_BITS 0
+
+#endif /* USE_FUSYN_ROBUST_MUTEX */
+
+
#endif /* lowlevellock.h */
diff -urN src.cvs/nptl/sysdeps/unix/sysv/linux/ia64/lowlevelrtlock.c
src/nptl/sysdeps/unix/sysv/linux/ia64/lowlevelrtlock.c
--- src.cvs/nptl/sysdeps/unix/sysv/linux/ia64/lowlevelrtlock.c
1970-01-01 08:00:00.000000000 +0800
+++ src/nptl/sysdeps/unix/sysv/linux/ia64/lowlevelrtlock.c
2004-01-31 11:51:20.000000000 +0800
@@ -0,0 +1,79 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by David Howell <david.p.howell@intel.com>, 2003.
+
+ Redirect lowlevellock to use Fast User SYNchronization(fusyn).
+ Based on implementation for i386 by Boris Hu (Intel).
+ Dave Howell <david.p.howell@intel.com>, 2003
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+
+#include <errno.h>
+#include <sysdep.h>
+#include <lowlevellock.h>
+#include <sys/time.h>
+#include <pthread.h>
+#include <pthreadP.h>
+
+#include <linux/fulock.h>
+
+int __lll_rtmutex_timedlock (volatile unsigned *vfulock, unsigned
flags,
+ unsigned pid, const struct timespec *rel)
+{
+ int result;
+ struct timeval tv;
+ struct timespec rt, *p = NULL;
+
+ if (rel != (void *)-1 && rel != NULL) {
+ if (rel->tv_nsec < 0 || rel->tv_nsec >= 1000000000)
+ return EINVAL;
+
+ (void) __gettimeofday (&tv, NULL);
+
+ rt.tv_sec = rel->tv_sec - tv.tv_sec;
+ rt.tv_nsec = rel->tv_nsec - tv.tv_usec * 1000;
+ if (rt.tv_nsec < 0)
+ {
+ rt.tv_nsec += 1000000000;
+ --rt.tv_sec;
+ }
+ if (rt.tv_sec < 0)
+ return ETIMEDOUT;
+ p = &rt;
+ } else if ((void *)-1 == rel)
+ p = (void *)-1;
+
+ restart:
+ if (! atomic_compare_and_exchange_bool_acq (vfulock, pid,
VFULOCK_UNLOCKED))
+ return 0;
+ result = INLINE_SYSCALL (ufulock_lock, 3, vfulock, flags, (void *)p);
+ SEA_P("result :%d\n", result);
+ if (__builtin_expect (result < 0, 0))
+ {
+ result = -result;
+ SEA_P("result set to :%d\n", result);
+ if (result == EAGAIN || result == EINTR)
+ goto restart;
+ }
+ return result;
+}
+
+int is_mutexattr_robust (const struct pthread_mutexattr *attr)
+{
+ return (attr->mutexkind & ((FULOCK_FL_RM | FULOCK_FL_RM_SUN) >> 1));
+}
+
diff -urN
src.cvs/nptl/sysdeps/unix/sysv/linux/ia64/pthread_cond_broadcast.c
src/nptl/sysdeps/unix/sysv/linux/ia64/pthread_cond_broadcast.c
--- src.cvs/nptl/sysdeps/unix/sysv/linux/ia64/pthread_cond_broadcast.c
1970-01-01 08:00:00.000000000 +0800
+++ src/nptl/sysdeps/unix/sysv/linux/ia64/pthread_cond_broadcast.c
2004-01-31 11:51:20.000000000 +0800
@@ -0,0 +1,2 @@
+
+#include "../i386/pthread_cond_broadcast.c"
diff -urN
src.cvs/nptl/sysdeps/unix/sysv/linux/ia64/pthread_cond_signal.c
src/nptl/sysdeps/unix/sysv/linux/ia64/pthread_cond_signal.c
--- src.cvs/nptl/sysdeps/unix/sysv/linux/ia64/pthread_cond_signal.c
1970-01-01 08:00:00.000000000 +0800
+++ src/nptl/sysdeps/unix/sysv/linux/ia64/pthread_cond_signal.c
2004-01-31 11:51:20.000000000 +0800
@@ -0,0 +1,2 @@
+
+#include "../i386/pthread_cond_signal.c"
diff -urN
src.cvs/nptl/sysdeps/unix/sysv/linux/ia64/pthread_cond_timedwait.c
src/nptl/sysdeps/unix/sysv/linux/ia64/pthread_cond_timedwait.c
--- src.cvs/nptl/sysdeps/unix/sysv/linux/ia64/pthread_cond_timedwait.c
1970-01-01 08:00:00.000000000 +0800
+++ src/nptl/sysdeps/unix/sysv/linux/ia64/pthread_cond_timedwait.c
2004-01-31 11:51:20.000000000 +0800
@@ -0,0 +1,2 @@
+
+#include "../i386/pthread_cond_timedwait.c"
diff -urN src.cvs/nptl/sysdeps/unix/sysv/linux/ia64/pthread_cond_wait.c
src/nptl/sysdeps/unix/sysv/linux/ia64/pthread_cond_wait.c
--- src.cvs/nptl/sysdeps/unix/sysv/linux/ia64/pthread_cond_wait.c
1970-01-01 08:00:00.000000000 +0800
+++ src/nptl/sysdeps/unix/sysv/linux/ia64/pthread_cond_wait.c
2004-01-31 11:51:20.000000000 +0800
@@ -0,0 +1,2 @@
+
+#include "../i386/pthread_cond_wait.c"
Good Luck !
Boris Hu (Hu Jiangtao)
Software Engineer@ICSL
86-021-5257-4545#1277
iNET: 8-752-1277
*****************************************
There are my thoughts, not my employer's.
*****************************************
"gpg --recv-keys --keyserver wwwkeys.pgp.net 0FD7685F"
{0FD7685F:CFD6 6F5C A2CB 7881 725B CEA0 956F 9F14 0FD7 685F}
More information about the Libc-alpha
mailing list