summaryrefslogtreecommitdiffstats
path: root/lib/libthr
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2008-03-20 09:35:44 +0000
committerdavidxu <davidxu@FreeBSD.org>2008-03-20 09:35:44 +0000
commit8326c062223a38eeb1d4cfb0ddf32a8fee20b743 (patch)
tree92134ce2740d526d06bcd2e56d04c37d75de77d2 /lib/libthr
parentb24f39223eb2d3d27b88fce15ebb098c2082cff3 (diff)
downloadFreeBSD-src-8326c062223a38eeb1d4cfb0ddf32a8fee20b743.zip
FreeBSD-src-8326c062223a38eeb1d4cfb0ddf32a8fee20b743.tar.gz
Preserve application code's errno in rtld locking code, it attemps to keep
any case safe.
Diffstat (limited to 'lib/libthr')
-rw-r--r--lib/libthr/thread/thr_rtld.c33
1 files changed, 31 insertions, 2 deletions
diff --git a/lib/libthr/thread/thr_rtld.c b/lib/libthr/thread/thr_rtld.c
index 14fb127..411e995 100644
--- a/lib/libthr/thread/thr_rtld.c
+++ b/lib/libthr/thread/thr_rtld.c
@@ -36,6 +36,9 @@
#include "rtld_lock.h"
#include "thr_private.h"
+#undef errno
+extern int errno;
+
#define CACHE_LINE_SIZE 64
#define WAFLAG 0x1
#define RC_INCR 0x2
@@ -88,20 +91,38 @@ _thr_rtld_lock_destroy(void *lock)
free(l->base);
}
+#define SAVE_ERRNO() { \
+ if (curthread != _thr_initial) \
+ errsave = curthread->error; \
+ else \
+ errsave = errno; \
+}
+
+#define RESTORE_ERRNO() { \
+ if (curthread != _thr_initial) \
+ curthread->error = errsave; \
+ else \
+ errno = errsave; \
+}
+
static void
_thr_rtld_rlock_acquire(void *lock)
{
struct pthread *curthread;
struct rtld_lock *l;
long v;
+ int errsave;
curthread = _get_curthread();
+ SAVE_ERRNO();
l = (struct rtld_lock *)lock;
THR_CRITICAL_ENTER(curthread);
atomic_add_acq_int(&l->lock, RC_INCR);
- if (!(l->lock & WAFLAG))
+ if (!(l->lock & WAFLAG)) {
+ RESTORE_ERRNO();
return;
+ }
v = l->rd_cv;
atomic_add_int(&l->rd_waiters, 1);
while (l->lock & WAFLAG) {
@@ -109,6 +130,7 @@ _thr_rtld_rlock_acquire(void *lock)
v = l->rd_cv;
}
atomic_add_int(&l->rd_waiters, -1);
+ RESTORE_ERRNO();
}
static void
@@ -117,14 +139,18 @@ _thr_rtld_wlock_acquire(void *lock)
struct pthread *curthread;
struct rtld_lock *l;
long v;
+ int errsave;
curthread = _get_curthread();
+ SAVE_ERRNO();
l = (struct rtld_lock *)lock;
_thr_signal_block(curthread);
for (;;) {
- if (atomic_cmpset_acq_int(&l->lock, 0, WAFLAG))
+ if (atomic_cmpset_acq_int(&l->lock, 0, WAFLAG)) {
+ RESTORE_ERRNO();
return;
+ }
v = l->wr_cv;
atomic_add_int(&l->wr_waiters, 1);
while (l->lock != 0) {
@@ -140,8 +166,10 @@ _thr_rtld_lock_release(void *lock)
{
struct pthread *curthread;
struct rtld_lock *l;
+ int errsave;
curthread = _get_curthread();
+ SAVE_ERRNO();
l = (struct rtld_lock *)lock;
if ((l->lock & WAFLAG) == 0) {
@@ -162,6 +190,7 @@ _thr_rtld_lock_release(void *lock)
}
_thr_signal_unblock(curthread);
}
+ RESTORE_ERRNO();
}
static int
OpenPOWER on IntegriCloud