This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC/PATCH] RT-NPTL-2.3 5/7


i386/lowlevellock.h           |   23 +++
 i386/pthread_cond_broadcast.c |   82 +++++++++++++
 lowlevelrtlock.h              |  251
++++++++++++++++++++++++++++++++++++++++++
 pthread_mutex_cond_lock.c     |   16 ++
 pthread_mutex_rq_lock.c       |   70 +++++++++++
 5 files changed, 439 insertions(+), 3 deletions(-)

--- /dev/null	Fri Jul 23 03:18:17 2004
+++
robustmutexes/rtnptl/src/nptl/sysdeps/unix/sysv/linux/lowlevelrtlock.h
Mon Jul 19 02:48:10 2004
@@ -0,0 +1,251 @@
+/*
+ *  (C) 2003,2004 Intel Corporation
+ *  Boris Hu <boris.hu@intel.com>
+ *
+ *  Distributed under the FSF's LGPL license, v2 or later. */
+
+#ifndef _LOWLEVELRTLOCK_H
+#define _LOWLEVELRTLOCK_H 1
+
+#ifdef USE_FUSYN_ROBUST_MUTEX
+#include <linux/fuqueue.h>
+#else
+#define FUQUEUE_WAITER_GOT_LOCK 0x401449
+#define FUQUEUE_CTL_RELEASE     0
+#endif
+
+
+enum {
+    /** Timeout is relative to the current clock source time. */
+  TIMEOUT_RELATIVE = 0x2,
+};
+
+struct timeout
+{
+  int flags;
+  clockid_t clock_id; /* Currently unused */
+  struct timespec ts;
+};
+
+#ifdef  USE_FUSYN_ROBUST_MUTEX
+//#define SEA_DEBUG       1  // To Enable the debug info
+#ifdef SEA_DEBUG
+/* 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 | FULOCK_FASTPATH_MODE |
\
+                                 FULOCK_UNLOCK_TYPE_MASK |
PRIOCEILING_MASK)
+#define FUSYN_FL_RT2K_MASK      (0x78000000 | FULOCK_FASTPATH_MODE |
\
+                                 PRIOCEILING_MASK)
+/*  Get fusyn flags. */
+#define __LK_FL(fulock)
\
+ ({ unsigned k_flags = 0;
\
+    unsigned flags = ((pthread_mutex_t *)(fulock))->__data.__kind
\
+                     & FUSYN_FL_RT2K_MASK;
\
+    k_flags = ((flags << 1) & FULOCK_FL_USER_MK);
\
+    k_flags;})
+/*  Get rtnptl flags. */
+#define __RT_FL(fulock)
\
+ ({ unsigned flags = ((pthread_mutex_t *)(fulock))->__data.__kind
\
+                     & FUSYN_FL_RT_MASK;
\
+    flags;})
+     
+
+extern int is_mutex_robust(const pthread_mutex_t *mutex);
+
+extern int __lll_rtmutex_trylock (volatile int *vfulock, unsigned
flags,
+                                  unsigned rtflags, unsigned tid);
+#define lll_rtmutex_trylock(futex, tid) \
+        __lll_rtmutex_trylock(&(futex), __LK_FL(&(futex)),
\
+                                __RT_FL(&(futex)), tid)
+
+
+extern int __lll_rtmutex_timedlock (volatile int *vfulock, unsigned
flags,
+                                    unsigned rtflags, unsigned tid,
+                                    const struct timeout *timeout);
+#define lll_rtmutex_timedlock(futex, tid, abs_time) \
+        ({ struct timeout to;
\
+           int __result = 0;
\
+           if (abs_time->tv_sec < 0 || abstime->tv_nsec >= 1000000000)
\
+                __result = EINVAL;
\
+           else {
\
+                memset(&to, 0, sizeof(to));
\
+                to.ts = *abs_time;
\
+                __result = __lll_rtmutex_timedlock(&(futex),
\
+                                __LK_FL(&(futex)),
\
+                                __RT_FL(&(futex)), tid, &to);
\
+          }
\
+        __result; })
+
+
+extern int __lll_rtmutex_lock (volatile int *vfulock, unsigned flags,
+                               unsigned rtflags, unsigned tid);
+#define lll_rtmutex_lock(futex, tid) \
+        __lll_rtmutex_lock(&(futex), __LK_FL(&(futex)),
\
+                                __RT_FL(&(futex)), tid)
+
+extern int __lll_rtmutex_unlock (volatile int *vfulock, unsigned flags,
+                                 unsigned rtflags, unsigned tid);
+#define lll_rtmutex_unlock(futex, tid) \
+        __lll_rtmutex_unlock(&(futex), __LK_FL(&(futex)),
\
+                                __RT_FL(&(futex)), tid)
+
+
+extern int __lll_rtmutex_unlock_nocheck (volatile int *vfulock,
+                                         unsigned flags, unsigned
rtflags);
+#define lll_rtmutex_unlock_nocheck(futex) \
+        __lll_rtmutex_unlock_nocheck(&(futex), __LK_FL(&(futex)),
\
+                                __RT_FL(&(futex)))
+
+
+extern int __lll_rtmutex_set_consistency (volatile int *vfulock,
+                                          unsigned flags, unsigned
rtflags,
+                                          enum fulock_ctl consistency);
+#define lll_rtmutex_set_consistency(futex, state) \
+        __lll_rtmutex_set_consistency(&(futex), __LK_FL(&(futex)),\
+                                __RT_FL(&(futex)), state)
+
+
+extern int __lll_rtmutex_get_consistency (volatile int *vfulock,
+                                          unsigned flags, unsigned
rtflags,
+                                          int *state);
+#define lll_rtmutex_get_consistency(futex, state) \
+        __lll_rtmutex_get_consistency(&(futex), __LK_FL(&(futex)),\
+                                __RT_FL(&(futex)), state)
+
+extern int __lll_rtmutex_ctl(volatile int *vfulock,
+                             unsigned flags, int ctl);
+#define lll_rtmutex_ctl(futex, ctl)     \
+        __lll_rtmutex_ctl(&(futex), __LK_FL(&(futex)), ctl)
+
+#define CONDVAR_RM_FLAGS        FULOCK_FL_RM
+
+#define lll_cmutex_lock(fulock, id)   \
+  do {
\
+        while (__lll_rtmutex_lock(&(fulock), CONDVAR_RM_FLAGS, 0, 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, 0, id)
+
+#define LLL_CMUTEX_LOCK(mutex, tid)     \
+        lll_cmutex_lock (mutex, tid)
+
+#define LLL_CMUTEX_UNLOCK(mutex, tid)   \
+        lll_cmutex_unlock (mutex, tid)
+
+#define ROBUST_MUTEX_FLAGS      FULOCK_FL_RM
+
+#define lll_robust_mutex_lock(mutex, tid)       \
+        __lll_rtmutex_lock(&(mutex), ROBUST_MUTEX_FLAGS, 0, tid)
+
+#define lll_robust_mutex_trylock(mutex, tid)       \
+        __lll_rtmutex_trylock(&(mutex), ROBUST_MUTEX_FLAGS, 0, tid)
+
+#define lll_robust_mutex_unlock(mutex, tid)     \
+        __lll_rtmutex_unlock(&(mutex), ROBUST_MUTEX_FLAGS, 0, tid)
+
+#define lll_fuqueue_wait(futex, val) \
+  ({ int ret;
\
+     INTERNAL_SYSCALL_DECL (err);
\
+     ret = INTERNAL_SYSCALL (ufuqueue_wait, err, 3, futex, val, (void
*)-1);  \
+     INTERNAL_SYSCALL_ERROR_P (ret, err) ? INTERNAL_SYSCALL_ERRNO (ret,
err)  \
+                : ret; })
+
+#define lll_fuqueue_wake(futex, nr) \
+  ({ int ret;
\
+     INTERNAL_SYSCALL_DECL (err);
\
+     ret = INTERNAL_SYSCALL (ufuqueue_wake, err, 3, futex, nr, 0);
\
+     INTERNAL_SYSCALL_ERROR_P (ret, err) ? INTERNAL_SYSCALL_ERRNO (ret,
err)  \
+                : ret; })
+
+#define lll_fuqueue_timedwait(futex, val, abs_time) \
+  ({ int ret;
\
+     struct timeout to;
\
+     INTERNAL_SYSCALL_DECL (err);
\
+     memset(&to, 0, sizeof(to));
\
+     to.ts = *abs_time;
\
+     ret = INTERNAL_SYSCALL (ufuqueue_wait, err, 3, futex, val, &to);
\
+     INTERNAL_SYSCALL_ERROR_P (ret, err) ? INTERNAL_SYSCALL_ERRNO (ret,
err)  \
+                : ret; })
+
+#define lll_fuqueue_requeue(futex, nr_wake, nr_move, mutex) \
+  ({ int ret;
\
+     INTERNAL_SYSCALL_DECL (err);
\
+     ret = INTERNAL_SYSCALL (ufulock_requeue, err, 4, futex, *futex,
mutex,   \
+                             __LK_FL(mutex));
\
+     INTERNAL_SYSCALL_ERROR_P (ret, err) ? INTERNAL_SYSCALL_ERRNO (ret,
err)  \
+                : ret; })
+
+#define lll_fuqueue_ctl(futex, code) \
+  ({ int ret;
\
+     INTERNAL_SYSCALL_DECL (err);
\
+     ret = INTERNAL_SYSCALL (ufuqueue_ctl, err, 2, futex, code);
\
+     INTERNAL_SYSCALL_ERROR_P (ret, err) ? INTERNAL_SYSCALL_ERRNO (ret,
err)  \
+                : ret; })
+
+#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_ctl(futex, ctl) 0
+
+#define lll_rtmutex_unlock_nocheck(futex) 0
+
+#define __LK_FL(fulock) 0
+#define __RT_FL(fulock) 0
+
+#define lll_robust_mutex_lock(mutex, tid)       0
+#define lll_robust_mutex_trylock(mutex, tid)    0
+#define lll_robust_mutex_unlock(mutex, tid)     0
+
+#define lll_fuqueue_wait(futex, val) \
+        lll_futex_wait (futex, val)
+
+#define lll_fuqueue_wake(futex, nr) \
+        lll_futex_wake (futex, nr)
+
+#define lll_fuqueue_timed_wait(futex, val, timeout) \
+        lll_futex_timed_wait (futex, val, timeout)
+
+#define lll_fuqueue_requeue(futex, nr_wake, nr_move, mutex) \
+        lll_futex_requeue(futex, nr_wake, nr_move, mutex)
+
+#define lll_fuqueue_ctl(futex, code)  0
+
+#endif /* USE_FUSYN_ROBUST_MUTEX */
+
+extern int is_mutex_robust(const pthread_mutex_t *mutex);
+
+#endif
---
robustmutexes/rtnptl/src/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond
_lock.c:1.1.1.1.2.1	Fri Mar 26 02:41:40 2004
+++
robustmutexes/rtnptl/src/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond
_lock.c	Tue Mar 30 09:20:29 2004
@@ -1,7 +1,19 @@
 #include <pthreadP.h>
 
-#define LLL_MUTEX_LOCK(mutex) lll_mutex_cond_lock(mutex)
-#define LLL_MUTEX_TRYLOCK(mutex) lll_mutex_cond_trylock(mutex)
+#ifdef USE_FUSYN_ROBUST_MUTEX
+#  define LLL_MUTEX_LOCK(mutex, tid)       \
+        do {                                            \
+                result = lll_rtmutex_lock (mutex,tid);  \
+                if (__builtin_expect (0 != result, 0))  \
+                        goto out_err;                   \
+        } while (0)
+#  define LLL_MUTEX_TRYLOCK(mutex, tid) \
+        lll_rtmutex_trylock(mutex, tid)
+#else
+#  define LLL_MUTEX_LOCK(mutex, tid) lll_mutex_cond_lock(mutex)
+#  define LLL_MUTEX_TRYLOCK(mutex, tid) lll_mutex_cond_trylock(mutex)
+#endif
+
 #define __pthread_mutex_lock __pthread_mutex_cond_lock
 #define NO_INCR
 
--- /dev/null	Fri Jul 23 03:18:18 2004
+++
robustmutexes/rtnptl/src/nptl/sysdeps/unix/sysv/linux/pthread_mutex_rq_l
ock.c	Mon Jul 19 08:38:39 2004
@@ -0,0 +1,70 @@
+/*
+ *  (C) 2003,2004 Intel Corporation
+ *  Boris Hu <boris.hu@intel.com>
+ *
+ *  Distributed under the FSF's LGPL license, v2 or later. */
+
+#include <assert.h>
+#include <errno.h>
+#include "pthreadP.h"
+#include <lowlevellock.h>
+
+int
+__pthread_mutex_rq_lock (mutex)
+     pthread_mutex_t *mutex;
+{
+  assert (sizeof (mutex->__size) >= sizeof (mutex->__data));
+
+  pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
+  int result = 0;
+  switch (__builtin_expect (mutex->__data.__kind &
~NON_MUTEX_KIND_MASK,
+                            PTHREAD_MUTEX_TIMED_NP))
+    {
+      /* Recursive mutex.  */
+    case PTHREAD_MUTEX_RECURSIVE_NP:
+      /* Check whether we already hold the mutex.  */
+      if (mutex->__data.__owner == id)
+	{
+	  /* Just bump the counter.  */
+	  if (__builtin_expect (mutex->__data.__count + 1 == 0, 0))
+	    /* Overflow of the counter.  */
+	    return EAGAIN;
+
+	  ++mutex->__data.__count;
+
+	  return 0;
+	}
+
+      mutex->__data.__count = 1;
+      break;
+
+      /* Error checking mutex.  */
+    case PTHREAD_MUTEX_ERRORCHECK_NP:
+      /* Check whether we already hold the mutex.  */
+      if (mutex->__data.__owner == id)
+	return EDEADLK;
+
+      /* FALLTHROUGH */
+
+    default:
+      /* Correct code cannot set any other type.  */
+    case PTHREAD_MUTEX_TIMED_NP:
+    simple:
+      break;
+
+    case PTHREAD_MUTEX_ADAPTIVE_NP:
+      if (! __is_smp)
+	goto simple;
+      break;
+    }
+  /* Record the ownership.  */
+  assert (mutex->__data.__owner == 0);
+  mutex->__data.__owner = id;
+#ifndef NO_INCR
+  ++mutex->__data.__nusers;
+#endif
+
+  return 0;
+}
+strong_alias (__pthread_mutex_rq_lock, pthread_mutex_rq_lock)
+
---
robustmutexes/rtnptl/src/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.
h:1.1.1.1.2.2	Fri Mar 26 02:41:42 2004
+++
robustmutexes/rtnptl/src/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.
h	Mon Jul 19 08:38:40 2004
@@ -2,6 +2,9 @@
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
+   Redirect lowlevellock to use Fast User SYNchronization(fusyn).
+   Boris Hu <boris.hu@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
@@ -35,7 +38,7 @@
 #define SYS_futex		240
 #define FUTEX_WAIT		0
 #define FUTEX_WAKE		1
-
+#define FUTEX_REQUEUE           3
 
 /* Initializer for compatibility lock.  */
 #define LLL_MUTEX_LOCK_INITIALIZER		(0)
@@ -93,6 +96,20 @@
 			"i" (offsetof (tcbhead_t, sysinfo)));
\
   } while (0)
 
