xref: /illumos-gate/usr/src/uts/common/disp/sysdc.c (revision efd4c9b6)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 /*
26  * The System Duty Cycle (SDC) scheduling class
27  * --------------------------------------------
28  *
29  * Background
30  *
31  * Kernel threads in Solaris have traditionally not been large consumers
32  * of CPU time.  They typically wake up, perform a small amount of
33  * work, then go back to sleep waiting for either a timeout or another
34  * signal.  On the assumption that the small amount of work that they do
35  * is important for the behavior of the whole system, these threads are
36  * treated kindly by the dispatcher and the SYS scheduling class: they run
37  * without preemption from anything other than real-time and interrupt
38  * threads; when preempted, they are put at the front of the queue, so they
39  * generally do not migrate between CPUs; and they are allowed to stay
40  * running until they voluntarily give up the CPU.
41  *
42  * As Solaris has evolved, new workloads have emerged which require the
43  * kernel to perform significant amounts of CPU-intensive work.  One
44  * example of such a workload is ZFS's transaction group sync processing.
45  * Each sync operation generates a large batch of I/Os, and each I/O
46  * may need to be compressed and/or checksummed before it is written to
47  * storage.  The taskq threads which perform the compression and checksums
48  * will run nonstop as long as they have work to do; a large sync operation
49  * on a compression-heavy dataset can keep them busy for seconds on end.
50  * This causes human-time-scale dispatch latency bubbles for any other
51  * threads which have the misfortune to share a CPU with the taskq threads.
52  *
53  * The SDC scheduling class is a solution to this problem.
54  *
55  *
56  * Overview
57  *
58  * SDC is centered around the concept of a thread's duty cycle (DC):
59  *
60  *			      ONPROC time
61  *	Duty Cycle =	----------------------
62  *			ONPROC + Runnable time
63  *
64  * This is the ratio of the time that the thread spent running on a CPU
65  * divided by the time it spent running or trying to run.  It is unaffected
66  * by any time the thread spent sleeping, stopped, etc.
67  *
68  * A thread joining the SDC class specifies a "target" DC that it wants
69  * to run at.  To implement this policy, the routine sysdc_update() scans
70  * the list of active SDC threads every few ticks and uses each thread's
71  * microstate data to compute the actual duty cycle that that thread
72  * has experienced recently.  If the thread is under its target DC, its
73  * priority is increased to the maximum available (sysdc_maxpri, which is
74  * 99 by default).  If the thread is over its target DC, its priority is
75  * reduced to the minimum available (sysdc_minpri, 0 by default).  This
76  * is a fairly primitive approach, in that it doesn't use any of the
77  * intermediate priorities, but it's not completely inappropriate.  Even
78  * though threads in the SDC class might take a while to do their job, they
79  * are by some definition important if they're running inside the kernel,
80  * so it is reasonable that they should get to run at priority 99.
81  *
82  * If a thread is running when sysdc_update() calculates its actual duty
83  * cycle, and there are other threads of equal or greater priority on its
84  * CPU's dispatch queue, sysdc_update() preempts that thread.  The thread
85  * acknowledges the preemption by calling sysdc_preempt(), which calls
86  * setbackdq(), which gives other threads with the same priority a chance
87  * to run.  This creates a de facto time quantum for threads in the SDC
88  * scheduling class.
89  *
90  * An SDC thread which is assigned priority 0 can continue to run if
91  * nothing else needs to use the CPU that it's running on.  Similarly, an
92  * SDC thread at priority 99 might not get to run as much as it wants to
93  * if there are other priority-99 or higher threads on its CPU.  These
94  * situations would cause the thread to get ahead of or behind its target
95  * DC; the longer the situations lasted, the further ahead or behind the
96  * thread would get.  Rather than condemning a thread to a lifetime of
97  * paying for its youthful indiscretions, SDC keeps "base" values for
98  * ONPROC and Runnable times in each thread's sysdc data, and updates these
99  * values periodically.  The duty cycle is then computed using the elapsed
100  * amount of ONPROC and Runnable times since those base times.
101  *
102  * Since sysdc_update() scans SDC threads fairly frequently, it tries to
103  * keep the list of "active" threads small by pruning out threads which
104  * have been asleep for a brief time.  They are not pruned immediately upon
105  * going to sleep, since some threads may bounce back and forth between
106  * sleeping and being runnable.
107  *
108  *
109  * Interfaces
110  *
111  * void sysdc_thread_enter(t, dc, flags)
112  *
113  *	Moves a kernel thread from the SYS scheduling class to the
114  *	SDC class. t must have an associated LWP (created by calling
115  *	lwp_kernel_create()).  The thread will have a target DC of dc.
116  *	Flags should be either 0 or SYSDC_THREAD_BATCH.  If
117  *	SYSDC_THREAD_BATCH is specified, the thread is expected to be
118  *	doing large amounts of processing.
119  *
120  *
121  * Complications
122  *
123  * - Run queue balancing
124  *
125  *	The Solaris dispatcher is biased towards letting a thread run
126  *	on the same CPU which it last ran on, if no more than 3 ticks
127  *	(i.e. rechoose_interval) have passed since the thread last ran.
128  *	This helps to preserve cache warmth.  On the other hand, it also
129  *	tries to keep the per-CPU run queues fairly balanced; if the CPU
130  *	chosen for a runnable thread has a run queue which is three or
131  *	more threads longer than a neighboring CPU's queue, the runnable
132  *	thread is dispatched onto the neighboring CPU instead.
133  *
134  *	These policies work well for some workloads, but not for many SDC
135  *	threads.  The taskq client of SDC, for example, has many discrete
136  *	units of work to do.  The work units are largely independent, so
137  *	cache warmth is not an important consideration.  It is important
138  *	that the threads fan out quickly to different CPUs, since the
139  *	amount of work these threads have to do (a few seconds worth at a
140  *	time) doesn't leave much time to correct thread placement errors
141  *	(i.e. two SDC threads being dispatched to the same CPU).
142  *
143  *	To fix this, SDC uses the TS_RUNQMATCH flag introduced for FSS.
144  *	This tells the dispatcher to keep neighboring run queues' lengths
145  *	more evenly matched, which allows SDC threads to migrate more
146  *	easily.
147  *
148  * - LWPs and system processes
149  *
150  *	SDC can only be used for kernel threads.  Since SDC uses microstate
151  *	accounting data to compute each thread's actual duty cycle, all
152  *	threads entering the SDC class must have associated LWPs (which
153  *	store the microstate data).  This means that the threads have to
154  *	be associated with an SSYS process, i.e. one created by newproc().
155  *	If the microstate accounting information is ever moved into the
156  *	kthread_t, this restriction could be lifted.
157  *
158  * - Dealing with oversubscription
159  *
160  *	Since SDC duty cycles are per-thread, it is possible that the
161  *	aggregate requested duty cycle of all SDC threads in a processor
162  *	set could be greater than the total CPU time available in that set.
163  *	The FSS scheduling class has an analogous situation, which it deals
164  *	with by reducing each thread's allotted CPU time proportionally.
165  *	Since SDC doesn't need to be as precise as FSS, it uses a simpler
166  *	solution to the oversubscription problem.
167  *
168  *	sysdc_update() accumulates the amount of time that max-priority SDC
169  *	threads have spent on-CPU in each processor set, and uses that sum
170  *	to create an implied duty cycle for that processor set:
171  *
172  *				accumulated CPU time
173  *	   pset DC =	-----------------------------------
174  *			 (# CPUs) * time since last update
175  *
176  *	If this implied duty cycle is above a maximum pset duty cycle (90%
177  *	by default), sysdc_update() sets the priority of all SDC threads
178  *	in that processor set to sysdc_minpri for a "break" period.  After
179  *	the break period, it waits for a "nobreak" period before trying to
180  *	enforce the pset duty cycle limit again.
181  *
182  * - Processor sets
183  *
184  *	As the above implies, SDC is processor set aware, but it does not
185  *	currently allow threads to change processor sets while in the SDC
186  *	class.  Instead, those threads must join the desired processor set
187  *	before entering SDC. [1]
188  *
189  * - Batch threads
190  *
191  *	A thread joining the SDC class can specify the SDC_THREAD_BATCH
192  *	flag.  This flag currently has no effect, but marks threads which
193  *	do bulk processing.
194  *
195  * - t_kpri_req
196  *
197  *	The TS and FSS scheduling classes pay attention to t_kpri_req,
198  *	which provides a simple form of priority inheritance for
199  *	synchronization primitives (such as rwlocks held as READER) which
200  *	cannot be traced to a unique thread.  The SDC class does not honor
201  *	t_kpri_req, for a few reasons:
202  *
203  *	1.  t_kpri_req is notoriously inaccurate.  A measure of its
204  *	    inaccuracy is that it needs to be cleared every time a thread
205  *	    returns to user mode, because it is frequently non-zero at that
206  *	    point.  This can happen because "ownership" of synchronization
207  *	    primitives that use t_kpri_req can be silently handed off,
208  *	    leaving no opportunity to will the t_kpri_req inheritance.
209  *
210  *	2.  Unlike in TS and FSS, threads in SDC *will* eventually run at
211  *	    kernel priority.  This means that even if an SDC thread
212  *	    is holding a synchronization primitive and running at low
213  *	    priority, its priority will eventually be raised above 60,
214  *	    allowing it to drive on and release the resource.
215  *
216  *	3.  The first consumer of SDC uses the taskq subsystem, which holds
217  *	    a reader lock for the duration of the task's execution.  This
218  *	    would mean that SDC threads would never drop below kernel
219  *	    priority in practice, which defeats one of the purposes of SDC.
220  *
221  * - Why not FSS?
222  *
223  *	It might seem that the existing FSS scheduling class could solve
224  *	the problems that SDC is attempting to solve.  FSS's more precise
225  *	solution to the oversubscription problem would hardly cause
226  *	trouble, as long as it performed well.  SDC is implemented as
227  *	a separate scheduling class for two main reasons: the initial
228  *	consumer of SDC does not map well onto the "project" abstraction
229  *	that is central to FSS, and FSS does not expect to run at kernel
230  *	priorities.
231  *
232  *
233  * Tunables
234  *
235  * - sysdc_update_interval_msec:  Number of milliseconds between
236  *	consecutive thread priority updates.
237  *
238  * - sysdc_reset_interval_msec:  Number of milliseconds between
239  *	consecutive resets of a thread's base ONPROC and Runnable
240  *	times.
241  *
242  * - sysdc_prune_interval_msec:  Number of milliseconds of sleeping
243  *	before a thread is pruned from the active list.
244  *
245  * - sysdc_max_pset_DC:  Allowable percentage of a processor set's
246  *	CPU time which SDC can give to its high-priority threads.
247  *
248  * - sysdc_break_msec:  Number of milliseconds of "break" taken when
249  *	sysdc_max_pset_DC is exceeded.
250  *
251  *
252  * Future work (in SDC and related subsystems)
253  *
254  * - Per-thread rechoose interval (0 for SDC)
255  *
256  *	Allow each thread to specify its own rechoose interval.  SDC
257  *	threads would specify an interval of zero, which would rechoose
258  *	the CPU with the lowest priority once per update.
259  *
260  * - Allow threads to change processor sets after joining the SDC class
261  *
262  * - Thread groups and per-group DC
263  *
264  *	It might be nice to be able to specify a duty cycle which applies
265  *	to a group of threads in aggregate.
266  *
267  * - Per-group DC callback to allow dynamic DC tuning
268  *
269  *	Currently, DCs are assigned when the thread joins SDC.  Some
270  *	workloads could benefit from being able to tune their DC using
271  *	subsystem-specific knowledge about the workload.
272  *
273  * - Finer-grained priority updates
274  *
275  * - More nuanced management of oversubscription
276  *
277  * - Moving other CPU-intensive threads into SDC
278  *
279  * - Move msacct data into kthread_t
280  *
281  *	This would allow kernel threads without LWPs to join SDC.
282  *
283  *
284  * Footnotes
285  *
286  * [1] The details of doing so are left as an exercise for the reader.
287  */
288 
289 #include <sys/types.h>
290 #include <sys/sysdc.h>
291 #include <sys/sysdc_impl.h>
292 
293 #include <sys/class.h>
294 #include <sys/cmn_err.h>
295 #include <sys/cpuvar.h>
296 #include <sys/cpupart.h>
297 #include <sys/debug.h>
298 #include <sys/disp.h>
299 #include <sys/errno.h>
300 #include <sys/inline.h>
301 #include <sys/kmem.h>
302 #include <sys/modctl.h>
303 #include <sys/schedctl.h>
304 #include <sys/sdt.h>
305 #include <sys/sunddi.h>
306 #include <sys/sysmacros.h>
307 #include <sys/systm.h>
308 #include <sys/var.h>
309 
310 /*
311  * Tunables - loaded into the internal state at module load time
312  */
313 uint_t		sysdc_update_interval_msec = 20;
314 uint_t		sysdc_reset_interval_msec = 400;
315 uint_t		sysdc_prune_interval_msec = 100;
316 uint_t		sysdc_max_pset_DC = 90;
317 uint_t		sysdc_break_msec = 80;
318 
319 /*
320  * Internal state - constants set up by sysdc_initparam()
321  */
322 static clock_t	sysdc_update_ticks;	/* ticks between updates */
323 static uint_t	sysdc_prune_updates;	/* updates asleep before pruning */
324 static uint_t	sysdc_reset_updates;	/* # of updates before reset */
325 static uint_t	sysdc_break_updates;	/* updates to break */
326 static uint_t	sysdc_nobreak_updates;	/* updates to not check */
327 static uint_t	sysdc_minDC;		/* minimum allowed DC */
328 static uint_t	sysdc_maxDC;		/* maximum allowed DC */
329 static pri_t	sysdc_minpri;		/* minimum allowed priority */
330 static pri_t	sysdc_maxpri;		/* maximum allowed priority */
331 
332 /*
333  * Internal state
334  */
335 static kmutex_t	sysdc_pset_lock;	/* lock protecting pset data */
336 static list_t	sysdc_psets;		/* list of psets with SDC threads */
337 static uint_t	sysdc_param_init;	/* sysdc_initparam() has been called */
338 static uint_t	sysdc_update_timeout_started; /* update timeout is active */
339 static hrtime_t	sysdc_last_update;	/* time of last sysdc_update() */
340 static sysdc_t	sysdc_dummy;		/* used to terminate active lists */
341 
342 /*
343  * Internal state - active hash table
344  */
345 #define	SYSDC_NLISTS	8
346 #define	SYSDC_HASH(sdc)	(((uintptr_t)(sdc) >> 6) & (SYSDC_NLISTS - 1))
347 static sysdc_list_t	sysdc_active[SYSDC_NLISTS];
348 #define	SYSDC_LIST(sdc)		(&sysdc_active[SYSDC_HASH(sdc)])
349 
350 #ifdef DEBUG
351 static struct {
352 	uint64_t	sysdc_update_times_asleep;
353 	uint64_t	sysdc_update_times_base_ran_backwards;
354 	uint64_t	sysdc_update_times_already_done;
355 	uint64_t	sysdc_update_times_cur_ran_backwards;
356 	uint64_t	sysdc_compute_pri_breaking;
357 	uint64_t	sysdc_activate_enter;
358 	uint64_t	sysdc_update_enter;
359 	uint64_t	sysdc_update_exited;
360 	uint64_t	sysdc_update_not_sdc;
361 	uint64_t	sysdc_update_idle;
362 	uint64_t	sysdc_update_take_break;
363 	uint64_t	sysdc_update_no_psets;
364 	uint64_t	sysdc_tick_not_sdc;
365 	uint64_t	sysdc_tick_quantum_expired;
366 	uint64_t	sysdc_thread_enter_enter;
367 } sysdc_stats;
368 
369 #define	SYSDC_INC_STAT(x)	(sysdc_stats.x++)
370 #else
371 #define	SYSDC_INC_STAT(x)	((void)0)
372 #endif
373 
374 /* macros are UPPER CASE */
375 #define	HOWMANY(a, b)	howmany((a), (b))
376 #define	MSECTOTICKS(a)	HOWMANY((a) * 1000, usec_per_tick)
377 
378 static void
379 sysdc_initparam(void)
380 {
381 	uint_t sysdc_break_ticks;
382 
383 	/* update / prune intervals */
384 	sysdc_update_ticks = MSECTOTICKS(sysdc_update_interval_msec);
385 
386 	sysdc_prune_updates = HOWMANY(sysdc_prune_interval_msec,
387 	    sysdc_update_interval_msec);
388 	sysdc_reset_updates = HOWMANY(sysdc_reset_interval_msec,
389 	    sysdc_update_interval_msec);
390 
391 	/* We must get at least a little time on CPU. */
392 	sysdc_minDC = 1;
393 	sysdc_maxDC = SYSDC_DC_MAX;
394 	sysdc_minpri = 0;
395 	sysdc_maxpri = maxclsyspri;
396 
397 	/* break parameters */
398 	if (sysdc_max_pset_DC > SYSDC_DC_MAX) {
399 		sysdc_max_pset_DC = SYSDC_DC_MAX;
400 	}
401 	sysdc_break_ticks = MSECTOTICKS(sysdc_break_msec);
402 	sysdc_break_updates = HOWMANY(sysdc_break_ticks, sysdc_update_ticks);
403 
404 	/*
405 	 * We want:
406 	 *
407 	 *	sysdc_max_pset_DC = (nobreak / (break + nobreak))
408 	 *
409 	 *	==>	  nobreak = sysdc_max_pset_DC * (break + nobreak)
410 	 *
411 	 *			    sysdc_max_pset_DC * break
412 	 *	==>	  nobreak = -------------------------
413 	 *			    1 - sysdc_max_pset_DC
414 	 */
415 	sysdc_nobreak_updates =
416 	    HOWMANY((uint64_t)sysdc_break_updates * sysdc_max_pset_DC,
417 	    (SYSDC_DC_MAX - sysdc_max_pset_DC));
418 
419 	sysdc_param_init = 1;
420 }
421 
422 #undef HOWMANY
423 #undef MSECTOTICKS
424 
425 #define	SDC_UPDATE_INITIAL	0x1	/* for the initial update */
426 #define	SDC_UPDATE_TIMEOUT	0x2	/* from sysdc_update() */
427 #define	SDC_UPDATE_TICK		0x4	/* from sysdc_tick(), on expiry */
428 
429 /*
430  * Updates the recorded times in the sdc, and returns the elapsed ONPROC
431  * and Runnable times since the last reset.
432  *
433  * newO is the thread's actual ONPROC time; it's used during sysdc_update()
434  * to track processor set usage.
435  */
436 static void
437 sysdc_update_times(sysdc_t *sdc, uint_t flags,
438     hrtime_t *O, hrtime_t *R, hrtime_t *newO)
439 {
440 	kthread_t *const t = sdc->sdc_thread;
441 	const uint_t	initial = (flags & SDC_UPDATE_INITIAL);
442 	const uint_t	update = (flags & SDC_UPDATE_TIMEOUT);
443 	const clock_t	now = ddi_get_lbolt();
444 	uint_t		do_reset;
445 
446 	ASSERT(THREAD_LOCK_HELD(t));
447 
448 	*O = *R = 0;
449 
450 	/* If we've been sleeping, we know we haven't had any ONPROC time. */
451 	if (sdc->sdc_sleep_updates != 0 &&
452 	    sdc->sdc_sleep_updates != sdc->sdc_nupdates) {
453 		*newO = sdc->sdc_last_base_O;
454 		SYSDC_INC_STAT(sysdc_update_times_asleep);
455 		return;
456 	}
457 
458 	/*
459 	 * If this is our first update, or we've hit the reset point,
460 	 * we need to reset our base_{O,R}.  Once we've updated them, we
461 	 * report O and R for the entire prior interval.
462 	 */
463 	do_reset = initial;
464 	if (update) {
465 		++sdc->sdc_nupdates;
466 		if ((sdc->sdc_nupdates % sysdc_reset_updates) == 0)
467 			do_reset = 1;
468 	}
469 	if (do_reset) {
470 		hrtime_t baseO, baseR;
471 		if (initial) {
472 			/*
473 			 * Start off our cycle count somewhere in the middle,
474 			 * to keep the resets from all happening at once.
475 			 *
476 			 * 4999 is a handy prime much larger than
477 			 * sysdc_reset_updates, so that we don't run into
478 			 * trouble if the resolution is a multiple of
479 			 * sysdc_reset_updates.
480 			 */
481 			sdc->sdc_nupdates = (uint_t)((gethrtime() % 4999) %
482 			    sysdc_reset_updates);
483 			baseO = baseR = 0;
484 		} else {
485 			baseO = sdc->sdc_base_O;
486 			baseR = sdc->sdc_base_R;
487 		}
488 
489 		mstate_systhread_times(t, &sdc->sdc_base_O, &sdc->sdc_base_R);
490 		*newO = sdc->sdc_base_O;
491 
492 		sdc->sdc_reset = now;
493 		sdc->sdc_pri_check = -1; /* force mismatch below */
494 
495 		/*
496 		 * See below for rationale.
497 		 */
498 		if (baseO > sdc->sdc_base_O || baseR > sdc->sdc_base_R) {
499 			SYSDC_INC_STAT(sysdc_update_times_base_ran_backwards);
500 			baseO = sdc->sdc_base_O;
501 			baseR = sdc->sdc_base_R;
502 		}
503 
504 		/* compute based on the entire interval */
505 		*O = (sdc->sdc_base_O - baseO);
506 		*R = (sdc->sdc_base_R - baseR);
507 		return;
508 	}
509 
510 	/*
511 	 * If we're called from sysdc_update(), we *must* return a value
512 	 * for newO, so we always call mstate_systhread_times().
513 	 *
514 	 * Otherwise, if we've already done a pri check this tick,
515 	 * we can skip it.
516 	 */
517 	if (!update && sdc->sdc_pri_check == now) {
518 		SYSDC_INC_STAT(sysdc_update_times_already_done);
519 		return;
520 	}
521 
522 	/* Get the current times from the thread */
523 	sdc->sdc_pri_check = now;
524 	mstate_systhread_times(t, &sdc->sdc_cur_O, &sdc->sdc_cur_R);
525 	*newO = sdc->sdc_cur_O;
526 
527 	/*
528 	 * The updating of microstate accounting is not done under a
529 	 * consistent set of locks, particularly the t_waitrq field.  This
530 	 * can lead to narrow windows in which we account for time in the
531 	 * wrong bucket, which on the next read will be accounted for
532 	 * correctly.
533 	 *
534 	 * If our sdc_base_* fields were affected by one of these blips, we
535 	 * throw away the old data, and pretend this tick didn't happen.
536 	 */
537 	if (sdc->sdc_cur_O < sdc->sdc_base_O ||
538 	    sdc->sdc_cur_R < sdc->sdc_base_R) {
539 
540 		sdc->sdc_base_O = sdc->sdc_cur_O;
541 		sdc->sdc_base_R = sdc->sdc_cur_R;
542 
543 		SYSDC_INC_STAT(sysdc_update_times_cur_ran_backwards);
544 		return;
545 	}
546 
547 	*O = sdc->sdc_cur_O - sdc->sdc_base_O;
548 	*R = sdc->sdc_cur_R - sdc->sdc_base_R;
549 }
550 
551 /*
552  * sysdc_compute_pri()
553  *
554  *	Recomputes the priority of the thread, leaving the result in
555  *	sdc->sdc_epri.  Returns 1 if a priority update should occur
556  *	(which will also trigger a cpu_surrender()), otherwise
557  *	returns 0.
558  */
559 static uint_t
560 sysdc_compute_pri(sysdc_t *sdc, uint_t flags)
561 {
562 	kthread_t *const t = sdc->sdc_thread;
563 	const uint_t	update = (flags & SDC_UPDATE_TIMEOUT);
564 	const uint_t	tick = (flags & SDC_UPDATE_TICK);
565 
566 	hrtime_t	O, R;
567 	hrtime_t	newO = -1;
568 
569 	ASSERT(THREAD_LOCK_HELD(t));
570 
571 	sysdc_update_times(sdc, flags, &O, &R, &newO);
572 	ASSERT(!update || newO != -1);
573 
574 	/* If we have new data, recompute our priority. */
575 	if ((O + R) != 0) {
576 		sdc->sdc_cur_DC = (O * SYSDC_DC_MAX) / (O + R);
577 
578 		/* Adjust our priority to move our DC closer to the target. */
579 		if (sdc->sdc_cur_DC < sdc->sdc_target_DC)
580 			sdc->sdc_pri = sdc->sdc_maxpri;
581 		else
582 			sdc->sdc_pri = sdc->sdc_minpri;
583 	}
584 
585 	/*
586 	 * If our per-pset duty cycle goes over the max, we will take a break.
587 	 * This forces all sysdc threads in the pset to minimum priority, in
588 	 * order to let everyone else have a chance at the CPU.
589 	 */
590 	if (sdc->sdc_pset->sdp_need_break) {
591 		SYSDC_INC_STAT(sysdc_compute_pri_breaking);
592 		sdc->sdc_epri = sdc->sdc_minpri;
593 	} else {
594 		sdc->sdc_epri = sdc->sdc_pri;
595 	}
596 
597 	DTRACE_PROBE4(sysdc__compute__pri,
598 	    kthread_t *, t, pri_t, sdc->sdc_epri, uint_t, sdc->sdc_cur_DC,
599 	    uint_t, sdc->sdc_target_DC);
600 
601 	/*
602 	 * For sysdc_update(), we compute the ONPROC time for high-priority
603 	 * threads, which is used to calculate the per-pset duty cycle.  We
604 	 * will always tell our callers to update the thread's priority,
605 	 * since we want to force a cpu_surrender().
606 	 *
607 	 * We reset sdc_update_ticks so that sysdc_tick() will only update
608 	 * the thread's priority if our timeout is delayed by a tick or
609 	 * more.
610 	 */
611 	if (update) {
612 		/* SDC threads are not allowed to change cpupart bindings. */
613 		ASSERT(t->t_cpupart == sdc->sdc_pset->sdp_cpupart);
614 
615 		/* If we were at MAXPRI, account for our onproc time. */
616 		if (t->t_pri == sdc->sdc_maxpri &&
617 		    sdc->sdc_last_base_O != 0 &&
618 		    sdc->sdc_last_base_O < newO) {
619 			sdc->sdc_last_O = newO - sdc->sdc_last_base_O;
620 			sdc->sdc_pset->sdp_onproc_time +=
621 			    (uint64_t)sdc->sdc_last_O;
622 			sdc->sdc_pset->sdp_onproc_threads++;
623 		} else {
624 			sdc->sdc_last_O = 0;
625 		}
626 		sdc->sdc_last_base_O = newO;
627 
628 		sdc->sdc_update_ticks = sdc->sdc_ticks + sysdc_update_ticks + 1;
629 		return (1);
630 	}
631 
632 	/*
633 	 * Like sysdc_update(), sysdc_tick() always wants to update the
634 	 * thread's priority, so that the CPU is surrendered if necessary.
635 	 * We reset sdc_update_ticks so that if the timeout continues to be
636 	 * delayed, we'll update at the regular interval.
637 	 */
638 	if (tick) {
639 		ASSERT(sdc->sdc_ticks == sdc->sdc_update_ticks);
640 		sdc->sdc_update_ticks = sdc->sdc_ticks + sysdc_update_ticks;
641 		return (1);
642 	}
643 
644 	/*
645 	 * Otherwise, only tell our callers to update the priority if it has
646 	 * changed.
647 	 */
648 	return (sdc->sdc_epri != t->t_pri);
649 }
650 
651 static void
652 sysdc_update_pri(sysdc_t *sdc, uint_t flags)
653 {
654 	kthread_t *t = sdc->sdc_thread;
655 
656 	ASSERT(THREAD_LOCK_HELD(t));
657 
658 	if (sysdc_compute_pri(sdc, flags)) {
659 		if (!thread_change_pri(t, sdc->sdc_epri, 0)) {
660 			cpu_surrender(t);
661 		}
662 	}
663 }
664 
665 /*
666  * Add a thread onto the active list.  It will only be removed by
667  * sysdc_update().
668  */
669 static void
670 sysdc_activate(sysdc_t *sdc)
671 {
672 	sysdc_t *volatile *headp = &SYSDC_LIST(sdc)->sdl_list;
673 	sysdc_t		*head;
674 	kthread_t	*t = sdc->sdc_thread;
675 
676 	SYSDC_INC_STAT(sysdc_activate_enter);
677 
678 	ASSERT(sdc->sdc_next == NULL);
679 	ASSERT(THREAD_LOCK_HELD(t));
680 
681 	do {
682 		head = *headp;
683 		sdc->sdc_next = head;
684 	} while (atomic_cas_ptr(headp, head, sdc) != head);
685 }
686 
687 /*
688  * sysdc_update() has two jobs:
689  *
690  *	1. It updates the priorities of all active SDC threads on the system.
691  *	2. It measures pset CPU usage and enforces sysdc_max_pset_DC.
692  */
693 static void
694 sysdc_update(void *arg)
695 {
696 	int		idx;
697 	sysdc_t		*freelist = NULL;
698 	sysdc_pset_t	*cur;
699 	hrtime_t	now, diff;
700 	uint_t		redeploy = 1;
701 
702 	SYSDC_INC_STAT(sysdc_update_enter);
703 
704 	ASSERT(sysdc_update_timeout_started);
705 
706 	/*
707 	 * If this is our first time through, diff will be gigantic, and
708 	 * no breaks will be necessary.
709 	 */
710 	now = gethrtime();
711 	diff = now - sysdc_last_update;
712 	sysdc_last_update = now;
713 
714 	mutex_enter(&sysdc_pset_lock);
715 	for (cur = list_head(&sysdc_psets); cur != NULL;
716 	    cur = list_next(&sysdc_psets, cur)) {
717 		boolean_t breaking = (cur->sdp_should_break != 0);
718 
719 		if (cur->sdp_need_break != breaking) {
720 			DTRACE_PROBE2(sdc__pset__break, sysdc_pset_t *, cur,
721 			    boolean_t, breaking);
722 		}
723 		cur->sdp_onproc_time = 0;
724 		cur->sdp_onproc_threads = 0;
725 		cur->sdp_need_break = breaking;
726 	}
727 	mutex_exit(&sysdc_pset_lock);
728 
729 	for (idx = 0; idx < SYSDC_NLISTS; idx++) {
730 		sysdc_list_t		*sdl = &sysdc_active[idx];
731 		sysdc_t *volatile	*headp = &sdl->sdl_list;
732 		sysdc_t			*head, *tail;
733 		sysdc_t			**prevptr;
734 
735 		if (*headp == &sysdc_dummy)
736 			continue;
737 
738 		/* Prevent any threads from exiting while we're poking them. */
739 		mutex_enter(&sdl->sdl_lock);
740 
741 		/*
742 		 * Each sdl_list contains a singly-linked list of active
743 		 * threads. Threads which become active while we are
744 		 * processing the list will be added to sdl_list.  Since we
745 		 * don't want that to interfere with our own processing, we
746 		 * swap in an empty list.  Any newly active threads will
747 		 * go on to this empty list.  When finished, we'll put any
748 		 * such threads at the end of the processed list.
749 		 */
750 		head = atomic_swap_ptr(headp, &sysdc_dummy);
751 		prevptr = &head;
752 		while (*prevptr != &sysdc_dummy) {
753 			sysdc_t		*const	sdc = *prevptr;
754 			kthread_t	*const	t = sdc->sdc_thread;
755 
756 			/*
757 			 * If the thread has exited, move its sysdc_t onto
758 			 * freelist, to be freed later.
759 			 */
760 			if (t == NULL) {
761 				*prevptr = sdc->sdc_next;
762 				SYSDC_INC_STAT(sysdc_update_exited);
763 				sdc->sdc_next = freelist;
764 				freelist = sdc;
765 				continue;
766 			}
767 
768 			thread_lock(t);
769 			if (t->t_cid != sysdccid) {
770 				thread_unlock(t);
771 				prevptr = &sdc->sdc_next;
772 				SYSDC_INC_STAT(sysdc_update_not_sdc);
773 				continue;
774 			}
775 			ASSERT(t->t_cldata == sdc);
776 
777 			/*
778 			 * If the thread has been sleeping for longer
779 			 * than sysdc_prune_interval, make it inactive by
780 			 * removing it from the list.
781 			 */
782 			if (!(t->t_state & (TS_RUN | TS_ONPROC)) &&
783 			    sdc->sdc_sleep_updates != 0 &&
784 			    (sdc->sdc_sleep_updates - sdc->sdc_nupdates) >
785 			    sysdc_prune_updates) {
786 				*prevptr = sdc->sdc_next;
787 				SYSDC_INC_STAT(sysdc_update_idle);
788 				sdc->sdc_next = NULL;
789 				thread_unlock(t);
790 				continue;
791 			}
792 			sysdc_update_pri(sdc, SDC_UPDATE_TIMEOUT);
793 			thread_unlock(t);
794 
795 			prevptr = &sdc->sdc_next;
796 		}
797 
798 		/*
799 		 * Add our list to the bucket, putting any new entries
800 		 * added while we were working at the tail of the list.
801 		 */
802 		do {
803 			tail = *headp;
804 			*prevptr = tail;
805 		} while (atomic_cas_ptr(headp, tail, head) != tail);
806 
807 		mutex_exit(&sdl->sdl_lock);
808 	}
809 
810 	mutex_enter(&sysdc_pset_lock);
811 	for (cur = list_head(&sysdc_psets); cur != NULL;
812 	    cur = list_next(&sysdc_psets, cur)) {
813 
814 		cur->sdp_vtime_last_interval =
815 		    diff * cur->sdp_cpupart->cp_ncpus;
816 		cur->sdp_DC_last_interval =
817 		    (cur->sdp_onproc_time * SYSDC_DC_MAX) /
818 		    cur->sdp_vtime_last_interval;
819 
820 		if (cur->sdp_should_break > 0) {
821 			cur->sdp_should_break--;	/* breaking */
822 			continue;
823 		}
824 		if (cur->sdp_dont_break > 0) {
825 			cur->sdp_dont_break--;	/* waiting before checking */
826 			continue;
827 		}
828 		if (cur->sdp_DC_last_interval > sysdc_max_pset_DC) {
829 			cur->sdp_should_break = sysdc_break_updates;
830 			cur->sdp_dont_break = sysdc_nobreak_updates;
831 			SYSDC_INC_STAT(sysdc_update_take_break);
832 		}
833 	}
834 
835 	/*
836 	 * If there are no sysdc_psets, there can be no threads, so
837 	 * we can stop doing our timeout.  Since we're holding the
838 	 * sysdc_pset_lock, no new sysdc_psets can come in, which will
839 	 * prevent anyone from racing with this and dropping our timeout
840 	 * on the floor.
841 	 */
842 	if (list_is_empty(&sysdc_psets)) {
843 		SYSDC_INC_STAT(sysdc_update_no_psets);
844 		ASSERT(sysdc_update_timeout_started);
845 		sysdc_update_timeout_started = 0;
846 
847 		redeploy = 0;
848 	}
849 	mutex_exit(&sysdc_pset_lock);
850 
851 	while (freelist != NULL) {
852 		sysdc_t *cur = freelist;
853 		freelist = cur->sdc_next;
854 		kmem_free(cur, sizeof (*cur));
855 	}
856 
857 	if (redeploy) {
858 		(void) timeout(sysdc_update, arg, sysdc_update_ticks);
859 	}
860 }
861 
862 static void
863 sysdc_preempt(kthread_t *t)
864 {
865 	ASSERT(t == curthread);
866 	ASSERT(THREAD_LOCK_HELD(t));
867 
868 	setbackdq(t);		/* give others a chance to run */
869 }
870 
871 static void
872 sysdc_tick(kthread_t *t)
873 {
874 	sysdc_t *sdc;
875 
876 	thread_lock(t);
877 	if (t->t_cid != sysdccid) {
878 		SYSDC_INC_STAT(sysdc_tick_not_sdc);
879 		thread_unlock(t);
880 		return;
881 	}
882 	sdc = t->t_cldata;
883 	if (t->t_state == TS_ONPROC &&
884 	    t->t_pri < t->t_disp_queue->disp_maxrunpri) {
885 		cpu_surrender(t);
886 	}
887 
888 	if (t->t_state == TS_ONPROC || t->t_state == TS_RUN) {
889 		ASSERT(sdc->sdc_sleep_updates == 0);
890 	}
891 
892 	ASSERT(sdc->sdc_ticks != sdc->sdc_update_ticks);
893 	sdc->sdc_ticks++;
894 	if (sdc->sdc_ticks == sdc->sdc_update_ticks) {
895 		SYSDC_INC_STAT(sysdc_tick_quantum_expired);
896 		sysdc_update_pri(sdc, SDC_UPDATE_TICK);
897 		ASSERT(sdc->sdc_ticks != sdc->sdc_update_ticks);
898 	}
899 	thread_unlock(t);
900 }
901 
902 static void
903 sysdc_setrun(kthread_t *t)
904 {
905 	sysdc_t *sdc = t->t_cldata;
906 
907 	ASSERT(THREAD_LOCK_HELD(t));	/* t should be in transition */
908 
909 	sdc->sdc_sleep_updates = 0;
910 
911 	if (sdc->sdc_next == NULL) {
912 		/*
913 		 * Since we're in transition, we don't want to use the
914 		 * full thread_update_pri().
915 		 */
916 		if (sysdc_compute_pri(sdc, 0)) {
917 			THREAD_CHANGE_PRI(t, sdc->sdc_epri);
918 		}
919 		sysdc_activate(sdc);
920 
921 		ASSERT(sdc->sdc_next != NULL);
922 	}
923 
924 	setbackdq(t);
925 }
926 
927 static void
928 sysdc_wakeup(kthread_t *t)
929 {
930 	sysdc_setrun(t);
931 }
932 
933 static void
934 sysdc_sleep(kthread_t *t)
935 {
936 	sysdc_t *sdc = t->t_cldata;
937 
938 	ASSERT(THREAD_LOCK_HELD(t));	/* t should be in transition */
939 
940 	sdc->sdc_sleep_updates = sdc->sdc_nupdates;
941 }
942 
943 /*ARGSUSED*/
944 static int
945 sysdc_enterclass(kthread_t *t, id_t cid, void *parmsp, cred_t *reqpcredp,
946     void *bufp)
947 {
948 	cpupart_t *const cpupart = t->t_cpupart;
949 	sysdc_t *sdc = bufp;
950 	sysdc_params_t *sdpp = parmsp;
951 	sysdc_pset_t *newpset = sdc->sdc_pset;
952 	sysdc_pset_t *pset;
953 	int start_timeout;
954 
955 	if (t->t_cid != syscid)
956 		return (EPERM);
957 
958 	ASSERT(ttolwp(t) != NULL);
959 	ASSERT(sdpp != NULL);
960 	ASSERT(newpset != NULL);
961 	ASSERT(sysdc_param_init);
962 
963 	ASSERT(sdpp->sdp_minpri >= sysdc_minpri);
964 	ASSERT(sdpp->sdp_maxpri <= sysdc_maxpri);
965 	ASSERT(sdpp->sdp_DC >= sysdc_minDC);
966 	ASSERT(sdpp->sdp_DC <= sysdc_maxDC);
967 
968 	sdc->sdc_thread = t;
969 	sdc->sdc_pri = sdpp->sdp_maxpri;	/* start off maximally */
970 	sdc->sdc_minpri = sdpp->sdp_minpri;
971 	sdc->sdc_maxpri = sdpp->sdp_maxpri;
972 	sdc->sdc_target_DC = sdpp->sdp_DC;
973 	sdc->sdc_ticks = 0;
974 	sdc->sdc_update_ticks = sysdc_update_ticks + 1;
975 
976 	/* Assign ourselves to the appropriate pset. */
977 	sdc->sdc_pset = NULL;
978 	mutex_enter(&sysdc_pset_lock);
979 	for (pset = list_head(&sysdc_psets); pset != NULL;
980 	    pset = list_next(&sysdc_psets, pset)) {
981 		if (pset->sdp_cpupart == cpupart) {
982 			break;
983 		}
984 	}
985 	if (pset == NULL) {
986 		pset = newpset;
987 		newpset = NULL;
988 		pset->sdp_cpupart = cpupart;
989 		list_insert_tail(&sysdc_psets, pset);
990 	}
991 	pset->sdp_nthreads++;
992 	ASSERT(pset->sdp_nthreads > 0);
993 
994 	sdc->sdc_pset = pset;
995 
996 	start_timeout = (sysdc_update_timeout_started == 0);
997 	sysdc_update_timeout_started = 1;
998 	mutex_exit(&sysdc_pset_lock);
999 
1000 	if (newpset != NULL)
1001 		kmem_free(newpset, sizeof (*newpset));
1002 
1003 	/* Update t's scheduling class and priority. */
1004 	thread_lock(t);
1005 	t->t_clfuncs = &(sclass[cid].cl_funcs->thread);
1006 	t->t_cid = cid;
1007 	t->t_cldata = sdc;
1008 	t->t_schedflag |= TS_RUNQMATCH;
1009 
1010 	sysdc_update_pri(sdc, SDC_UPDATE_INITIAL);
1011 	thread_unlock(t);
1012 
1013 	/* Kick off the thread timeout if we're the first one in. */
1014 	if (start_timeout) {
1015 		(void) timeout(sysdc_update, NULL, sysdc_update_ticks);
1016 	}
1017 
1018 	return (0);
1019 }
1020 
1021 static void
1022 sysdc_leave(sysdc_t *sdc)
1023 {
1024 	sysdc_pset_t *sdp = sdc->sdc_pset;
1025 	sysdc_list_t *sdl = SYSDC_LIST(sdc);
1026 	uint_t freedc;
1027 
1028 	mutex_enter(&sdl->sdl_lock);		/* block sysdc_update() */
1029 	sdc->sdc_thread = NULL;
1030 	freedc = (sdc->sdc_next == NULL);
1031 	mutex_exit(&sdl->sdl_lock);
1032 
1033 	mutex_enter(&sysdc_pset_lock);
1034 	ASSERT(sdp != NULL);
1035 	ASSERT(sdp->sdp_nthreads > 0);
1036 	--sdp->sdp_nthreads;
1037 	if (sdp->sdp_nthreads == 0) {
1038 		list_remove(&sysdc_psets, sdp);
1039 	} else {
1040 		sdp = NULL;
1041 	}
1042 	mutex_exit(&sysdc_pset_lock);
1043 
1044 	if (freedc)
1045 		kmem_free(sdc, sizeof (*sdc));
1046 	if (sdp != NULL)
1047 		kmem_free(sdp, sizeof (*sdp));
1048 }
1049 
1050 static void
1051 sysdc_exitclass(void *buf)
1052 {
1053 	sysdc_leave((sysdc_t *)buf);
1054 }
1055 
1056 /*ARGSUSED*/
1057 static int
1058 sysdc_canexit(kthread_t *t, cred_t *reqpcredp)
1059 {
1060 	/* Threads cannot exit SDC once joined, except in a body bag. */
1061 	return (EPERM);
1062 }
1063 
1064 static void
1065 sysdc_exit(kthread_t *t)
1066 {
1067 	sysdc_t *sdc;
1068 
1069 	/* We're exiting, so we just rejoin the SYS class. */
1070 	thread_lock(t);
1071 	ASSERT(t->t_cid == sysdccid);
1072 	sdc = t->t_cldata;
1073 	t->t_cid = syscid;
1074 	t->t_cldata = NULL;
1075 	t->t_clfuncs = &(sclass[syscid].cl_funcs->thread);
1076 	(void) thread_change_pri(t, maxclsyspri, 0);
1077 	t->t_schedflag &= ~TS_RUNQMATCH;
1078 	thread_unlock_nopreempt(t);
1079 
1080 	/* Unlink the sdc from everything. */
1081 	sysdc_leave(sdc);
1082 }
1083 
1084 /*ARGSUSED*/
1085 static int
1086 sysdc_fork(kthread_t *t, kthread_t *ct, void *bufp)
1087 {
1088 	/*
1089 	 * Threads cannot be created with SDC as their class; they must
1090 	 * be created as SYS and then added with sysdc_thread_enter().
1091 	 * Because of this restriction, sysdc_fork() should never be called.
1092 	 */
1093 	panic("sysdc cannot be forked");
1094 
1095 	return (ENOSYS);
1096 }
1097 
1098 /*ARGSUSED*/
1099 static void
1100 sysdc_forkret(kthread_t *t, kthread_t *ct)
1101 {
1102 	/* SDC threads are part of system processes, which never fork. */
1103 	panic("sysdc cannot be forked");
1104 }
1105 
1106 static pri_t
1107 sysdc_globpri(kthread_t *t)
1108 {
1109 	return (t->t_epri);
1110 }
1111 
1112 /*ARGSUSED*/
1113 static pri_t
1114 sysdc_no_swap(kthread_t *t, int flags)
1115 {
1116 	/* SDC threads cannot be swapped. */
1117 	return (-1);
1118 }
1119 
1120 /*
1121  * Get maximum and minimum priorities enjoyed by SDC threads.
1122  */
1123 static int
1124 sysdc_getclpri(pcpri_t *pcprip)
1125 {
1126 	pcprip->pc_clpmax = sysdc_maxpri;
1127 	pcprip->pc_clpmin = sysdc_minpri;
1128 	return (0);
1129 }
1130 
1131 /*ARGSUSED*/
1132 static int
1133 sysdc_getclinfo(void *arg)
1134 {
1135 	return (0);		/* no class-specific info */
1136 }
1137 
1138 /*ARGSUSED*/
1139 static int
1140 sysdc_alloc(void **p, int flag)
1141 {
1142 	sysdc_t *new;
1143 
1144 	*p = NULL;
1145 	if ((new = kmem_zalloc(sizeof (*new), flag)) == NULL) {
1146 		return (ENOMEM);
1147 	}
1148 	if ((new->sdc_pset = kmem_zalloc(sizeof (*new->sdc_pset), flag)) ==
1149 	    NULL) {
1150 		kmem_free(new, sizeof (*new));
1151 		return (ENOMEM);
1152 	}
1153 	*p = new;
1154 	return (0);
1155 }
1156 
1157 static void
1158 sysdc_free(void *p)
1159 {
1160 	sysdc_t *sdc = p;
1161 
1162 	if (sdc != NULL) {
1163 		/*
1164 		 * We must have failed CL_ENTERCLASS(), so our pset should be
1165 		 * there and unused.
1166 		 */
1167 		ASSERT(sdc->sdc_pset != NULL);
1168 		ASSERT(sdc->sdc_pset->sdp_cpupart == NULL);
1169 		kmem_free(sdc->sdc_pset, sizeof (*sdc->sdc_pset));
1170 		kmem_free(sdc, sizeof (*sdc));
1171 	}
1172 }
1173 
1174 static int sysdc_enosys();	/* Boy, ANSI-C's K&R compatibility is weird. */
1175 static int sysdc_einval();
1176 static void sysdc_nullsys();
1177 
1178 static struct classfuncs sysdc_classfuncs = {
1179 	/* messages to class manager */
1180 	{
1181 		sysdc_enosys,	/* admin */
1182 		sysdc_getclinfo,
1183 		sysdc_enosys,	/* parmsin */
1184 		sysdc_enosys,	/* parmsout */
1185 		sysdc_enosys,	/* vaparmsin */
1186 		sysdc_enosys,	/* vaparmsout */
1187 		sysdc_getclpri,
1188 		sysdc_alloc,
1189 		sysdc_free,
1190 	},
1191 	/* operations on threads */
1192 	{
1193 		sysdc_enterclass,
1194 		sysdc_exitclass,
1195 		sysdc_canexit,
1196 		sysdc_fork,
1197 		sysdc_forkret,
1198 		sysdc_nullsys,	/* parmsget */
1199 		sysdc_enosys,	/* parmsset */
1200 		sysdc_nullsys,	/* stop */
1201 		sysdc_exit,
1202 		sysdc_nullsys,	/* active */
1203 		sysdc_nullsys,	/* inactive */
1204 		sysdc_no_swap,	/* swapin */
1205 		sysdc_no_swap,	/* swapout */
1206 		sysdc_nullsys,	/* trapret */
1207 		sysdc_preempt,
1208 		sysdc_setrun,
1209 		sysdc_sleep,
1210 		sysdc_tick,
1211 		sysdc_wakeup,
1212 		sysdc_einval,	/* donice */
1213 		sysdc_globpri,
1214 		sysdc_nullsys,	/* set_process_group */
1215 		sysdc_nullsys,	/* yield */
1216 		sysdc_einval,	/* doprio */
1217 	}
1218 };
1219 
1220 static int
1221 sysdc_enosys()
1222 {
1223 	return (ENOSYS);
1224 }
1225 
1226 static int
1227 sysdc_einval()
1228 {
1229 	return (EINVAL);
1230 }
1231 
1232 static void
1233 sysdc_nullsys()
1234 {
1235 }
1236 
1237 /*ARGSUSED*/
1238 static pri_t
1239 sysdc_init(id_t cid, int clparmsz, classfuncs_t **clfuncspp)
1240 {
1241 	int idx;
1242 
1243 	list_create(&sysdc_psets, sizeof (sysdc_pset_t),
1244 	    offsetof(sysdc_pset_t, sdp_node));
1245 
1246 	for (idx = 0; idx < SYSDC_NLISTS; idx++) {
1247 		sysdc_active[idx].sdl_list = &sysdc_dummy;
1248 	}
1249 
1250 	sysdc_initparam();
1251 
1252 	sysdccid = cid;
1253 	*clfuncspp = &sysdc_classfuncs;
1254 
1255 	return ((pri_t)v.v_maxsyspri);
1256 }
1257 
1258 static struct sclass csw = {
1259 	"SDC",
1260 	sysdc_init,
1261 	0
1262 };
1263 
1264 static struct modlsched modlsched = {
1265 	&mod_schedops, "system duty cycle scheduling class", &csw
1266 };
1267 
1268 static struct modlinkage modlinkage = {
1269 	MODREV_1, (void *)&modlsched, NULL
1270 };
1271 
1272 int
1273 _init()
1274 {
1275 	return (mod_install(&modlinkage));
1276 }
1277 
1278 int
1279 _fini()
1280 {
1281 	return (EBUSY);		/* can't unload for now */
1282 }
1283 
1284 int
1285 _info(struct modinfo *modinfop)
1286 {
1287 	return (mod_info(&modlinkage, modinfop));
1288 }
1289 
1290 /* --- consolidation-private interfaces --- */
1291 void
1292 sysdc_thread_enter(kthread_t *t, uint_t dc, uint_t flags)
1293 {
1294 	void *buf = NULL;
1295 	sysdc_params_t sdp;
1296 
1297 	SYSDC_INC_STAT(sysdc_thread_enter_enter);
1298 
1299 	ASSERT(sysdc_param_init);
1300 	ASSERT(sysdccid >= 0);
1301 
1302 	ASSERT((flags & ~SYSDC_THREAD_BATCH) == 0);
1303 
1304 	sdp.sdp_minpri = sysdc_minpri;
1305 	sdp.sdp_maxpri = sysdc_maxpri;
1306 	sdp.sdp_DC = MAX(MIN(dc, sysdc_maxDC), sysdc_minDC);
1307 
1308 	VERIFY3U(CL_ALLOC(&buf, sysdccid, KM_SLEEP), ==, 0);
1309 
1310 	ASSERT(t->t_lwp != NULL);
1311 	ASSERT(t->t_cid == syscid);
1312 	ASSERT(t->t_cldata == NULL);
1313 	VERIFY3U(CL_CANEXIT(t, NULL), ==, 0);
1314 	VERIFY3U(CL_ENTERCLASS(t, sysdccid, &sdp, kcred, buf), ==, 0);
1315 	CL_EXITCLASS(syscid, NULL);
1316 }
1317