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