dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libumem / common / misc.c
blob6a0ad589b5070fe58e9bac601330ceafd0a2399a
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 #include <unistd.h>
29 #include <dlfcn.h>
30 #include <signal.h>
31 #include <stdarg.h>
32 #include <stdio.h>
33 #include <string.h>
35 #include <sys/machelf.h>
37 #include <umem_impl.h>
38 #include "misc.h"
40 #define UMEM_ERRFD 2 /* goes to standard error */
41 #define UMEM_MAX_ERROR_SIZE 4096 /* error messages are truncated to this */
44 * This is a circular buffer for holding error messages.
45 * umem_error_enter appends to the buffer, adding "..." to the beginning
46 * if data has been lost.
49 #define ERR_SIZE 8192 /* must be a power of 2 */
51 static mutex_t umem_error_lock = DEFAULTMUTEX;
53 static char umem_error_buffer[ERR_SIZE] = "";
54 static uint_t umem_error_begin = 0;
55 static uint_t umem_error_end = 0;
57 #define WRITE_AND_INC(var, value) { \
58 umem_error_buffer[(var)++] = (value); \
59 var = P2PHASE((var), ERR_SIZE); \
62 static void
63 umem_log_enter(const char *error_str)
65 int looped;
66 char c;
68 looped = 0;
70 (void) mutex_lock(&umem_error_lock);
72 while ((c = *error_str++) != '\0') {
73 WRITE_AND_INC(umem_error_end, c);
74 if (umem_error_end == umem_error_begin)
75 looped = 1;
78 umem_error_buffer[umem_error_end] = 0;
80 if (looped) {
81 uint_t idx;
82 umem_error_begin = P2PHASE(umem_error_end + 1, ERR_SIZE);
84 idx = umem_error_begin;
85 WRITE_AND_INC(idx, '.');
86 WRITE_AND_INC(idx, '.');
87 WRITE_AND_INC(idx, '.');
90 (void) mutex_unlock(&umem_error_lock);
93 void
94 umem_error_enter(const char *error_str)
96 #ifndef UMEM_STANDALONE
97 if (umem_output && !issetugid())
98 (void) write(UMEM_ERRFD, error_str, strlen(error_str));
99 #endif
101 umem_log_enter(error_str);
105 highbit(ulong_t i)
107 register int h = 1;
109 if (i == 0)
110 return (0);
111 #ifdef _LP64
112 if (i & 0xffffffff00000000ul) {
113 h += 32; i >>= 32;
115 #endif
116 if (i & 0xffff0000) {
117 h += 16; i >>= 16;
119 if (i & 0xff00) {
120 h += 8; i >>= 8;
122 if (i & 0xf0) {
123 h += 4; i >>= 4;
125 if (i & 0xc) {
126 h += 2; i >>= 2;
128 if (i & 0x2) {
129 h += 1;
131 return (h);
135 lowbit(ulong_t i)
137 register int h = 1;
139 if (i == 0)
140 return (0);
141 #ifdef _LP64
142 if (!(i & 0xffffffff)) {
143 h += 32; i >>= 32;
145 #endif
146 if (!(i & 0xffff)) {
147 h += 16; i >>= 16;
149 if (!(i & 0xff)) {
150 h += 8; i >>= 8;
152 if (!(i & 0xf)) {
153 h += 4; i >>= 4;
155 if (!(i & 0x3)) {
156 h += 2; i >>= 2;
158 if (!(i & 0x1)) {
159 h += 1;
161 return (h);
164 void
165 hrt2ts(hrtime_t hrt, timestruc_t *tsp)
167 tsp->tv_sec = hrt / NANOSEC;
168 tsp->tv_nsec = hrt % NANOSEC;
171 void
172 log_message(const char *format, ...)
174 char buf[UMEM_MAX_ERROR_SIZE] = "";
176 va_list va;
178 va_start(va, format);
179 (void) vsnprintf(buf, UMEM_MAX_ERROR_SIZE-1, format, va);
180 va_end(va);
182 #ifndef UMEM_STANDALONE
183 if (umem_output > 1)
184 (void) write(UMEM_ERRFD, buf, strlen(buf));
185 #endif
187 umem_log_enter(buf);
190 #ifndef UMEM_STANDALONE
191 void
192 debug_printf(const char *format, ...)
194 char buf[UMEM_MAX_ERROR_SIZE] = "";
196 va_list va;
198 va_start(va, format);
199 (void) vsnprintf(buf, UMEM_MAX_ERROR_SIZE-1, format, va);
200 va_end(va);
202 (void) write(UMEM_ERRFD, buf, strlen(buf));
204 #endif
206 void
207 umem_vprintf(const char *format, va_list va)
209 char buf[UMEM_MAX_ERROR_SIZE] = "";
211 (void) vsnprintf(buf, UMEM_MAX_ERROR_SIZE-1, format, va);
213 umem_error_enter(buf);
216 void
217 umem_printf(const char *format, ...)
219 va_list va;
221 va_start(va, format);
222 umem_vprintf(format, va);
223 va_end(va);
226 /*ARGSUSED*/
227 void
228 umem_printf_warn(void *ignored, const char *format, ...)
230 va_list va;
232 va_start(va, format);
233 umem_vprintf(format, va);
234 va_end(va);
238 * print_sym tries to print out the symbol and offset of a pointer
241 print_sym(void *pointer)
243 int result;
244 Dl_info sym_info;
246 uintptr_t end = (uintptr_t)NULL;
248 Sym *ext_info = NULL;
250 result = dladdr1(pointer, &sym_info, (void **)&ext_info,
251 RTLD_DL_SYMENT);
253 if (result != 0) {
254 const char *endpath;
256 end = (uintptr_t)sym_info.dli_saddr + ext_info->st_size;
258 endpath = strrchr(sym_info.dli_fname, '/');
259 if (endpath)
260 endpath++;
261 else
262 endpath = sym_info.dli_fname;
263 umem_printf("%s'", endpath);
266 if (result == 0 || (uintptr_t)pointer > end) {
267 umem_printf("?? (0x%p)", pointer);
268 return (0);
269 } else {
270 umem_printf("%s+0x%p", sym_info.dli_sname,
271 (char *)pointer - (char *)sym_info.dli_saddr);
272 return (1);