4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
28 * Copyright 2015 Joyent, Inc.
32 #include "thr_uberdata.h"
37 static mutex_t assert_lock
= DEFAULTMUTEX
;
38 static ulwp_t
*assert_thread
= NULL
;
40 mutex_t
*panic_mutex
= NULL
;
43 * Called from __assert() to set panicstr and panic_thread.
46 __set_panicstr(const char *msg
)
49 panic_thread
= __curthread();
53 * Called from exit() (atexit function) to give precedence
54 * to assertion failures and a core dump over _exit().
59 (void) _lwp_mutex_lock(&assert_lock
);
63 Abort(const char *msg
)
70 /* to help with core file debugging */
72 if ((self
= __curthread()) != NULL
) {
74 lwpid
= self
->ul_lwpid
;
79 /* set SIGABRT signal handler to SIG_DFL w/o grabbing any locks */
80 (void) memset(&act
, 0, sizeof (act
));
81 act
.sa_sigaction
= SIG_DFL
;
82 (void) __sigaction(SIGABRT
, &act
, NULL
);
84 /* delete SIGABRT from the signal mask */
85 (void) sigemptyset(&sigmask
);
86 (void) sigaddset(&sigmask
, SIGABRT
);
87 (void) __lwp_sigmask(SIG_UNBLOCK
, &sigmask
);
89 (void) _lwp_kill(lwpid
, SIGABRT
); /* never returns */
90 (void) kill(getpid(), SIGABRT
); /* if it does, try harder */
95 * Write a panic message w/o grabbing any locks other than assert_lock.
96 * We have no idea what locks are held at this point.
99 common_panic(const char *head
, const char *why
)
101 char msg
[400]; /* no panic() message in the library is this long */
105 if ((self
= __curthread()) != NULL
)
106 enter_critical(self
);
107 (void) _lwp_mutex_lock(&assert_lock
);
109 (void) memset(msg
, 0, sizeof (msg
));
110 (void) strcpy(msg
, head
);
113 if (len1
+ len2
>= sizeof (msg
))
114 len2
= sizeof (msg
) - len1
- 1;
115 (void) strncat(msg
, why
, len2
);
117 if (msg
[len1
- 1] != '\n')
119 (void) __write(2, msg
, len1
);
124 thr_panic(const char *why
)
126 common_panic("*** libc thread failure: ", why
);
130 aio_panic(const char *why
)
132 common_panic("*** libc aio system failure: ", why
);
136 mutex_panic(mutex_t
*mp
, const char *why
)
139 common_panic("*** libc mutex system failure: ", why
);
143 * Utility function for converting a long integer to a string, avoiding stdio.
144 * 'base' must be one of 10 or 16
147 ultos(uint64_t n
, int base
, char *s
)
149 char lbuf
[24]; /* 64 bits fits in 16 hex digits, 20 decimal */
153 *cp
++ = "0123456789abcdef"[n
%base
];
167 * Report application lock usage error for mutexes and condvars.
168 * Not called if _THREAD_ERROR_DETECTION=0.
169 * Continue execution if _THREAD_ERROR_DETECTION=1.
170 * Dump core if _THREAD_ERROR_DETECTION=2.
173 lock_error(const mutex_t
*mp
, const char *who
, void *cv
, const char *msg
)
183 * Take a snapshot of the mutex before it changes (we hope!).
184 * Use memcpy() rather than 'mcopy = *mp' in case mp is unaligned.
186 (void) memcpy(&mcopy
, mp
, sizeof (mcopy
));
188 /* avoid recursion deadlock */
189 if ((self
= __curthread()) != NULL
) {
190 if (assert_thread
== self
)
192 enter_critical(self
);
193 (void) _lwp_mutex_lock(&assert_lock
);
194 assert_thread
= self
;
195 lwpid
= self
->ul_lwpid
;
196 udp
= self
->ul_uberdata
;
200 (void) _lwp_mutex_lock(&assert_lock
);
207 "\n*** _THREAD_ERROR_DETECTION: lock usage error detected ***\n");
208 (void) strcat(buf
, who
);
209 (void) strcat(buf
, "(");
211 ultos((uint64_t)(uintptr_t)cv
, 16, buf
+ strlen(buf
));
212 (void) strcat(buf
, ", ");
214 ultos((uint64_t)(uintptr_t)mp
, 16, buf
+ strlen(buf
));
215 (void) strcat(buf
, ")");
217 (void) strcat(buf
, ": ");
218 (void) strcat(buf
, msg
);
219 } else if (!mutex_held(&mcopy
)) {
220 (void) strcat(buf
, ": calling thread does not own the lock");
221 } else if (mcopy
.mutex_rcount
) {
222 (void) strcat(buf
, ": mutex rcount = ");
223 ultos((uint64_t)mcopy
.mutex_rcount
, 10, buf
+ strlen(buf
));
225 (void) strcat(buf
, ": calling thread already owns the lock");
227 (void) strcat(buf
, "\ncalling thread is ");
228 ultos((uint64_t)(uintptr_t)self
, 16, buf
+ strlen(buf
));
229 (void) strcat(buf
, " thread-id ");
230 ultos((uint64_t)lwpid
, 10, buf
+ strlen(buf
));
231 if (msg
!= NULL
|| mutex_held(&mcopy
))
233 else if (mcopy
.mutex_lockw
== 0)
234 (void) strcat(buf
, "\nthe lock is unowned");
235 else if (!(mcopy
.mutex_type
& USYNC_PROCESS
)) {
236 (void) strcat(buf
, "\nthe lock owner is ");
237 ultos((uint64_t)mcopy
.mutex_owner
, 16, buf
+ strlen(buf
));
239 (void) strcat(buf
, " in process ");
240 ultos((uint64_t)pid
, 10, buf
+ strlen(buf
));
241 (void) strcat(buf
, "\nthe lock owner is ");
242 ultos((uint64_t)mcopy
.mutex_owner
, 16, buf
+ strlen(buf
));
243 (void) strcat(buf
, " in process ");
244 ultos((uint64_t)mcopy
.mutex_ownerpid
, 10, buf
+ strlen(buf
));
246 (void) strcat(buf
, "\n\n");
247 (void) __write(2, buf
, strlen(buf
));
248 if (udp
->uberflags
.uf_thread_error_detection
>= 2)
250 assert_thread
= NULL
;
251 (void) _lwp_mutex_unlock(&assert_lock
);
257 * Report application lock usage error for rwlocks.
258 * Not called if _THREAD_ERROR_DETECTION=0.
259 * Continue execution if _THREAD_ERROR_DETECTION=1.
260 * Dump core if _THREAD_ERROR_DETECTION=2.
263 rwlock_error(const rwlock_t
*rp
, const char *who
, const char *msg
)
275 * Take a snapshot of the rwlock before it changes (we hope!).
276 * Use memcpy() rather than 'rcopy = *rp' in case rp is unaligned.
278 (void) memcpy(&rcopy
, rp
, sizeof (rcopy
));
280 /* avoid recursion deadlock */
281 if ((self
= __curthread()) != NULL
) {
282 if (assert_thread
== self
)
284 enter_critical(self
);
285 (void) _lwp_mutex_lock(&assert_lock
);
286 assert_thread
= self
;
287 lwpid
= self
->ul_lwpid
;
288 udp
= self
->ul_uberdata
;
292 (void) _lwp_mutex_lock(&assert_lock
);
298 rwstate
= (uint32_t)rcopy
.rwlock_readers
;
299 process
= (rcopy
.rwlock_type
& USYNC_PROCESS
);
302 "\n*** _THREAD_ERROR_DETECTION: lock usage error detected ***\n");
303 (void) strcat(buf
, who
);
304 (void) strcat(buf
, "(");
305 ultos((uint64_t)(uintptr_t)rp
, 16, buf
+ strlen(buf
));
306 (void) strcat(buf
, "): ");
307 (void) strcat(buf
, msg
);
308 (void) strcat(buf
, "\ncalling thread is ");
309 ultos((uint64_t)(uintptr_t)self
, 16, buf
+ strlen(buf
));
310 (void) strcat(buf
, " thread-id ");
311 ultos((uint64_t)lwpid
, 10, buf
+ strlen(buf
));
313 (void) strcat(buf
, " in process ");
314 ultos((uint64_t)pid
, 10, buf
+ strlen(buf
));
316 if (rwstate
& URW_WRITE_LOCKED
) {
317 (void) strcat(buf
, "\nthe writer lock owner is ");
318 ultos((uint64_t)rcopy
.rwlock_owner
, 16,
321 (void) strcat(buf
, " in process ");
322 ultos((uint64_t)rcopy
.rwlock_ownerpid
, 10,
325 } else if (rwstate
& URW_READERS_MASK
) {
326 (void) strcat(buf
, "\nthe reader lock is held by ");
327 ultos((uint64_t)(rwstate
& URW_READERS_MASK
), 10,
329 (void) strcat(buf
, " readers");
331 (void) strcat(buf
, "\nthe lock is unowned");
333 if (rwstate
& URW_HAS_WAITERS
)
334 (void) strcat(buf
, "\nand the lock appears to have waiters");
335 (void) strcat(buf
, "\n\n");
336 (void) __write(2, buf
, strlen(buf
));
337 if (udp
->uberflags
.uf_thread_error_detection
>= 2)
339 assert_thread
= NULL
;
340 (void) _lwp_mutex_unlock(&assert_lock
);
346 * Report a thread usage error.
347 * Not called if _THREAD_ERROR_DETECTION=0.
348 * Writes message and continues execution if _THREAD_ERROR_DETECTION=1.
349 * Writes message and dumps core if _THREAD_ERROR_DETECTION=2.
352 thread_error(const char *msg
)
359 /* avoid recursion deadlock */
360 if ((self
= __curthread()) != NULL
) {
361 if (assert_thread
== self
)
363 enter_critical(self
);
364 (void) _lwp_mutex_lock(&assert_lock
);
365 assert_thread
= self
;
366 lwpid
= self
->ul_lwpid
;
367 udp
= self
->ul_uberdata
;
370 (void) _lwp_mutex_lock(&assert_lock
);
375 (void) strcpy(buf
, "\n*** _THREAD_ERROR_DETECTION: "
376 "thread usage error detected ***\n*** ");
377 (void) strcat(buf
, msg
);
379 (void) strcat(buf
, "\n*** calling thread is ");
380 ultos((uint64_t)(uintptr_t)self
, 16, buf
+ strlen(buf
));
381 (void) strcat(buf
, " thread-id ");
382 ultos((uint64_t)lwpid
, 10, buf
+ strlen(buf
));
383 (void) strcat(buf
, "\n\n");
384 (void) __write(2, buf
, strlen(buf
));
385 if (udp
->uberflags
.uf_thread_error_detection
>= 2)
387 assert_thread
= NULL
;
388 (void) _lwp_mutex_unlock(&assert_lock
);
394 * We use __assfail() because the libc __assert() calls
395 * gettext() which calls malloc() which grabs a mutex.
396 * We do everything without calling standard i/o.
397 * assfail() and _assfail() are exported functions;
398 * __assfail() is private to libc.
400 #pragma weak _assfail = __assfail
402 __assfail(const char *assertion
, const char *filename
, int line_num
)
404 char buf
[800]; /* no assert() message in the library is this long */
408 /* avoid recursion deadlock */
409 if ((self
= __curthread()) != NULL
) {
410 if (assert_thread
== self
)
412 enter_critical(self
);
413 (void) _lwp_mutex_lock(&assert_lock
);
414 assert_thread
= self
;
415 lwpid
= self
->ul_lwpid
;
418 (void) _lwp_mutex_lock(&assert_lock
);
423 * This is a hack, but since the Abort function isn't exported
424 * to outside consumers, libzpool's vpanic() function calls
425 * assfail() with a filename set to NULL. In that case, it'd be
426 * best not to print "assertion failed" since it was a panic and
427 * not an assertion failure.
429 if (filename
== NULL
) {
430 (void) strcpy(buf
, "failure for thread ");
432 (void) strcpy(buf
, "assertion failed for thread ");
435 ultos((uint64_t)(uintptr_t)self
, 16, buf
+ strlen(buf
));
436 (void) strcat(buf
, ", thread-id ");
437 ultos((uint64_t)lwpid
, 10, buf
+ strlen(buf
));
438 (void) strcat(buf
, ": ");
439 (void) strcat(buf
, assertion
);
441 if (filename
!= NULL
) {
442 (void) strcat(buf
, ", file ");
443 (void) strcat(buf
, filename
);
444 (void) strcat(buf
, ", line ");
445 ultos((uint64_t)line_num
, 10, buf
+ strlen(buf
));
448 (void) strcat(buf
, "\n");
449 (void) __write(2, buf
, strlen(buf
));
451 * We could replace the call to Abort() with the following code
452 * if we want just to issue a warning message and not die.
453 * assert_thread = NULL;
454 * _lwp_mutex_unlock(&assert_lock);
456 * exit_critical(self);
462 * We define and export this version of assfail() just because libaio
463 * used to define and export it, needlessly. Now that libaio is folded
464 * into libc, we need to continue this for ABI/version reasons.
465 * We don't use "#pragma weak assfail __assfail" in order to avoid
466 * warnings from the check_fnames utility at build time for libraries
467 * that define their own version of assfail().
470 assfail(const char *assertion
, const char *filename
, int line_num
)
472 __assfail(assertion
, filename
, line_num
);
476 assfail3(const char *assertion
, uintmax_t lv
, const char *op
, uintmax_t rv
,
477 const char *filename
, int line_num
)
480 (void) strcpy(buf
, assertion
);
481 (void) strcat(buf
, " (");
482 ultos((uint64_t)lv
, 16, buf
+ strlen(buf
));
483 (void) strcat(buf
, " ");
484 (void) strcat(buf
, op
);
485 (void) strcat(buf
, " ");
486 ultos((uint64_t)rv
, 16, buf
+ strlen(buf
));
487 (void) strcat(buf
, ")");
488 __assfail(buf
, filename
, line_num
);