Print this page
patch mdb_var_alloc
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/mdb/common/mdb/mdb_nv.c
+++ new/usr/src/cmd/mdb/common/mdb/mdb_nv.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22 /*
23 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 #pragma ident "%Z%%M% %I% %E% SMI"
28 28
29 29 #include <mdb/mdb_debug.h>
30 30 #include <mdb/mdb_string.h>
↓ open down ↓ |
30 lines elided |
↑ open up ↑ |
31 31 #include <mdb/mdb_modapi.h>
32 32 #include <mdb/mdb_err.h>
33 33 #include <mdb/mdb_nv.h>
34 34 #include <mdb/mdb.h>
35 35
36 36 #define NV_NAME(v) \
37 37 (((v)->v_flags & MDB_NV_EXTNAME) ? (v)->v_ename : (v)->v_lname)
38 38
39 39 #define NV_SIZE(v) \
40 40 (((v)->v_flags & MDB_NV_EXTNAME) ? sizeof (mdb_var_t) : \
41 - sizeof (mdb_var_t) + MDB_NV_NAMELEN - 1)
41 + sizeof (mdb_var_t) + strlen((v)->v_lname))
42 42
43 43 #define NV_HASHSZ 211
44 44
45 45 static size_t
46 46 nv_hashstring(const char *key)
47 47 {
48 48 size_t g, h = 0;
49 49 const char *p;
50 50
51 51 ASSERT(key != NULL);
52 52
53 53 for (p = key; *p != '\0'; p++) {
54 54 h = (h << 4) + *p;
55 55
56 56 if ((g = (h & 0xf0000000)) != 0) {
57 57 h ^= (g >> 24);
58 58 h ^= g;
↓ open down ↓ |
7 lines elided |
↑ open up ↑ |
59 59 }
60 60 }
61 61
62 62 return (h);
63 63 }
64 64
65 65 static mdb_var_t *
66 66 nv_var_alloc(const char *name, const mdb_nv_disc_t *disc,
67 67 uintmax_t value, uint_t flags, uint_t um_flags, mdb_var_t *next)
68 68 {
69 - size_t nbytes = (flags & MDB_NV_EXTNAME) ? sizeof (mdb_var_t) :
70 - (sizeof (mdb_var_t) + MDB_NV_NAMELEN - 1);
69 + size_t nbytes;
70 + mdb_var_t *v;
71 +
72 + if (flags & MDB_NV_EXTNAME)
73 + nbytes = sizeof (mdb_var_t);
74 + else
75 + nbytes = sizeof (mdb_var_t) + strlen(name);
71 76
72 - mdb_var_t *v = mdb_alloc(nbytes, um_flags);
77 + v = mdb_alloc(nbytes, um_flags);
73 78
74 79 if (v == NULL)
75 80 return (NULL);
76 81
77 82 if (flags & MDB_NV_EXTNAME) {
78 83 v->v_ename = name;
79 - v->v_lname[0] = 0;
84 + v->v_lname[0] = '\0';
80 85 } else {
81 - (void) strncpy(v->v_lname, name, MDB_NV_NAMELEN - 1);
82 - v->v_lname[MDB_NV_NAMELEN - 1] = '\0';
86 + strcpy(v->v_lname, name);
83 87 v->v_ename = NULL;
84 88 }
85 89
86 90 v->v_uvalue = value;
87 91 v->v_flags = flags & ~(MDB_NV_SILENT | MDB_NV_INTERPOS);
88 92 v->v_disc = disc;
89 93 v->v_next = next;
90 94
91 95 return (v);
92 96 }
93 97
94 98 static void
95 99 nv_var_free(mdb_var_t *v, uint_t um_flags)
96 100 {
97 101 if (um_flags & UM_GC)
98 102 return;
99 103
100 104 if (v->v_flags & MDB_NV_OVERLOAD) {
101 105 mdb_var_t *w, *nw;
102 106
103 107 for (w = v->v_ndef; w != NULL; w = nw) {
104 108 nw = w->v_ndef;
105 109 mdb_free(w, NV_SIZE(w));
106 110 }
107 111 }
108 112
109 113 mdb_free(v, NV_SIZE(v));
110 114 }
111 115
112 116 /*
113 117 * Can return NULL only if the nv's memory allocation flags include UM_NOSLEEP
114 118 */
115 119 mdb_nv_t *
116 120 mdb_nv_create(mdb_nv_t *nv, uint_t um_flags)
117 121 {
118 122 nv->nv_hash = mdb_zalloc(sizeof (mdb_var_t *) * NV_HASHSZ, um_flags);
119 123
120 124 if (nv->nv_hash == NULL)
121 125 return (NULL);
122 126
123 127 nv->nv_hashsz = NV_HASHSZ;
124 128 nv->nv_nelems = 0;
125 129 nv->nv_iter_elt = NULL;
126 130 nv->nv_iter_bucket = 0;
127 131 nv->nv_um_flags = um_flags;
128 132
129 133 return (nv);
130 134 }
131 135
132 136 void
133 137 mdb_nv_destroy(mdb_nv_t *nv)
134 138 {
135 139 mdb_var_t *v, *w;
136 140 size_t i;
137 141
138 142 if (nv->nv_um_flags & UM_GC)
139 143 return;
140 144
141 145 for (i = 0; i < nv->nv_hashsz; i++) {
142 146 for (v = nv->nv_hash[i]; v != NULL; v = w) {
143 147 w = v->v_next;
144 148 nv_var_free(v, nv->nv_um_flags);
145 149 }
146 150 }
147 151
148 152 mdb_free(nv->nv_hash, sizeof (mdb_var_t *) * NV_HASHSZ);
149 153 }
150 154
151 155 mdb_var_t *
152 156 mdb_nv_lookup(mdb_nv_t *nv, const char *name)
153 157 {
154 158 size_t i = nv_hashstring(name) % nv->nv_hashsz;
155 159 mdb_var_t *v;
156 160
157 161 for (v = nv->nv_hash[i]; v != NULL; v = v->v_next) {
158 162 if (strcmp(NV_NAME(v), name) == 0)
159 163 return (v);
160 164 }
161 165
162 166 return (NULL);
163 167 }
164 168
165 169 /*
166 170 * Interpose W in place of V. We replace V with W in nv_hash, and then
167 171 * set W's v_ndef overload chain to point at V.
168 172 */
169 173 static mdb_var_t *
170 174 nv_var_interpos(mdb_nv_t *nv, size_t i, mdb_var_t *v, mdb_var_t *w)
171 175 {
172 176 mdb_var_t **pvp = &nv->nv_hash[i];
173 177
174 178 while (*pvp != v) {
175 179 mdb_var_t *vp = *pvp;
176 180 ASSERT(vp != NULL);
177 181 pvp = &vp->v_next;
178 182 }
179 183
180 184 *pvp = w;
181 185 w->v_next = v->v_next;
182 186 w->v_ndef = v;
183 187 v->v_next = NULL;
184 188
185 189 return (w);
186 190 }
187 191
188 192 /*
189 193 * Add W to the end of V's overload chain. We simply follow v_ndef to the
190 194 * end, and then append W. We don't expect these chains to grow very long.
191 195 */
192 196 static mdb_var_t *
193 197 nv_var_overload(mdb_var_t *v, mdb_var_t *w)
194 198 {
195 199 while (v->v_ndef != NULL)
196 200 v = v->v_ndef;
197 201
198 202 v->v_ndef = w;
199 203 return (w);
200 204 }
201 205
202 206 /*
203 207 * Can return NULL only if the nv's memory allocation flags include UM_NOSLEEP
204 208 */
205 209 mdb_var_t *
206 210 mdb_nv_insert(mdb_nv_t *nv, const char *name, const mdb_nv_disc_t *disc,
207 211 uintmax_t value, uint_t flags)
208 212 {
209 213 size_t i = nv_hashstring(name) % nv->nv_hashsz;
210 214 mdb_var_t *v;
211 215
212 216 ASSERT(!(flags & MDB_NV_EXTNAME) || !(flags & MDB_NV_OVERLOAD));
213 217 ASSERT(!(flags & MDB_NV_RDONLY) || !(flags & MDB_NV_OVERLOAD));
214 218
215 219 /*
216 220 * If the specified name is already hashed,
217 221 * and MDB_NV_OVERLOAD is set: insert new var into overload chain
218 222 * and MDB_NV_RDONLY is set: leave var unchanged, issue warning
219 223 * otherwise: update var with new value
220 224 */
221 225 for (v = nv->nv_hash[i]; v != NULL; v = v->v_next) {
222 226 if (strcmp(NV_NAME(v), name) == 0) {
223 227 if (v->v_flags & MDB_NV_OVERLOAD) {
224 228 mdb_var_t *w = nv_var_alloc(NV_NAME(v), disc,
225 229 value, flags, nv->nv_um_flags, NULL);
226 230
227 231 if (w == NULL) {
228 232 ASSERT(nv->nv_um_flags & UM_NOSLEEP);
229 233 return (NULL);
230 234 }
231 235
232 236 if (flags & MDB_NV_INTERPOS)
233 237 v = nv_var_interpos(nv, i, v, w);
234 238 else
235 239 v = nv_var_overload(v, w);
236 240
237 241 } else if (v->v_flags & MDB_NV_RDONLY) {
238 242 if (!(flags & MDB_NV_SILENT)) {
239 243 warn("cannot modify read-only "
240 244 "variable '%s'\n", NV_NAME(v));
241 245 }
242 246 } else
243 247 v->v_uvalue = value;
244 248
245 249 ASSERT(v != NULL);
246 250 return (v);
247 251 }
248 252 }
249 253
250 254 /*
251 255 * If the specified name was not found, initialize a new element
252 256 * and add it to the hash table at the beginning of this chain:
253 257 */
254 258 v = nv_var_alloc(name, disc, value, flags, nv->nv_um_flags,
255 259 nv->nv_hash[i]);
256 260
257 261 if (v == NULL) {
258 262 ASSERT(nv->nv_um_flags & UM_NOSLEEP);
259 263 return (NULL);
260 264 }
261 265
262 266 nv->nv_hash[i] = v;
263 267 nv->nv_nelems++;
264 268
265 269 return (v);
266 270 }
267 271
268 272 static void
269 273 nv_var_defn_remove(mdb_var_t *v, mdb_var_t *corpse, uint_t um_flags)
270 274 {
271 275 mdb_var_t *w = v;
272 276
273 277 while (v->v_ndef != NULL && v->v_ndef != corpse)
274 278 v = v->v_ndef;
275 279
276 280 if (v == NULL) {
277 281 fail("var %p ('%s') not found on defn chain of %p\n",
278 282 (void *)corpse, NV_NAME(corpse), (void *)w);
279 283 }
280 284
281 285 v->v_ndef = corpse->v_ndef;
282 286 corpse->v_ndef = NULL;
283 287 nv_var_free(corpse, um_flags);
284 288 }
285 289
286 290 void
287 291 mdb_nv_remove(mdb_nv_t *nv, mdb_var_t *corpse)
288 292 {
289 293 const char *cname = NV_NAME(corpse);
290 294 size_t i = nv_hashstring(cname) % nv->nv_hashsz;
291 295 mdb_var_t *v = nv->nv_hash[i];
292 296 mdb_var_t **pvp;
293 297
294 298 if (corpse->v_flags & MDB_NV_PERSIST) {
295 299 warn("cannot remove persistent variable '%s'\n", cname);
296 300 return;
297 301 }
298 302
299 303 if (v != corpse) {
300 304 do {
301 305 if (strcmp(NV_NAME(v), cname) == 0) {
302 306 if (corpse->v_flags & MDB_NV_OVERLOAD) {
303 307 nv_var_defn_remove(v, corpse,
304 308 nv->nv_um_flags);
305 309 return; /* No v_next changes needed */
306 310 } else
307 311 goto notfound;
308 312 }
309 313
310 314 if (v->v_next == corpse)
311 315 break; /* Corpse is next on the chain */
312 316
313 317 } while ((v = v->v_next) != NULL);
314 318
315 319 if (v == NULL)
316 320 goto notfound;
317 321
318 322 pvp = &v->v_next;
319 323 } else
320 324 pvp = &nv->nv_hash[i];
321 325
322 326 if ((corpse->v_flags & MDB_NV_OVERLOAD) && corpse->v_ndef != NULL) {
323 327 corpse->v_ndef->v_next = corpse->v_next;
324 328 *pvp = corpse->v_ndef;
325 329 corpse->v_ndef = NULL;
326 330 } else {
327 331 *pvp = corpse->v_next;
328 332 nv->nv_nelems--;
329 333 }
330 334
331 335 nv_var_free(corpse, nv->nv_um_flags);
332 336 return;
333 337
334 338 notfound:
335 339 fail("var %p ('%s') not found on hash chain: nv=%p [%lu]\n",
336 340 (void *)corpse, cname, (void *)nv, (ulong_t)i);
337 341 }
338 342
339 343 void
340 344 mdb_nv_rewind(mdb_nv_t *nv)
341 345 {
342 346 size_t i;
343 347
344 348 for (i = 0; i < nv->nv_hashsz; i++) {
345 349 if (nv->nv_hash[i] != NULL)
346 350 break;
347 351 }
348 352
349 353 nv->nv_iter_elt = i < nv->nv_hashsz ? nv->nv_hash[i] : NULL;
350 354 nv->nv_iter_bucket = i;
351 355 }
352 356
353 357 mdb_var_t *
354 358 mdb_nv_advance(mdb_nv_t *nv)
355 359 {
356 360 mdb_var_t *v = nv->nv_iter_elt;
357 361 size_t i;
358 362
359 363 if (v == NULL)
360 364 return (NULL);
361 365
362 366 if (v->v_next != NULL) {
363 367 nv->nv_iter_elt = v->v_next;
364 368 return (v);
365 369 }
366 370
367 371 for (i = nv->nv_iter_bucket + 1; i < nv->nv_hashsz; i++) {
368 372 if (nv->nv_hash[i] != NULL)
369 373 break;
370 374 }
371 375
372 376 nv->nv_iter_elt = i < nv->nv_hashsz ? nv->nv_hash[i] : NULL;
373 377 nv->nv_iter_bucket = i;
374 378
375 379 return (v);
376 380 }
377 381
378 382 mdb_var_t *
379 383 mdb_nv_peek(mdb_nv_t *nv)
380 384 {
381 385 return (nv->nv_iter_elt);
382 386 }
383 387
384 388 size_t
385 389 mdb_nv_size(mdb_nv_t *nv)
386 390 {
387 391 return (nv->nv_nelems);
388 392 }
389 393
390 394 static int
391 395 nv_compare(const mdb_var_t **lp, const mdb_var_t **rp)
392 396 {
393 397 return (strcmp(mdb_nv_get_name(*lp), mdb_nv_get_name(*rp)));
394 398 }
395 399
396 400 void
397 401 mdb_nv_sort_iter(mdb_nv_t *nv, int (*func)(mdb_var_t *, void *),
398 402 void *private, uint_t um_flags)
399 403 {
400 404 mdb_var_t **vps =
401 405 mdb_alloc(nv->nv_nelems * sizeof (mdb_var_t *), um_flags);
402 406
403 407 if (nv->nv_nelems != 0 && vps != NULL) {
404 408 mdb_var_t *v, **vpp = vps;
405 409 size_t i;
406 410
407 411 for (mdb_nv_rewind(nv); (v = mdb_nv_advance(nv)) != NULL; )
408 412 *vpp++ = v;
409 413
410 414 qsort(vps, nv->nv_nelems, sizeof (mdb_var_t *),
411 415 (int (*)(const void *, const void *))nv_compare);
412 416
413 417 for (vpp = vps, i = 0; i < nv->nv_nelems; i++) {
414 418 if (func(*vpp++, private) == -1)
415 419 break;
416 420 }
417 421
418 422 if (!(um_flags & UM_GC))
419 423 mdb_free(vps, nv->nv_nelems * sizeof (mdb_var_t *));
420 424 }
421 425 }
422 426
423 427 void
424 428 mdb_nv_defn_iter(mdb_var_t *v, int (*func)(mdb_var_t *, void *), void *private)
425 429 {
426 430 if (func(v, private) == -1 || !(v->v_flags & MDB_NV_OVERLOAD))
427 431 return;
428 432
429 433 for (v = v->v_ndef; v != NULL; v = v->v_ndef) {
430 434 if (func(v, private) == -1)
431 435 break;
432 436 }
433 437 }
434 438
435 439 uintmax_t
436 440 mdb_nv_get_value(const mdb_var_t *v)
437 441 {
438 442 if (v->v_disc)
439 443 return (v->v_disc->disc_get(v));
440 444
441 445 return (v->v_uvalue);
442 446 }
443 447
444 448 void
445 449 mdb_nv_set_value(mdb_var_t *v, uintmax_t l)
446 450 {
447 451 if (v->v_flags & MDB_NV_RDONLY) {
448 452 warn("cannot modify read-only variable '%s'\n", NV_NAME(v));
449 453 return;
450 454 }
451 455
452 456 if (v->v_disc)
453 457 v->v_disc->disc_set(v, l);
454 458 else
455 459 v->v_uvalue = l;
456 460 }
457 461
458 462 void *
459 463 mdb_nv_get_cookie(const mdb_var_t *v)
460 464 {
461 465 if (v->v_disc)
462 466 return ((void *)(uintptr_t)v->v_disc->disc_get(v));
463 467
464 468 return (MDB_NV_COOKIE(v));
465 469 }
466 470
467 471 void
468 472 mdb_nv_set_cookie(mdb_var_t *v, void *cookie)
469 473 {
470 474 mdb_nv_set_value(v, (uintmax_t)(uintptr_t)cookie);
471 475 }
472 476
473 477 const char *
474 478 mdb_nv_get_name(const mdb_var_t *v)
475 479 {
476 480 return (NV_NAME(v));
477 481 }
478 482
479 483 mdb_var_t *
480 484 mdb_nv_get_ndef(const mdb_var_t *v)
481 485 {
482 486 if (v->v_flags & MDB_NV_OVERLOAD)
483 487 return (v->v_ndef);
484 488
485 489 return (NULL);
486 490 }
↓ open down ↓ |
394 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX