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.
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.
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]
23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
26 #include "libuutil_common.h"
36 #include <sys/debug.h>
41 #if !defined(TEXT_DOMAIN)
42 #define TEXT_DOMAIN "SYS_TEST"
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.
54 #if defined(PTHREAD_ONCE_KEY_NP)
55 static pthread_key_t uu_error_key = PTHREAD_ONCE_KEY_NP;
56 #else /* PTHREAD_ONCE_KEY_NP */
57 static pthread_key_t uu_error_key = 0;
58 static pthread_mutex_t uu_key_lock = PTHREAD_MUTEX_INITIALIZER;
59 #endif /* PTHREAD_ONCE_KEY_NP */
61 static int uu_error_key_setup = 0;
63 static pthread_mutex_t uu_panic_lock = PTHREAD_MUTEX_INITIALIZER;
64 /* LINTED static unused */
65 static const char *uu_panic_format;
66 /* LINTED static unused */
67 static va_list uu_panic_args;
68 static pthread_t uu_panic_thread;
70 static uint32_t _uu_main_error;
73 uu_set_error(uint_t code)
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;
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;
88 uu_error_key_setup = 1;
90 (void) pthread_mutex_unlock(&uu_key_lock);
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);
102 if (uu_error_key_setup < 0) /* can't happen? */
103 return (UU_ERROR_UNKNOWN);
106 * Because UU_ERROR_NONE == 0, if uu_set_error() was
107 * never called, then this will return UU_ERROR_NONE:
109 return ((uint32_t)(uintptr_t)pthread_getspecific(uu_error_key));
113 uu_strerror(uint32_t code)
119 str = dgettext(TEXT_DOMAIN, "No error");
122 case UU_ERROR_INVALID_ARGUMENT:
123 str = dgettext(TEXT_DOMAIN, "Invalid argument");
126 case UU_ERROR_UNKNOWN_FLAG:
127 str = dgettext(TEXT_DOMAIN, "Unknown flag passed");
130 case UU_ERROR_NO_MEMORY:
131 str = dgettext(TEXT_DOMAIN, "Out of memory");
134 case UU_ERROR_CALLBACK_FAILED:
135 str = dgettext(TEXT_DOMAIN, "Callback-initiated failure");
138 case UU_ERROR_NOT_SUPPORTED:
139 str = dgettext(TEXT_DOMAIN, "Operation not supported");
143 str = dgettext(TEXT_DOMAIN, "No value provided");
146 case UU_ERROR_UNDERFLOW:
147 str = dgettext(TEXT_DOMAIN, "Value too small");
150 case UU_ERROR_OVERFLOW:
151 str = dgettext(TEXT_DOMAIN, "Value too large");
154 case UU_ERROR_INVALID_CHAR:
155 str = dgettext(TEXT_DOMAIN,
156 "Value contains unexpected character");
159 case UU_ERROR_INVALID_DIGIT:
160 str = dgettext(TEXT_DOMAIN,
161 "Value contains digit not in base");
164 case UU_ERROR_SYSTEM:
165 str = dgettext(TEXT_DOMAIN, "Underlying system error");
168 case UU_ERROR_UNKNOWN:
169 str = dgettext(TEXT_DOMAIN, "Error status not known");
181 uu_panic(const char *format, ...)
185 va_start(args, format);
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);
193 (void) pthread_mutex_unlock(&uu_panic_lock);
195 (void) vfprintf(stderr, format, args);
197 if (uu_panic_thread == pthread_self())
205 assfail(const char *astring, const char *file, int line)
207 __assert(astring, file, line);
215 (void) pthread_mutex_lock(&uu_panic_lock);
216 #if !defined(PTHREAD_ONCE_KEY_NP)
217 (void) pthread_mutex_lock(&uu_key_lock);
226 (void) pthread_mutex_unlock(&uu_panic_lock);
227 #if !defined(PTHREAD_ONCE_KEY_NP)
228 (void) pthread_mutex_unlock(&uu_key_lock);
235 uu_release_child(void)
237 uu_panic_format = NULL;
243 #pragma init(uu_init)
247 (void) pthread_atfork(uu_lockup, uu_release, uu_release_child);
251 * Dump a block of memory in hex+ascii, for debugging
254 uu_dump(FILE *out, const char *prefix, const void *buf, size_t len)
256 const unsigned char *p = buf;
259 for (i = 0; i < len; i += 16) {
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]);
266 for (; j < 16; j++) {
267 (void) fprintf(out, " ");
269 for (j = 0; j < 16 && i + j < len; j++) {
270 (void) fprintf(out, "%c",
271 isprint(p[i + j]) ? p[i + j] : '.');
273 (void) fprintf(out, "\n");