void __assfail(const char *assertion, const char *filename, int line_num) { char buf[800]; /* no assert() message in the library is this long */ ulwp_t *self; lwpid_t lwpid; /* avoid recursion deadlock */ if ((self = __curthread()) != NULL) { if (assert_thread == self) _exit(127); enter_critical(self); (void) _lwp_mutex_lock(&assert_lock); assert_thread = self; lwpid = self->ul_lwpid; } else { self = NULL; (void) _lwp_mutex_lock(&assert_lock); lwpid = _lwp_self(); } /* * This is a hack, but since the Abort function isn't exported * to outside consumers, libzpool's vpanic() function calls * assfail() with a filename set to NULL. In that case, it'd be * best not to print "assertion failed" since it was a panic and * not an assertion failure. */ if (filename == NULL) { (void) strcpy(buf, "failure for thread "); } else { (void) strcpy(buf, "assertion failed for thread "); } ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf)); (void) strcat(buf, ", thread-id "); ultos((uint64_t)lwpid, 10, buf + strlen(buf)); (void) strcat(buf, ": "); (void) strcat(buf, assertion); if (filename != NULL) { (void) strcat(buf, ", file "); (void) strcat(buf, filename); (void) strcat(buf, ", line "); ultos((uint64_t)line_num, 10, buf + strlen(buf)); } (void) strcat(buf, "\n"); (void) __write(2, buf, strlen(buf)); /* * We could replace the call to Abort() with the following code * if we want just to issue a warning message and not die. * assert_thread = NULL; * _lwp_mutex_unlock(&assert_lock); * if (self != NULL) * exit_critical(self); */ Abort(buf); }
void assfail3(const char *assertion, uintmax_t lv, const char *op, uintmax_t rv, const char *filename, int line_num) { char buf[1000]; (void) strcpy(buf, assertion); (void) strcat(buf, " ("); ultos((uint64_t)lv, 16, buf + strlen(buf)); (void) strcat(buf, " "); (void) strcat(buf, op); (void) strcat(buf, " "); ultos((uint64_t)rv, 16, buf + strlen(buf)); (void) strcat(buf, ")"); __assfail(buf, filename, line_num); }
/* * Report a thread usage error. * Not called if _THREAD_ERROR_DETECTION=0. * Writes message and continues execution if _THREAD_ERROR_DETECTION=1. * Writes message and dumps core if _THREAD_ERROR_DETECTION=2. */ void thread_error(const char *msg) { char buf[800]; uberdata_t *udp; ulwp_t *self; lwpid_t lwpid; /* avoid recursion deadlock */ if ((self = __curthread()) != NULL) { if (assert_thread == self) _exit(127); enter_critical(self); (void) _lwp_mutex_lock(&assert_lock); assert_thread = self; lwpid = self->ul_lwpid; udp = self->ul_uberdata; } else { self = NULL; (void) _lwp_mutex_lock(&assert_lock); lwpid = _lwp_self(); udp = &__uberdata; } (void) strcpy(buf, "\n*** _THREAD_ERROR_DETECTION: " "thread usage error detected ***\n*** "); (void) strcat(buf, msg); (void) strcat(buf, "\n*** calling thread is "); ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf)); (void) strcat(buf, " thread-id "); ultos((uint64_t)lwpid, 10, buf + strlen(buf)); (void) strcat(buf, "\n\n"); (void) __write(2, buf, strlen(buf)); if (udp->uberflags.uf_thread_error_detection >= 2) Abort(buf); assert_thread = NULL; (void) _lwp_mutex_unlock(&assert_lock); if (self != NULL) exit_critical(self); }
/* * Report application lock usage error for rwlocks. * Not called if _THREAD_ERROR_DETECTION=0. * Continue execution if _THREAD_ERROR_DETECTION=1. * Dump core if _THREAD_ERROR_DETECTION=2. */ void rwlock_error(const rwlock_t *rp, const char *who, const char *msg) { rwlock_t rcopy; uint32_t rwstate; char buf[800]; uberdata_t *udp; ulwp_t *self; lwpid_t lwpid; pid_t pid; int process; /* * Take a snapshot of the rwlock before it changes (we hope!). * Use memcpy() rather than 'rcopy = *rp' in case rp is unaligned. */ (void) memcpy(&rcopy, rp, sizeof (rcopy)); /* avoid recursion deadlock */ if ((self = __curthread()) != NULL) { if (assert_thread == self) _exit(127); enter_critical(self); (void) _lwp_mutex_lock(&assert_lock); assert_thread = self; lwpid = self->ul_lwpid; udp = self->ul_uberdata; pid = udp->pid; } else { self = NULL; (void) _lwp_mutex_lock(&assert_lock); lwpid = _lwp_self(); udp = &__uberdata; pid = getpid(); } rwstate = (uint32_t)rcopy.rwlock_readers; process = (rcopy.rwlock_type & USYNC_PROCESS); (void) strcpy(buf, "\n*** _THREAD_ERROR_DETECTION: lock usage error detected ***\n"); (void) strcat(buf, who); (void) strcat(buf, "("); ultos((uint64_t)(uintptr_t)rp, 16, buf + strlen(buf)); (void) strcat(buf, "): "); (void) strcat(buf, msg); (void) strcat(buf, "\ncalling thread is "); ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf)); (void) strcat(buf, " thread-id "); ultos((uint64_t)lwpid, 10, buf + strlen(buf)); if (process) { (void) strcat(buf, " in process "); ultos((uint64_t)pid, 10, buf + strlen(buf)); } if (rwstate & URW_WRITE_LOCKED) { (void) strcat(buf, "\nthe writer lock owner is "); ultos((uint64_t)rcopy.rwlock_owner, 16, buf + strlen(buf)); if (process) { (void) strcat(buf, " in process "); ultos((uint64_t)rcopy.rwlock_ownerpid, 10, buf + strlen(buf)); } } else if (rwstate & URW_READERS_MASK) { (void) strcat(buf, "\nthe reader lock is held by "); ultos((uint64_t)(rwstate & URW_READERS_MASK), 10, buf + strlen(buf)); (void) strcat(buf, " readers"); } else { (void) strcat(buf, "\nthe lock is unowned"); } if (rwstate & URW_HAS_WAITERS) (void) strcat(buf, "\nand the lock appears to have waiters"); (void) strcat(buf, "\n\n"); (void) __write(2, buf, strlen(buf)); if (udp->uberflags.uf_thread_error_detection >= 2) Abort(buf); assert_thread = NULL; (void) _lwp_mutex_unlock(&assert_lock); if (self != NULL) exit_critical(self); }
/* * Report application lock usage error for mutexes and condvars. * Not called if _THREAD_ERROR_DETECTION=0. * Continue execution if _THREAD_ERROR_DETECTION=1. * Dump core if _THREAD_ERROR_DETECTION=2. */ void lock_error(const mutex_t *mp, const char *who, void *cv, const char *msg) { mutex_t mcopy; char buf[800]; uberdata_t *udp; ulwp_t *self; lwpid_t lwpid; pid_t pid; /* * Take a snapshot of the mutex before it changes (we hope!). * Use memcpy() rather than 'mcopy = *mp' in case mp is unaligned. */ (void) memcpy(&mcopy, mp, sizeof (mcopy)); /* avoid recursion deadlock */ if ((self = __curthread()) != NULL) { if (assert_thread == self) _exit(127); enter_critical(self); (void) _lwp_mutex_lock(&assert_lock); assert_thread = self; lwpid = self->ul_lwpid; udp = self->ul_uberdata; pid = udp->pid; } else { self = NULL; (void) _lwp_mutex_lock(&assert_lock); lwpid = _lwp_self(); udp = &__uberdata; pid = getpid(); } (void) strcpy(buf, "\n*** _THREAD_ERROR_DETECTION: lock usage error detected ***\n"); (void) strcat(buf, who); (void) strcat(buf, "("); if (cv != NULL) { ultos((uint64_t)(uintptr_t)cv, 16, buf + strlen(buf)); (void) strcat(buf, ", "); } ultos((uint64_t)(uintptr_t)mp, 16, buf + strlen(buf)); (void) strcat(buf, ")"); if (msg != NULL) { (void) strcat(buf, ": "); (void) strcat(buf, msg); } else if (!mutex_held(&mcopy)) { (void) strcat(buf, ": calling thread does not own the lock"); } else if (mcopy.mutex_rcount) { (void) strcat(buf, ": mutex rcount = "); ultos((uint64_t)mcopy.mutex_rcount, 10, buf + strlen(buf)); } else { (void) strcat(buf, ": calling thread already owns the lock"); } (void) strcat(buf, "\ncalling thread is "); ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf)); (void) strcat(buf, " thread-id "); ultos((uint64_t)lwpid, 10, buf + strlen(buf)); if (msg != NULL || mutex_held(&mcopy)) /* EMPTY */; else if (mcopy.mutex_lockw == 0) (void) strcat(buf, "\nthe lock is unowned"); else if (!(mcopy.mutex_type & USYNC_PROCESS)) { (void) strcat(buf, "\nthe lock owner is "); ultos((uint64_t)mcopy.mutex_owner, 16, buf + strlen(buf)); } else { (void) strcat(buf, " in process "); ultos((uint64_t)pid, 10, buf + strlen(buf)); (void) strcat(buf, "\nthe lock owner is "); ultos((uint64_t)mcopy.mutex_owner, 16, buf + strlen(buf)); (void) strcat(buf, " in process "); ultos((uint64_t)mcopy.mutex_ownerpid, 10, buf + strlen(buf)); } (void) strcat(buf, "\n\n"); (void) __write(2, buf, strlen(buf)); if (udp->uberflags.uf_thread_error_detection >= 2) Abort(buf); assert_thread = NULL; (void) _lwp_mutex_unlock(&assert_lock); if (self != NULL) exit_critical(self); }
StrPP::StrPP(const unsigned long n) { Init(); ultos(n); }
StrPP::StrPP(const unsigned int n) { Init(); ultos((unsigned long)n); }
StrPP& StrPP::operator=(const unsigned long n) { ultos(n); return *this; }