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 */