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