GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/amd/amd/sched.c Lines: 0 60 0.0 %
Date: 2017-11-07 Branches: 0 30 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: sched.c,v 1.18 2014/10/26 03:28:41 guenther Exp $	*/
2
3
/*
4
 * Copyright (c) 1990 Jan-Simon Pendry
5
 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
6
 * Copyright (c) 1990, 1993
7
 *	The Regents of the University of California.  All rights reserved.
8
 *
9
 * This code is derived from software contributed to Berkeley by
10
 * Jan-Simon Pendry at Imperial College, London.
11
 *
12
 * Redistribution and use in source and binary forms, with or without
13
 * modification, are permitted provided that the following conditions
14
 * are met:
15
 * 1. Redistributions of source code must retain the above copyright
16
 *    notice, this list of conditions and the following disclaimer.
17
 * 2. Redistributions in binary form must reproduce the above copyright
18
 *    notice, this list of conditions and the following disclaimer in the
19
 *    documentation and/or other materials provided with the distribution.
20
 * 3. Neither the name of the University nor the names of its contributors
21
 *    may be used to endorse or promote products derived from this software
22
 *    without specific prior written permission.
23
 *
24
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34
 * SUCH DAMAGE.
35
 *
36
 *	from: @(#)sched.c	8.1 (Berkeley) 6/6/93
37
 *	$Id: sched.c,v 1.18 2014/10/26 03:28:41 guenther Exp $
38
 */
39
40
/*
41
 * Process scheduler
42
 */
43
44
#include "am.h"
45
#include <signal.h>
46
#include <sys/wait.h>
47
#include <setjmp.h>
48
extern jmp_buf select_intr;
49
extern int select_intr_valid;
50
51
typedef struct pjob pjob;
52
struct pjob {
53
	qelem hdr;			/* Linked list */
54
	pid_t pid;			/* Process ID of job */
55
	cb_fun cb_fun;			/* Callback function */
56
	void *cb_closure;		/* Closure for callback */
57
	int w;				/* Status filled in by sigchld */
58
	void *wchan;			/* Wait channel */
59
};
60
61
extern qelem proc_list_head;
62
qelem proc_list_head = { &proc_list_head, &proc_list_head };
63
extern qelem proc_wait_list;
64
qelem proc_wait_list = { &proc_wait_list, &proc_wait_list };
65
66
int task_notify_todo;
67
68
void
69
ins_que(qelem *elem, qelem *pred)
70
{
71
	qelem *p = pred->q_forw;
72
	elem->q_back = pred;
73
	elem->q_forw = p;
74
	pred->q_forw = elem;
75
	p->q_back = elem;
76
}
77
78
void
79
rem_que(qelem *elem)
80
{
81
	qelem *p = elem->q_forw;
82
	qelem *p2 = elem->q_back;
83
	p2->q_forw = p;
84
	p->q_back = p2;
85
}
86
87
static pjob *
88
sched_job(cb_fun cf, void *ca)
89
{
90
	pjob *p = ALLOC(pjob);
91
92
	p->cb_fun = cf;
93
	p->cb_closure = ca;
94
95
	/*
96
	 * Now place on wait queue
97
	 */
98
	ins_que(&p->hdr, &proc_wait_list);
99
100
	return p;
101
}
102
103
void
104
run_task(task_fun tf, void *ta, cb_fun cf, void *ca)
105
{
106
	pjob *p = sched_job(cf, ca);
107
	sigset_t mask, omask;
108
109
	p->wchan = p;
110
111
	sigemptyset(&mask);
112
	sigaddset(&mask, SIGCHLD);
113
	sigprocmask(SIG_BLOCK, &mask, &omask);
114
115
	if ((p->pid = background())) {
116
		sigprocmask(SIG_SETMASK, &omask, NULL);
117
		return;
118
	}
119
120
	exit((*tf)(ta));
121
	/* firewall... */
122
	abort();
123
}
124
125
/*
126
 * Schedule a task to be run when woken up
127
 */
