Skip to content

Commit

Permalink
6209 libc mutexes break kernel writers hearts
Browse files Browse the repository at this point in the history
Reviewed by: Jerry Jelinek <[email protected]>
Reviewed by: Josef 'Jeff' Sipek <[email protected]>
Reviewed by: Dan McDonald <[email protected]>
Reviewed by: Garrett D'Amore <[email protected]>
Approved by: Dan McDonald <[email protected]>
  • Loading branch information
rmustacc committed Sep 14, 2015
1 parent 7bbfa3e commit 0d045c0
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 5 deletions.
6 changes: 6 additions & 0 deletions usr/src/head/synch.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion usr/src/lib/libc/inc/thr_uberdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 *);
Expand Down
2 changes: 2 additions & 0 deletions usr/src/lib/libc/port/mapfile-vers
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand Down
10 changes: 10 additions & 0 deletions usr/src/lib/libc/port/threads/assfail.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
*/
/*
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
* Copyright 2015 Joyent, Inc.
*/

#include "lint.h"
Expand All @@ -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.
*/
Expand Down Expand Up @@ -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
Expand Down
43 changes: 43 additions & 0 deletions usr/src/lib/libc/port/threads/synch.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions usr/src/lib/libzpool/common/kernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
6 changes: 4 additions & 2 deletions usr/src/lib/libzpool/common/sys/zfs_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down

0 comments on commit 0d045c0

Please sign in to comment.