+#define lll_futex_timed_wait(futex, val, timespec) \
+  ({ int ret;
\
+     INTERNAL_SYSCALL_DECL (err);
\
+     ret = INTERNAL_SYSCALL (futex, err, 5, futex, FUTEX_WAIT, val,
\
+                             timespec, 0);
\
+     INTERNAL_SYSCALL_ERROR_P (ret, err) ? INTERNAL_SYSCALL_ERRNO (ret,
err)  \
+                : ret; })
+ 
+#define lll_futex_requeue(futex, nr_wake, nr_move, mutex) \
+  ({ int ret;
\
+     INTERNAL_SYSCALL_DECL (err);
\
+     ret = INTERNAL_SYSCALL (futex, err, 5, futex, FUTEX_WAKE, INT_MAX,
0, 0);\
+     INTERNAL_SYSCALL_ERROR_P (ret, err) ? INTERNAL_SYSCALL_ERRNO (ret,
err)  \
+                : ret; })
 
 /* Does not preserve %eax and %ecx.  */
 extern int __lll_mutex_lock_wait (int val, int *__futex)
@@ -370,5 +387,9 @@
 #define lll_cond_broadcast(cond) \
   __lll_cond_broadcast (cond)
 
+/* To Enable Robust Mutexes features. */     
+#include <linux/fulock.h>
+#include <lowlevelrtlock.h>
 
