[Glibc-bsd-commits] r4591 - in trunk/glibc-ports/kfreebsd: . fbtl x86/fbtl

Petr Salinger ps-guest at alioth.debian.org
Mon Jul 8 12:43:14 UTC 2013


Author: ps-guest
Date: 2013-06-23 14:16:38 +0000 (Sun, 23 Jun 2013)
New Revision: 4591

Added:
   trunk/glibc-ports/kfreebsd/fbtl/lowlevellock.h
   trunk/glibc-ports/kfreebsd/lowlevelumtx.h
   trunk/glibc-ports/kfreebsd/x86/fbtl/lowlevellock.h
Modified:
   trunk/glibc-ports/kfreebsd/fbtl/Versions
   trunk/glibc-ports/kfreebsd/fbtl/lowlevellock.c
Log:
FreeBSD's futex like interface


Modified: trunk/glibc-ports/kfreebsd/fbtl/Versions
===================================================================
--- trunk/glibc-ports/kfreebsd/fbtl/Versions	2013-06-23 12:50:52 UTC (rev 4590)
+++ trunk/glibc-ports/kfreebsd/fbtl/Versions	2013-06-23 14:16:38 UTC (rev 4591)
@@ -13,5 +13,6 @@
     __syscall_sigsuspend;
     __ioctl;
     __syscall_sigaction;
+    __syscall__umtx_op;
   }
 }

Modified: trunk/glibc-ports/kfreebsd/fbtl/lowlevellock.c
===================================================================
--- trunk/glibc-ports/kfreebsd/fbtl/lowlevellock.c	2013-06-23 12:50:52 UTC (rev 4590)
+++ trunk/glibc-ports/kfreebsd/fbtl/lowlevellock.c	2013-06-23 14:16:38 UTC (rev 4591)
@@ -1,7 +1,6 @@
 /* low level locking for pthread library.  Generic futex-using version.
    Copyright (C) 2003-2013 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
-   Contributed by Paul Mackerras <paulus at au.ibm.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
@@ -14,48 +13,56 @@
    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, see
+   License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
 #include <errno.h>
 #include <sysdep.h>
 #include <lowlevellock.h>
 #include <sys/time.h>
-#include <atomic.h>
 
 void
 __lll_lock_wait_private (int *futex)
 {
-  if (*futex == 2)
-    lll_futex_wait (futex, 2, LLL_PRIVATE);
-
-  while (atomic_exchange_acq (futex, 2) != 0)
-    lll_futex_wait (futex, 2, LLL_PRIVATE);
+  do
+    {
+      int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1);
+      if (oldval != 0)
+	lll_futex_wait (futex, 2, LLL_PRIVATE);
+    }
+  while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0);
 }
 
 
 /* These functions don't get included in libc.so  */
 #ifdef IS_IN_libpthread
 void
-__lll_lock_wait (int *futex, int private)
+__lll_lock_wait_shared (int *futex)
 {
-  if (*futex == 2)
-    lll_futex_wait (futex, 2, private);
-
-  while (atomic_exchange_acq (futex, 2) != 0)
-    lll_futex_wait (futex, 2, private);
+  do
+    {
+      int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1);
+      if (oldval != 0)
+	lll_futex_wait (futex, 2, LLL_SHARED);
+    }
+  while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0);
 }
 
 
 int
 __lll_timedlock_wait (int *futex, const struct timespec *abstime, int private)
 {
+  struct timespec rt;
+
   /* Reject invalid timeouts.  */
   if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
     return EINVAL;
 
-  /* Try locking.  */
-  while (atomic_exchange_acq (futex, 2) != 0)
+  /* Upgrade the lock.  */
+  if (atomic_exchange_acq (futex, 2) == 0)
+    return 0;
+
+  do
     {
       struct timeval tv;
 
@@ -63,7 +70,6 @@
       (void) __gettimeofday (&tv, NULL);
 
       /* Compute relative timeout.  */
-      struct timespec rt;
       rt.tv_sec = abstime->tv_sec - tv.tv_sec;
       rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
       if (rt.tv_nsec < 0)
@@ -72,17 +78,19 @@
 	  --rt.tv_sec;
 	}
 
+      /* Already timed out?  */
       if (rt.tv_sec < 0)
 	return ETIMEDOUT;
 
-      /* Wait.  */
+      // XYZ: Lost the lock to check whether it was private.
       lll_futex_timed_wait (futex, 2, &rt, private);
     }
+  while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0);
 
   return 0;
 }
 
-
+#if 0
 int
 __lll_timedwait_tid (int *tidp, const struct timespec *abstime)
 {
@@ -113,8 +121,8 @@
       if (rt.tv_sec < 0)
 	return ETIMEDOUT;
 
-      /* Wait until thread terminates.  The kernel so far does not use
-	 the private futex operations for this.  */
+      /* Wait until thread terminates.  */
+      // XYZ: Lost the lock to check whether it was private.
       if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) == -ETIMEDOUT)
 	return ETIMEDOUT;
     }
@@ -122,3 +130,4 @@
   return 0;
 }
 #endif
+#endif

Added: trunk/glibc-ports/kfreebsd/fbtl/lowlevellock.h
===================================================================
--- trunk/glibc-ports/kfreebsd/fbtl/lowlevellock.h	                        (rev 0)
+++ trunk/glibc-ports/kfreebsd/fbtl/lowlevellock.h	2013-06-23 14:16:38 UTC (rev 4591)
@@ -0,0 +1,174 @@
+/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LOWLEVELLOCK_H
+#define _LOWLEVELLOCK_H	1
+
+/* Values for 'private' parameter of locking macros.  Yes, the
+   definition seems to be backwards.  But it is not.  
+   They are the same as linux one's
+ */  
+
+#define FUTEX_PRIVATE_FLAG 128
+
+#define LLL_PRIVATE	0
+#define LLL_SHARED	FUTEX_PRIVATE_FLAG
+
+#include <stap-probe.h>
+
+#ifndef __ASSEMBLER__
+
+#include <time.h>
+#include <sys/param.h>
+#include <bits/pthreadtypes.h>
+#include <kernel-features.h>
+#include <tcb-offsets.h>
+#include <atomic.h>
+#include <lowlevelumtx.h>
+
+/* Initializer for lock.  */
+#define LLL_LOCK_INITIALIZER		(0)
+#define LLL_LOCK_INITIALIZER_LOCKED	(1)
+#define LLL_LOCK_INITIALIZER_WAITERS	(2)
+
+#define lll_futex_wait(futex, val, private) \
+  lll_futex_timed_wait(futex, val, NULL, private)
+
+#define lll_futex_timed_wait(futex, val, timeout, private) 		\
+  ({									\
+      int __status;							\
+      if ((private) == LLL_PRIVATE)					\
+          __status = lll_umtx_int_wait_private (futex, val, timeout);	\
+      else     								\
+          __status = lll_umtx_int_wait_shared (futex, val, timeout);	\
+    __status;								\
+  })
+
+#define lll_futex_wake(futex, nr, private) \
+  ({									\
+      int __status;							\
+      if ((private) == LLL_PRIVATE)					\
+          __status = lll_umtx_int_wake_private (futex, nr);		\
+      else     								\
+          __status = lll_umtx_int_wake_shared (futex, nr);		\
+    __status;								\
+  })
+
+#define lll_trylock(lock)	\
+  atomic_compare_and_exchange_val_acq(&(lock), 1, 0)
+
+#define lll_cond_trylock(lock)	\
+  atomic_compare_and_exchange_val_acq(&(lock), 2, 0)
+
+extern void __lll_lock_wait_private (int *futex) attribute_hidden;
+extern void __lll_lock_wait_shared  (int *futex) attribute_hidden;
+
+#define __lll_lock_wait(futex, private)				\
+  ((void) ({								\
+	if ((private) == LLL_PRIVATE)	      				\
+	  __lll_lock_wait_private (futex);				\
+	else								\
+	  __lll_lock_wait_shared  (futex);				\
+  }))
+
+#define __lll_lock(futex, private)					\
+  ((void) ({								      \
+    int *__futex = (futex);						      \
+    if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex,       \
+								1, 0), 0))    \
+      {									      \
+	  __lll_lock_wait (__futex, private);				      \
+      }									      \
+  }))
+
+#define lll_lock(futex, private) __lll_lock (&(futex), private)
+
+
+#define __lll_cond_lock(futex, private)					      \
+  ((void) ({								      \
+    int *__futex = (futex);						      \
+    if (__builtin_expect (atomic_exchange_acq (__futex, 2), 0))		      \
+      __lll_lock_wait (__futex, private);				      \
+  }))
+  
+#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private)
+
+
+extern int __lll_timedlock_wait (int *futex, const struct timespec *,
+				 int private) attribute_hidden;
+
+#define __lll_timedlock(futex, abstime, private)			      \
+  ({									      \
+     int *__futex = (futex);						      \
+     int __val = 0;							      \
+									      \
+     if (__builtin_expect (atomic_exchange_acq (__futex, 1), 0))	      \
+       __val = __lll_timedlock_wait (__futex, abstime, private);	      \
+     __val;								      \
+  })
+  
+#define lll_timedlock(futex, abstime, private) \
+  __lll_timedlock (&(futex), abstime, private)
+
+
+#define __lll_unlock(futex, private) \
+  (void)							\
+    ({ int *__futex = (futex);					\
+       int __oldval = atomic_exchange_rel (__futex, 0);		\
+       if (__builtin_expect (__oldval > 1, 0))			\
+	 lll_futex_wake (__futex, 1, private);			\
+    })
+    
+#define lll_unlock(futex, private) __lll_unlock(&(futex), private)
+
+
+#define lll_islocked(futex) \
+  (futex != 0)
+
+
+#if 1
+/* TODO:::::  #warning pthread join waiting */
+#define lll_wait_tid(tid)	do {} while (0)
+#define lll_timedwait_tid(tid, abstime)	0
+#else
+/* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex
+   wakeup when the clone terminates.  The memory location contains the
+   thread ID while the clone is running and is reset to zero
+   afterwards.	*/
+#define lll_wait_tid(tid) \
+  do {					\
+    __typeof (tid) __tid;		\
+    while ((__tid = (tid)) != 0)	\
+      lll_futex_wait (&(tid), __tid, LLL_SHARED);\
+  } while (0)
+
+extern int __lll_timedwait_tid (int *, const struct timespec *)
+     attribute_hidden;
+
+#define lll_timedwait_tid(tid, abstime) \
+  ({							\
+    int __res = 0;					\
+    if ((tid) != 0)					\
+      __res = __lll_timedwait_tid (&(tid), (abstime));	\
+    __res;						\
+  })
+  
+#endif
+
+#endif  /* !__ASSEMBLER__ */
+
+#endif	/* lowlevellock.h */

Added: trunk/glibc-ports/kfreebsd/lowlevelumtx.h
===================================================================
--- trunk/glibc-ports/kfreebsd/lowlevelumtx.h	                        (rev 0)
+++ trunk/glibc-ports/kfreebsd/lowlevelumtx.h	2013-06-23 14:16:38 UTC (rev 4591)
@@ -0,0 +1,129 @@
+/* Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LOWLEVELUMTX_H
+#define _LOWLEVELUMTX_H	1
+
+#include <kernel-features.h>
+#include <sysdep.h>
+#include <atomic.h>
+
+/* from <sys/umtx.h> */
+/* op code for _umtx_op */
+#define	UMTX_OP_WAIT		2
+#define	UMTX_OP_WAKE		3
+#define	UMTX_OP_WAIT_UINT	11
+#define	UMTX_OP_WAIT_UINT_PRIVATE	15
+#define	UMTX_OP_WAKE_PRIVATE	16
+
+extern int __syscall__umtx_op(void *, int, long, void*, void*);
+#define UMTX_SYSCALL __syscall__umtx_op
+
+/*
+ * 
+   we provide set of functions
+   lll_umtx_{int,long}_{wait,wake}_{private,shared}
+ *  
+ */
+
+/*******************************************************/
+
+#define lll_umtx_int_wait_private(addr, val, timeout)	\
+  ({							\
+    UMTX_SYSCALL(					\
+        addr,						\
+        UMTX_OP_WAIT_UINT_PRIVATE, 			\
+        (long)((unsigned int)(val)),			\
+        NULL,						\
+        timeout);					\
+   })
+
+#define lll_umtx_int_wait_shared(addr, val, timeout)	\
+  ({							\
+    UMTX_SYSCALL(					\
+        addr,						\
+        UMTX_OP_WAIT_UINT,	 			\
+        (long)((unsigned int)(val)),			\
+        NULL,						\
+        timeout);					\
+   })
+
+#define lll_umtx_long_wait_private(addr, val, timeout)	\
+  ({							\
+    UMTX_SYSCALL(					\
+        addr,						\
+        UMTX_OP_WAIT,  /* only autoshare available */	\
+        val,						\
+        NULL,						\
+        timeout);					\
+   })
+
+#define lll_umtx_long_wait_shared(addr, val, timeout)	\
+  ({							\
+    UMTX_SYSCALL(					\
+        addr,						\
+        UMTX_OP_WAIT,  /* only autoshare available */	\
+        val,						\
+        NULL,						\
+        timeout);					\
+   })
+
+/*******************************************************/
+
+#define lll_umtx_int_wake_private(addr, num)  		\
+  ({							\
+    UMTX_SYSCALL(					\
+        addr,						\
+        UMTX_OP_WAKE_PRIVATE,	 			\
+        num,						\
+        NULL,						\
+        NULL);						\
+   })
+
+#define lll_umtx_int_wake_shared(addr, num)  		\
+  ({							\
+    UMTX_SYSCALL(					\
+        addr,						\
+        UMTX_OP_WAKE,		 			\
+        num,						\
+        NULL,						\
+        NULL);						\
+   })
+
+#define lll_umtx_long_wake_private(addr, num) 		\
+  ({							\
+    UMTX_SYSCALL(					\
+        addr,						\
+        UMTX_OP_WAKE_PRIVATE,	 			\
+        num,						\
+        NULL,						\
+        NULL);						\
+   })
+
+#define lll_umtx_long_wake_shared(addr, num)  		\
+  ({							\
+    UMTX_SYSCALL(					\
+        addr,						\
+        UMTX_OP_WAKE,		 			\
+        num,						\
+        NULL,						\
+        NULL);						\
+   })
+
+/*******************************************************/
+
+#endif	/* _LOWLEVELUMTX_H */

Added: trunk/glibc-ports/kfreebsd/x86/fbtl/lowlevellock.h
===================================================================
--- trunk/glibc-ports/kfreebsd/x86/fbtl/lowlevellock.h	                        (rev 0)
+++ trunk/glibc-ports/kfreebsd/x86/fbtl/lowlevellock.h	2013-06-23 14:16:38 UTC (rev 4591)
@@ -0,0 +1,38 @@
+/* Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include_next <lowlevellock.h>
+
+#ifndef __ASSEMBLER__
+  /* Delay in spinlock loop.  */
+# define BUSY_WAIT_NOP	asm ("rep; nop")
+# ifndef LOCK_INSTR
+#  ifdef UP
+#   define LOCK_INSTR	/* nothing */
+#  else
+#   define LOCK_INSTR "lock;"
+#  endif
+# endif
+#else
+# ifndef LOCK
+#  ifdef UP
+#   define LOCK
+#  else
+#   define LOCK lock
+#  endif
+# endif
+#endif  /* !__ASSEMBLER__ */




More information about the Glibc-bsd-commits mailing list