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.
31 #include "thr_uberdata.h"
36 static mutex_t assert_lock
= DEFAULTMUTEX
;
37 static ulwp_t
*assert_thread
= NULL
;
40 * Called from __assert() to set panicstr and panic_thread.
43 __set_panicstr(const char *msg
)
46 panic_thread
= __curthread();
50 * Called from exit() (atexit function) to give precedence
51 * to assertion failures and a core dump over _exit().
56 (void) _lwp_mutex_lock(&assert_lock
);
60 Abort(const char *msg
)
67 /* to help with core file debugging */
69 if ((self
= __curthread()) != NULL
) {
71 lwpid
= self
->ul_lwpid
;
76 /* set SIGABRT signal handler to SIG_DFL w/o grabbing any locks */
77 (void) memset(&act
, 0, sizeof (act
));
78 act
.sa_sigaction
= SIG_DFL
;
79 (void) __sigaction(SIGABRT
, &act
, NULL
);
81 /* delete SIGABRT from the signal mask */
82 (void) sigemptyset(&sigmask
);
83 (void) sigaddset(&sigmask
, SIGABRT
);
84 (void) __lwp_sigmask(SIG_UNBLOCK
, &sigmask
);
86 (void) _lwp_kill(lwpid
, SIGABRT
); /* never returns */
87 (void) kill(getpid(), SIGABRT
); /* if it does, try harder */
92 * Write a panic message w/o grabbing any locks other than assert_lock.
93 * We have no idea what locks are held at this point.
96 common_panic(const char *head
, const char *why
)
98 char msg
[400]; /* no panic() message in the library is this long */
102 if ((self
= __curthread()) != NULL
)
103 enter_critical(self
);
104 (void) _lwp_mutex_lock(&assert_lock
);
106 (void) memset(msg
, 0, sizeof (msg
));
107 (void) strcpy(msg
, head
);
110 if (len1
+ len2
>= sizeof (msg
))
111 len2
= sizeof (msg
) - len1
- 1;
112 (void) strncat(msg
, why
, len2
);
114 if (msg
[len1
- 1] != '\n')
116 (void) __write(2, msg
, len1
);
121 thr_panic(const char *why
)
123 common_panic("*** libc thread failure: ", why
);
127 aio_panic(const char *why
)
129 common_panic("*** libc aio system failure: ", why
);
133 * Utility function for converting a long integer to a string, avoiding stdio.
134 * 'base' must be one of 10 or 16
137 ultos(uint64_t n
, int base
, char *s
)
139 char lbuf
[24]; /* 64 bits fits in 16 hex digits, 20 decimal */
143 *cp
++ = "0123456789abcdef"[n
%base
];
157 * Report application lock usage error for mutexes and condvars.
158 * Not called if _THREAD_ERROR_DETECTION=0.
159 * Continue execution if _THREAD_ERROR_DETECTION=1.
160 * Dump core if _THREAD_ERROR_DETECTION=2.
163 lock_error(const mutex_t
*mp
, const char *who
, void *cv
, const char *msg
)
173 * Take a snapshot of the mutex before it changes (we hope!).
174 * Use memcpy() rather than 'mcopy = *mp' in case mp is unaligned.
176 (void) memcpy(&mcopy
, mp
, sizeof (mcopy
));
178 /* avoid recursion deadlock */
179 if ((self
= __curthread()) != NULL
) {
180 if (assert_thread
== self
)
182 enter_critical(self
);
183 (void) _lwp_mutex_lock(&assert_lock
);
184 assert_thread
= self
;
185 lwpid
= self
->ul_lwpid
;
186 udp
= self
->ul_uberdata
;
190 (void) _lwp_mutex_lock(&assert_lock
);
197 "\n*** _THREAD_ERROR_DETECTION: lock usage error detected ***\n");
198 (void) strcat(buf
, who
);
199 (void) strcat(buf
, "(");
201 ultos((uint64_t)(uintptr_t)cv
, 16, buf
+ strlen(buf
));
202 (void) strcat(buf
, ", ");
204 ultos((uint64_t)(uintptr_t)mp
, 16, buf
+ strlen(buf
));
205 (void) strcat(buf
, ")");
207 (void) strcat(buf
, ": ");
208 (void) strcat(buf
, msg
);
209 } else if (!mutex_held(&mcopy
)) {
210 (void) strcat(buf
, ": calling thread does not own the lock");
211 } else if (mcopy
.mutex_rcount
) {
212 (void) strcat(buf
, ": mutex rcount = ");
213 ultos((uint64_t)mcopy
.mutex_rcount
, 10, buf
+ strlen(buf
));
215 (void) strcat(buf
, ": calling thread already owns the lock");
217 (void) strcat(buf
, "\ncalling thread is ");
218 ultos((uint64_t)(uintptr_t)self
, 16, buf
+ strlen(buf
));
219 (void) strcat(buf
, " thread-id ");
220 ultos((uint64_t)lwpid
, 10, buf
+ strlen(buf
));
221 if (msg
!= NULL
|| mutex_held(&mcopy
))
223 else if (mcopy
.mutex_lockw
== 0)
224 (void) strcat(buf
, "\nthe lock is unowned");
225 else if (!(mcopy
.mutex_type
& USYNC_PROCESS
)) {
226 (void) strcat(buf
, "\nthe lock owner is ");
227 ultos((uint64_t)mcopy
.mutex_owner
, 16, buf
+ strlen(buf
));
229 (void) strcat(buf
, " in process ");
230 ultos((uint64_t)pid
, 10, buf
+ strlen(buf
));
231 (void) strcat(buf
, "\nthe lock owner is ");
232 ultos((uint64_t)mcopy
.mutex_owner
, 16, buf
+ strlen(buf
));
233 (void) strcat(buf
, " in process ");
234 ultos((uint64_t)mcopy
.mutex_ownerpid
, 10, buf
+ strlen(buf
));
236 (void) strcat(buf
, "\n\n");
237 (void) __write(2, buf
, strlen(buf
));
238 if (udp
->uberflags
.uf_thread_error_detection
>= 2)
240 assert_thread
= NULL
;
241 (void) _lwp_mutex_unlock(&assert_lock
);
247 * Report application lock usage error for rwlocks.
248 * Not called if _THREAD_ERROR_DETECTION=0.
249 * Continue execution if _THREAD_ERROR_DETECTION=1.
250 * Dump core if _THREAD_ERROR_DETECTION=2.
253 rwlock_error(const rwlock_t
*rp
, const char *who
, const char *msg
)
265 * Take a snapshot of the rwlock before it changes (we hope!).
266 * Use memcpy() rather than 'rcopy = *rp' in case rp is unaligned.
268 (void) memcpy(&rcopy
, rp
, sizeof (rcopy
));
270 /* avoid recursion deadlock */
271 if ((self
= __curthread()) != NULL
) {
272 if (assert_thread
== self
)
274 enter_critical(self
);
275 (void) _lwp_mutex_lock(&assert_lock
);
276 assert_thread
= self
;
277 lwpid
= self
->ul_lwpid
;
278 udp
= self
->ul_uberdata
;
282 (void) _lwp_mutex_lock(&assert_lock
);
288 rwstate
= (uint32_t)rcopy
.rwlock_readers
;
289 process
= (rcopy
.rwlock_type
& USYNC_PROCESS
);
292 "\n*** _THREAD_ERROR_DETECTION: lock usage error detected ***\n");
293 (void) strcat(buf
, who
);
294 (void) strcat(buf
, "(");
295 ultos((uint64_t)(uintptr_t)rp
, 16, buf
+ strlen(buf
));
296 (void) strcat(buf
, "): ");
297 (void) strcat(buf
, msg
);
298 (void) strcat(buf
, "\ncalling thread is ");
299 ultos((uint64_t)(uintptr_t)self
, 16, buf
+ strlen(buf
));
300 (void) strcat(buf
, " thread-id ");
301 ultos((uint64_t)lwpid
, 10, buf
+ strlen(buf
));
303 (void) strcat(buf
, " in process ");
304 ultos((uint64_t)pid
, 10, buf
+ strlen(buf
));
306 if (rwstate
& URW_WRITE_LOCKED
) {
307 (void) strcat(buf
, "\nthe writer lock owner is ");
308 ultos((uint64_t)rcopy
.rwlock_owner
, 16,
311 (void) strcat(buf
, " in process ");
312 ultos((uint64_t)rcopy
.rwlock_ownerpid
, 10,
315 } else if (rwstate
& URW_READERS_MASK
) {
316 (void) strcat(buf
, "\nthe reader lock is held by ");
317 ultos((uint64_t)(rwstate
& URW_READERS_MASK
), 10,
319 (void) strcat(buf
, " readers");
321 (void) strcat(buf
, "\nthe lock is unowned");
323 if (rwstate
& URW_HAS_WAITERS
)
324 (void) strcat(buf
, "\nand the lock appears to have waiters");
325 (void) strcat(buf
, "\n\n");
326 (void) __write(2, buf
, strlen(buf
));
327 if (udp
->uberflags
.uf_thread_error_detection
>= 2)
329 assert_thread
= NULL
;
330 (void) _lwp_mutex_unlock(&assert_lock
);
336 * Report a thread usage error.
337 * Not called if _THREAD_ERROR_DETECTION=0.
338 * Writes message and continues execution if _THREAD_ERROR_DETECTION=1.
339 * Writes message and dumps core if _THREAD_ERROR_DETECTION=2.
342 thread_error(const char *msg
)
349 /* avoid recursion deadlock */
350 if ((self
= __curthread()) != NULL
) {
351 if (assert_thread
== self
)
353 enter_critical(self
);
354 (void) _lwp_mutex_lock(&assert_lock
);
355 assert_thread
= self
;
356 lwpid
= self
->ul_lwpid
;
357 udp
= self
->ul_uberdata
;
360 (void) _lwp_mutex_lock(&assert_lock
);
365 (void) strcpy(buf
, "\n*** _THREAD_ERROR_DETECTION: "
366 "thread usage error detected ***\n*** ");
367 (void) strcat(buf
, msg
);
369 (void) strcat(buf
, "\n*** calling thread is ");
370 ultos((uint64_t)(uintptr_t)self
, 16, buf
+ strlen(buf
));
371 (void) strcat(buf
, " thread-id ");
372 ultos((uint64_t)lwpid
, 10, buf
+ strlen(buf
));
373 (void) strcat(buf
, "\n\n");
374 (void) __write(2, buf
, strlen(buf
));
375 if (udp
->uberflags
.uf_thread_error_detection
>= 2)
377 assert_thread
= NULL
;
378 (void) _lwp_mutex_unlock(&assert_lock
);
384 * We use __assfail() because the libc __assert() calls
385 * gettext() which calls malloc() which grabs a mutex.
386 * We do everything without calling standard i/o.
387 * assfail() and _assfail() are exported functions;
388 * __assfail() is private to libc.
390 #pragma weak _assfail = __assfail
392 __assfail(const char *assertion
, const char *filename
, int line_num
)
394 char buf
[800]; /* no assert() message in the library is this long */
398 /* avoid recursion deadlock */
399 if ((self
= __curthread()) != NULL
) {
400 if (assert_thread
== self
)
402 enter_critical(self
);
403 (void) _lwp_mutex_lock(&assert_lock
);
404 assert_thread
= self
;
405 lwpid
= self
->ul_lwpid
;
408 (void) _lwp_mutex_lock(&assert_lock
);
413 * This is a hack, but since the Abort function isn't exported
414 * to outside consumers, libzpool's vpanic() function calls
415 * assfail() with a filename set to NULL. In that case, it'd be
416 * best not to print "assertion failed" since it was a panic and
417 * not an assertion failure.
419 if (filename
== NULL
) {
420 (void) strcpy(buf
, "failure for thread ");
422 (void) strcpy(buf
, "assertion failed for thread ");
425 ultos((uint64_t)(uintptr_t)self
, 16, buf
+ strlen(buf
));
426 (void) strcat(buf
, ", thread-id ");
427 ultos((uint64_t)lwpid
, 10, buf
+ strlen(buf
));
428 (void) strcat(buf
, ": ");
429 (void) strcat(buf
, assertion
);
431 if (filename
!= NULL
) {
432 (void) strcat(buf
, ", file ");
433 (void) strcat(buf
, filename
);
434 (void) strcat(buf
, ", line ");
435 ultos((uint64_t)line_num
, 10, buf
+ strlen(buf
));
438 (void) strcat(buf
, "\n");
439 (void) __write(2, buf
, strlen(buf
));
441 * We could replace the call to Abort() with the following code
442 * if we want just to issue a warning message and not die.
443 * assert_thread = NULL;
444 * _lwp_mutex_unlock(&assert_lock);
446 * exit_critical(self);
452 * We define and export this version of assfail() just because libaio
453 * used to define and export it, needlessly. Now that libaio is folded
454 * into libc, we need to continue this for ABI/version reasons.
455 * We don't use "#pragma weak assfail __assfail" in order to avoid
456 * warnings from the check_fnames utility at build time for libraries
457 * that define their own version of assfail().
460 assfail(const char *assertion
, const char *filename
, int line_num
)
462 __assfail(assertion
, filename
, line_num
);
466 assfail3(const char *assertion
, uintmax_t lv
, const char *op
, uintmax_t rv
,
467 const char *filename
, int line_num
)
470 (void) strcpy(buf
, assertion
);
471 (void) strcat(buf
, " (");
472 ultos((uint64_t)lv
, 16, buf
+ strlen(buf
));
473 (void) strcat(buf
, " ");
474 (void) strcat(buf
, op
);
475 (void) strcat(buf
, " ");
476 ultos((uint64_t)rv
, 16, buf
+ strlen(buf
));
477 (void) strcat(buf
, ")");
478 __assfail(buf
, filename
, line_num
);