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