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