Print this page
XXXX introduce drv_sectohz
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/avs/ns/nsctl/nsc_gen.c
+++ new/usr/src/uts/common/avs/ns/nsctl/nsc_gen.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 (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 #include <sys/types.h>
27 27 #include <sys/cmn_err.h>
28 28 #include <sys/errno.h>
29 29 #include <sys/ksynch.h>
30 30 #include <sys/kmem.h>
31 31 #include <sys/ddi.h>
32 32 #include <sys/varargs.h>
33 33 #if defined(DEBUG) && !defined(DS_DDICT)
34 34 #include <sys/kobj.h>
35 35 #endif
36 36
37 37 #include <sys/ncall/ncall.h>
38 38
39 39 #define __NSC_GEN__
40 40 #include "nsc_gen.h"
41 41 #include "nsc_mem.h"
42 42 #include "../nsctl.h"
43 43 #ifdef DS_DDICT
44 44 #include "../contract.h"
45 45 #endif
46 46
47 47
48 48 static kcondvar_t _nsc_delay_cv;
49 49 static kmutex_t _nsc_delay_mutex;
50 50
51 51 static nsc_service_t *_nsc_services;
52 52 static kmutex_t _nsc_svc_mutex;
53 53
54 54 static int _nsc_rmmap_inuse(nsc_rmmap_t *, ulong_t *, size_t *);
55 55
↓ open down ↓ |
55 lines elided |
↑ open up ↑ |
56 56 static void _nsc_sprint_dec(char **, int, int, int);
57 57 static void _nsc_sprint_hex(char **, unsigned int, int, int, int, int);
58 58
59 59 clock_t HZ;
60 60
61 61 extern nsc_rmhdr_t *_nsc_rmhdr_ptr;
62 62
63 63 void
64 64 _nsc_init_gen()
65 65 {
66 - HZ = drv_usectohz(1000000);
66 + HZ = drv_sectohz(1);
67 67 }
68 68
69 69
70 70 void
71 71 nsc_decode_param(nsc_def_t *args, nsc_def_t *def, long *v)
72 72 {
73 73 nsc_def_t *dp;
74 74
75 75 for (; def && def->name; def++) {
76 76 for (dp = args; dp && dp->name; dp++) {
77 77 if (strcmp(dp->name, def->name) == 0) {
78 78 v[def->offset] = dp->value;
79 79 break;
80 80 }
81 81 }
82 82
83 83 if ((!dp || !dp->name) && !v[def->offset])
84 84 v[def->offset] = def->value;
85 85 }
86 86 }
87 87
88 88
89 89 clock_t
90 90 nsc_lbolt()
91 91 {
92 92 #ifdef _SunOS_5_6
93 93 clock_t lbolt;
94 94 time_t time;
95 95
96 96 if (drv_getparm(LBOLT, &lbolt) == 0)
97 97 return (lbolt);
98 98
99 99 if (drv_getparm(TIME, &time) != 0)
100 100 return ((clock_t)0);
101 101
102 102 time %= (60 * 60 * 24 * 365);
103 103
104 104 return (clock_t)(time * HZ);
105 105 #else
106 106 return (ddi_get_lbolt());
107 107 #endif
108 108 }
109 109
110 110
111 111 time_t
112 112 nsc_time()
113 113 {
114 114 time_t time;
115 115
116 116 if (drv_getparm(TIME, &time) != 0)
117 117 return ((time_t)0);
118 118
119 119 return (time);
120 120 }
121 121
122 122
123 123 int
124 124 nsc_node_up(int node)
125 125 {
126 126 return (node == ncall_self());
127 127 }
128 128
129 129
130 130
131 131 /*
132 132 * HACK increment nodeid in data parameter
133 133 */
134 134 int
135 135 nsc_nodeid_data()
136 136 {
137 137 int data;
138 138 return ((data = nsc_node_id()) == 0 ? 1 : data);
139 139 }
140 140
141 141
142 142 int
143 143 nsc_node_id(void)
144 144 {
145 145 return (ncall_self());
146 146 }
147 147
148 148 char *
149 149 nsc_node_name()
150 150 {
151 151 return (ncall_nodename(ncall_self()));
152 152 }
153 153
154 154
155 155 /*
156 156 * int
157 157 * _nsc_rmmap_init (nsc_rmmap_t *map, char *name, int nslot,
158 158 * size_t size, ulong_t offset)
159 159 * Initialise a global resource map.
160 160 *
161 161 * Calling/Exit State:
162 162 * Returns TRUE if the map was successfully created. Otherwise
163 163 * returns FALSE.
164 164 *
165 165 * Description:
166 166 * Initialises a global resource map. If the map already exists
167 167 * the arguments are validated against it.
168 168 */
169 169 int
170 170 _nsc_rmmap_init(nsc_rmmap_t *map, char *name,
171 171 int nslot, size_t size, ulong_t offset)
172 172 {
173 173 nsc_rmmap_t *nvmap = NULL;
174 174
175 175 if (!size)
176 176 return (0);
177 177
178 178 mutex_enter(&_nsc_global_lock);
179 179
180 180 if (_nsc_rm_nvmem_base)
181 181 nvmap = _nsc_global_nvmemmap_lookup(map);
182 182
183 183 if (!map->size)
184 184 map->size = size;
185 185 if (!map->inuse)
186 186 map->inuse = nslot;
187 187 if (!map->offset)
188 188 map->offset = offset;
189 189
190 190 if (!map->name[0])
191 191 (void) strncpy(map->name, name, _NSC_MAXNAME);
192 192
193 193 /* actually we only need to do this if an update occurred above */
194 194 if (nvmap) {
195 195 (void) nsc_commit_mem(map, nvmap,
196 196 sizeof (nsc_rmmap_t), nsc_cm_errhdlr);
197 197 }
198 198
199 199 if (strncmp(map->name, name, _NSC_MAXNAME) ||
200 200 (uint32_t)size != map->size || (int32_t)offset != map->offset) {
201 201 mutex_exit(&_nsc_global_lock);
202 202 return (0);
203 203 }
204 204
205 205 mutex_exit(&_nsc_global_lock);
206 206 return (1);
207 207 }
208 208
209 209
210 210 /*
211 211 * ulong_t
212 212 * _nsc_rmmap_alloc (nsc_rmmap_t *map, char *name,
213 213 * size_t size, void (*alloc)())
214 214 * Allocate entry in a global resource map.
215 215 *
216 216 * Calling/Exit State:
217 217 * On success, returns the base of the allocated area. Otherwise,
218 218 * returns NULL. The function 'alloc' will be called if the
219 219 * allocated area is not currently in use.
220 220 *
221 221 * Description:
222 222 * Allocates an entry in the global resource map. If the entry
223 223 * already exists but is a different size an error is returned.
224 224 */
225 225 ulong_t
226 226 _nsc_rmmap_alloc(nsc_rmmap_t *map, char *name, size_t size, void (*alloc)())
227 227 {
228 228 int i, nslot = map[0].inuse;
229 229 size_t want = size;
230 230 ulong_t offset;
231 231 nsc_rmmap_t *nvmap = NULL;
232 232
233 233 if (!size)
234 234 return (0);
235 235
236 236 mutex_enter(&_nsc_global_lock);
237 237 if (_nsc_rm_nvmem_base)
238 238 nvmap = _nsc_global_nvmemmap_lookup(map);
239 239
240 240 for (i = 1; i < nslot; i++) {
241 241 if (!map[i].inuse || !map[i].size)
242 242 continue;
243 243 if (strncmp(map[i].name, name, _NSC_MAXNAME))
244 244 continue;
245 245 if ((uint32_t)size == map[i].size) {
246 246 map[i].inuse |= (1 << nsc_node_id());
247 247 if (nvmap) {
248 248 (void) nsc_commit_mem(&map[i], &nvmap[i],
249 249 sizeof (nsc_rmmap_t), nsc_cm_errhdlr);
250 250 }
251 251 mutex_exit(&_nsc_global_lock);
252 252 return (map[i].offset);
253 253 }
254 254
255 255 mutex_exit(&_nsc_global_lock);
256 256 return (0);
257 257 }
258 258
259 259 offset = map[0].offset;
260 260
261 261 while ((int32_t)offset < (map[0].offset + map[0].size)) {
262 262 if (_nsc_rmmap_inuse(map, &offset, &want))
263 263 continue;
264 264
265 265 if (size > want) {
266 266 offset += want;
267 267 want = size;
268 268 continue;
269 269 }
270 270
271 271 for (i = 1; i < nslot; i++)
272 272 if (!map[i].inuse || !map[i].size)
273 273 break;
274 274
275 275 if (i == nslot)
276 276 break;
277 277
278 278 bzero(&map[i], sizeof (map[i]));
279 279 (void) strncpy(map[i].name, name, _NSC_MAXNAME);
280 280
281 281 map[i].size = size;
282 282 map[i].offset = offset;
283 283 map[i].inuse = (1 << nsc_node_id());
284 284 if (nvmap) { /* update the map and hdr dirty bit. */
285 285 (void) nsc_commit_mem(&map[i], &nvmap[i],
286 286 sizeof (nsc_rmmap_t), nsc_cm_errhdlr);
287 287 }
288 288
289 289 if (alloc)
290 290 (*alloc)(offset, size);
291 291
292 292 mutex_exit(&_nsc_global_lock);
293 293 return (offset);
294 294 }
295 295
296 296 mutex_exit(&_nsc_global_lock);
297 297 return (0);
298 298 }
299 299
300 300
301 301 /*
302 302 * void
303 303 * _nsc_rmmap_free (nsc_rmmap_t *map, char *name)
304 304 * Free entry in a global resource map.
305 305 *
306 306 * Description:
307 307 * Frees an entry in the global resource map.
308 308 */
309 309 void
310 310 _nsc_rmmap_free(nsc_rmmap_t *map, char *name, nsc_mem_t *mp)
311 311 {
312 312 int i, nslot = map[0].inuse;
313 313 nsc_rmmap_t *nvmap = NULL;
314 314
315 315 mutex_enter(&_nsc_global_lock);
316 316 if (_nsc_rm_nvmem_base)
317 317 nvmap = _nsc_global_nvmemmap_lookup(map);
318 318
319 319 for (i = 1; i < nslot; i++) {
320 320 if (!map[i].inuse || !map[i].size)
321 321 continue;
322 322 if (strncmp(map[i].name, name, _NSC_MAXNAME))
323 323 continue;
324 324
325 325 map[i].inuse &= ~(1 << nsc_node_id());
326 326 if (nvmap) {
327 327 /*
328 328 * if dirty, set the inuse bit so this area
329 329 * will not be _nsc_global_zero'd on restart.
330 330 */
331 331 if (mp && (mp->type & NSC_MEM_NVDIRTY)) {
332 332 map[i].inuse |= (1 << nsc_node_id());
333 333 }
334 334
335 335 (void) nsc_commit_mem(&map[i], &nvmap[i],
336 336 sizeof (nsc_rmmap_t), nsc_cm_errhdlr);
337 337 }
338 338 mutex_exit(&_nsc_global_lock);
339 339 return;
340 340 }
341 341
342 342 mutex_exit(&_nsc_global_lock);
343 343
344 344 cmn_err(CE_WARN, "!nsctl: _nsc_rmmap_free: invalid free");
345 345 }
346 346
347 347
348 348 /*
349 349 * size_t
350 350 * _nsc_rmmap_size (nsc_rmmap_t *map, char *name)
351 351 * Find size of area in map.
352 352 *
353 353 * Calling/Exit State:
354 354 * Returns the size of the specified area in the map,
355 355 * or 0 if it is currently unallocated.
356 356 */
357 357 size_t
358 358 _nsc_rmmap_size(nsc_rmmap_t *map, char *name)
359 359 {
360 360 int i, nslot = map[0].inuse;
361 361 size_t size = 0;
362 362
363 363 mutex_enter(&_nsc_global_lock);
364 364
365 365 for (i = 1; i < nslot; i++) {
366 366 if (!map[i].inuse || !map[i].size)
367 367 continue;
368 368
369 369 if (strncmp(map[i].name, name, _NSC_MAXNAME) == 0) {
370 370 size = map[i].size;
371 371 break;
372 372 }
373 373 }
374 374
375 375 mutex_exit(&_nsc_global_lock);
376 376 return (size);
377 377 }
378 378
379 379
380 380 /*
381 381 * size_t
382 382 * _nsc_rmmap_avail (nsc_rmmap_t *map)
383 383 * Find available space in global resource map.
384 384 *
385 385 * Calling/Exit State:
386 386 * Returns the size of the largest available area in
387 387 * the global resource map.
388 388 */
389 389 size_t
390 390 _nsc_rmmap_avail(nsc_rmmap_t *map)
391 391 {
392 392 size_t size, avail = 0;
393 393 ulong_t offset;
394 394
395 395 mutex_enter(&_nsc_global_lock);
396 396
397 397 size = 1;
398 398 offset = map[0].offset;
399 399
400 400 while ((int32_t)offset < (map[0].offset + map[0].size))
401 401 if (!_nsc_rmmap_inuse(map, &offset, &size)) {
402 402 if (size > avail)
403 403 avail = size;
404 404 offset += size;
405 405 size = 1;
406 406 }
407 407
408 408 mutex_exit(&_nsc_global_lock);
409 409 return (avail);
410 410 }
411 411
412 412
413 413 /*
414 414 * static int
415 415 * _nsc_rmmap_inuse (nsc_rmmap_t *map, ulong_t *offsetp, size_t *sizep)
416 416 * Check if a section of the map is in use.
417 417 *
418 418 * Calling/Exit State:
419 419 * The global lock must be held across calls to the function.
420 420 *
421 421 * Returns TRUE if the specified area is currently in use and
422 422 * updates offset to point just past the section that was found
423 423 * to be in use.
424 424 *
425 425 * Otherwise, returns FALSE and updates size to reflect the
426 426 * amount of free space at the specified offset.
427 427 *
428 428 * Description:
429 429 * Checks the specified global map to determine if any part
430 430 * of the area is in use.
431 431 */
432 432 static int
433 433 _nsc_rmmap_inuse(nsc_rmmap_t *map, ulong_t *offsetp, size_t *sizep)
434 434 {
435 435 size_t avail, size = (*sizep);
436 436 ulong_t offset = (*offsetp);
437 437 int i, nslot;
438 438
439 439 nslot = map[0].inuse;
440 440 avail = map[0].offset + map[0].size - offset;
441 441
442 442 for (i = 1; i < nslot; i++) {
443 443 if (!map[i].size || !map[i].inuse)
444 444 continue;
445 445 if ((int32_t)(offset + size) > map[i].offset &&
446 446 (int32_t)offset < (map[i].offset + map[i].size)) {
447 447 (*offsetp) = map[i].offset + map[i].size;
448 448 return (1);
449 449 }
450 450
451 451 if (map[i].offset >= (int32_t)offset)
452 452 if (avail > map[i].offset - offset)
453 453 avail = map[i].offset - offset;
454 454 }
455 455
456 456 (*sizep) = avail;
457 457 return (0);
458 458 }
459 459
460 460 /*
461 461 * int
462 462 * nsc_delay_sig (clock_t tics)
463 463 * Delay for a number of clock ticks.
464 464 *
465 465 * Calling/Exit State:
466 466 * Returns FALSE if the delay was interrupted by a
467 467 * signal, TRUE otherwise.
468 468 *
469 469 * Description:
470 470 * Delays execution for the specified number of ticks
471 471 * or until a signal is received.
472 472 */
473 473 int
474 474 nsc_delay_sig(clock_t tics)
475 475 {
476 476 clock_t target, remain, rc;
477 477
478 478 target = nsc_lbolt() + tics;
479 479 rc = 1;
480 480
481 481 mutex_enter(&_nsc_delay_mutex);
482 482
483 483 /* CONSTCOND */
484 484
485 485 while (1) {
486 486 remain = target - nsc_lbolt();
487 487
488 488 if (remain <= 0 || rc == -1) {
489 489 /* timeout */
490 490 break;
491 491 }
492 492
493 493 rc = cv_timedwait_sig(&_nsc_delay_cv,
494 494 &_nsc_delay_mutex, target);
495 495
496 496 if (rc == 0) {
497 497 /* signalled */
498 498 mutex_exit(&_nsc_delay_mutex);
499 499 return (FALSE);
500 500 }
501 501 }
502 502
503 503 mutex_exit(&_nsc_delay_mutex);
504 504
505 505 return (TRUE);
506 506 }
507 507
508 508
509 509 /*
510 510 * void
511 511 * nsc_sprintf (char *s, char *fmt, ...)
512 512 * String printf.
513 513 *
514 514 * Calling/Exit State:
515 515 * Builds a NULL terminated string in the buffer
516 516 * pointed to by 's', using the format 'fmt'.
517 517 *
518 518 * Description:
519 519 * Simple version of sprintf supporting fairly
520 520 * basic formats.
521 521 */
522 522
523 523 /* PRINTFLIKE2 */
524 524
525 525 void
526 526 nsc_sprintf(char *s, char *fmt, ...)
527 527 {
528 528 int alt, zero, len;
529 529 char c, *cp;
530 530 va_list p;
531 531
532 532 va_start(p, fmt);
533 533
534 534 /* CONSTCOND */
535 535
536 536 while (1) {
537 537 alt = 0, zero = 0, len = 0;
538 538
539 539 if ((c = *fmt++) != '%') {
540 540 if (!c)
541 541 break;
542 542 *s++ = c;
543 543 continue;
544 544 }
545 545
546 546 if ((c = *fmt++) == 0) {
547 547 *s++ = '%';
548 548 break;
549 549 }
550 550
551 551 alt = (c == '#');
552 552 if (alt && !(c = *fmt++))
553 553 break;
554 554
555 555 zero = (c == '0');
556 556 if (zero && !(c = *fmt++))
557 557 break;
558 558
559 559 while ((len ? '0' : '1') <= c && c <= '9') {
560 560 len = (len * 10) + (c - '0');
561 561 if (!(c = *fmt++))
562 562 break;
563 563 }
564 564
565 565 if (c == 's') {
566 566 cp = (char *)va_arg(p, caddr_t);
567 567 while (*cp)
568 568 *s++ = *cp++;
569 569 continue;
570 570 }
571 571
572 572 if (c == 'd' || c == 'u') {
573 573 _nsc_sprint_dec(&s, va_arg(p, int), zero, len);
574 574 continue;
575 575 }
576 576
577 577 if (c == 'x' || c == 'X') {
578 578 _nsc_sprint_hex(&s, va_arg(p, uint_t),
579 579 (c == 'X'), alt, zero, len);
580 580 continue;
581 581 }
582 582
583 583 *s++ = '%';
584 584 if (alt)
585 585 *s++ = '#';
586 586 if (zero)
587 587 *s++ = '0';
588 588
589 589 if (len)
590 590 _nsc_sprint_dec(&s, len, 0, 0);
591 591 *s++ = c;
592 592 }
593 593
594 594 if (alt || zero || len) {
595 595 *s++ = '%';
596 596
597 597 if (alt)
598 598 *s++ = '#';
599 599 if (zero)
600 600 *s++ = '0';
601 601
602 602 if (len)
603 603 _nsc_sprint_dec(&s, len, 0, 0);
604 604 }
605 605
606 606 va_end(p);
607 607 *s = 0;
608 608 }
609 609
610 610
611 611 /*
612 612 * static void
613 613 * _nsc_sprint_dec (char **sptr, int n, int zero, int len)
614 614 * Decimal to string conversion.
615 615 *
616 616 * Calling/Exit State:
617 617 * Stores a character representation of 'n' in the
618 618 * buffer referenced by 'sptr' and updates the pointer
619 619 * accordingly.
620 620 *
621 621 * Description:
622 622 * Generates a string representation of a signed decimal
623 623 * integer.
624 624 */
625 625
626 626 static void
627 627 _nsc_sprint_dec(char **sptr, int n, int zero, int len)
628 628 {
629 629 unsigned int v = (n < 0) ? (-n) : n;
630 630 char c[20];
631 631 int i;
632 632
633 633 for (i = 0; v; i++) {
634 634 c[i] = (v % 10) + '0';
635 635 v /= 10;
636 636 }
637 637
638 638 len -= (i ? i : 1);
639 639
640 640 if (n < 0 && !zero)
641 641 for (len--; len > 0; len--)
642 642 *(*sptr)++ = ' ';
643 643
644 644 if (n < 0) {
645 645 *(*sptr)++ = '-';
646 646 len--;
647 647 }
648 648
649 649 for (; len > 0; len--)
650 650 *(*sptr)++ = (zero ? '0' : ' ');
651 651
652 652 if (!i)
653 653 *(*sptr)++ = '0';
654 654
655 655 while (i--)
656 656 *(*sptr)++ = c[i];
657 657 }
658 658
659 659
660 660 /*
661 661 * static void
662 662 * _nsc_sprint_hex (char **sptr, unsigned int v,
663 663 * int up, int alt, int zero, int len)
664 664 * Hexadecimal to string conversion.
665 665 *
666 666 * Calling/Exit State:
667 667 * Stores a character representation of 'v' in the
668 668 * buffer referenced by 'sptr' and updates the pointer
669 669 * accordingly.
670 670 *
671 671 * Description:
672 672 * Generates a string representation of an unsigned
673 673 * hexadecimal integer.
674 674 */
675 675
676 676 static void
677 677 _nsc_sprint_hex(char **sptr, uint_t v, int up, int alt, int zero, int len)
678 678 {
679 679 char *str = "0123456789abcdef";
680 680 char c[20];
681 681 int i;
682 682
683 683 if (up)
684 684 str = "0123456789ABCDEF";
685 685
686 686 for (i = 0; v; i++) {
687 687 c[i] = str[(v % 16)];
688 688 v /= 16;
689 689 }
690 690
691 691 if (alt) {
692 692 *(*sptr)++ = '0';
693 693 *(*sptr)++ = (up ? 'X' : 'x');
694 694 }
695 695
696 696 for (len -= (i ? i : 1); len > 0; len--)
697 697 *(*sptr)++ = (zero ? '0' : ' ');
698 698
699 699 if (!i)
700 700 *(*sptr)++ = '0';
701 701 while (i--)
702 702 *(*sptr)++ = c[i];
703 703 }
704 704
705 705
706 706 /*
707 707 * char *
708 708 * nsc_strdup (char *s)
709 709 * Duplicate string.
710 710 *
711 711 * Calling/Exit State:
712 712 * Returns the address of the new string.
713 713 *
714 714 * Description:
715 715 * Allocates a suitably sized area of memory and
716 716 * copies the string into it. The string should be
717 717 * free'd using nsc_strfree().
718 718 */
719 719 char *
720 720 nsc_strdup(char *s)
721 721 {
722 722 char *cp;
723 723
724 724 if (s == NULL)
725 725 return (NULL);
726 726
727 727 cp = nsc_kmem_alloc(strlen(s) + 1, KM_SLEEP, NULL);
728 728 (void) strcpy(cp, s);
729 729 return (cp);
730 730 }
731 731
732 732
733 733 /*
734 734 * void
735 735 * nsc_strfree (char *s)
736 736 * Free string.
737 737 *
738 738 * Description:
739 739 * Frees a string previously allocated by nsc_strdup.
740 740 */
741 741 void
742 742 nsc_strfree(char *s)
743 743 {
744 744 if (s)
745 745 nsc_kmem_free(s, strlen(s) + 1);
746 746 }
747 747
748 748
749 749 /*
750 750 * int
751 751 * nsc_strmatch (char *s, char *pat)
752 752 * Match string against pattern.
753 753 *
754 754 * Calling/Exit State:
755 755 * Returns TRUE if the string matches against the
756 756 * pattern, FALSE otherwise.
757 757 *
758 758 * Description:
759 759 * Compares string against regular expression which
760 760 * can contain '*', '?' and '[]' constructs.
761 761 */
762 762 int
763 763 nsc_strmatch(char *s, char *pat)
764 764 {
765 765 int neg;
766 766
767 767 for (; *pat; pat++, s++) {
768 768 if (*pat == '*') {
769 769 while (*pat == '*')
770 770 pat++;
771 771
772 772 if (!*pat)
773 773 return (1);
774 774
775 775 for (; *s; s++)
776 776 if (*pat == '[' || *pat == '?' || *pat == *s)
777 777 if (nsc_strmatch(s, pat))
778 778 return (1);
779 779 return (0);
780 780 }
781 781
782 782 if (!*s)
783 783 return (0);
784 784
785 785 if (*pat == '[') {
786 786 if ((neg = (*++pat == '^')) != 0)
787 787 pat++;
788 788
789 789 while (*pat) {
790 790 if (*pat == *s)
791 791 break;
792 792
793 793 if (pat[1] == '-' && pat[2] != ']') {
794 794 if (*pat <= *s && *s <= pat[2])
795 795 break;
796 796 pat += 2;
797 797 }
798 798
799 799 if (*++pat == ']') {
800 800 if (neg)
801 801 goto lp;
802 802 else
803 803 return (0);
804 804 }
805 805 }
806 806
807 807 while (*pat && *++pat != ']')
808 808 ;
809 809
810 810 if (!*pat || neg)
811 811 return (0);
812 812 lp:
813 813 continue;
814 814 }
815 815
816 816 if (*pat != '?' && *pat != *s)
817 817 return (0);
818 818 }
819 819
820 820 return (!*s);
821 821 }
822 822
823 823
824 824 /*
825 825 * uint64_t
826 826 * nsc_strhash(char *str)
827 827 * Calculate a simple hash for the specified string
828 828 *
829 829 * Calling/Exit State:
830 830 * Returns a simple hash of the NULL terminated string, str.
831 831 *
832 832 * Description:
833 833 */
834 834 uint64_t
835 835 nsc_strhash(char *str)
836 836 {
837 837 uint64_t hash = (uint64_t)0;
838 838
839 839 if (str == NULL)
840 840 return (hash);
841 841
842 842 while (*str != '\0') {
843 843 hash <<= 1;
844 844 hash += (uint64_t)*str;
845 845 str++;
846 846 }
847 847
848 848 return (hash);
849 849 }
850 850
851 851
852 852 /*
853 853 * int
854 854 * nsc_fatal(void)
855 855 * Fatal error stub function
856 856 *
857 857 * Calling/Exit State:
858 858 * Returns EINVAL (non-DEBUG) or forces a panic.
859 859 *
860 860 * Description:
861 861 * This is a stub function suitable for default actions in
862 862 * nsctl i/o provider definitions. It should be used when
863 863 * calling the stub would be a programming error. The most
864 864 * common reason for nsc_fatal() being called is that an
865 865 * nsctl client module has called an nsc_fd_t i/o function
866 866 * without the fd already reserved.
867 867 *
868 868 * The function will display a diagnostic message and when
869 869 * built -DDEBUG will force a panic and display the textual
870 870 * name of the symbol closest to the caller address of this
871 871 * function.
872 872 */
873 873 int
874 874 nsc_fatal()
875 875 {
876 876 void *caller = nsc_caller();
877 877 #ifdef DEBUG
878 878 caddr_t caller_sym = NULL;
879 879 ulong_t offset = 0UL;
880 880
881 881 #ifndef DS_DDICT
882 882 caller_sym = kobj_getsymname((uintptr_t)caller, &offset);
883 883 #endif /* !DS_DDICT */
884 884
885 885 cmn_err(CE_WARN, "!nsctl: nsc_fatal called at 0x%p (%s+0x%lx)",
886 886 caller, caller_sym ? caller_sym : "?", offset);
887 887
888 888 /*
889 889 * Force TRAP due to NULL pointer dereference
890 890 * - CE_PANIC can result in the stack trace being unreadable
891 891 * by (k)adb.
892 892 */
893 893 *(int *)0 = 0x12345678;
894 894
895 895 #else /* !DEBUG */
896 896
897 897 cmn_err(CE_WARN, "!nsctl: nsc_fatal called at 0x%p", caller);
898 898
899 899 #endif /* DEBUG */
900 900
901 901 return (EINVAL);
902 902 }
903 903
904 904
905 905 int nsc_null() { return (0); }
906 906 int nsc_true() { return (1); }
907 907 int nsc_inval() { return (-1); }
908 908 int nsc_ioerr() { return (EIO); }
909 909
910 910 /*ARGSUSED*/
911 911 int
912 912 nsc_commit_mem(void *src, void *dst, size_t len, nsc_mem_err_cb err_action)
913 913 {
914 914
915 915 return (0);
916 916 }
917 917
918 918 static int _nsc_nvmem_errs;
919 919
920 920 /* ARGSUSED */
921 921 void
922 922 nsc_cm_errhdlr(void *src, void *dst, size_t len, int errval)
923 923 {
924 924 static int _nsc_baddma_already_seen = 0;
925 925
926 926 if (!(_nsc_baddma_already_seen % 100)) {
927 927 cmn_err(CE_WARN, "!nsc_cm_errhdlr: media down, forced_wrthru");
928 928
929 929 _nsc_baddma_already_seen += 1;
930 930
931 931 if (_nsc_baddma_already_seen >= 100) {
932 932 cmn_err(CE_WARN,
933 933 "!nsc_cm_errhdlr: this message "
934 934 "displayed every 100 errors");
935 935 }
936 936 }
937 937
938 938 (void) nsc_node_hints_set(NSC_FORCED_WRTHRU);
939 939
940 940 _nsc_nvmem_errs++;
941 941 }
942 942
943 943
944 944 void
945 945 _nsc_init_svc(void)
946 946 {
947 947 mutex_init(&_nsc_svc_mutex, NULL, MUTEX_DRIVER, NULL);
948 948 mutex_init(&_nsc_delay_mutex, NULL, MUTEX_DRIVER, NULL);
949 949 cv_init(&_nsc_delay_cv, NULL, CV_DRIVER, NULL);
950 950 }
951 951
952 952
953 953 void
954 954 _nsc_deinit_svc(void)
955 955 {
956 956 if (_nsc_services != NULL) {
957 957 cmn_err(CE_PANIC,
958 958 "nsctl: services registered in _nsc_deinit_svc");
959 959 /* NOTREACHED */
960 960 }
961 961
962 962 cv_destroy(&_nsc_delay_cv);
963 963 mutex_destroy(&_nsc_delay_mutex);
964 964 mutex_destroy(&_nsc_svc_mutex);
965 965 }
966 966
967 967
968 968 nsc_svc_t *
969 969 nsc_register_svc(char *name, void (*service_fn)(intptr_t))
970 970 {
971 971 nsc_service_t *sp, *new;
972 972 nsc_svc_t *svc;
973 973
974 974 new = nsc_kmem_zalloc(sizeof (*new), KM_SLEEP, 0);
975 975 if (new == NULL)
976 976 return (NULL);
977 977
978 978 svc = nsc_kmem_zalloc(sizeof (*svc), KM_SLEEP, 0);
979 979 if (svc == NULL) {
980 980 nsc_kmem_free(new, sizeof (*new));
981 981 return (NULL);
982 982 }
983 983
984 984 mutex_enter(&_nsc_svc_mutex);
985 985
986 986 for (sp = _nsc_services; sp != NULL; sp = sp->s_next)
987 987 if (strcmp(name, sp->s_name) == 0)
988 988 break;
989 989
990 990 if (sp == NULL) {
991 991 sp = new;
992 992 sp->s_name = nsc_strdup(name);
993 993 if (sp->s_name == NULL) {
994 994 mutex_exit(&_nsc_svc_mutex);
995 995 nsc_kmem_free(new, sizeof (*new));
996 996 nsc_kmem_free(svc, sizeof (*svc));
997 997 return (NULL);
998 998 }
999 999
1000 1000 rw_init(&sp->s_rwlock, NULL, RW_DRIVER, NULL);
1001 1001 sp->s_next = _nsc_services;
1002 1002 _nsc_services = sp;
1003 1003 }
1004 1004
1005 1005 rw_enter(&sp->s_rwlock, RW_WRITER);
1006 1006
1007 1007 svc->svc_fn = service_fn;
1008 1008 svc->svc_svc = sp;
1009 1009
1010 1010 if (svc->svc_fn != NULL) {
1011 1011 svc->svc_next = sp->s_servers;
1012 1012 sp->s_servers = svc;
1013 1013 } else {
1014 1014 svc->svc_next = sp->s_clients;
1015 1015 sp->s_clients = svc;
1016 1016 }
1017 1017
1018 1018 rw_exit(&sp->s_rwlock);
1019 1019 mutex_exit(&_nsc_svc_mutex);
1020 1020
1021 1021 if (sp != new)
1022 1022 nsc_kmem_free(new, sizeof (*new));
1023 1023
1024 1024 return (svc);
1025 1025 }
1026 1026
1027 1027
1028 1028 int
1029 1029 nsc_unregister_svc(nsc_svc_t *svc)
1030 1030 {
1031 1031 nsc_service_t *sp, **spp;
1032 1032 nsc_svc_t **svcp;
1033 1033
1034 1034 if (svc == NULL)
1035 1035 return (EINVAL);
1036 1036
1037 1037 sp = svc->svc_svc;
1038 1038 if (sp == NULL)
1039 1039 return (EINVAL);
1040 1040
1041 1041 mutex_enter(&_nsc_svc_mutex);
1042 1042 rw_enter(&sp->s_rwlock, RW_WRITER);
1043 1043
1044 1044 svcp = (svc->svc_fn == NULL) ? &sp->s_clients : &sp->s_servers;
1045 1045 for (; *svcp; svcp = &((*svcp)->svc_next))
1046 1046 if (svc == (*svcp))
1047 1047 break;
1048 1048
1049 1049 if (*svcp)
1050 1050 (*svcp) = svc->svc_next;
1051 1051
1052 1052 nsc_kmem_free(svc, sizeof (*svc));
1053 1053
1054 1054 if (sp->s_servers == NULL && sp->s_clients == NULL) {
1055 1055 for (spp = &_nsc_services; *spp; spp = &((*spp)->s_next))
1056 1056 if ((*spp) == sp)
1057 1057 break;
1058 1058
1059 1059 if (*spp)
1060 1060 (*spp) = sp->s_next;
1061 1061
1062 1062 rw_exit(&sp->s_rwlock);
1063 1063 mutex_exit(&_nsc_svc_mutex);
1064 1064
1065 1065 rw_destroy(&sp->s_rwlock);
1066 1066 nsc_strfree(sp->s_name);
1067 1067
1068 1068 nsc_kmem_free(sp, sizeof (*sp));
1069 1069 return (0);
1070 1070 }
1071 1071
1072 1072 rw_exit(&sp->s_rwlock);
1073 1073 mutex_exit(&_nsc_svc_mutex);
1074 1074
1075 1075 return (0);
1076 1076 }
1077 1077
1078 1078
1079 1079 int
1080 1080 nsc_call_svc(nsc_svc_t *svc, intptr_t arg)
1081 1081 {
1082 1082 nsc_service_t *sp;
1083 1083 nsc_svc_t *svcp;
1084 1084 int found;
1085 1085
1086 1086 if (svc == NULL)
1087 1087 return (EINVAL);
1088 1088
1089 1089 sp = svc->svc_svc;
1090 1090 if (sp == NULL)
1091 1091 return (EINVAL);
1092 1092
1093 1093 rw_enter(&sp->s_rwlock, RW_READER);
1094 1094
1095 1095 found = (sp->s_servers != NULL);
1096 1096
1097 1097 for (svcp = sp->s_servers; svcp; svcp = svcp->svc_next)
1098 1098 (*svcp->svc_fn)(arg);
1099 1099
1100 1100 rw_exit(&sp->s_rwlock);
1101 1101
1102 1102 if (found == 0)
1103 1103 return (ENOSYS);
1104 1104
1105 1105 return (0);
1106 1106 }
↓ open down ↓ |
1030 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX