Skip to content
Permalink
Browse files

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>
  • Loading branch information
rmustacc committed Jun 2, 2015
1 parent 7bbfa3e commit 0d045c0d0cb001d79480ee33be28514e847f8612
@@ -211,6 +211,12 @@ void smt_pause(void);

#endif /* _ASM */

/*
* Panicking versions of our favorite friends.
*/
void mutex_enter(mutex_t *);
void mutex_exit(mutex_t *);

#ifdef __cplusplus
}
#endif
@@ -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 *);
@@ -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 };
@@ -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
@@ -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 @@ mutex_unlock(mutex_t *mp)
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.
@@ -156,7 +156,7 @@ zmutex_destroy(kmutex_t *mp)
}

void
mutex_enter(kmutex_t *mp)
zmutex_enter(kmutex_t *mp)
{
ASSERT(mp->initialized == B_TRUE);
ASSERT(mp->m_owner != (void *)-1UL);
@@ -181,7 +181,7 @@ mutex_tryenter(kmutex_t *mp)
}

void
mutex_exit(kmutex_t *mp)
zmutex_exit(kmutex_t *mp)
{
ASSERT(mp->initialized == B_TRUE);
ASSERT(mutex_owner(mp) == curthread);
@@ -225,11 +225,13 @@ extern int _mutex_destroy(mutex_t *mp);

#define mutex_init(mp, b, c, d) zmutex_init((kmutex_t *)(mp))
#define mutex_destroy(mp) zmutex_destroy((kmutex_t *)(mp))
#define mutex_enter(mp) zmutex_enter(mp)
#define mutex_exit(mp) zmutex_exit(mp)

extern void zmutex_init(kmutex_t *mp);
extern void zmutex_destroy(kmutex_t *mp);
extern void mutex_enter(kmutex_t *mp);
extern void mutex_exit(kmutex_t *mp);
extern void zmutex_enter(kmutex_t *mp);
extern void zmutex_exit(kmutex_t *mp);
extern int mutex_tryenter(kmutex_t *mp);
extern void *mutex_owner(kmutex_t *mp);

0 comments on commit 0d045c0

Please sign in to comment.
You can’t perform that action at this time.