summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/sys/disp.h
blob: cb3711edcd0d0066b14a68637fdb3ef3767008fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 *
 * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
 *
 * Copyright 2018 Joyent, Inc.
 */

/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
/*	  All Rights Reserved	*/


#ifndef _SYS_DISP_H
#define	_SYS_DISP_H

#include <sys/priocntl.h>
#include <sys/thread.h>
#include <sys/class.h>

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * The following is the format of a dispatcher queue entry.
 */
typedef struct dispq {
	kthread_t	*dq_first;	/* first thread on queue or NULL */
	kthread_t	*dq_last;	/* last thread on queue or NULL */
	int		dq_sruncnt;	/* number of loaded, runnable */
					/*    threads on queue */
} dispq_t;

/*
 * Dispatch queue structure.
 */
typedef struct _disp {
	disp_lock_t	disp_lock;	/* protects dispatching fields */
	pri_t		disp_npri;	/* # of priority levels in queue */
	dispq_t		*disp_q;		/* the dispatch queue */
	dispq_t		*disp_q_limit;	/* ptr past end of dispatch queue */
	ulong_t		*disp_qactmap;	/* bitmap of active dispatch queues */

	/*
	 * Priorities:
	 *	disp_maxrunpri is the maximum run priority of runnable threads
	 *	on this queue.  It is -1 if nothing is runnable.
	 *
	 *	disp_max_unbound_pri is the maximum run priority of threads on
	 *	this dispatch queue but runnable by any CPU.  This may be left
	 *	artificially high, then corrected when some CPU tries to take
	 *	an unbound thread.  It is -1 if nothing is runnable.
	 */
	pri_t		disp_maxrunpri;	/* maximum run priority */
	pri_t		disp_max_unbound_pri;	/* max pri of unbound threads */

	volatile int	disp_nrunnable;	/* runnable threads in cpu dispq */

	struct cpu	*disp_cpu;	/* cpu owning this queue or NULL */
	hrtime_t	disp_steal;	/* time when threads become stealable */
} disp_t;

#if defined(_KERNEL) || defined(_FAKE_KERNEL)

#define	MAXCLSYSPRI	99
#define	MINCLSYSPRI	60


/*
 * Global scheduling variables.
 *	- See sys/cpuvar.h for CPU-local variables.
 */
extern int	nswapped;	/* number of swapped threads */
				/* nswapped protected by swap_lock */

extern	pri_t	minclsyspri;	/* minimum level of any system class */
extern	pri_t	maxclsyspri;	/* maximum level of any system class */
extern	pri_t	intr_pri;	/* interrupt thread priority base level */

#endif	/* _KERNEL || _FAKE_KERNEL */
#if defined(_KERNEL)

/*
 * Minimum amount of time that a thread can remain runnable before it can
 * be stolen by another CPU (in nanoseconds).
 */
extern hrtime_t nosteal_nsec;

/*
 * Kernel preemption occurs if a higher-priority thread is runnable with
 * a priority at or above kpreemptpri.
 *
 * So that other processors can watch for such threads, a separate
 * dispatch queue with unbound work above kpreemptpri is maintained.
 * This is part of the CPU partition structure (cpupart_t).
 */
extern	pri_t	kpreemptpri;	/* level above which preemption takes place */

extern void		disp_kp_alloc(disp_t *, pri_t);	/* allocate kp queue */
extern void		disp_kp_free(disp_t *);		/* free kp queue */

/*
 * Macro for use by scheduling classes to decide whether the thread is about
 * to be scheduled or not.  This returns the maximum run priority.
 */
#define	DISP_MAXRUNPRI(t)	((t)->t_disp_queue->disp_maxrunpri)

/*
 * Platform callbacks for various dispatcher operations
 *
 * idle_cpu() is invoked when a cpu goes idle, and has nothing to do.
 * disp_enq_thread() is invoked when a thread is placed on a run queue.
 */
extern void	(*idle_cpu)();
extern void	(*disp_enq_thread)(struct cpu *, int);


extern int		dispdeq(kthread_t *);
extern void		dispinit(void);
extern void		disp_add(sclass_t *);
extern int		intr_active(struct cpu *, int);
extern int		servicing_interrupt(void);
extern void		preempt(void);
extern void		setbackdq(kthread_t *);
extern void		setfrontdq(kthread_t *);
extern void		swtch(void);
extern void		swtch_to(kthread_t *);
extern void		swtch_from_zombie(void)
				__NORETURN;
extern void		dq_sruninc(kthread_t *);
extern void		dq_srundec(kthread_t *);
extern void		cpu_rechoose(kthread_t *);
extern void		cpu_surrender(kthread_t *);
extern void		kpreempt(int);
extern struct cpu	*disp_lowpri_cpu(struct cpu *, kthread_t *, pri_t);
extern int		disp_bound_threads(struct cpu *, int);
extern int		disp_bound_anythreads(struct cpu *, int);
extern int		disp_bound_partition(struct cpu *, int);
extern void		disp_cpu_init(struct cpu *);
extern void		disp_cpu_fini(struct cpu *);
extern void		disp_cpu_inactive(struct cpu *);
extern void		disp_adjust_unbound_pri(kthread_t *);
extern void		resume(kthread_t *);
extern void		resume_from_intr(kthread_t *);
extern void		resume_from_zombie(kthread_t *)
				__NORETURN;
extern void		disp_swapped_enq(kthread_t *);
extern int		disp_anywork(void);

extern struct cpu	*disp_choose_best_cpu(void);

#define	KPREEMPT_SYNC		(-1)
#define	kpreempt_disable()				\
	{						\
		curthread->t_preempt++;			\
		ASSERT(curthread->t_preempt >= 1);	\
	}
#define	kpreempt_enable()				\
	{						\
		ASSERT(curthread->t_preempt >= 1);	\
		if (--curthread->t_preempt == 0 &&	\
		    CPU->cpu_kprunrun)			\
			kpreempt(KPREEMPT_SYNC);	\
	}

#endif	/* _KERNEL */

#define	CPU_IDLE_PRI (-1)

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_DISP_H */