Home | History | Annotate | Download | only in threads
      1      0  stevel /*
      2      0  stevel  * CDDL HEADER START
      3      0  stevel  *
      4      0  stevel  * The contents of this file are subject to the terms of the
      5   2248     raf  * Common Development and Distribution License (the "License").
      6   2248     raf  * You may not use this file except in compliance with the License.
      7      0  stevel  *
      8      0  stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9      0  stevel  * or http://www.opensolaris.org/os/licensing.
     10      0  stevel  * See the License for the specific language governing permissions
     11      0  stevel  * and limitations under the License.
     12      0  stevel  *
     13      0  stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14      0  stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15      0  stevel  * If applicable, add the following below this CDDL HEADER, with the
     16      0  stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17      0  stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18      0  stevel  *
     19      0  stevel  * CDDL HEADER END
     20      0  stevel  */
     21   2248     raf 
     22      0  stevel /*
     23  10629   Roger  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24      0  stevel  * Use is subject to license terms.
     25      0  stevel  */
     26      0  stevel 
     27      0  stevel #include "lint.h"
     28      0  stevel #include "thr_uberdata.h"
     29      0  stevel 
     30      0  stevel const char *panicstr;
     31      0  stevel ulwp_t *panic_thread;
     32      0  stevel 
     33      0  stevel static mutex_t assert_lock = DEFAULTMUTEX;
     34      0  stevel static ulwp_t *assert_thread = NULL;
     35      0  stevel 
     36      0  stevel /*
     37      0  stevel  * Called from __assert() to set panicstr and panic_thread.
     38      0  stevel  */
     39      0  stevel void
     40      0  stevel __set_panicstr(const char *msg)
     41      0  stevel {
     42      0  stevel 	panicstr = msg;
     43      0  stevel 	panic_thread = __curthread();
     44      0  stevel }
     45      0  stevel 
     46      0  stevel /*
     47      0  stevel  * Called from exit() (atexit function) to give precedence
     48      0  stevel  * to assertion failures and a core dump over _exit().
     49      0  stevel  */
     50      0  stevel void
     51      0  stevel grab_assert_lock()
     52      0  stevel {
     53   6515     raf 	(void) _lwp_mutex_lock(&assert_lock);
     54      0  stevel }
     55      0  stevel 
     56      0  stevel static void
     57      0  stevel Abort(const char *msg)
     58      0  stevel {
     59      0  stevel 	ulwp_t *self;
     60      0  stevel 	struct sigaction act;
     61      0  stevel 	sigset_t sigmask;
     62      0  stevel 	lwpid_t lwpid;
     63      0  stevel 
     64      0  stevel 	/* to help with core file debugging */
     65      0  stevel 	panicstr = msg;
     66      0  stevel 	if ((self = __curthread()) != NULL) {
     67      0  stevel 		panic_thread = self;
     68      0  stevel 		lwpid = self->ul_lwpid;
     69      0  stevel 	} else {
     70   6812     raf 		lwpid = _lwp_self();
     71      0  stevel 	}
     72      0  stevel 
     73      0  stevel 	/* set SIGABRT signal handler to SIG_DFL w/o grabbing any locks */
     74   6515     raf 	(void) memset(&act, 0, sizeof (act));
     75      0  stevel 	act.sa_sigaction = SIG_DFL;
     76      0  stevel 	(void) __sigaction(SIGABRT, &act, NULL);
     77      0  stevel 
     78      0  stevel 	/* delete SIGABRT from the signal mask */
     79   6515     raf 	(void) sigemptyset(&sigmask);
     80   6515     raf 	(void) sigaddset(&sigmask, SIGABRT);
     81      0  stevel 	(void) __lwp_sigmask(SIG_UNBLOCK, &sigmask, NULL);
     82      0  stevel 
     83   6812     raf 	(void) _lwp_kill(lwpid, SIGABRT);	/* never returns */
     84   6812     raf 	(void) kill(getpid(), SIGABRT);	/* if it does, try harder */
     85      0  stevel 	_exit(127);
     86      0  stevel }
     87      0  stevel 
     88      0  stevel /*
     89      0  stevel  * Write a panic message w/o grabbing any locks other than assert_lock.
     90      0  stevel  * We have no idea what locks are held at this point.
     91      0  stevel  */
     92   2248     raf static void
     93   2248     raf common_panic(const char *head, const char *why)
     94      0  stevel {
     95      0  stevel 	char msg[400];	/* no panic() message in the library is this long */
     96      0  stevel 	ulwp_t *self;
     97      0  stevel 	size_t len1, len2;
     98      0  stevel 
     99      0  stevel 	if ((self = __curthread()) != NULL)
    100      0  stevel 		enter_critical(self);
    101   6515     raf 	(void) _lwp_mutex_lock(&assert_lock);
    102      0  stevel 
    103   6515     raf 	(void) memset(msg, 0, sizeof (msg));
    104   2248     raf 	(void) strcpy(msg, head);
    105      0  stevel 	len1 = strlen(msg);
    106      0  stevel 	len2 = strlen(why);
    107      0  stevel 	if (len1 + len2 >= sizeof (msg))
    108      0  stevel 		len2 = sizeof (msg) - len1 - 1;
    109      0  stevel 	(void) strncat(msg, why, len2);
    110      0  stevel 	len1 = strlen(msg);
    111      0  stevel 	if (msg[len1 - 1] != '\n')
    112      0  stevel 		msg[len1++] = '\n';
    113   5891     raf 	(void) __write(2, msg, len1);
    114      0  stevel 	Abort(msg);
    115   2248     raf }
    116   2248     raf 
    117   2248     raf void
    118   2248     raf thr_panic(const char *why)
    119   2248     raf {
    120   2248     raf 	common_panic("*** libc thread failure: ", why);
    121   2248     raf }
    122   2248     raf 
    123   2248     raf void
    124   2248     raf aio_panic(const char *why)
    125   2248     raf {
    126   2248     raf 	common_panic("*** libc aio system failure: ", why);
    127      0  stevel }
    128      0  stevel 
    129      0  stevel /*
    130      0  stevel  * Utility function for converting a long integer to a string, avoiding stdio.
    131      0  stevel  * 'base' must be one of 10 or 16
    132      0  stevel  */
    133      0  stevel void
    134      0  stevel ultos(uint64_t n, int base, char *s)
    135      0  stevel {
    136      0  stevel 	char lbuf[24];		/* 64 bits fits in 16 hex digits, 20 decimal */
    137      0  stevel 	char *cp = lbuf;
    138      0  stevel 
    139      0  stevel 	do {
    140      0  stevel 		*cp++ = "0123456789abcdef"[n%base];
    141      0  stevel 		n /= base;
    142      0  stevel 	} while (n);
    143      0  stevel 	if (base == 16) {
    144      0  stevel 		*s++ = '0';
    145      0  stevel 		*s++ = 'x';
    146      0  stevel 	}
    147      0  stevel 	do {
    148      0  stevel 		*s++ = *--cp;
    149      0  stevel 	} while (cp > lbuf);
    150      0  stevel 	*s = '\0';
    151      0  stevel }
    152      0  stevel 
    153      0  stevel /*
    154      0  stevel  * Report application lock usage error for mutexes and condvars.
    155      0  stevel  * Not called if _THREAD_ERROR_DETECTION=0.
    156      0  stevel  * Continue execution if _THREAD_ERROR_DETECTION=1.
    157      0  stevel  * Dump core if _THREAD_ERROR_DETECTION=2.
    158      0  stevel  */
    159      0  stevel void
    160      0  stevel lock_error(const mutex_t *mp, const char *who, void *cv, const char *msg)
    161      0  stevel {
    162  10629   Roger 	mutex_t mcopy;
    163      0  stevel 	char buf[800];
    164      0  stevel 	uberdata_t *udp;
    165      0  stevel 	ulwp_t *self;
    166      0  stevel 	lwpid_t lwpid;
    167      0  stevel 	pid_t pid;
    168  10629   Roger 
    169  10629   Roger 	/*
    170  10629   Roger 	 * Take a snapshot of the mutex before it changes (we hope!).
    171  10629   Roger 	 * Use memcpy() rather than 'mcopy = *mp' in case mp is unaligned.
    172  10629   Roger 	 */
    173  10629   Roger 	(void) memcpy(&mcopy, mp, sizeof (mcopy));
    174      0  stevel 
    175      0  stevel 	/* avoid recursion deadlock */
    176      0  stevel 	if ((self = __curthread()) != NULL) {
    177      0  stevel 		if (assert_thread == self)
    178      0  stevel 			_exit(127);
    179      0  stevel 		enter_critical(self);
    180   6515     raf 		(void) _lwp_mutex_lock(&assert_lock);
    181      0  stevel 		assert_thread = self;
    182      0  stevel 		lwpid = self->ul_lwpid;
    183      0  stevel 		udp = self->ul_uberdata;
    184      0  stevel 		pid = udp->pid;
    185      0  stevel 	} else {
    186      0  stevel 		self = NULL;
    187   6515     raf 		(void) _lwp_mutex_lock(&assert_lock);
    188   6812     raf 		lwpid = _lwp_self();
    189      0  stevel 		udp = &__uberdata;
    190   6515     raf 		pid = getpid();
    191      0  stevel 	}
    192      0  stevel 
    193      0  stevel 	(void) strcpy(buf,
    194      0  stevel 	    "\n*** _THREAD_ERROR_DETECTION: lock usage error detected ***\n");
    195      0  stevel 	(void) strcat(buf, who);
    196      0  stevel 	(void) strcat(buf, "(");
    197      0  stevel 	if (cv != NULL) {
    198      0  stevel 		ultos((uint64_t)(uintptr_t)cv, 16, buf + strlen(buf));
    199      0  stevel 		(void) strcat(buf, ", ");
    200      0  stevel 	}
    201      0  stevel 	ultos((uint64_t)(uintptr_t)mp, 16, buf + strlen(buf));
    202      0  stevel 	(void) strcat(buf, ")");
    203      0  stevel 	if (msg != NULL) {
    204      0  stevel 		(void) strcat(buf, ": ");
    205      0  stevel 		(void) strcat(buf, msg);
    206   6812     raf 	} else if (!mutex_held(&mcopy)) {
    207      0  stevel 		(void) strcat(buf, ": calling thread does not own the lock");
    208      0  stevel 	} else if (mcopy.mutex_rcount) {
    209      0  stevel 		(void) strcat(buf, ": mutex rcount = ");
    210      0  stevel 		ultos((uint64_t)mcopy.mutex_rcount, 10, buf + strlen(buf));
    211      0  stevel 	} else {
    212      0  stevel 		(void) strcat(buf, ": calling thread already owns the lock");
    213      0  stevel 	}
    214      0  stevel 	(void) strcat(buf, "\ncalling thread is ");
    215      0  stevel 	ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf));
    216      0  stevel 	(void) strcat(buf, " thread-id ");
    217      0  stevel 	ultos((uint64_t)lwpid, 10, buf + strlen(buf));
    218   6812     raf 	if (msg != NULL || mutex_held(&mcopy))
    219      0  stevel 		/* EMPTY */;
    220      0  stevel 	else if (mcopy.mutex_lockw == 0)
    221      0  stevel 		(void) strcat(buf, "\nthe lock is unowned");
    222   4574     raf 	else if (!(mcopy.mutex_type & USYNC_PROCESS)) {
    223      0  stevel 		(void) strcat(buf, "\nthe lock owner is ");
    224      0  stevel 		ultos((uint64_t)mcopy.mutex_owner, 16, buf + strlen(buf));
    225      0  stevel 	} else {
    226      0  stevel 		(void) strcat(buf, " in process ");
    227      0  stevel 		ultos((uint64_t)pid, 10, buf + strlen(buf));
    228      0  stevel 		(void) strcat(buf, "\nthe lock owner is ");
    229      0  stevel 		ultos((uint64_t)mcopy.mutex_owner, 16, buf + strlen(buf));
    230      0  stevel 		(void) strcat(buf, " in process ");
    231      0  stevel 		ultos((uint64_t)mcopy.mutex_ownerpid, 10, buf + strlen(buf));
    232      0  stevel 	}
    233      0  stevel 	(void) strcat(buf, "\n\n");
    234   5891     raf 	(void) __write(2, buf, strlen(buf));
    235      0  stevel 	if (udp->uberflags.uf_thread_error_detection >= 2)
    236      0  stevel 		Abort(buf);
    237      0  stevel 	assert_thread = NULL;
    238   6515     raf 	(void) _lwp_mutex_unlock(&assert_lock);
    239      0  stevel 	if (self != NULL)
    240      0  stevel 		exit_critical(self);
    241      0  stevel }
    242      0  stevel 
    243      0  stevel /*
    244      0  stevel  * Report application lock usage error for rwlocks.
    245      0  stevel  * Not called if _THREAD_ERROR_DETECTION=0.
    246      0  stevel  * Continue execution if _THREAD_ERROR_DETECTION=1.
    247      0  stevel  * Dump core if _THREAD_ERROR_DETECTION=2.
    248      0  stevel  */
    249      0  stevel void
    250      0  stevel rwlock_error(const rwlock_t *rp, const char *who, const char *msg)
    251      0  stevel {
    252  10629   Roger 	rwlock_t rcopy;
    253   4570     raf 	uint32_t rwstate;
    254      0  stevel 	char buf[800];
    255      0  stevel 	uberdata_t *udp;
    256      0  stevel 	ulwp_t *self;
    257      0  stevel 	lwpid_t lwpid;
    258      0  stevel 	pid_t pid;
    259   4570     raf 	int process;
    260  10629   Roger 
    261  10629   Roger 	/*
    262  10629   Roger 	 * Take a snapshot of the rwlock before it changes (we hope!).
    263  10629   Roger 	 * Use memcpy() rather than 'rcopy = *rp' in case rp is unaligned.
    264  10629   Roger 	 */
    265  10629   Roger 	(void) memcpy(&rcopy, rp, sizeof (rcopy));
    266      0  stevel 
    267      0  stevel 	/* avoid recursion deadlock */
    268      0  stevel 	if ((self = __curthread()) != NULL) {
    269      0  stevel 		if (assert_thread == self)
    270      0  stevel 			_exit(127);
    271      0  stevel 		enter_critical(self);
    272   6515     raf 		(void) _lwp_mutex_lock(&assert_lock);
    273      0  stevel 		assert_thread = self;
    274      0  stevel 		lwpid = self->ul_lwpid;
    275      0  stevel 		udp = self->ul_uberdata;
    276      0  stevel 		pid = udp->pid;
    277      0  stevel 	} else {
    278      0  stevel 		self = NULL;
    279   6515     raf 		(void) _lwp_mutex_lock(&assert_lock);
    280   6812     raf 		lwpid = _lwp_self();
    281      0  stevel 		udp = &__uberdata;
    282   6515     raf 		pid = getpid();
    283      0  stevel 	}
    284      0  stevel 
    285   4570     raf 	rwstate = (uint32_t)rcopy.rwlock_readers;
    286   4570     raf 	process = (rcopy.rwlock_type & USYNC_PROCESS);
    287   4570     raf 
    288      0  stevel 	(void) strcpy(buf,
    289      0  stevel 	    "\n*** _THREAD_ERROR_DETECTION: lock usage error detected ***\n");
    290      0  stevel 	(void) strcat(buf, who);
    291      0  stevel 	(void) strcat(buf, "(");
    292      0  stevel 	ultos((uint64_t)(uintptr_t)rp, 16, buf + strlen(buf));
    293      0  stevel 	(void) strcat(buf, "): ");
    294      0  stevel 	(void) strcat(buf, msg);
    295      0  stevel 	(void) strcat(buf, "\ncalling thread is ");
    296      0  stevel 	ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf));
    297      0  stevel 	(void) strcat(buf, " thread-id ");
    298      0  stevel 	ultos((uint64_t)lwpid, 10, buf + strlen(buf));
    299   4570     raf 	if (process) {
    300      0  stevel 		(void) strcat(buf, " in process ");
    301      0  stevel 		ultos((uint64_t)pid, 10, buf + strlen(buf));
    302   4570     raf 	}
    303   4570     raf 	if (rwstate & URW_WRITE_LOCKED) {
    304   4570     raf 		(void) strcat(buf, "\nthe writer lock owner is ");
    305   4570     raf 		ultos((uint64_t)rcopy.rwlock_owner, 16,
    306   4570     raf 		    buf + strlen(buf));
    307   4570     raf 		if (process) {
    308      0  stevel 			(void) strcat(buf, " in process ");
    309      0  stevel 			ultos((uint64_t)rcopy.rwlock_ownerpid, 10,
    310      0  stevel 			    buf + strlen(buf));
    311      0  stevel 		}
    312   4570     raf 	} else if (rwstate & URW_READERS_MASK) {
    313   4570     raf 		(void) strcat(buf, "\nthe reader lock is held by ");
    314   4570     raf 		ultos((uint64_t)(rwstate & URW_READERS_MASK), 10,
    315   4570     raf 		    buf + strlen(buf));
    316   4570     raf 		(void) strcat(buf, " readers");
    317      0  stevel 	} else {
    318      0  stevel 		(void) strcat(buf, "\nthe lock is unowned");
    319      0  stevel 	}
    320   4570     raf 	if (rwstate & URW_HAS_WAITERS)
    321   4570     raf 		(void) strcat(buf, "\nand the lock appears to have waiters");
    322      0  stevel 	(void) strcat(buf, "\n\n");
    323   5891     raf 	(void) __write(2, buf, strlen(buf));
    324      0  stevel 	if (udp->uberflags.uf_thread_error_detection >= 2)
    325      0  stevel 		Abort(buf);
    326      0  stevel 	assert_thread = NULL;
    327   6515     raf 	(void) _lwp_mutex_unlock(&assert_lock);
    328      0  stevel 	if (self != NULL)
    329      0  stevel 		exit_critical(self);
    330      0  stevel }
    331      0  stevel 
    332      0  stevel /*
    333      0  stevel  * Report a thread usage error.
    334      0  stevel  * Not called if _THREAD_ERROR_DETECTION=0.
    335      0  stevel  * Writes message and continues execution if _THREAD_ERROR_DETECTION=1.
    336      0  stevel  * Writes message and dumps core if _THREAD_ERROR_DETECTION=2.
    337      0  stevel  */
    338      0  stevel void
    339      0  stevel thread_error(const char *msg)
    340      0  stevel {
    341      0  stevel 	char buf[800];
    342      0  stevel 	uberdata_t *udp;
    343      0  stevel 	ulwp_t *self;
    344      0  stevel 	lwpid_t lwpid;
    345      0  stevel 
    346      0  stevel 	/* avoid recursion deadlock */
    347      0  stevel 	if ((self = __curthread()) != NULL) {
    348      0  stevel 		if (assert_thread == self)
    349      0  stevel 			_exit(127);
    350      0  stevel 		enter_critical(self);
    351   6515     raf 		(void) _lwp_mutex_lock(&assert_lock);
    352      0  stevel 		assert_thread = self;
    353      0  stevel 		lwpid = self->ul_lwpid;
    354      0  stevel 		udp = self->ul_uberdata;
    355      0  stevel 	} else {
    356      0  stevel 		self = NULL;
    357   6515     raf 		(void) _lwp_mutex_lock(&assert_lock);
    358   6812     raf 		lwpid = _lwp_self();
    359      0  stevel 		udp = &__uberdata;
    360      0  stevel 	}
    361      0  stevel 
    362      0  stevel 	(void) strcpy(buf, "\n*** _THREAD_ERROR_DETECTION: "
    363   5891     raf 	    "thread usage error detected ***\n*** ");
    364      0  stevel 	(void) strcat(buf, msg);
    365      0  stevel 
    366      0  stevel 	(void) strcat(buf, "\n*** calling thread is ");
    367      0  stevel 	ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf));
    368      0  stevel 	(void) strcat(buf, " thread-id ");
    369      0  stevel 	ultos((uint64_t)lwpid, 10, buf + strlen(buf));
    370      0  stevel 	(void) strcat(buf, "\n\n");
    371   5891     raf 	(void) __write(2, buf, strlen(buf));
    372      0  stevel 	if (udp->uberflags.uf_thread_error_detection >= 2)
    373      0  stevel 		Abort(buf);
    374      0  stevel 	assert_thread = NULL;
    375   6515     raf 	(void) _lwp_mutex_unlock(&assert_lock);
    376      0  stevel 	if (self != NULL)
    377      0  stevel 		exit_critical(self);
    378      0  stevel }
    379      0  stevel 
    380      0  stevel /*
    381      0  stevel  * We use __assfail() because the libc __assert() calls
    382      0  stevel  * gettext() which calls malloc() which grabs a mutex.
    383      0  stevel  * We do everything without calling standard i/o.
    384   2248     raf  * assfail() and _assfail() are exported functions;
    385   2248     raf  * __assfail() is private to libc.
    386      0  stevel  */
    387      0  stevel #pragma weak _assfail = __assfail
    388      0  stevel void
    389      0  stevel __assfail(const char *assertion, const char *filename, int line_num)
    390      0  stevel {
    391      0  stevel 	char buf[800];	/* no assert() message in the library is this long */
    392      0  stevel 	ulwp_t *self;
    393      0  stevel 	lwpid_t lwpid;
    394      0  stevel 
    395      0  stevel 	/* avoid recursion deadlock */
    396      0  stevel 	if ((self = __curthread()) != NULL) {
    397      0  stevel 		if (assert_thread == self)
    398      0  stevel 			_exit(127);
    399      0  stevel 		enter_critical(self);
    400   6515     raf 		(void) _lwp_mutex_lock(&assert_lock);
    401      0  stevel 		assert_thread = self;
    402      0  stevel 		lwpid = self->ul_lwpid;
    403      0  stevel 	} else {
    404      0  stevel 		self = NULL;
    405   6515     raf 		(void) _lwp_mutex_lock(&assert_lock);
    406   6812     raf 		lwpid = _lwp_self();
    407      0  stevel 	}
    408      0  stevel 
    409      0  stevel 	(void) strcpy(buf, "assertion failed for thread ");
    410      0  stevel 	ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf));
    411      0  stevel 	(void) strcat(buf, ", thread-id ");
    412      0  stevel 	ultos((uint64_t)lwpid, 10, buf + strlen(buf));
    413      0  stevel 	(void) strcat(buf, ": ");
    414      0  stevel 	(void) strcat(buf, assertion);
    415      0  stevel 	(void) strcat(buf, ", file ");
    416      0  stevel 	(void) strcat(buf, filename);
    417      0  stevel 	(void) strcat(buf, ", line ");
    418      0  stevel 	ultos((uint64_t)line_num, 10, buf + strlen(buf));
    419      0  stevel 	(void) strcat(buf, "\n");
    420   5891     raf 	(void) __write(2, buf, strlen(buf));
    421      0  stevel 	/*
    422      0  stevel 	 * We could replace the call to Abort() with the following code
    423      0  stevel 	 * if we want just to issue a warning message and not die.
    424      0  stevel 	 *	assert_thread = NULL;
    425   6515     raf 	 *	_lwp_mutex_unlock(&assert_lock);
    426      0  stevel 	 *	if (self != NULL)
    427      0  stevel 	 *		exit_critical(self);
    428      0  stevel 	 */
    429      0  stevel 	Abort(buf);
    430      0  stevel }
    431   2248     raf 
    432   2248     raf /*
    433   2248     raf  * We define and export this version of assfail() just because libaio
    434   2248     raf  * used to define and export it, needlessly.  Now that libaio is folded
    435   2248     raf  * into libc, we need to continue this for ABI/version reasons.
    436   2248     raf  * We don't use "#pragma weak assfail __assfail" in order to avoid
    437   2248     raf  * warnings from the check_fnames utility at build time for libraries
    438   2248     raf  * that define their own version of assfail().
    439   2248     raf  */
    440   2248     raf void
    441   2248     raf assfail(const char *assertion, const char *filename, int line_num)
    442   2248     raf {
    443   2248     raf 	__assfail(assertion, filename, line_num);
    444   2248     raf }
    445