Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/openzfs/lib/libuutil/uu_misc.c
48378 views
1
// SPDX-License-Identifier: CDDL-1.0
2
/*
3
* CDDL HEADER START
4
*
5
* The contents of this file are subject to the terms of the
6
* Common Development and Distribution License (the "License").
7
* You may not use this file except in compliance with the License.
8
*
9
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10
* or https://opensource.org/licenses/CDDL-1.0.
11
* See the License for the specific language governing permissions
12
* and limitations under the License.
13
*
14
* When distributing Covered Code, include this CDDL HEADER in each
15
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16
* If applicable, add the following below this CDDL HEADER, with the
17
* fields enclosed by brackets "[]" replaced with your own identifying
18
* information: Portions Copyright [yyyy] [name of copyright owner]
19
*
20
* CDDL HEADER END
21
*/
22
23
/*
24
* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
25
*/
26
27
#include "libuutil_common.h"
28
29
#include <assert.h>
30
#include <errno.h>
31
#include <libintl.h>
32
#include <pthread.h>
33
#include <stdarg.h>
34
#include <stdio.h>
35
#include <stdlib.h>
36
#include <string.h>
37
#include <sys/debug.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)
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 */
60
61
static int uu_error_key_setup = 0;
62
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;
69
70
static uint32_t _uu_main_error;
71
static __thread int _uu_main_thread = 0;
72
73
void
74
uu_set_error(uint_t code)
75
{
76
if (_uu_main_thread) {
77
_uu_main_error = code;
78
return;
79
}
80
#if defined(PTHREAD_ONCE_KEY_NP)
81
if (pthread_key_create_once_np(&uu_error_key, NULL) != 0)
82
uu_error_key_setup = -1;
83
else
84
uu_error_key_setup = 1;
85
#else /* PTHREAD_ONCE_KEY_NP */
86
if (uu_error_key_setup == 0) {
87
(void) pthread_mutex_lock(&uu_key_lock);
88
if (uu_error_key_setup == 0) {
89
if (pthread_key_create(&uu_error_key, NULL) != 0)
90
uu_error_key_setup = -1;
91
else
92
uu_error_key_setup = 1;
93
}
94
(void) pthread_mutex_unlock(&uu_key_lock);
95
}
96
#endif /* PTHREAD_ONCE_KEY_NP */
97
if (uu_error_key_setup > 0)
98
(void) pthread_setspecific(uu_error_key,
99
(void *)(uintptr_t)code);
100
}
101
102
uint32_t
103
uu_error(void)
104
{
105
if (_uu_main_thread)
106
return (_uu_main_error);
107
108
if (uu_error_key_setup < 0) /* can't happen? */
109
return (UU_ERROR_UNKNOWN);
110
111
/*
112
* Because UU_ERROR_NONE == 0, if uu_set_error() was
113
* never called, then this will return UU_ERROR_NONE:
114
*/
115
return ((uint32_t)(uintptr_t)pthread_getspecific(uu_error_key));
116
}
117
118
const char *
119
uu_strerror(uint32_t code)
120
{
121
const char *str;
122
123
switch (code) {
124
case UU_ERROR_NONE:
125
str = dgettext(TEXT_DOMAIN, "No error");
126
break;
127
128
case UU_ERROR_INVALID_ARGUMENT:
129
str = dgettext(TEXT_DOMAIN, "Invalid argument");
130
break;
131
132
case UU_ERROR_UNKNOWN_FLAG:
133
str = dgettext(TEXT_DOMAIN, "Unknown flag passed");
134
break;
135
136
case UU_ERROR_NO_MEMORY:
137
str = dgettext(TEXT_DOMAIN, "Out of memory");
138
break;
139
140
case UU_ERROR_CALLBACK_FAILED:
141
str = dgettext(TEXT_DOMAIN, "Callback-initiated failure");
142
break;
143
144
case UU_ERROR_NOT_SUPPORTED:
145
str = dgettext(TEXT_DOMAIN, "Operation not supported");
146
break;
147
148
case UU_ERROR_EMPTY:
149
str = dgettext(TEXT_DOMAIN, "No value provided");
150
break;
151
152
case UU_ERROR_UNDERFLOW:
153
str = dgettext(TEXT_DOMAIN, "Value too small");
154
break;
155
156
case UU_ERROR_OVERFLOW:
157
str = dgettext(TEXT_DOMAIN, "Value too large");
158
break;
159
160
case UU_ERROR_INVALID_CHAR:
161
str = dgettext(TEXT_DOMAIN,
162
"Value contains unexpected character");
163
break;
164
165
case UU_ERROR_INVALID_DIGIT:
166
str = dgettext(TEXT_DOMAIN,
167
"Value contains digit not in base");
168
break;
169
170
case UU_ERROR_SYSTEM:
171
str = dgettext(TEXT_DOMAIN, "Underlying system error");
172
break;
173
174
case UU_ERROR_UNKNOWN:
175
str = dgettext(TEXT_DOMAIN, "Error status not known");
176
break;
177
178
default:
179
errno = ESRCH;
180
str = NULL;
181
break;
182
}
183
return (str);
184
}
185
186
void
187
uu_panic(const char *format, ...)
188
{
189
va_list args;
190
191
va_start(args, format);
192
193
(void) pthread_mutex_lock(&uu_panic_lock);
194
if (uu_panic_thread == 0) {
195
uu_panic_thread = pthread_self();
196
uu_panic_format = format;
197
va_copy(uu_panic_args, args);
198
}
199
(void) pthread_mutex_unlock(&uu_panic_lock);
200
201
(void) vfprintf(stderr, format, args);
202
203
va_end(args);
204
205
if (uu_panic_thread == pthread_self())
206
abort();
207
else
208
for (;;)
209
(void) pause();
210
}
211
212
static void
213
uu_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
223
static void
224
uu_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
234
static void
235
uu_release_child(void)
236
{
237
uu_panic_format = NULL;
238
uu_panic_thread = 0;
239
240
uu_release();
241
}
242
243
#ifdef __GNUC__
244
static void
245
uu_init(void) __attribute__((constructor));
246
#else
247
#pragma init(uu_init)
248
#endif
249
250
static void
251
uu_init(void)
252
{
253
_uu_main_thread = 1;
254
(void) pthread_atfork(uu_lockup, uu_release, uu_release_child);
255
}
256
257