xref: /illumos-gate/usr/src/uts/common/sys/disp.h (revision 66582b606a8194f7f3ba5b3a3a6dca5b0d346361)
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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  *
25  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
26  *
27  * Copyright 2018 Joyent, Inc.
28  */
29 
30 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
31 /*	  All Rights Reserved	*/
32 
33 
34 #ifndef _SYS_DISP_H
35 #define	_SYS_DISP_H
36 
37 #include <sys/priocntl.h>
38 #include <sys/thread.h>
39 #include <sys/class.h>
40 
41 #ifdef	__cplusplus
42 extern "C" {
43 #endif
44 
45 /*
46  * The following is the format of a dispatcher queue entry.
47  */
48 typedef struct dispq {
49 	kthread_t	*dq_first;	/* first thread on queue or NULL */
50 	kthread_t	*dq_last;	/* last thread on queue or NULL */
51 	int		dq_sruncnt;	/* number of loaded, runnable */
52 					/*    threads on queue */
53 } dispq_t;
54 
55 /*
56  * Dispatch queue structure.
57  */
58 typedef struct _disp {
59 	disp_lock_t	disp_lock;	/* protects dispatching fields */
60 	pri_t		disp_npri;	/* # of priority levels in queue */
61 	dispq_t		*disp_q;		/* the dispatch queue */
62 	dispq_t		*disp_q_limit;	/* ptr past end of dispatch queue */
63 	ulong_t		*disp_qactmap;	/* bitmap of active dispatch queues */
64 
65 	/*
66 	 * Priorities:
67 	 *	disp_maxrunpri is the maximum run priority of runnable threads
68 	 *	on this queue.  It is -1 if nothing is runnable.
69 	 *
70 	 *	disp_max_unbound_pri is the maximum run priority of threads on
71 	 *	this dispatch queue but runnable by any CPU.  This may be left
72 	 *	artificially high, then corrected when some CPU tries to take
73 	 *	an unbound thread.  It is -1 if nothing is runnable.
74 	 */
75 	pri_t		disp_maxrunpri;	/* maximum run priority */
76 	pri_t		disp_max_unbound_pri;	/* max pri of unbound threads */
77 
78 	volatile int	disp_nrunnable;	/* runnable threads in cpu dispq */
79 
80 	struct cpu	*disp_cpu;	/* cpu owning this queue or NULL */
81 	hrtime_t	disp_steal;	/* time when threads become stealable */
82 } disp_t;
83 
84 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
85 
86 #define	MAXCLSYSPRI	99
87 #define	MINCLSYSPRI	60
88 
89 
90 /*
91  * Global scheduling variables.
92  *	- See sys/cpuvar.h for CPU-local variables.
93  */
94 extern int	nswapped;	/* number of swapped threads */
95 				/* nswapped protected by swap_lock */
96 
97 extern	pri_t	minclsyspri;	/* minimum level of any system class */
98 extern	pri_t	maxclsyspri;	/* maximum level of any system class */
99 extern	pri_t	intr_pri;	/* interrupt thread priority base level */
100 
101 #endif	/* _KERNEL || _FAKE_KERNEL */
102 #if defined(_KERNEL)
103 
104 /*
105  * Minimum amount of time that a thread can remain runnable before it can
106  * be stolen by another CPU (in nanoseconds).
107  */
108 extern hrtime_t nosteal_nsec;
109 
110 /*
111  * Kernel preemption occurs if a higher-priority thread is runnable with
112  * a priority at or above kpreemptpri.
113  *
114  * So that other processors can watch for such threads, a separate
115  * dispatch queue with unbound work above kpreemptpri is maintained.
116  * This is part of the CPU partition structure (cpupart_t).
117  */
118 extern	pri_t	kpreemptpri;	/* level above which preemption takes place */
119 
120 extern void		disp_kp_alloc(disp_t *, pri_t);	/* allocate kp queue */
121 extern void		disp_kp_free(disp_t *);		/* free kp queue */
122 
123 /*
124  * Macro for use by scheduling classes to decide whether the thread is about
125  * to be scheduled or not.  This returns the maximum run priority.
126  */
127 #define	DISP_MAXRUNPRI(t)	((t)->t_disp_queue->disp_maxrunpri)
128 
129 /*
130  * Platform callbacks for various dispatcher operations
131  *
132  * idle_cpu() is invoked when a cpu goes idle, and has nothing to do.
133  * disp_enq_thread() is invoked when a thread is placed on a run queue.
134  */
135 extern void	(*idle_cpu)();
136 extern void	(*disp_enq_thread)(struct cpu *, int);
137 
138 
139 extern int		dispdeq(kthread_t *);
140 extern void		dispinit(void);
141 extern void		disp_add(sclass_t *);
142 extern int		intr_active(struct cpu *, int);
143 extern int		servicing_interrupt(void);
144 extern void		preempt(void);
145 extern void		setbackdq(kthread_t *);
146 extern void		setfrontdq(kthread_t *);
147 extern void		swtch(void);
148 extern void		swtch_to(kthread_t *);
149 extern void		swtch_from_zombie(void)
150 				__NORETURN;
151 extern void		dq_sruninc(kthread_t *);
152 extern void		dq_srundec(kthread_t *);
153 extern void		cpu_rechoose(kthread_t *);
154 extern void		cpu_surrender(kthread_t *);
155 extern void		kpreempt(int);
156 extern struct cpu	*disp_lowpri_cpu(struct cpu *, kthread_t *, pri_t);
157 extern int		disp_bound_threads(struct cpu *, int);
158 extern int		disp_bound_anythreads(struct cpu *, int);
159 extern int		disp_bound_partition(struct cpu *, int);
160 extern void		disp_cpu_init(struct cpu *);
161 extern void		disp_cpu_fini(struct cpu *);
162 extern void		disp_cpu_inactive(struct cpu *);
163 extern void		disp_adjust_unbound_pri(kthread_t *);
164 extern void		resume(kthread_t *);
165 extern void		resume_from_intr(kthread_t *);
166 extern void		resume_from_zombie(kthread_t *)
167 				__NORETURN;
168 extern void		disp_swapped_enq(kthread_t *);
169 extern int		disp_anywork(void);
170 
171 extern struct cpu	*disp_choose_best_cpu(void);
172 
173 #define	KPREEMPT_SYNC		(-1)
174 #define	kpreempt_disable()				\
175 	{						\
176 		curthread->t_preempt++;			\
177 		ASSERT(curthread->t_preempt >= 1);	\
178 	}
179 #define	kpreempt_enable()				\
180 	{						\
181 		ASSERT(curthread->t_preempt >= 1);	\
182 		if (--curthread->t_preempt == 0 &&	\
183 		    CPU->cpu_kprunrun)			\
184 			kpreempt(KPREEMPT_SYNC);	\
185 	}
186 
187 #endif	/* _KERNEL */
188 
189 #define	CPU_IDLE_PRI (-1)
190 
191 #ifdef	__cplusplus
192 }
193 #endif
194 
195 #endif	/* _SYS_DISP_H */
196