1/* 2 * CDDL HEADER START 3 * 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. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or https://opensource.org/licenses/CDDL-1.0. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21/* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25/* 26 * Copyright (c) 2024, Rob Norris <robn@despairlabs.com> 27 */ 28 29#include <assert.h> 30#include <pthread.h> 31#include <sys/backtrace.h> 32 33#if defined(__linux__) 34#include <errno.h> 35#include <sys/prctl.h> 36#ifdef HAVE_GETTID 37#define libspl_gettid() gettid() 38#else 39#include <sys/syscall.h> 40#define libspl_gettid() ((pid_t)syscall(__NR_gettid)) 41#endif 42#define libspl_getprogname() (program_invocation_short_name) 43#define libspl_getthreadname(buf, len) \ 44 prctl(PR_GET_NAME, (unsigned long)(buf), 0, 0, 0) 45#elif defined(__FreeBSD__) || defined(__APPLE__) 46#if !defined(__APPLE__) 47#include <pthread_np.h> 48#define libspl_gettid() pthread_getthreadid_np() 49#endif 50#define libspl_getprogname() getprogname() 51#define libspl_getthreadname(buf, len) \ 52 pthread_getname_np(pthread_self(), buf, len); 53#endif 54 55#if defined(__APPLE__) 56static inline uint64_t 57libspl_gettid(void) 58{ 59 uint64_t tid; 60 61 if (pthread_threadid_np(NULL, &tid) != 0) 62 tid = 0; 63 64 return (tid); 65} 66#endif 67 68static boolean_t libspl_assert_ok = B_FALSE; 69 70void 71libspl_set_assert_ok(boolean_t val) 72{ 73 libspl_assert_ok = val; 74} 75 76static pthread_mutex_t assert_lock = PTHREAD_MUTEX_INITIALIZER; 77 78/* printf version of libspl_assert */ 79void 80libspl_assertf(const char *file, const char *func, int line, 81 const char *format, ...) 82{ 83 pthread_mutex_lock(&assert_lock); 84 85 va_list args; 86 char tname[64]; 87 88 libspl_getthreadname(tname, sizeof (tname)); 89 90 fprintf(stderr, "ASSERT at %s:%d:%s()\n", file, line, func); 91 92 va_start(args, format); 93 vfprintf(stderr, format, args); 94 va_end(args); 95 96 fprintf(stderr, "\n" 97 " PID: %-8u COMM: %s\n" 98#if defined(__APPLE__) 99 " TID: %-8" PRIu64 " NAME: %s\n", 100#else 101 " TID: %-8u NAME: %s\n", 102#endif 103 getpid(), libspl_getprogname(), 104 libspl_gettid(), tname); 105 106 libspl_backtrace(STDERR_FILENO); 107 108#if !__has_feature(attribute_analyzer_noreturn) && !defined(__COVERITY__) 109 if (libspl_assert_ok) { 110 pthread_mutex_unlock(&assert_lock); 111 return; 112 } 113#endif 114 abort(); 115} 116