diff options
author | Robert Mustacchi <rm@joyent.com> | 2015-06-02 17:12:04 +0000 |
---|---|---|
committer | Robert Mustacchi <rm@joyent.com> | 2015-09-14 13:47:46 -0700 |
commit | 0d045c0d0cb001d79480ee33be28514e847f8612 (patch) | |
tree | 3454a95214e5f8ac18f52c0db7886d5027091b9a /usr/src/lib/libc | |
parent | 7bbfa3ee1f517d6d5762f10047886094cea843a1 (diff) | |
download | illumos-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.h | 4 | ||||
-rw-r--r-- | usr/src/lib/libc/port/mapfile-vers | 2 | ||||
-rw-r--r-- | usr/src/lib/libc/port/threads/assfail.c | 10 | ||||
-rw-r--r-- | usr/src/lib/libc/port/threads/synch.c | 43 |
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. |