+     
 #endif	/* lowlevellock.h */
--- /dev/null	Fri Jul 23 03:18:18 2004
+++
robustmutexes/rtnptl/src/nptl/sysdeps/unix/sysv/linux/i386/pthread_cond_
broadcast.c	Wed Jun  9 12:38:03 2004
@@ -0,0 +1,82 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
+
+   Hacked to add robust featuers to condvar by
+   Boris Hu <boris.hu@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 <endian.h>
+#include <errno.h>
+#include <sysdep.h>
+#include <lowlevellock.h>
+#include <pthread.h>
+#include <pthreadP.h>
+
+#include <shlib-compat.h>
+#include <kernel-features.h>
+
+
+int
+__pthread_cond_broadcast (cond)
+     pthread_cond_t *cond;
+{
+  pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
+
+  /* Make sure we are alone.  */
+  LLL_CMUTEX_LOCK (cond->__data.__lock, id);
+
+  /* Are there any waiters to be woken?  */
+  if (cond->__data.__total_seq > cond->__data.__wakeup_seq)
+    {
+      /* Yes.  Mark them all as woken.  */
+      cond->__data.__wakeup_seq = cond->__data.__total_seq;
+      cond->__data.__woken_seq = cond->__data.__total_seq;
+      cond->__data.__futex = (unsigned int) cond->__data.__total_seq *
2;
+      /* Signal that a broadcast happened.  */
+      ++cond->__data.__broadcast_seq;
+ 
+      /* We are done.  */
+      LLL_CMUTEX_UNLOCK (cond->__data.__lock, id);
+
+      /* Do not use requeue for pshared condvars.  */
+      if (cond->__data.__mutex == (void *) ~0l)
+	goto wake_all;
+      
+      /* Wake everybody.  */
+      pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex;
+      /* lll_futex_requeue returns 0 for success and non-zero for
errors. */
+      if (__builtin_expect (lll_fuqueue_requeue (&cond->__data.__futex,
1,
+                                                 INT_MAX,
+                                                 &mut->__data.__lock),
0))
+        {
+	  /* The requeue functionality is not available.  */
+        wake_all:
+	  lll_fuqueue_wake (&cond->__data.__futex, INT_MAX);
+	}
+
+      /* That's all.  */
+      return 0;
+    }
+
+  /* We are done.  */
+  LLL_CMUTEX_UNLOCK (cond->__data.__lock, id);
+  return 0;
+}
+
+versioned_symbol (libpthread, __pthread_cond_broadcast,
pthread_cond_broadcast,
+		  GLIBC_2_3_2);

Boris Hu (Hu Jiangtao)
Intel China Software Center 
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}

Attachment: rtnptl-2.3.patch-4
Description: rtnptl-2.3.patch-4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]