root/trunk/misc.c

Revision 2, 5.4 kB (checked in by wez, 8 years ago)

Initial revision

  • Property svn:eol-style set to native
Line 
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
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  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 /*
27  * Portions Copyright 2006 OmniTI, Inc.
28  */
29
30 /* #pragma ident        "@(#)misc.c     1.6     05/06/08 SMI" */
31
32 #define _BUILDING_UMEM_MISC_C
33 #include "config.h"
34 /* #include "mtlib.h" */
35 #if HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif
38 #if HAVE_DLFCN_H
39 #include <dlfcn.h>
40 #endif
41 #include <signal.h>
42 #include <stdarg.h>
43 #include <stdio.h>
44 #include <string.h>
45
46 #if HAVE_SYS_MACHELF_H
47 #include <sys/machelf.h>
48 #endif
49
50 #include <umem_impl.h>
51 #include "misc.h"
52 #include "util.h"
53
54 #define UMEM_ERRFD      2       /* goes to standard error */
55 #define UMEM_MAX_ERROR_SIZE 4096 /* error messages are truncated to this */
56
57 /*
58  * This is a circular buffer for holding error messages.
59  * umem_error_enter appends to the buffer, adding "..." to the beginning
60  * if data has been lost.
61  */
62
63 #define ERR_SIZE 8192           /* must be a power of 2 */
64
65 static mutex_t umem_error_lock = DEFAULTMUTEX;
66
67 static char umem_error_buffer[ERR_SIZE] = "";
68 static uint_t umem_error_begin = 0;
69 static uint_t umem_error_end = 0;
70
71 #define WRITE_AND_INC(var, value) { \
72         umem_error_buffer[(var)++] = (value); \
73         var = P2PHASE((var), ERR_SIZE); \
74 }
75
76 static void
77 umem_log_enter(const char *error_str, int serious)
78 {
79         int looped;
80         char c;
81
82         looped = 0;
83         mem_printf(serious ? DCRITICAL : DINFO, "umem: %s", error_str);
84
85         (void) mutex_lock(&umem_error_lock);
86
87         while ((c = *error_str++) != '\0') {
88                 WRITE_AND_INC(umem_error_end, c);
89                 if (umem_error_end == umem_error_begin)
90                         looped = 1;
91         }
92
93         umem_error_buffer[umem_error_end] = 0;
94
95         if (looped) {
96                 uint_t idx;
97                 umem_error_begin = P2PHASE(umem_error_end + 1, ERR_SIZE);
98
99                 idx = umem_error_begin;
100                 WRITE_AND_INC(idx, '.');
101                 WRITE_AND_INC(idx, '.');
102                 WRITE_AND_INC(idx, '.');
103         }
104
105         (void) mutex_unlock(&umem_error_lock);
106 }
107
108 void
109 umem_error_enter(const char *error_str)
110 {
111 #ifndef UMEM_STANDALONE
112         if (umem_output && !issetugid())
113                 (void) write(UMEM_ERRFD, error_str, strlen(error_str));
114 #endif
115
116         umem_log_enter(error_str, 1);
117 }
118
119 int
120 highbit(ulong_t i)
121 {
122         register int h = 1;
123
124         if (i == 0)
125                 return (0);
126 #ifdef _LP64
127         if (i & 0xffffffff00000000ul) {
128                 h += 32; i >>= 32;
129         }
130 #endif
131         if (i & 0xffff0000) {
132                 h += 16; i >>= 16;
133         }
134         if (i & 0xff00) {
135                 h += 8; i >>= 8;
136         }
137         if (i & 0xf0) {
138                 h += 4; i >>= 4;
139         }
140         if (i & 0xc) {
141                 h += 2; i >>= 2;
142         }
143         if (i & 0x2) {
144                 h += 1;
145         }
146         return (h);
147 }
148
149 int
150 lowbit(ulong_t i)
151 {
152         register int h = 1;
153
154         if (i == 0)
155                 return (0);
156 #ifdef _LP64
157         if (!(i & 0xffffffff)) {
158                 h += 32; i >>= 32;
159         }
160 #endif
161         if (!(i & 0xffff)) {
162                 h += 16; i >>= 16;
163         }
164         if (!(i & 0xff)) {
165                 h += 8; i >>= 8;
166         }
167         if (!(i & 0xf)) {
168                 h += 4; i >>= 4;
169         }
170         if (!(i & 0x3)) {
171                 h += 2; i >>= 2;
172         }
173         if (!(i & 0x1)) {
174                 h += 1;
175         }
176         return (h);
177 }
178
179 void
180 hrt2ts(hrtime_t hrt, timestruc_t *tsp)
181 {
182         tsp->tv_sec = hrt / NANOSEC;
183         tsp->tv_nsec = hrt % NANOSEC;
184 }
185
186 void
187 log_message(const char *format, ...)
188 {
189         char buf[UMEM_MAX_ERROR_SIZE] = "";
190
191         va_list va;
192
193         va_start(va, format);
194         (void) vsnprintf(buf, UMEM_MAX_ERROR_SIZE-1, format, va);
195         va_end(va);
196
197 #ifndef UMEM_STANDALONE
198         if (umem_output > 1)
199                 (void) write(UMEM_ERRFD, buf, strlen(buf));
200 #endif
201
202         umem_log_enter(buf, 0);
203 }
204
205 #ifndef UMEM_STANDALONE
206 void
207 debug_printf(const char *format, ...)
208 {
209         char buf[UMEM_MAX_ERROR_SIZE] = "";
210
211         va_list va;
212
213         va_start(va, format);
214         (void) vsnprintf(buf, UMEM_MAX_ERROR_SIZE-1, format, va);
215         va_end(va);
216
217         (void) write(UMEM_ERRFD, buf, strlen(buf));
218 }
219 #endif
220
221 void
222 umem_vprintf(const char *format, va_list va)
223 {
224         char buf[UMEM_MAX_ERROR_SIZE] = "";
225
226         (void) vsnprintf(buf, UMEM_MAX_ERROR_SIZE-1, format, va);
227
228         umem_error_enter(buf);
229 }
230
231 void
232 umem_printf(const char *format, ...)
233 {
234         va_list va;
235
236         va_start(va, format);
237         umem_vprintf(format, va);
238         va_end(va);
239 }
240
241 /*ARGSUSED*/
242 void
243 umem_printf_warn(void *ignored, const char *format, ...)
244 {
245         va_list va;
246
247         va_start(va, format);
248         umem_vprintf(format, va);
249         va_end(va);
250 }
251
252 /*
253  * print_sym tries to print out the symbol and offset of a pointer
254  */
255 int
256 print_sym(void *pointer)
257 {
258 #if HAVE_SYS_MACHELF_H
259         int result;
260         Dl_info sym_info;
261
262         uintptr_t end = NULL;
263
264         Sym *ext_info = NULL;
265
266         result = dladdr1(pointer, &sym_info, (void **)&ext_info,
267             RTLD_DL_SYMENT);
268
269         if (result != 0) {
270                 const char *endpath;
271
272                 end = (uintptr_t)sym_info.dli_saddr + ext_info->st_size;
273
274                 endpath = strrchr(sym_info.dli_fname, '/');
275                 if (endpath)
276                         endpath++;
277                 else
278                         endpath = sym_info.dli_fname;
279                 umem_printf("%s'", endpath);
280         }
281
282         if (result == 0 || (uintptr_t)pointer > end) {
283                 umem_printf("?? (0x%p)", pointer);
284                 return (0);
285         } else {
286                 umem_printf("%s+0x%p", sym_info.dli_sname,
287                     (char *)pointer - (char *)sym_info.dli_saddr);
288                 return (1);
289         }
290 #else
291         return 0;
292 #endif
293 }
Note: See TracBrowser for help on using the browser.