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