128
void
129
sched_task(cb_fun cf, void *ca, void *wchan)
130
{
131
	/*
132
	 * Allocate a new task
133
	 */
134
	pjob *p = sched_job(cf, ca);
135
#ifdef DEBUG_SLEEP
136
	dlog("SLEEP on %#x", wchan);
137
#endif
138
	p->wchan = wchan;
139
	p->pid = 0;
140
	bzero(&p->w, sizeof(p->w));
141
}
142
143
static void
144
wakeupjob(pjob *p)
145
{
146
	rem_que(&p->hdr);
147
	ins_que(&p->hdr, &proc_list_head);
148
	task_notify_todo++;
149
}
150
151
void
152
wakeup(void *wchan)
153
{
154
	pjob *p, *p2;
155
#ifdef DEBUG_SLEEP
156
	int done = 0;
157
#endif
158
	if (!foreground)
159
		return;
160
161
#ifdef DEBUG_SLEEP
162
	/*dlog("wakeup(%#x)", wchan);*/
163
#endif
164
	/*
165
	 * Can't user ITER() here because
166
	 * wakeupjob() juggles the list.
167
	 */
168
	for (p = FIRST(pjob, &proc_wait_list);
169
			p2 = NEXT(pjob, p), p != HEAD(pjob, &proc_wait_list);
170
			p = p2) {
171
		if (p->wchan == wchan) {
172
#ifdef DEBUG_SLEEP
173
			done = 1;
174
#endif
175
			wakeupjob(p);
176
		}
177
	}
178
179
#ifdef DEBUG_SLEEP
180
	if (!done)
181
		dlog("Nothing SLEEPing on %#x", wchan);
182
#endif
183
}
184
185
void
186
wakeup_task(int rc, int term, void *cl)
187
{
188
	wakeup(cl);
189
}
190
191
192
void
193
sigchld(int sig)
194
{
195
	int w;
196
	int save_errno = errno;
197
	pid_t pid;
198
199
	while ((pid = waitpid((pid_t)-1, &w, WNOHANG)) > 0) {
200
		pjob *p, *p2;
201
202
		if (WIFSIGNALED(w))
203
			plog(XLOG_ERROR, "Process %ld exited with signal %d",
204
				(long)pid, WTERMSIG(w));
205
#ifdef DEBUG
206
		else
207
			dlog("Process %ld exited with status %d",
208
				(long)pid, WEXITSTATUS(w));
209
#endif /* DEBUG */
210
211
		for (p = FIRST(pjob, &proc_wait_list);
212
		     p2 = NEXT(pjob, p), p != HEAD(pjob, &proc_wait_list);
213
		     p = p2) {
214
			if (p->pid == pid) {
215
				p->w = w;
216
				wakeupjob(p);
217
				break;
218
			}
219
		}
220
221
#ifdef DEBUG
222
		if (p == NULL)
223
			dlog("can't locate task block for pid %ld", (long)pid);
224
#endif /* DEBUG */
225
	}
226
227
	if (select_intr_valid)
228
		longjmp(select_intr, sig);
229
	errno = save_errno;
230
}
231
232
/*
233
 * Run any pending tasks.
234
 * This must be called with SIGCHLD disabled
235
 */
236
void
237
do_task_notify(void)
238
{
239
	/*
240
	 * Keep taking the first item off the list and processing it.
241
	 *
242
	 * Done this way because the callback can, quite reasonably,
243
	 * queue a new task, so no local reference into the list can be
244
	 * held here.
245
	 */
246
	while (FIRST(pjob, &proc_list_head) != HEAD(pjob, &proc_list_head)) {
247
		pjob *p = FIRST(pjob, &proc_list_head);
248
		rem_que(&p->hdr);
249
		/*
250
		 * This job has completed
251
		 */
252
		--task_notify_todo;
253
254
		/*
255
		 * Do callback if it exists
256
		 */
257
		if (p->cb_fun)
258
			(*p->cb_fun)(WIFEXITED(p->w) ? WEXITSTATUS(p->w) : 0,
259
				WIFSIGNALED(p->w) ? WTERMSIG(p->w) : 0,
260
				p->cb_closure);
261
262
		free(p);
263
	}
264
}