subr_sleepqueue.c (165292) | subr_sleepqueue.c (169666) |
---|---|
1/*- 2 * Copyright (c) 2004 John Baldwin <jhb@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 46 unchanged lines hidden (view full) --- 55 * must consistently use the same lock to synchronize with a wait channel, 56 * though this check is currently only a warning for sleep/wakeup due to 57 * pre-existing abuse of that API. The same lock must also be held when 58 * awakening threads, though that is currently only enforced for condition 59 * variables. 60 */ 61 62#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2004 John Baldwin <jhb@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 46 unchanged lines hidden (view full) --- 55 * must consistently use the same lock to synchronize with a wait channel, 56 * though this check is currently only a warning for sleep/wakeup due to 57 * pre-existing abuse of that API. The same lock must also be held when 58 * awakening threads, though that is currently only enforced for condition 59 * variables. 60 */ 61 62#include <sys/cdefs.h> |
63__FBSDID("$FreeBSD: head/sys/kern/subr_sleepqueue.c 165292 2006-12-17 00:14:20Z kmacy $"); | 63__FBSDID("$FreeBSD: head/sys/kern/subr_sleepqueue.c 169666 2007-05-18 06:32:24Z jeff $"); |
64 65#include "opt_sleepqueue_profiling.h" 66#include "opt_ddb.h" 67 68#include <sys/param.h> 69#include <sys/systm.h> 70#include <sys/lock.h> 71#include <sys/kernel.h> 72#include <sys/ktr.h> | 64 65#include "opt_sleepqueue_profiling.h" 66#include "opt_ddb.h" 67 68#include <sys/param.h> 69#include <sys/systm.h> 70#include <sys/lock.h> 71#include <sys/kernel.h> 72#include <sys/ktr.h> |
73#include <sys/malloc.h> | |
74#include <sys/mutex.h> 75#include <sys/proc.h> 76#include <sys/sched.h> 77#include <sys/signalvar.h> 78#include <sys/sleepqueue.h> 79#include <sys/sysctl.h> 80 | 73#include <sys/mutex.h> 74#include <sys/proc.h> 75#include <sys/sched.h> 76#include <sys/signalvar.h> 77#include <sys/sleepqueue.h> 78#include <sys/sysctl.h> 79 |
80#include <vm/uma.h> 81 |
|
81#ifdef DDB 82#include <ddb/ddb.h> 83#endif 84 85/* 86 * Constants for the hash table of sleep queue chains. These constants are 87 * the same ones that 4BSD (and possibly earlier versions of BSD) used. 88 * Basically, we ignore the lower 8 bits of the address since most wait --- 48 unchanged lines hidden (view full) --- 137u_int sleepq_max_depth; 138SYSCTL_NODE(_debug, OID_AUTO, sleepq, CTLFLAG_RD, 0, "sleepq profiling"); 139SYSCTL_NODE(_debug_sleepq, OID_AUTO, chains, CTLFLAG_RD, 0, 140 "sleepq chain stats"); 141SYSCTL_UINT(_debug_sleepq, OID_AUTO, max_depth, CTLFLAG_RD, &sleepq_max_depth, 142 0, "maxmimum depth achieved of a single chain"); 143#endif 144static struct sleepqueue_chain sleepq_chains[SC_TABLESIZE]; | 82#ifdef DDB 83#include <ddb/ddb.h> 84#endif 85 86/* 87 * Constants for the hash table of sleep queue chains. These constants are 88 * the same ones that 4BSD (and possibly earlier versions of BSD) used. 89 * Basically, we ignore the lower 8 bits of the address since most wait --- 48 unchanged lines hidden (view full) --- 138u_int sleepq_max_depth; 139SYSCTL_NODE(_debug, OID_AUTO, sleepq, CTLFLAG_RD, 0, "sleepq profiling"); 140SYSCTL_NODE(_debug_sleepq, OID_AUTO, chains, CTLFLAG_RD, 0, 141 "sleepq chain stats"); 142SYSCTL_UINT(_debug_sleepq, OID_AUTO, max_depth, CTLFLAG_RD, &sleepq_max_depth, 143 0, "maxmimum depth achieved of a single chain"); 144#endif 145static struct sleepqueue_chain sleepq_chains[SC_TABLESIZE]; |
146static uma_zone_t sleepq_zone; |
|
145 | 147 |
146static MALLOC_DEFINE(M_SLEEPQUEUE, "sleepqueue", "sleep queues"); 147 | |
148/* 149 * Prototypes for non-exported routines. 150 */ 151static int sleepq_catch_signals(void *wchan); 152static int sleepq_check_signals(void); 153static int sleepq_check_timeout(void); | 148/* 149 * Prototypes for non-exported routines. 150 */ 151static int sleepq_catch_signals(void *wchan); 152static int sleepq_check_signals(void); 153static int sleepq_check_timeout(void); |
154#ifdef INVARIANTS 155static void sleepq_dtor(void *mem, int size, void *arg); 156#endif 157static int sleepq_init(void *mem, int size, int flags); 158static void sleepq_resume_thread(struct sleepqueue *sq, struct thread *td, 159 int pri); |
|
154static void sleepq_switch(void *wchan); 155static void sleepq_timeout(void *arg); | 160static void sleepq_switch(void *wchan); 161static void sleepq_timeout(void *arg); |
156static void sleepq_resume_thread(struct sleepqueue *sq, struct thread *td, int pri); | |
157 158/* 159 * Early initialization of sleep queues that is called from the sleepinit() 160 * SYSINIT. 161 */ 162void 163init_sleepqueues(void) 164{ --- 14 unchanged lines hidden (view full) --- 179 chain_name, CTLFLAG_RD, NULL, "sleepq chain stats"); 180 SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(chain_oid), OID_AUTO, 181 "depth", CTLFLAG_RD, &sleepq_chains[i].sc_depth, 0, NULL); 182 SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(chain_oid), OID_AUTO, 183 "max_depth", CTLFLAG_RD, &sleepq_chains[i].sc_max_depth, 0, 184 NULL); 185#endif 186 } | 162 163/* 164 * Early initialization of sleep queues that is called from the sleepinit() 165 * SYSINIT. 166 */ 167void 168init_sleepqueues(void) 169{ --- 14 unchanged lines hidden (view full) --- 184 chain_name, CTLFLAG_RD, NULL, "sleepq chain stats"); 185 SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(chain_oid), OID_AUTO, 186 "depth", CTLFLAG_RD, &sleepq_chains[i].sc_depth, 0, NULL); 187 SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(chain_oid), OID_AUTO, 188 "max_depth", CTLFLAG_RD, &sleepq_chains[i].sc_max_depth, 0, 189 NULL); 190#endif 191 } |
192 sleepq_zone = uma_zcreate("SLEEPQUEUE", sizeof(struct sleepqueue), 193#ifdef INVARIANTS 194 NULL, sleepq_dtor, sleepq_init, NULL, UMA_ALIGN_CACHE, 0); 195#else 196 NULL, NULL, sleepq_init, NULL, UMA_ALIGN_CACHE, 0); 197#endif 198 |
|
187 thread0.td_sleepqueue = sleepq_alloc(); 188} 189 190/* | 199 thread0.td_sleepqueue = sleepq_alloc(); 200} 201 202/* |
191 * Malloc and initialize a new sleep queue for a new thread. | 203 * Get a sleep queue for a new thread. |
192 */ 193struct sleepqueue * 194sleepq_alloc(void) 195{ | 204 */ 205struct sleepqueue * 206sleepq_alloc(void) 207{ |
196 struct sleepqueue *sq; 197 int i; | |
198 | 208 |
199 sq = malloc(sizeof(struct sleepqueue), M_SLEEPQUEUE, M_WAITOK | M_ZERO); 200 for (i = 0; i < NR_SLEEPQS; i++) 201 TAILQ_INIT(&sq->sq_blocked[i]); 202 LIST_INIT(&sq->sq_free); 203 return (sq); | 209 return (uma_zalloc(sleepq_zone, M_WAITOK)); |
204} 205 206/* 207 * Free a sleep queue when a thread is destroyed. 208 */ 209void 210sleepq_free(struct sleepqueue *sq) 211{ | 210} 211 212/* 213 * Free a sleep queue when a thread is destroyed. 214 */ 215void 216sleepq_free(struct sleepqueue *sq) 217{ |
212 int i; | |
213 | 218 |
214 MPASS(sq != NULL); 215 for (i = 0; i < NR_SLEEPQS; i++) 216 MPASS(TAILQ_EMPTY(&sq->sq_blocked[i])); 217 free(sq, M_SLEEPQUEUE); | 219 uma_zfree(sleepq_zone, sq); |
218} 219 220/* 221 * Lock the sleep queue chain associated with the specified wait channel. 222 */ 223void 224sleepq_lock(void *wchan) 225{ --- 435 unchanged lines hidden (view full) --- 661 662 /* Adjust priority if requested. */ 663 MPASS(pri == -1 || (pri >= PRI_MIN && pri <= PRI_MAX)); 664 if (pri != -1 && td->td_priority > pri) 665 sched_prio(td, pri); 666 setrunnable(td); 667} 668 | 220} 221 222/* 223 * Lock the sleep queue chain associated with the specified wait channel. 224 */ 225void 226sleepq_lock(void *wchan) 227{ --- 435 unchanged lines hidden (view full) --- 663 664 /* Adjust priority if requested. */ 665 MPASS(pri == -1 || (pri >= PRI_MIN && pri <= PRI_MAX)); 666 if (pri != -1 && td->td_priority > pri) 667 sched_prio(td, pri); 668 setrunnable(td); 669} 670 |
671#ifdef INVARIANTS |
|
669/* | 672/* |
673 * UMA zone item deallocator. 674 */ 675static void 676sleepq_dtor(void *mem, int size, void *arg) 677{ 678 struct sleepqueue *sq; 679 int i; 680 681 sq = mem; 682 for (i = 0; i < NR_SLEEPQS; i++) 683 MPASS(TAILQ_EMPTY(&sq->sq_blocked[i])); 684} 685#endif 686 687/* 688 * UMA zone item initializer. 689 */ 690static int 691sleepq_init(void *mem, int size, int flags) 692{ 693 struct sleepqueue *sq; 694 int i; 695 696 bzero(mem, size); 697 sq = mem; 698 for (i = 0; i < NR_SLEEPQS; i++) 699 TAILQ_INIT(&sq->sq_blocked[i]); 700 LIST_INIT(&sq->sq_free); 701 return (0); 702} 703 704/* |
|
670 * Find the highest priority thread sleeping on a wait channel and resume it. 671 */ 672void 673sleepq_signal(void *wchan, int flags, int pri, int queue) 674{ 675 struct sleepqueue *sq; 676 struct thread *td, *besttd; 677 --- 261 unchanged lines hidden --- | 705 * Find the highest priority thread sleeping on a wait channel and resume it. 706 */ 707void 708sleepq_signal(void *wchan, int flags, int pri, int queue) 709{ 710 struct sleepqueue *sq; 711 struct thread *td, *besttd; 712 --- 261 unchanged lines hidden --- |