uu_misc.c revision 168404
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 http://www.opensolaris.org/os/licensing. 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/* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27#pragma ident "%Z%%M% %I% %E% SMI" 28 29#include "libuutil_common.h" 30 31#include <assert.h> 32#include <errno.h> 33#include <libintl.h> 34#include <pthread.h> 35#include <stdarg.h> 36#include <stdio.h> 37#include <stdlib.h> 38#include <string.h> 39#include <sys/debug.h> 40#include <thread.h> 41#include <unistd.h> 42 43#if !defined(TEXT_DOMAIN) 44#define TEXT_DOMAIN "SYS_TEST" 45#endif 46 47/* 48 * All of the old code under !defined(PTHREAD_ONCE_KEY_NP) 49 * is here to enable the building of a native version of 50 * libuutil.so when the build machine has not yet been upgraded 51 * to a version of libc that provides pthread_key_create_once_np(). 52 * It should all be deleted when solaris_nevada ships. 53 * The code is not MT-safe in a relaxed memory model. 54 */ 55 56#if defined(PTHREAD_ONCE_KEY_NP) 57static pthread_key_t uu_error_key = PTHREAD_ONCE_KEY_NP; 58#else /* PTHREAD_ONCE_KEY_NP */ 59static pthread_key_t uu_error_key = 0; 60static pthread_mutex_t uu_key_lock = PTHREAD_MUTEX_INITIALIZER; 61#endif /* PTHREAD_ONCE_KEY_NP */ 62 63static int uu_error_key_setup = 0; 64 65static pthread_mutex_t uu_panic_lock = PTHREAD_MUTEX_INITIALIZER; 66/* LINTED static unused */ 67static const char *uu_panic_format; 68/* LINTED static unused */ 69static va_list uu_panic_args; 70static pthread_t uu_panic_thread; 71 72static uint32_t _uu_main_error; 73 74void 75uu_set_error(uint_t code) 76{ 77 78#if defined(PTHREAD_ONCE_KEY_NP) 79 if (pthread_key_create_once_np(&uu_error_key, NULL) != 0) 80 uu_error_key_setup = -1; 81 else 82 uu_error_key_setup = 1; 83#else /* PTHREAD_ONCE_KEY_NP */ 84 if (uu_error_key_setup == 0) { 85 (void) pthread_mutex_lock(&uu_key_lock); 86 if (uu_error_key_setup == 0) { 87 if (pthread_key_create(&uu_error_key, NULL) != 0) 88 uu_error_key_setup = -1; 89 else 90 uu_error_key_setup = 1; 91 } 92 (void) pthread_mutex_unlock(&uu_key_lock); 93 } 94#endif /* PTHREAD_ONCE_KEY_NP */ 95 if (uu_error_key_setup > 0) 96 (void) pthread_setspecific(uu_error_key, 97 (void *)(uintptr_t)code); 98} 99 100uint32_t 101uu_error(void) 102{ 103 104 if (uu_error_key_setup < 0) /* can't happen? */ 105 return (UU_ERROR_UNKNOWN); 106 107 /* 108 * Because UU_ERROR_NONE == 0, if uu_set_error() was 109 * never called, then this will return UU_ERROR_NONE: 110 */ 111 return ((uint32_t)(uintptr_t)pthread_getspecific(uu_error_key)); 112} 113 114const char * 115uu_strerror(uint32_t code) 116{ 117 const char *str; 118 119 switch (code) { 120 case UU_ERROR_NONE: 121 str = dgettext(TEXT_DOMAIN, "No error"); 122 break; 123 124 case UU_ERROR_INVALID_ARGUMENT: 125 str = dgettext(TEXT_DOMAIN, "Invalid argument"); 126 break; 127 128 case UU_ERROR_UNKNOWN_FLAG: 129 str = dgettext(TEXT_DOMAIN, "Unknown flag passed"); 130 break; 131 132 case UU_ERROR_NO_MEMORY: 133 str = dgettext(TEXT_DOMAIN, "Out of memory"); 134 break; 135 136 case UU_ERROR_CALLBACK_FAILED: 137 str = dgettext(TEXT_DOMAIN, "Callback-initiated failure"); 138 break; 139 140 case UU_ERROR_NOT_SUPPORTED: 141 str = dgettext(TEXT_DOMAIN, "Operation not supported"); 142 break; 143 144 case UU_ERROR_EMPTY: 145 str = dgettext(TEXT_DOMAIN, "No value provided"); 146 break; 147 148 case UU_ERROR_UNDERFLOW: 149 str = dgettext(TEXT_DOMAIN, "Value too small"); 150 break; 151 152 case UU_ERROR_OVERFLOW: 153 str = dgettext(TEXT_DOMAIN, "Value too large"); 154 break; 155 156 case UU_ERROR_INVALID_CHAR: 157 str = dgettext(TEXT_DOMAIN, 158 "Value contains unexpected character"); 159 break; 160 161 case UU_ERROR_INVALID_DIGIT: 162 str = dgettext(TEXT_DOMAIN, 163 "Value contains digit not in base"); 164 break; 165 166 case UU_ERROR_SYSTEM: 167 str = dgettext(TEXT_DOMAIN, "Underlying system error"); 168 break; 169 170 case UU_ERROR_UNKNOWN: 171 str = dgettext(TEXT_DOMAIN, "Error status not known"); 172 break; 173 174 default: 175 errno = ESRCH; 176 str = NULL; 177 break; 178 } 179 return (str); 180} 181 182void 183uu_panic(const char *format, ...) 184{ 185 va_list args; 186 187 va_start(args, format); 188 189 (void) pthread_mutex_lock(&uu_panic_lock); 190 if (uu_panic_thread == 0) { 191 uu_panic_thread = pthread_self(); 192 uu_panic_format = format; 193 va_copy(uu_panic_args, args); 194 } 195 (void) pthread_mutex_unlock(&uu_panic_lock); 196 197 (void) vfprintf(stderr, format, args); 198 199 if (uu_panic_thread == pthread_self()) 200 abort(); 201 else 202 for (;;) 203 (void) pause(); 204} 205 206int 207assfail(const char *astring, const char *file, int line) 208{ 209 __assert(astring, file, line); 210 /*NOTREACHED*/ 211 return (0); 212} 213 214static void 215uu_lockup(void) 216{ 217 (void) pthread_mutex_lock(&uu_panic_lock); 218#if !defined(PTHREAD_ONCE_KEY_NP) 219 (void) pthread_mutex_lock(&uu_key_lock); 220#endif 221 uu_avl_lockup(); 222 uu_list_lockup(); 223} 224 225static void 226uu_release(void) 227{ 228 (void) pthread_mutex_unlock(&uu_panic_lock); 229#if !defined(PTHREAD_ONCE_KEY_NP) 230 (void) pthread_mutex_unlock(&uu_key_lock); 231#endif 232 uu_avl_release(); 233 uu_list_release(); 234} 235 236static void 237uu_release_child(void) 238{ 239 uu_panic_format = NULL; 240 uu_panic_thread = 0; 241 242 uu_release(); 243} 244 245#pragma init(uu_init) 246static void 247uu_init(void) 248{ 249 (void) pthread_atfork(uu_lockup, uu_release, uu_release_child); 250} 251