Deleted Added
full compact
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 ---