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