summaryrefslogtreecommitdiff
path: root/usr/src/lib/libc
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@joyent.com>2015-06-02 17:12:04 +0000
committerRobert Mustacchi <rm@joyent.com>2015-09-14 13:47:46 -0700
commit0d045c0d0cb001d79480ee33be28514e847f8612 (patch)
tree3454a95214e5f8ac18f52c0db7886d5027091b9a /usr/src/lib/libc
parent7bbfa3ee1f517d6d5762f10047886094cea843a1 (diff)
downloadillumos-joyent-0d045c0d0cb001d79480ee33be28514e847f8612.tar.gz
6209 libc mutexes break kernel writers hearts
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Reviewed by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net> Reviewed by: Dan McDonald <danmcd@omniti.com> Reviewed by: Garrett D'Amore <garrett@damore.org> Approved by: Dan McDonald <danmcd@omniti.com>
Diffstat (limited to 'usr/src/lib/libc')
-rw-r--r--usr/src/lib/libc/inc/thr_uberdata.h4
-rw-r--r--usr/src/lib/libc/port/mapfile-vers2
-rw-r--r--usr/src/lib/libc/port/threads/assfail.c10
-rw-r--r--usr/src/lib/libc/port/threads/synch.c43
4 files changed, 58 insertions, 1 deletions
diff --git a/usr/src/lib/libc/inc/thr_uberdata.h b/usr/src/lib/libc/inc/thr_uberdata.h
index de0d4a6b05..4815d11486 100644
--- a/usr/src/lib/libc/inc/thr_uberdata.h
+++ b/usr/src/lib/libc/inc/thr_uberdata.h
@@ -23,7 +23,7 @@
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
- * Copyright (c) 2014, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2015, Joyent, Inc.
*/
#ifndef _THR_UBERDATA_H
@@ -1229,6 +1229,8 @@ extern void getgregs(ulwp_t *, gregset_t);
extern void setgregs(ulwp_t *, gregset_t);
extern void thr_panic(const char *);
#pragma rarely_called(thr_panic)
+extern void mutex_panic(mutex_t *, const char *);
+#pragma rarely_called(mutex_panic)
extern ulwp_t *find_lwp(thread_t);
extern void finish_init(void);
extern void update_sched(ulwp_t *);
diff --git a/usr/src/lib/libc/port/mapfile-vers b/usr/src/lib/libc/port/mapfile-vers
index c4571ef2f1..c6967141b6 100644
--- a/usr/src/lib/libc/port/mapfile-vers
+++ b/usr/src/lib/libc/port/mapfile-vers
@@ -2915,6 +2915,8 @@ $endif
msgctl64;
__multi_innetgr;
_mutex_destroy { FLAGS = NODYNSORT };
+ mutex_enter;
+ mutex_exit;
mutex_held;
_mutex_init { FLAGS = NODYNSORT };
_mutex_unlock { FLAGS = NODYNSORT };
diff --git a/usr/src/lib/libc/port/threads/assfail.c b/usr/src/lib/libc/port/threads/assfail.c
index 8aebefbe4a..b40e6dc029 100644
--- a/usr/src/lib/libc/port/threads/assfail.c
+++ b/usr/src/lib/libc/port/threads/assfail.c
@@ -25,6 +25,7 @@
*/
/*
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
+ * Copyright 2015 Joyent, Inc.
*/
#include "lint.h"
@@ -36,6 +37,8 @@ ulwp_t *panic_thread;
static mutex_t assert_lock = DEFAULTMUTEX;
static ulwp_t *assert_thread = NULL;
+mutex_t *panic_mutex = NULL;
+
/*
* Called from __assert() to set panicstr and panic_thread.
*/
@@ -129,6 +132,13 @@ aio_panic(const char *why)
common_panic("*** libc aio system failure: ", why);
}
+void
+mutex_panic(mutex_t *mp, const char *why)
+{
+ panic_mutex = mp;
+ common_panic("*** libc mutex system failure: ", why);
+}
+
/*
* Utility function for converting a long integer to a string, avoiding stdio.
* 'base' must be one of 10 or 16
diff --git a/usr/src/lib/libc/port/threads/synch.c b/usr/src/lib/libc/port/threads/synch.c
index a7c4aed9ef..b4efb58d17 100644
--- a/usr/src/lib/libc/port/threads/synch.c
+++ b/usr/src/lib/libc/port/threads/synch.c
@@ -22,6 +22,7 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright 2015, Joyent, Inc.
*/
#include "lint.h"
@@ -2314,6 +2315,29 @@ mutex_lock(mutex_t *mp)
return (mutex_lock_impl(mp, NULL));
}
+void
+mutex_enter(mutex_t *mp)
+{
+ int ret;
+ int attr = mp->mutex_type & ALL_ATTRIBUTES;
+
+ /*
+ * Require LOCK_ERRORCHECK, accept LOCK_RECURSIVE.
+ */
+ if (attr != LOCK_ERRORCHECK &&
+ attr != (LOCK_ERRORCHECK | LOCK_RECURSIVE)) {
+ mutex_panic(mp, "mutex_enter: bad mutex type");
+ }
+ ret = mutex_lock(mp);
+ if (ret == EDEADLK) {
+ mutex_panic(mp, "recursive mutex_enter");
+ } else if (ret == EAGAIN) {
+ mutex_panic(mp, "excessive recursive mutex_enter");
+ } else if (ret != 0) {
+ mutex_panic(mp, "unknown mutex_enter failure");
+ }
+}
+
int
pthread_mutex_timedlock(pthread_mutex_t *_RESTRICT_KYWD mp,
const struct timespec *_RESTRICT_KYWD abstime)
@@ -2573,6 +2597,25 @@ slow_unlock:
return (mutex_unlock_internal(mp, 0));
}
+void
+mutex_exit(mutex_t *mp)
+{
+ int ret;
+ int attr = mp->mutex_type & ALL_ATTRIBUTES;
+
+ if (attr != LOCK_ERRORCHECK &&
+ attr != (LOCK_ERRORCHECK | LOCK_RECURSIVE)) {
+ mutex_panic(mp, "mutex_exit: bad mutex type");
+ }
+ ret = mutex_unlock(mp);
+ if (ret == EPERM) {
+ mutex_panic(mp, "mutex_exit: not owner");
+ } else if (ret != 0) {
+ mutex_panic(mp, "unknown mutex_exit failure");
+ }
+
+}
+
/*
* Internally to the library, almost all mutex lock/unlock actions
* go through these lmutex_ functions, to protect critical regions.