Print this page
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/os/pid.c
+++ new/usr/src/uts/common/os/pid.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 /*
23 23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 * Copyright 2015 Joyent, Inc.
25 25 */
26 26
27 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 28 /* All Rights Reserved */
29 29
30 30 #include <sys/types.h>
31 31 #include <sys/param.h>
32 32 #include <sys/sysmacros.h>
33 33 #include <sys/proc.h>
34 34 #include <sys/kmem.h>
35 35 #include <sys/tuneable.h>
36 36 #include <sys/var.h>
37 37 #include <sys/cred.h>
38 38 #include <sys/systm.h>
39 39 #include <sys/prsystm.h>
40 40 #include <sys/vnode.h>
41 41 #include <sys/session.h>
42 42 #include <sys/cpuvar.h>
43 43 #include <sys/cmn_err.h>
44 44 #include <sys/bitmap.h>
45 45 #include <sys/debug.h>
46 46 #include <c2/audit.h>
47 47 #include <sys/project.h>
48 48 #include <sys/task.h>
49 49 #include <sys/zone.h>
50 50
51 51 /* directory entries for /proc */
52 52 union procent {
53 53 proc_t *pe_proc;
54 54 union procent *pe_next;
55 55 };
56 56
57 57 struct pid pid0 = {
58 58 0, /* pid_prinactive */
59 59 1, /* pid_pgorphaned */
60 60 0, /* pid_padding */
61 61 0, /* pid_prslot */
62 62 0, /* pid_id */
63 63 NULL, /* pid_pglink */
64 64 NULL, /* pid_pgtail */
65 65 NULL, /* pid_link */
66 66 3 /* pid_ref */
67 67 };
68 68
69 69 static int pid_hashlen = 4; /* desired average hash chain length */
70 70 static int pid_hashsz; /* number of buckets in the hash table */
71 71
72 72 #define HASHPID(pid) (pidhash[((pid)&(pid_hashsz-1))])
73 73
74 74 extern uint_t nproc;
75 75 extern struct kmem_cache *process_cache;
76 76 static void upcount_init(void);
77 77
78 78 kmutex_t pidlock; /* global process lock */
79 79 kmutex_t pr_pidlock; /* /proc global process lock */
80 80 kcondvar_t *pr_pid_cv; /* for /proc, one per process slot */
81 81 struct plock *proc_lock; /* persistent array of p_lock's */
82 82
83 83 /*
84 84 * See the comment above pid_getlockslot() for a detailed explanation of this
85 85 * constant. Note that a PLOCK_SHIFT of 3 implies 64-byte coherence
86 86 * granularity; if the coherence granularity is ever changed, this constant
87 87 * should be modified to reflect the change to minimize proc_lock false
88 88 * sharing (correctness, however, is guaranteed regardless of the coherence
89 89 * granularity).
90 90 */
91 91 #define PLOCK_SHIFT 3
92 92
93 93 static kmutex_t pidlinklock;
94 94 static struct pid **pidhash;
95 95 static pid_t minpid;
96 96 static pid_t mpid = FAMOUS_PIDS; /* one more than the last famous pid */
97 97 static union procent *procdir;
98 98 static union procent *procentfree;
99 99
100 100 static struct pid *
101 101 pid_lookup(pid_t pid)
102 102 {
103 103 struct pid *pidp;
104 104
105 105 ASSERT(MUTEX_HELD(&pidlinklock));
106 106
107 107 for (pidp = HASHPID(pid); pidp; pidp = pidp->pid_link) {
108 108 if (pidp->pid_id == pid) {
109 109 ASSERT(pidp->pid_ref > 0);
110 110 break;
111 111 }
112 112 }
113 113 return (pidp);
114 114 }
115 115
116 116 struct pid *
117 117 pid_find(pid_t pid)
118 118 {
119 119 struct pid *pidp;
120 120
121 121 mutex_enter(&pidlinklock);
122 122 pidp = pid_lookup(pid);
123 123 mutex_exit(&pidlinklock);
124 124
125 125 return (pidp);
126 126 }
127 127
128 128 void
129 129 pid_setmin(void)
130 130 {
131 131 if (jump_pid && jump_pid > mpid)
132 132 minpid = mpid = jump_pid;
133 133 else
134 134 minpid = mpid;
135 135 }
136 136
137 137 /*
138 138 * When prslots are simply used as an index to determine a process' p_lock,
139 139 * adjacent prslots share adjacent p_locks. On machines where the size
140 140 * of a mutex is smaller than that of a cache line (which, as of this writing,
141 141 * is true for all machines on which Solaris runs), this can potentially
142 142 * induce false sharing. The standard solution for false sharing is to pad
143 143 * out one's data structures (in this case, struct plock). However,
144 144 * given the size and (generally) sparse use of the proc_lock array, this
145 145 * is suboptimal. We therefore stride through the proc_lock array with
146 146 * a stride of PLOCK_SHIFT. PLOCK_SHIFT should be defined as:
147 147 *
148 148 * log_2 (coherence_granularity / sizeof (kmutex_t))
149 149 *
150 150 * Under this scheme, false sharing is still possible -- but only when
151 151 * the number of active processes is very large. Note that the one-to-one
152 152 * mapping between prslots and lockslots is maintained.
153 153 */
154 154 static int
155 155 pid_getlockslot(int prslot)
156 156 {
157 157 int even = (v.v_proc >> PLOCK_SHIFT) << PLOCK_SHIFT;
158 158 int perlap = even >> PLOCK_SHIFT;
159 159
160 160 if (prslot >= even)
161 161 return (prslot);
162 162
163 163 return (((prslot % perlap) << PLOCK_SHIFT) + (prslot / perlap));
164 164 }
165 165
166 166 /*
167 167 * This function allocates a pid structure, a free pid, and optionally a
168 168 * slot in the proc table for it.
169 169 *
170 170 * pid_allocate() returns the new pid on success, -1 on failure.
171 171 */
172 172 pid_t
173 173 pid_allocate(proc_t *prp, pid_t pid, int flags)
174 174 {
175 175 struct pid *pidp;
176 176 union procent *pep;
177 177 pid_t newpid, startpid;
178 178
179 179 pidp = kmem_zalloc(sizeof (struct pid), KM_SLEEP);
180 180
181 181 mutex_enter(&pidlinklock);
182 182 if ((flags & PID_ALLOC_PROC) && (pep = procentfree) == NULL) {
183 183 /*
184 184 * ran out of /proc directory entries
185 185 */
186 186 goto failed;
187 187 }
188 188
189 189 if (pid != 0) {
190 190 VERIFY(minpid == 0);
191 191 VERIFY3P(pid, <, mpid);
192 192 VERIFY3P(pid_lookup(pid), ==, NULL);
193 193 newpid = pid;
194 194 } else {
195 195 /*
196 196 * Allocate a pid
197 197 */
198 198 ASSERT(minpid <= mpid && mpid < maxpid);
199 199
200 200 startpid = mpid;
201 201 for (;;) {
202 202 newpid = mpid;
203 203 if (++mpid == maxpid)
204 204 mpid = minpid;
205 205
206 206 if (pid_lookup(newpid) == NULL)
207 207 break;
208 208
209 209 if (mpid == startpid)
210 210 goto failed;
211 211 }
212 212 }
213 213
214 214 /*
215 215 * Put pid into the pid hash table.
216 216 */
217 217 pidp->pid_link = HASHPID(newpid);
218 218 HASHPID(newpid) = pidp;
219 219 pidp->pid_ref = 1;
220 220 pidp->pid_id = newpid;
221 221
222 222 if (flags & PID_ALLOC_PROC) {
223 223 procentfree = pep->pe_next;
224 224 pidp->pid_prslot = pep - procdir;
225 225 pep->pe_proc = prp;
226 226 prp->p_pidp = pidp;
227 227 prp->p_lockp = &proc_lock[pid_getlockslot(pidp->pid_prslot)];
228 228 } else {
229 229 pidp->pid_prslot = 0;
230 230 }
231 231
232 232 mutex_exit(&pidlinklock);
233 233
234 234 return (newpid);
235 235
236 236 failed:
237 237 mutex_exit(&pidlinklock);
238 238 kmem_free(pidp, sizeof (struct pid));
239 239 return (-1);
240 240 }
241 241
242 242 /*
243 243 * decrement the reference count for pid
244 244 */
245 245 int
246 246 pid_rele(struct pid *pidp)
247 247 {
248 248 struct pid **pidpp;
249 249
250 250 mutex_enter(&pidlinklock);
251 251 ASSERT(pidp != &pid0);
252 252
253 253 pidpp = &HASHPID(pidp->pid_id);
254 254 for (;;) {
255 255 ASSERT(*pidpp != NULL);
256 256 if (*pidpp == pidp)
257 257 break;
258 258 pidpp = &(*pidpp)->pid_link;
259 259 }
260 260
261 261 *pidpp = pidp->pid_link;
262 262 mutex_exit(&pidlinklock);
263 263
264 264 kmem_free(pidp, sizeof (*pidp));
265 265 return (0);
266 266 }
267 267
268 268 void
269 269 proc_entry_free(struct pid *pidp)
270 270 {
271 271 mutex_enter(&pidlinklock);
272 272 pidp->pid_prinactive = 1;
273 273 procdir[pidp->pid_prslot].pe_next = procentfree;
274 274 procentfree = &procdir[pidp->pid_prslot];
275 275 mutex_exit(&pidlinklock);
276 276 }
277 277
278 278 /*
279 279 * The original task needs to be passed in since the process has already been
280 280 * detached from the task at this point in time.
281 281 */
282 282 void
283 283 pid_exit(proc_t *prp, struct task *tk)
284 284 {
285 285 struct pid *pidp;
286 286 zone_t *zone = prp->p_zone;
287 287
288 288 ASSERT(MUTEX_HELD(&pidlock));
289 289
290 290 /*
291 291 * Exit process group. If it is NULL, it's because fork failed
292 292 * before calling pgjoin().
293 293 */
294 294 ASSERT(prp->p_pgidp != NULL || prp->p_stat == SIDL);
295 295 if (prp->p_pgidp != NULL)
296 296 pgexit(prp);
297 297
298 298 sess_rele(prp->p_sessp, B_TRUE);
299 299
300 300 pidp = prp->p_pidp;
301 301
302 302 proc_entry_free(pidp);
303 303
304 304 if (audit_active)
305 305 audit_pfree(prp);
306 306
307 307 if (practive == prp) {
308 308 practive = prp->p_next;
309 309 }
310 310
311 311 if (prp->p_next) {
312 312 prp->p_next->p_prev = prp->p_prev;
313 313 }
314 314 if (prp->p_prev) {
315 315 prp->p_prev->p_next = prp->p_next;
316 316 }
317 317
318 318 PID_RELE(pidp);
319 319
320 320 mutex_destroy(&prp->p_crlock);
321 321 kmem_cache_free(process_cache, prp);
322 322 nproc--;
323 323
324 324 /*
325 325 * Decrement the process counts of the original task, project and zone.
326 326 */
327 327 mutex_enter(&zone->zone_nlwps_lock);
328 328 tk->tk_nprocs--;
329 329 tk->tk_proj->kpj_nprocs--;
330 330 zone->zone_nprocs--;
331 331 mutex_exit(&zone->zone_nlwps_lock);
332 332 }
333 333
334 334 /*
335 335 * Find a process visible from the specified zone given its process ID.
336 336 */
337 337 proc_t *
338 338 prfind_zone(pid_t pid, zoneid_t zoneid)
339 339 {
340 340 struct pid *pidp;
341 341 proc_t *p;
342 342
343 343 ASSERT(MUTEX_HELD(&pidlock));
344 344
345 345 mutex_enter(&pidlinklock);
346 346 pidp = pid_lookup(pid);
347 347 mutex_exit(&pidlinklock);
348 348 if (pidp != NULL && pidp->pid_prinactive == 0) {
349 349 p = procdir[pidp->pid_prslot].pe_proc;
350 350 if (zoneid == ALL_ZONES || p->p_zone->zone_id == zoneid)
351 351 return (p);
352 352 }
353 353 return (NULL);
354 354 }
355 355
356 356 /*
357 357 * Find a process given its process ID. This obeys zone restrictions,
358 358 * so if the caller is in a non-global zone it won't find processes
359 359 * associated with other zones. Use prfind_zone(pid, ALL_ZONES) to
360 360 * bypass this restriction.
361 361 */
362 362 proc_t *
363 363 prfind(pid_t pid)
364 364 {
365 365 zoneid_t zoneid;
366 366
367 367 if (INGLOBALZONE(curproc))
368 368 zoneid = ALL_ZONES;
369 369 else
370 370 zoneid = getzoneid();
371 371 return (prfind_zone(pid, zoneid));
372 372 }
373 373
374 374 proc_t *
375 375 pgfind_zone(pid_t pgid, zoneid_t zoneid)
376 376 {
377 377 struct pid *pidp;
378 378
379 379 ASSERT(MUTEX_HELD(&pidlock));
380 380
381 381 mutex_enter(&pidlinklock);
382 382 pidp = pid_lookup(pgid);
383 383 mutex_exit(&pidlinklock);
384 384 if (pidp != NULL) {
385 385 proc_t *p = pidp->pid_pglink;
386 386
387 387 if (zoneid == ALL_ZONES || pgid == 0 || p == NULL ||
388 388 p->p_zone->zone_id == zoneid)
389 389 return (p);
390 390 }
391 391 return (NULL);
392 392 }
393 393
394 394 /*
395 395 * return the head of the list of processes whose process group ID is 'pgid',
396 396 * or NULL, if no such process group
397 397 */
398 398 proc_t *
399 399 pgfind(pid_t pgid)
400 400 {
401 401 zoneid_t zoneid;
402 402
403 403 if (INGLOBALZONE(curproc))
404 404 zoneid = ALL_ZONES;
405 405 else
406 406 zoneid = getzoneid();
407 407 return (pgfind_zone(pgid, zoneid));
408 408 }
409 409
410 410 /*
411 411 * Sets P_PR_LOCK on a non-system process. Process must be fully created
412 412 * and not exiting to succeed.
413 413 *
414 414 * Returns 0 on success.
415 415 * Returns 1 if P_PR_LOCK is set.
416 416 * Returns -1 if proc is in invalid state.
417 417 */
418 418 int
419 419 sprtrylock_proc(proc_t *p)
420 420 {
421 421 ASSERT(MUTEX_HELD(&p->p_lock));
422 422
423 423 /* skip system and incomplete processes */
424 424 if (p->p_stat == SIDL || p->p_stat == SZOMB ||
425 425 (p->p_flag & (SSYS | SEXITING | SEXITLWPS))) {
426 426 return (-1);
427 427 }
428 428
429 429 if (p->p_proc_flag & P_PR_LOCK)
430 430 return (1);
431 431
432 432 p->p_proc_flag |= P_PR_LOCK;
433 433 THREAD_KPRI_REQUEST();
434 434
435 435 return (0);
436 436 }
437 437
438 438 /*
439 439 * Wait for P_PR_LOCK to become clear. Returns with p_lock dropped,
440 440 * and the proc pointer no longer valid, as the proc may have exited.
441 441 */
442 442 void
443 443 sprwaitlock_proc(proc_t *p)
444 444 {
445 445 kmutex_t *mp;
446 446
447 447 ASSERT(MUTEX_HELD(&p->p_lock));
448 448 ASSERT(p->p_proc_flag & P_PR_LOCK);
449 449
450 450 /*
451 451 * p_lock is persistent, but p itself is not -- it could
452 452 * vanish during cv_wait(). Load p->p_lock now so we can
453 453 * drop it after cv_wait() without referencing p.
454 454 */
455 455 mp = &p->p_lock;
456 456 cv_wait(&pr_pid_cv[p->p_slot], mp);
457 457 mutex_exit(mp);
458 458 }
459 459
460 460 /*
461 461 * If pid exists, find its proc, acquire its p_lock and mark it P_PR_LOCK.
462 462 * Returns the proc pointer on success, NULL on failure. sprlock() is
463 463 * really just a stripped-down version of pr_p_lock() to allow practive
464 464 * walkers like dofusers() and dumpsys() to synchronize with /proc.
465 465 */
466 466 proc_t *
467 467 sprlock_zone(pid_t pid, zoneid_t zoneid)
468 468 {
469 469 proc_t *p;
470 470 int ret;
471 471
472 472 for (;;) {
473 473 mutex_enter(&pidlock);
474 474 if ((p = prfind_zone(pid, zoneid)) == NULL) {
475 475 mutex_exit(&pidlock);
476 476 return (NULL);
477 477 }
478 478 mutex_enter(&p->p_lock);
479 479 mutex_exit(&pidlock);
480 480
481 481 if (panicstr)
482 482 return (p);
483 483
484 484 ret = sprtrylock_proc(p);
485 485 if (ret == -1) {
486 486 mutex_exit(&p->p_lock);
487 487 return (NULL);
488 488 } else if (ret == 0) {
489 489 break;
490 490 }
491 491 sprwaitlock_proc(p);
492 492 }
493 493 return (p);
494 494 }
495 495
496 496 proc_t *
497 497 sprlock(pid_t pid)
498 498 {
499 499 zoneid_t zoneid;
500 500
501 501 if (INGLOBALZONE(curproc))
502 502 zoneid = ALL_ZONES;
503 503 else
504 504 zoneid = getzoneid();
505 505 return (sprlock_zone(pid, zoneid));
506 506 }
507 507
508 508 void
509 509 sprlock_proc(proc_t *p)
510 510 {
511 511 ASSERT(MUTEX_HELD(&p->p_lock));
512 512
513 513 while (p->p_proc_flag & P_PR_LOCK) {
514 514 cv_wait(&pr_pid_cv[p->p_slot], &p->p_lock);
515 515 }
516 516
517 517 p->p_proc_flag |= P_PR_LOCK;
518 518 THREAD_KPRI_REQUEST();
519 519 }
520 520
521 521 void
522 522 sprunlock(proc_t *p)
523 523 {
524 524 if (panicstr) {
525 525 mutex_exit(&p->p_lock);
526 526 return;
527 527 }
528 528
529 529 ASSERT(p->p_proc_flag & P_PR_LOCK);
530 530 ASSERT(MUTEX_HELD(&p->p_lock));
531 531
532 532 cv_signal(&pr_pid_cv[p->p_slot]);
533 533 p->p_proc_flag &= ~P_PR_LOCK;
534 534 mutex_exit(&p->p_lock);
535 535 THREAD_KPRI_RELEASE();
536 536 }
537 537
538 538 /*
539 539 * Undo effects of sprlock but without dropping p->p_lock
540 540 */
541 541 void
542 542 sprunprlock(proc_t *p)
543 543 {
544 544 ASSERT(p->p_proc_flag & P_PR_LOCK);
545 545 ASSERT(MUTEX_HELD(&p->p_lock));
546 546
547 547 cv_signal(&pr_pid_cv[p->p_slot]);
548 548 p->p_proc_flag &= ~P_PR_LOCK;
549 549 THREAD_KPRI_RELEASE();
550 550 }
551 551
552 552 void
553 553 pid_init(void)
554 554 {
555 555 int i;
556 556
557 557 pid_hashsz = 1 << highbit(v.v_proc / pid_hashlen);
558 558
559 559 pidhash = kmem_zalloc(sizeof (struct pid *) * pid_hashsz, KM_SLEEP);
560 560 procdir = kmem_alloc(sizeof (union procent) * v.v_proc, KM_SLEEP);
561 561 pr_pid_cv = kmem_zalloc(sizeof (kcondvar_t) * v.v_proc, KM_SLEEP);
562 562 proc_lock = kmem_zalloc(sizeof (struct plock) * v.v_proc, KM_SLEEP);
563 563
564 564 nproc = 1;
565 565 practive = proc_sched;
566 566 proc_sched->p_next = NULL;
567 567 procdir[0].pe_proc = proc_sched;
568 568
569 569 procentfree = &procdir[1];
570 570 for (i = 1; i < v.v_proc - 1; i++)
571 571 procdir[i].pe_next = &procdir[i+1];
572 572 procdir[i].pe_next = NULL;
573 573
574 574 HASHPID(0) = &pid0;
575 575
576 576 upcount_init();
577 577 }
578 578
579 579 proc_t *
580 580 pid_entry(int slot)
581 581 {
582 582 union procent *pep;
583 583 proc_t *prp;
584 584
585 585 ASSERT(MUTEX_HELD(&pidlock));
586 586 ASSERT(slot >= 0 && slot < v.v_proc);
587 587
588 588 pep = procdir[slot].pe_next;
589 589 if (pep >= procdir && pep < &procdir[v.v_proc])
590 590 return (NULL);
591 591 prp = procdir[slot].pe_proc;
592 592 if (prp != 0 && prp->p_stat == SIDL)
593 593 return (NULL);
594 594 return (prp);
595 595 }
596 596
597 597 /*
598 598 * Send the specified signal to all processes whose process group ID is
599 599 * equal to 'pgid'
600 600 */
601 601
602 602 void
603 603 signal(pid_t pgid, int sig)
604 604 {
605 605 struct pid *pidp;
606 606 proc_t *prp;
607 607
608 608 mutex_enter(&pidlock);
609 609 mutex_enter(&pidlinklock);
610 610 if (pgid == 0 || (pidp = pid_lookup(pgid)) == NULL) {
611 611 mutex_exit(&pidlinklock);
612 612 mutex_exit(&pidlock);
613 613 return;
614 614 }
615 615 mutex_exit(&pidlinklock);
616 616 for (prp = pidp->pid_pglink; prp; prp = prp->p_pglink) {
617 617 mutex_enter(&prp->p_lock);
618 618 sigtoproc(prp, NULL, sig);
619 619 mutex_exit(&prp->p_lock);
620 620 }
621 621 mutex_exit(&pidlock);
622 622 }
623 623
624 624 /*
625 625 * Send the specified signal to the specified process
626 626 */
627 627
628 628 void
629 629 prsignal(struct pid *pidp, int sig)
630 630 {
631 631 if (!(pidp->pid_prinactive))
632 632 psignal(procdir[pidp->pid_prslot].pe_proc, sig);
633 633 }
634 634
635 635 #include <sys/sunddi.h>
636 636
637 637 /*
638 638 * DDI/DKI interfaces for drivers to send signals to processes
639 639 */
640 640
641 641 /*
642 642 * obtain an opaque reference to a process for signaling
643 643 */
644 644 void *
645 645 proc_ref(void)
646 646 {
647 647 struct pid *pidp;
648 648
649 649 mutex_enter(&pidlock);
650 650 pidp = curproc->p_pidp;
651 651 PID_HOLD(pidp);
652 652 mutex_exit(&pidlock);
653 653
654 654 return (pidp);
655 655 }
656 656
657 657 /*
658 658 * release a reference to a process
659 659 * - a process can exit even if a driver has a reference to it
660 660 * - one proc_unref for every proc_ref
661 661 */
662 662 void
663 663 proc_unref(void *pref)
664 664 {
665 665 mutex_enter(&pidlock);
666 666 PID_RELE((struct pid *)pref);
667 667 mutex_exit(&pidlock);
668 668 }
669 669
670 670 /*
671 671 * send a signal to a process
672 672 *
673 673 * - send the process the signal
674 674 * - if the process went away, return a -1
675 675 * - if the process is still there return 0
676 676 */
677 677 int
678 678 proc_signal(void *pref, int sig)
679 679 {
680 680 struct pid *pidp = pref;
681 681
682 682 prsignal(pidp, sig);
683 683 return (pidp->pid_prinactive ? -1 : 0);
684 684 }
685 685
686 686
687 687 static struct upcount **upc_hash; /* a boot time allocated array */
688 688 static ulong_t upc_hashmask;
689 689 #define UPC_HASH(x, y) ((ulong_t)(x ^ y) & upc_hashmask)
690 690
691 691 /*
692 692 * Get us off the ground. Called once at boot.
693 693 */
694 694 void
695 695 upcount_init(void)
696 696 {
697 697 ulong_t upc_hashsize;
698 698
699 699 /*
700 700 * An entry per MB of memory is our current guess
701 701 */
702 702 /*
703 703 * 2^20 is a meg, so shifting right by 20 - PAGESHIFT
704 704 * converts pages to megs (without overflowing a u_int
705 705 * if you have more than 4G of memory, like ptob(physmem)/1M
706 706 * would).
707 707 */
708 708 upc_hashsize = (1 << highbit(physmem >> (20 - PAGESHIFT)));
709 709 upc_hashmask = upc_hashsize - 1;
710 710 upc_hash = kmem_zalloc(upc_hashsize * sizeof (struct upcount *),
711 711 KM_SLEEP);
712 712 }
713 713
714 714 /*
715 715 * Increment the number of processes associated with a given uid and zoneid.
716 716 */
717 717 void
718 718 upcount_inc(uid_t uid, zoneid_t zoneid)
719 719 {
720 720 struct upcount **upc, **hupc;
721 721 struct upcount *new;
722 722
723 723 ASSERT(MUTEX_HELD(&pidlock));
724 724 new = NULL;
725 725 hupc = &upc_hash[UPC_HASH(uid, zoneid)];
726 726 top:
727 727 upc = hupc;
728 728 while ((*upc) != NULL) {
729 729 if ((*upc)->up_uid == uid && (*upc)->up_zoneid == zoneid) {
730 730 (*upc)->up_count++;
731 731 if (new) {
732 732 /*
733 733 * did not need `new' afterall.
734 734 */
735 735 kmem_free(new, sizeof (*new));
736 736 }
737 737 return;
738 738 }
739 739 upc = &(*upc)->up_next;
740 740 }
741 741
742 742 /*
743 743 * There is no entry for this <uid,zoneid> pair.
744 744 * Allocate one. If we have to drop pidlock, check
745 745 * again.
746 746 */
747 747 if (new == NULL) {
748 748 new = (struct upcount *)kmem_alloc(sizeof (*new), KM_NOSLEEP);
749 749 if (new == NULL) {
750 750 mutex_exit(&pidlock);
751 751 new = (struct upcount *)kmem_alloc(sizeof (*new),
752 752 KM_SLEEP);
753 753 mutex_enter(&pidlock);
754 754 goto top;
755 755 }
756 756 }
757 757
758 758
759 759 /*
760 760 * On the assumption that a new user is going to do some
761 761 * more forks, put the new upcount structure on the front.
762 762 */
763 763 upc = hupc;
764 764
765 765 new->up_uid = uid;
766 766 new->up_zoneid = zoneid;
767 767 new->up_count = 1;
768 768 new->up_next = *upc;
769 769
770 770 *upc = new;
771 771 }
772 772
773 773 /*
774 774 * Decrement the number of processes a given uid and zoneid has.
775 775 */
776 776 void
777 777 upcount_dec(uid_t uid, zoneid_t zoneid)
778 778 {
779 779 struct upcount **upc;
780 780 struct upcount *done;
781 781
782 782 ASSERT(MUTEX_HELD(&pidlock));
783 783
784 784 upc = &upc_hash[UPC_HASH(uid, zoneid)];
785 785 while ((*upc) != NULL) {
786 786 if ((*upc)->up_uid == uid && (*upc)->up_zoneid == zoneid) {
787 787 (*upc)->up_count--;
788 788 if ((*upc)->up_count == 0) {
789 789 done = *upc;
790 790 *upc = (*upc)->up_next;
791 791 kmem_free(done, sizeof (*done));
792 792 }
793 793 return;
794 794 }
795 795 upc = &(*upc)->up_next;
796 796 }
797 797 cmn_err(CE_PANIC, "decr_upcount-off the end");
798 798 }
799 799
800 800 /*
801 801 * Returns the number of processes a uid has.
802 802 * Non-existent uid's are assumed to have no processes.
803 803 */
804 804 int
805 805 upcount_get(uid_t uid, zoneid_t zoneid)
806 806 {
807 807 struct upcount *upc;
808 808
809 809 ASSERT(MUTEX_HELD(&pidlock));
810 810
811 811 upc = upc_hash[UPC_HASH(uid, zoneid)];
812 812 while (upc != NULL) {
813 813 if (upc->up_uid == uid && upc->up_zoneid == zoneid) {
814 814 return (upc->up_count);
815 815 }
816 816 upc = upc->up_next;
817 817 }
818 818 return (0);
819 819 }
|
↓ open down ↓ |
819 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX