[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