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