disp.h revision 2041:f13eb9eafd9e
1129198Scognet/* 2129198Scognet * CDDL HEADER START 3139735Simp * 4129198Scognet * The contents of this file are subject to the terms of the 5129198Scognet * Common Development and Distribution License, Version 1.0 only 6129198Scognet * (the "License"). You may not use this file except in compliance 7129198Scognet * with the License. 8129198Scognet * 9129198Scognet * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10129198Scognet * or http://www.opensolaris.org/os/licensing. 11129198Scognet * See the License for the specific language governing permissions 12129198Scognet * and limitations under the License. 13129198Scognet * 14129198Scognet * When distributing Covered Code, include this CDDL HEADER in each 15129198Scognet * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16129198Scognet * If applicable, add the following below this CDDL HEADER, with the 17129198Scognet * fields enclosed by brackets "[]" replaced with your own identifying 18129198Scognet * information: Portions Copyright [yyyy] [name of copyright owner] 19129198Scognet * 20129198Scognet * CDDL HEADER END 21129198Scognet */ 22129198Scognet/* 23129198Scognet * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24129198Scognet * Use is subject to license terms. 25129198Scognet */ 26129198Scognet 27129198Scognet/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28129198Scognet/* All Rights Reserved */ 29129198Scognet 30129198Scognet 31129198Scognet#ifndef _SYS_DISP_H 32129198Scognet#define _SYS_DISP_H 33129198Scognet 34129198Scognet#pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.11 */ 35129198Scognet 36129198Scognet#include <sys/priocntl.h> 37129198Scognet#include <sys/thread.h> 38129198Scognet#include <sys/class.h> 39129198Scognet 40129198Scognet#ifdef __cplusplus 41129198Scognetextern "C" { 42129198Scognet#endif 43129198Scognet 44129198Scognet/* 45129198Scognet * The following is the format of a dispatcher queue entry. 46129198Scognet */ 47129198Scognettypedef struct dispq { 48129198Scognet kthread_t *dq_first; /* first thread on queue or NULL */ 49129198Scognet kthread_t *dq_last; /* last thread on queue or NULL */ 50129198Scognet int dq_sruncnt; /* number of loaded, runnable */ 51129198Scognet /* threads on queue */ 52129198Scognet} dispq_t; 53129198Scognet 54132472Scognet/* 55132472Scognet * Dispatch queue structure. 56129198Scognet */ 57129198Scognettypedef struct _disp { 58129198Scognet disp_lock_t disp_lock; /* protects dispatching fields */ 59129198Scognet pri_t disp_npri; /* # of priority levels in queue */ 60129198Scognet dispq_t *disp_q; /* the dispatch queue */ 61166655Scognet dispq_t *disp_q_limit; /* ptr past end of dispatch queue */ 62129198Scognet ulong_t *disp_qactmap; /* bitmap of active dispatch queues */ 63129198Scognet 64129198Scognet /* 65129198Scognet * Priorities: 66129198Scognet * disp_maxrunpri is the maximum run priority of runnable threads 67129198Scognet * on this queue. It is -1 if nothing is runnable. 68135646Scognet * 69135646Scognet * disp_max_unbound_pri is the maximum run priority of threads on 70129198Scognet * this dispatch queue but runnable by any CPU. This may be left 71129198Scognet * artificially high, then corrected when some CPU tries to take 72161592Scognet * an unbound thread. It is -1 if nothing is runnable. 73135646Scognet */ 74135646Scognet pri_t disp_maxrunpri; /* maximum run priority */ 75129198Scognet pri_t disp_max_unbound_pri; /* max pri of unbound threads */ 76129198Scognet 77243579Smarcel volatile int disp_nrunnable; /* runnable threads in cpu dispq */ 78243579Smarcel 79243579Smarcel struct cpu *disp_cpu; /* cpu owning this queue or NULL */ 80243579Smarcel hrtime_t disp_steal; /* time when threads become stealable */ 81243579Smarcel} disp_t; 82243579Smarcel 83243579Smarcel#if defined(_KERNEL) 84164080Scognet 85164080Scognet#define MAXCLSYSPRI 99 86164080Scognet#define MINCLSYSPRI 60 87129198Scognet 88135646Scognet 89135646Scognet/* 90129198Scognet * Global scheduling variables. 91129198Scognet * - See sys/cpuvar.h for CPU-local variables. 92129198Scognet */ 93129198Scognetextern int nswapped; /* number of swapped threads */ 94129198Scognet /* nswapped protected by swap_lock */ 95129198Scognet 96129198Scognetextern pri_t minclsyspri; /* minimum level of any system class */ 97129198Scognetextern pri_t maxclsyspri; /* maximum level of any system class */ 98129198Scognetextern pri_t intr_pri; /* interrupt thread priority base level */ 99129198Scognet 100129198Scognet/* 101129198Scognet * Amount of time that may elapse before a thread is considered to have 102129198Scognet * lost it's cache investment. 103129198Scognet */ 104129198Scognet#define RECHOOSE_INTERVAL 3 105129198Scognetextern int rechoose_interval; 106129198Scognet 107239268Sgonzo/* 108239268Sgonzo * Minimum amount of time that a thread can remain runnable before it can 109239268Sgonzo * be stolen by another CPU (in nanoseconds). 110239268Sgonzo */ 111129198Scognetextern hrtime_t nosteal_nsec; 112129198Scognet 113129198Scognet/* 114129198Scognet * Kernel preemption occurs if a higher-priority thread is runnable with 115129198Scognet * a priority at or above kpreemptpri. 116129198Scognet * 117129198Scognet * So that other processors can watch for such threads, a separate 118129198Scognet * dispatch queue with unbound work above kpreemptpri is maintained. 119129198Scognet * This is part of the CPU partition structure (cpupart_t). 120129198Scognet */ 121129198Scognetextern pri_t kpreemptpri; /* level above which preemption takes place */ 122129198Scognet 123129198Scognetextern void disp_kp_alloc(disp_t *, pri_t); /* allocate kp queue */ 124129198Scognetextern void disp_kp_free(disp_t *); /* free kp queue */ 125129198Scognet 126129198Scognet/* 127129198Scognet * Macro for use by scheduling classes to decide whether the thread is about 128129198Scognet * to be scheduled or not. This returns the maximum run priority. 129129198Scognet */ 130129198Scognet#define DISP_MAXRUNPRI(t) ((t)->t_disp_queue->disp_maxrunpri) 131129198Scognet 132129198Scognet/* 133129198Scognet * Platform callbacks for various dispatcher operations 134129198Scognet * 135129198Scognet * idle_cpu() is invoked when a cpu goes idle, and has nothing to do. 136129198Scognet * disp_enq_thread() is invoked when a thread is placed on a run queue. 137129198Scognet */ 138129198Scognetextern void (*idle_cpu)(); 139129198Scognetextern void (*disp_enq_thread)(struct cpu *, int); 140129198Scognet 141129198Scognet 142129198Scognetextern int dispdeq(kthread_t *); 143129198Scognetextern void dispinit(void); 144129198Scognetextern void disp_add(sclass_t *); 145129198Scognetextern int intr_active(struct cpu *, int); 146129198Scognetextern int servicing_interrupt(void); 147129198Scognetextern void preempt(void); 148129198Scognetextern void setbackdq(kthread_t *); 149129198Scognetextern void setfrontdq(kthread_t *); 150129198Scognetextern void swtch(void); 151171618Scognetextern void swtch_to(kthread_t *); 152171781Scognetextern void swtch_from_zombie(void) 153171781Scognet __NORETURN; 154171781Scognetextern void dq_sruninc(kthread_t *); 155129198Scognetextern void dq_srundec(kthread_t *); 156129198Scognetextern void cpu_rechoose(kthread_t *); 157129198Scognetextern void cpu_surrender(kthread_t *); 158129198Scognetextern void kpreempt(int); 159129198Scognetextern struct cpu *disp_lowpri_cpu(struct cpu *, struct lgrp_ld *, pri_t, 160129198Scognet struct cpu *); 161129198Scognetextern int disp_bound_threads(struct cpu *, int); 162129198Scognetextern int disp_bound_anythreads(struct cpu *, int); 163129198Scognetextern int disp_bound_partition(struct cpu *, int); 164129198Scognetextern void disp_cpu_init(struct cpu *); 165129198Scognetextern void disp_cpu_fini(struct cpu *); 166129198Scognetextern void disp_cpu_inactive(struct cpu *); 167129198Scognetextern void disp_adjust_unbound_pri(kthread_t *); 168129198Scognetextern void resume(kthread_t *); 169129198Scognetextern void resume_from_intr(kthread_t *); 170129198Scognetextern void resume_from_zombie(kthread_t *) 171129198Scognet __NORETURN; 172129198Scognetextern void disp_swapped_enq(kthread_t *); 173129198Scognetextern int disp_anywork(void); 174129198Scognet 175129198Scognet#define KPREEMPT_SYNC (-1) 176129198Scognet#define kpreempt_disable() \ 177129198Scognet { \ 178129198Scognet curthread->t_preempt++; \ 179129198Scognet ASSERT(curthread->t_preempt >= 1); \ 180129198Scognet } 181129198Scognet#define kpreempt_enable() \ 182129198Scognet { \ 183129198Scognet ASSERT(curthread->t_preempt >= 1); \ 184129198Scognet if (--curthread->t_preempt == 0 && \ 185129198Scognet CPU->cpu_kprunrun) \ 186129198Scognet kpreempt(KPREEMPT_SYNC); \ 187129198Scognet } 188129198Scognet 189129198Scognet#endif /* _KERNEL */ 190129198Scognet 191129198Scognet#ifdef __cplusplus 192129198Scognet} 193129198Scognet#endif 194129198Scognet 195129198Scognet#endif /* _SYS_DISP_H */ 196129198Scognet