summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/libthr/arch/amd64/Makefile.inc2
-rw-r--r--lib/libthr/arch/amd64/amd64/_umtx_op_err.S37
-rw-r--r--lib/libthr/arch/amd64/include/pthread_md.h3
-rw-r--r--lib/libthr/arch/i386/Makefile.inc2
-rw-r--r--lib/libthr/arch/i386/i386/_umtx_op_err.S36
-rw-r--r--lib/libthr/arch/i386/include/pthread_md.h3
-rw-r--r--lib/libthr/thread/thr_private.h2
-rw-r--r--lib/libthr/thread/thr_rtld.c2
-rw-r--r--lib/libthr/thread/thr_umtx.c76
9 files changed, 112 insertions, 51 deletions
diff --git a/lib/libthr/arch/amd64/Makefile.inc b/lib/libthr/arch/amd64/Makefile.inc
index 439bc69..f62999f 100644
--- a/lib/libthr/arch/amd64/Makefile.inc
+++ b/lib/libthr/arch/amd64/Makefile.inc
@@ -2,4 +2,4 @@
.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/${MACHINE_ARCH}
-SRCS+= pthread_md.c
+SRCS+= pthread_md.c _umtx_op_err.S
diff --git a/lib/libthr/arch/amd64/amd64/_umtx_op_err.S b/lib/libthr/arch/amd64/amd64/_umtx_op_err.S
new file mode 100644
index 0000000..d11753d
--- /dev/null
+++ b/lib/libthr/arch/amd64/amd64/_umtx_op_err.S
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (C) 2008 David Xu <davidxu@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/syscall.h>
+#include <machine/asm.h>
+
+#define RSYSCALL_ERR(x) ENTRY(__CONCAT(x, _err)); \
+ mov __CONCAT($SYS_,x),%rax; KERNCALL; ret;
+
+#define KERNCALL movq %rcx, %r10; syscall
+
+RSYSCALL_ERR(_umtx_op)
diff --git a/lib/libthr/arch/amd64/include/pthread_md.h b/lib/libthr/arch/amd64/include/pthread_md.h
index 6814cac..9f6d3a1 100644
--- a/lib/libthr/arch/amd64/include/pthread_md.h
+++ b/lib/libthr/arch/amd64/include/pthread_md.h
@@ -97,4 +97,7 @@ _get_curthread(void)
{
return (TCB_GET64(tcb_thread));
}
+
+#define HAS__UMTX_OP_ERR 1
+
#endif
diff --git a/lib/libthr/arch/i386/Makefile.inc b/lib/libthr/arch/i386/Makefile.inc
index b6a4acd..35e93a2 100644
--- a/lib/libthr/arch/i386/Makefile.inc
+++ b/lib/libthr/arch/i386/Makefile.inc
@@ -2,4 +2,4 @@
.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/${MACHINE_ARCH}
-SRCS+= pthread_md.c
+SRCS+= pthread_md.c _umtx_op_err.S
diff --git a/lib/libthr/arch/i386/i386/_umtx_op_err.S b/lib/libthr/arch/i386/i386/_umtx_op_err.S
new file mode 100644
index 0000000..9b6f0b0
--- /dev/null
+++ b/lib/libthr/arch/i386/i386/_umtx_op_err.S
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (C) 2008 David Xu <davidxu@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <machine/asm.h>
+#include <sys/syscall.h>
+
+#define SYSCALL_ERR(x) \
+ ENTRY(__CONCAT(x, _err)); \
+ mov __CONCAT($SYS_,x),%eax; int $0x80; ret
+
+SYSCALL_ERR(_umtx_op)
diff --git a/lib/libthr/arch/i386/include/pthread_md.h b/lib/libthr/arch/i386/include/pthread_md.h
index 1f629e1..5c00cf6 100644
--- a/lib/libthr/arch/i386/include/pthread_md.h
+++ b/lib/libthr/arch/i386/include/pthread_md.h
@@ -102,4 +102,7 @@ _get_curthread(void)
{
return (TCB_GET32(tcb_thread));
}
+
+#define HAS__UMTX_OP_ERR 1
+
#endif
diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h
index 711ae5e..e377c5b 100644
--- a/lib/libthr/thread/thr_private.h
+++ b/lib/libthr/thread/thr_private.h
@@ -709,6 +709,8 @@ ssize_t __sys_write(int, const void *, size_t);
void __sys_exit(int);
#endif
+int _umtx_op_err(void *, int op, u_long, void *, void *);
+
static inline int
_thr_isthreaded(void)
{
diff --git a/lib/libthr/thread/thr_rtld.c b/lib/libthr/thread/thr_rtld.c
index 8c6eddb..f8437a1 100644
--- a/lib/libthr/thread/thr_rtld.c
+++ b/lib/libthr/thread/thr_rtld.c
@@ -219,7 +219,7 @@ _thr_rtld_init(void)
curthread = _get_curthread();
/* force to resolve _umtx_op PLT */
- _umtx_op((struct umtx *)&dummy, UMTX_OP_WAKE, 1, 0, 0);
+ _umtx_op_err((struct umtx *)&dummy, UMTX_OP_WAKE, 1, 0, 0);
/* force to resolve errno() PLT */
__error();
diff --git a/lib/libthr/thread/thr_umtx.c b/lib/libthr/thread/thr_umtx.c
index d0a225d..ff8c60e 100644
--- a/lib/libthr/thread/thr_umtx.c
+++ b/lib/libthr/thread/thr_umtx.c
@@ -30,6 +30,15 @@
#include "thr_private.h"
#include "thr_umtx.h"
+#ifndef HAS__UMTX_OP_ERR
+int _umtx_op_err(void *obj, int op, u_long val, void *uaddr, void *uaddr2)
+{
+ if (_umtx_op(obj, op, val, uaddr, uaddr2) == -1)
+ return (errno);
+ return (0);
+}
+#endif
+
void
_thr_umutex_init(struct umutex *mtx)
{
@@ -41,9 +50,7 @@ _thr_umutex_init(struct umutex *mtx)
int
__thr_umutex_lock(struct umutex *mtx)
{
- if (_umtx_op(mtx, UMTX_OP_MUTEX_LOCK, 0, 0, 0) != -1)
- return 0;
- return (errno);
+ return _umtx_op_err(mtx, UMTX_OP_MUTEX_LOCK, 0, 0, 0);
}
int
@@ -53,35 +60,27 @@ __thr_umutex_timedlock(struct umutex *mtx,
if (timeout && (timeout->tv_sec < 0 || (timeout->tv_sec == 0 &&
timeout->tv_nsec <= 0)))
return (ETIMEDOUT);
- if (_umtx_op(mtx, UMTX_OP_MUTEX_LOCK, 0, 0,
- __DECONST(void *, timeout)) != -1)
- return (0);
- return (errno);
+ return _umtx_op_err(mtx, UMTX_OP_MUTEX_LOCK, 0, 0,
+ __DECONST(void *, timeout));
}
int
__thr_umutex_unlock(struct umutex *mtx)
{
- if (_umtx_op(mtx, UMTX_OP_MUTEX_UNLOCK, 0, 0, 0) != -1)
- return (0);
- return (errno);
+ return _umtx_op_err(mtx, UMTX_OP_MUTEX_UNLOCK, 0, 0, 0);
}
int
__thr_umutex_trylock(struct umutex *mtx)
{
- if (_umtx_op(mtx, UMTX_OP_MUTEX_TRYLOCK, 0, 0, 0) != -1)
- return (0);
- return (errno);
+ return _umtx_op_err(mtx, UMTX_OP_MUTEX_TRYLOCK, 0, 0, 0);
}
int
__thr_umutex_set_ceiling(struct umutex *mtx, uint32_t ceiling,
uint32_t *oldceiling)
{
- if (_umtx_op(mtx, UMTX_OP_SET_CEILING, ceiling, oldceiling, 0) != -1)
- return (0);
- return (errno);
+ return _umtx_op_err(mtx, UMTX_OP_SET_CEILING, ceiling, oldceiling, 0);
}
int
@@ -90,10 +89,8 @@ _thr_umtx_wait(volatile long *mtx, long id, const struct timespec *timeout)
if (timeout && (timeout->tv_sec < 0 || (timeout->tv_sec == 0 &&
timeout->tv_nsec <= 0)))
return (ETIMEDOUT);
- if (_umtx_op(__DEVOLATILE(void *, mtx), UMTX_OP_WAIT, id, 0,
- __DECONST(void*, timeout)) != -1)
- return (0);
- return (errno);
+ return _umtx_op_err(__DEVOLATILE(void *, mtx), UMTX_OP_WAIT, id, 0,
+ __DECONST(void*, timeout));
}
int
@@ -102,19 +99,15 @@ _thr_umtx_wait_uint(volatile u_int *mtx, u_int id, const struct timespec *timeou
if (timeout && (timeout->tv_sec < 0 || (timeout->tv_sec == 0 &&
timeout->tv_nsec <= 0)))
return (ETIMEDOUT);
- if (_umtx_op(__DEVOLATILE(void *, mtx), UMTX_OP_WAIT_UINT, id, 0,
- __DECONST(void*, timeout)) != -1)
- return (0);
- return (errno);
+ return _umtx_op_err(__DEVOLATILE(void *, mtx), UMTX_OP_WAIT_UINT, id, 0,
+ __DECONST(void*, timeout));
}
int
_thr_umtx_wake(volatile void *mtx, int nr_wakeup)
{
- if (_umtx_op(__DEVOLATILE(void *, mtx), UMTX_OP_WAKE,
- nr_wakeup, 0, 0) != -1)
- return (0);
- return (errno);
+ return _umtx_op_err(__DEVOLATILE(void *, mtx), UMTX_OP_WAKE,
+ nr_wakeup, 0, 0);
}
void
@@ -132,12 +125,9 @@ _thr_ucond_wait(struct ucond *cv, struct umutex *m,
__thr_umutex_unlock(m);
return (ETIMEDOUT);
}
- if (_umtx_op(cv, UMTX_OP_CV_WAIT,
+ return _umtx_op_err(cv, UMTX_OP_CV_WAIT,
check_unparking ? UMTX_CHECK_UNPARKING : 0,
- m, __DECONST(void*, timeout)) != -1) {
- return (0);
- }
- return (errno);
+ m, __DECONST(void*, timeout));
}
int
@@ -145,9 +135,7 @@ _thr_ucond_signal(struct ucond *cv)
{
if (!cv->c_has_waiters)
return (0);
- if (_umtx_op(cv, UMTX_OP_CV_SIGNAL, 0, NULL, NULL) != -1)
- return (0);
- return (errno);
+ return _umtx_op_err(cv, UMTX_OP_CV_SIGNAL, 0, NULL, NULL);
}
int
@@ -155,31 +143,23 @@ _thr_ucond_broadcast(struct ucond *cv)
{
if (!cv->c_has_waiters)
return (0);
- if (_umtx_op(cv, UMTX_OP_CV_BROADCAST, 0, NULL, NULL) != -1)
- return (0);
- return (errno);
+ return _umtx_op_err(cv, UMTX_OP_CV_BROADCAST, 0, NULL, NULL);
}
int
__thr_rwlock_rdlock(struct urwlock *rwlock, int flags, struct timespec *tsp)
{
- if (_umtx_op(rwlock, UMTX_OP_RW_RDLOCK, flags, NULL, tsp) != -1)
- return (0);
- return (errno);
+ return _umtx_op_err(rwlock, UMTX_OP_RW_RDLOCK, flags, NULL, tsp);
}
int
__thr_rwlock_wrlock(struct urwlock *rwlock, struct timespec *tsp)
{
- if (_umtx_op(rwlock, UMTX_OP_RW_WRLOCK, 0, NULL, tsp) != -1)
- return (0);
- return (errno);
+ return _umtx_op_err(rwlock, UMTX_OP_RW_WRLOCK, 0, NULL, tsp);
}
int
__thr_rwlock_unlock(struct urwlock *rwlock)
{
- if (_umtx_op(rwlock, UMTX_OP_RW_UNLOCK, 0, NULL, NULL) != -1)
- return (0);
- return (errno);
+ return _umtx_op_err(rwlock, UMTX_OP_RW_UNLOCK, 0, NULL, NULL);
}
OpenPOWER on IntegriCloud