xref: /original-bsd/usr.sbin/amd/amd/sched.c (revision 4092c5cc)
1398a5aebSmckusick /*
2398a5aebSmckusick  * Copyright (c) 1990 Jan-Simon Pendry
3398a5aebSmckusick  * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
4*4092c5ccSbostic  * Copyright (c) 1990, 1993
5*4092c5ccSbostic  *	The Regents of the University of California.  All rights reserved.
6398a5aebSmckusick  *
7398a5aebSmckusick  * This code is derived from software contributed to Berkeley by
8398a5aebSmckusick  * Jan-Simon Pendry at Imperial College, London.
9398a5aebSmckusick  *
10398a5aebSmckusick  * %sccs.include.redist.c%
11398a5aebSmckusick  *
12*4092c5ccSbostic  *	@(#)sched.c	8.1 (Berkeley) 06/06/93
13c626267eSpendry  *
14cc0207dcSpendry  * $Id: sched.c,v 5.2.2.1 1992/02/09 15:09:02 jsp beta $
15c626267eSpendry  *
16398a5aebSmckusick  */
17398a5aebSmckusick 
18398a5aebSmckusick /*
19398a5aebSmckusick  * Process scheduler
20398a5aebSmckusick  */
21398a5aebSmckusick 
22398a5aebSmckusick #include "am.h"
23398a5aebSmckusick #include <sys/signal.h>
24398a5aebSmckusick #include WAIT
25398a5aebSmckusick #include <setjmp.h>
26398a5aebSmckusick extern jmp_buf select_intr;
27398a5aebSmckusick extern int select_intr_valid;
28398a5aebSmckusick 
29398a5aebSmckusick typedef struct pjob pjob;
30398a5aebSmckusick struct pjob {
31398a5aebSmckusick 	qelem hdr;			/* Linked list */
32398a5aebSmckusick 	int pid;			/* Process ID of job */
33398a5aebSmckusick 	cb_fun cb_fun;			/* Callback function */
34398a5aebSmckusick 	voidp cb_closure;		/* Closure for callback */
35398a5aebSmckusick 	union wait w;			/* Status filled in by sigchld */
36398a5aebSmckusick 	voidp wchan;			/* Wait channel */
37398a5aebSmckusick };
38398a5aebSmckusick 
39398a5aebSmckusick extern qelem proc_list_head;
40398a5aebSmckusick qelem proc_list_head = { &proc_list_head, &proc_list_head };
41398a5aebSmckusick extern qelem proc_wait_list;
42398a5aebSmckusick qelem proc_wait_list = { &proc_wait_list, &proc_wait_list };
43398a5aebSmckusick 
44398a5aebSmckusick int task_notify_todo;
45398a5aebSmckusick 
ins_que(elem,pred)46398a5aebSmckusick void ins_que(elem, pred)
47398a5aebSmckusick qelem *elem, *pred;
48398a5aebSmckusick {
49398a5aebSmckusick 	qelem *p = pred->q_forw;
50398a5aebSmckusick 	elem->q_back = pred;
51398a5aebSmckusick 	elem->q_forw = p;
52398a5aebSmckusick 	pred->q_forw = elem;
53398a5aebSmckusick 	p->q_back = elem;
54398a5aebSmckusick }
55398a5aebSmckusick 
rem_que(elem)56398a5aebSmckusick void rem_que(elem)
57398a5aebSmckusick qelem *elem;
58398a5aebSmckusick {
59398a5aebSmckusick 	qelem *p = elem->q_forw;
60398a5aebSmckusick 	qelem *p2 = elem->q_back;
61398a5aebSmckusick 	p2->q_forw = p;
62398a5aebSmckusick 	p->q_back = p2;
63398a5aebSmckusick }
64398a5aebSmckusick 
sched_job(cf,ca)65398a5aebSmckusick static pjob *sched_job(cf, ca)
66398a5aebSmckusick cb_fun cf;
67398a5aebSmckusick voidp ca;
68398a5aebSmckusick {
69398a5aebSmckusick 	pjob *p = ALLOC(pjob);
70398a5aebSmckusick 
71398a5aebSmckusick 	p->cb_fun = cf;
72398a5aebSmckusick 	p->cb_closure = ca;
73398a5aebSmckusick 
74398a5aebSmckusick 	/*
75398a5aebSmckusick 	 * Now place on wait queue
76398a5aebSmckusick 	 */
77398a5aebSmckusick 	ins_que(&p->hdr, &proc_wait_list);
78398a5aebSmckusick 
79398a5aebSmckusick 	return p;
80398a5aebSmckusick }
81398a5aebSmckusick 
run_task(tf,ta,cf,ca)82398a5aebSmckusick void run_task(tf, ta, cf, ca)
83398a5aebSmckusick task_fun tf;
84398a5aebSmckusick voidp ta;
85398a5aebSmckusick cb_fun cf;
86398a5aebSmckusick voidp ca;
87398a5aebSmckusick {
88398a5aebSmckusick 	pjob *p = sched_job(cf, ca);
89398a5aebSmckusick 	int mask;
90398a5aebSmckusick 
91398a5aebSmckusick 	p->wchan = (voidp) p;
92398a5aebSmckusick 
93398a5aebSmckusick 	mask = sigblock(sigmask(SIGCHLD));
94398a5aebSmckusick 
95398a5aebSmckusick 	if (p->pid = background()) {
96398a5aebSmckusick 		sigsetmask(mask);
97398a5aebSmckusick 		return;
98398a5aebSmckusick 	}
99398a5aebSmckusick 
100398a5aebSmckusick 	exit((*tf)(ta));
101398a5aebSmckusick 	/* firewall... */
102398a5aebSmckusick 	abort();
103398a5aebSmckusick }
104398a5aebSmckusick 
105398a5aebSmckusick /*
106398a5aebSmckusick  * Schedule a task to be run when woken up
107398a5aebSmckusick  */
sched_task(cf,ca,wchan)108398a5aebSmckusick void sched_task(cf, ca, wchan)
109398a5aebSmckusick cb_fun cf;
110398a5aebSmckusick voidp ca;
111398a5aebSmckusick voidp wchan;
112398a5aebSmckusick {
113398a5aebSmckusick 	/*
114398a5aebSmckusick 	 * Allocate a new task
115398a5aebSmckusick 	 */
116398a5aebSmckusick 	pjob *p = sched_job(cf, ca);
117c626267eSpendry #ifdef DEBUG_SLEEP
118c626267eSpendry 	dlog("SLEEP on %#x", wchan);
119c626267eSpendry #endif
120398a5aebSmckusick 	p->wchan = wchan;
121398a5aebSmckusick 	p->pid = 0;
122398a5aebSmckusick 	bzero((voidp) &p->w, sizeof(p->w));
123398a5aebSmckusick }
124398a5aebSmckusick 
wakeupjob(p)125398a5aebSmckusick static void wakeupjob(p)
126398a5aebSmckusick pjob *p;
127398a5aebSmckusick {
128398a5aebSmckusick 	rem_que(&p->hdr);
129398a5aebSmckusick 	ins_que(&p->hdr, &proc_list_head);
130398a5aebSmckusick 	task_notify_todo++;
131398a5aebSmckusick }
132398a5aebSmckusick 
wakeup(wchan)133398a5aebSmckusick void wakeup(wchan)
134398a5aebSmckusick voidp wchan;
135398a5aebSmckusick {
136398a5aebSmckusick 	pjob *p, *p2;
137c626267eSpendry #ifdef DEBUG_SLEEP
138c626267eSpendry 	int done = 0;
139c626267eSpendry #endif
140398a5aebSmckusick 	if (!foreground)
141398a5aebSmckusick 		return;
142398a5aebSmckusick 
143c626267eSpendry #ifdef DEBUG_SLEEP
144398a5aebSmckusick 	/*dlog("wakeup(%#x)", wchan);*/
145c626267eSpendry #endif
146398a5aebSmckusick 	/*
147398a5aebSmckusick 	 * Can't user ITER() here because
148398a5aebSmckusick 	 * wakeupjob() juggles the list.
149398a5aebSmckusick 	 */
150398a5aebSmckusick 	for (p = FIRST(pjob, &proc_wait_list);
151398a5aebSmckusick 			p2 = NEXT(pjob, p), p != HEAD(pjob, &proc_wait_list);
152398a5aebSmckusick 			p = p2) {
153c626267eSpendry 		if (p->wchan == wchan) {
154c626267eSpendry #ifdef DEBUG_SLEEP
155c626267eSpendry 			done = 1;
156c626267eSpendry #endif
157398a5aebSmckusick 			wakeupjob(p);
158398a5aebSmckusick 		}
159398a5aebSmckusick 	}
160398a5aebSmckusick 
161c626267eSpendry #ifdef DEBUG_SLEEP
162c626267eSpendry 	if (!done)
163c626267eSpendry 		dlog("Nothing SLEEPing on %#x", wchan);
164c626267eSpendry #endif
165c626267eSpendry }
166c626267eSpendry 
wakeup_task(rc,term,cl)167398a5aebSmckusick void wakeup_task(rc, term, cl)
168398a5aebSmckusick int rc;
169398a5aebSmckusick int term;
170398a5aebSmckusick voidp cl;
171398a5aebSmckusick {
172398a5aebSmckusick 	wakeup(cl);
173398a5aebSmckusick }
174398a5aebSmckusick 
175398a5aebSmckusick /*ARGSUSED*/
176398a5aebSmckusick 
sigchld(sig)177398a5aebSmckusick void sigchld(sig)
178398a5aebSmckusick int sig;
179398a5aebSmckusick {
180398a5aebSmckusick 	union wait w;
181398a5aebSmckusick 	int pid;
182398a5aebSmckusick 
183398a5aebSmckusick #ifdef SYS5_SIGNALS
184398a5aebSmckusick 	if ((pid = wait(&w)) > 0) {
185398a5aebSmckusick #else
1868a89c22cSpendry 	while ((pid = wait3((int *) &w, WNOHANG, (struct rusage *) 0)) > 0) {
187398a5aebSmckusick #endif /* SYS5_SIGNALS */
188398a5aebSmckusick 		pjob *p, *p2;
189398a5aebSmckusick 
190398a5aebSmckusick 		if (WIFSIGNALED(w))
191398a5aebSmckusick 			plog(XLOG_ERROR, "Process %d exited with signal %d",
192398a5aebSmckusick 				pid, w.w_termsig);
193398a5aebSmckusick #ifdef DEBUG
194398a5aebSmckusick 		else
195398a5aebSmckusick 			dlog("Process %d exited with status %d",
196398a5aebSmckusick 				pid, w.w_retcode);
197398a5aebSmckusick #endif /* DEBUG */
198398a5aebSmckusick 
199398a5aebSmckusick 		for (p = FIRST(pjob, &proc_wait_list);
200398a5aebSmckusick 				p2 = NEXT(pjob, p), p != HEAD(pjob, &proc_wait_list);
201398a5aebSmckusick 				p = p2) {
202398a5aebSmckusick 			if (p->pid == pid) {
203398a5aebSmckusick 				p->w = w;
204398a5aebSmckusick 				wakeupjob(p);
205398a5aebSmckusick 				break;
206398a5aebSmckusick 			}
207398a5aebSmckusick 		}
208398a5aebSmckusick 
209398a5aebSmckusick #ifdef DEBUG
210398a5aebSmckusick 		if (p) ; else dlog("can't locate task block for pid %d", pid);
211398a5aebSmckusick #endif /* DEBUG */
212398a5aebSmckusick 	}
213398a5aebSmckusick 
214398a5aebSmckusick #ifdef SYS5_SIGNALS
215398a5aebSmckusick 	signal(sig, sigchld);
216398a5aebSmckusick #endif /* SYS5_SIGNALS */
217398a5aebSmckusick 	if (select_intr_valid)
2188a89c22cSpendry 		longjmp(select_intr, sig);
219398a5aebSmckusick }
220398a5aebSmckusick 
221398a5aebSmckusick /*
222398a5aebSmckusick  * Run any pending tasks.
223398a5aebSmckusick  * This must be called with SIGCHLD disabled
224398a5aebSmckusick  */
do_task_notify(P_void)2258a89c22cSpendry void do_task_notify(P_void)
226398a5aebSmckusick {
227398a5aebSmckusick 	/*
228398a5aebSmckusick 	 * Keep taking the first item off the list and processing it.
229398a5aebSmckusick 	 *
230398a5aebSmckusick 	 * Done this way because the the callback can, quite reasonably,
231398a5aebSmckusick 	 * queue a new task, so no local reference into the list can be
232398a5aebSmckusick 	 * held here.
233398a5aebSmckusick 	 */
234398a5aebSmckusick 	while (FIRST(pjob, &proc_list_head) != HEAD(pjob, &proc_list_head)) {
235398a5aebSmckusick 		pjob *p = FIRST(pjob, &proc_list_head);
236398a5aebSmckusick 		rem_que(&p->hdr);
237398a5aebSmckusick 		/*
238398a5aebSmckusick 		 * This job has completed
239398a5aebSmckusick 		 */
240398a5aebSmckusick 		--task_notify_todo;
241398a5aebSmckusick 
242398a5aebSmckusick 		/*
243398a5aebSmckusick 		 * Do callback if it exists
244398a5aebSmckusick 		 */
245398a5aebSmckusick 		if (p->cb_fun)
246398a5aebSmckusick 			(*p->cb_fun)(p->w.w_retcode,
247398a5aebSmckusick 				p->w.w_termsig, p->cb_closure);
248398a5aebSmckusick 
2498a89c22cSpendry 		free((voidp) p);
250398a5aebSmckusick 	}
251398a5aebSmckusick }
252cc0207dcSpendry 
253cc0207dcSpendry #ifdef HAS_SVR3_SIGNALS
254cc0207dcSpendry /*
255cc0207dcSpendry  * 4.2 signal library based on svr3 (4.1+ bsd) interface
256cc0207dcSpendry  * From Stephen C. Pope <scp@acl.lanl.gov).
257cc0207dcSpendry  */
258cc0207dcSpendry 
259cc0207dcSpendry static int current_mask = 0;
260cc0207dcSpendry 
sigblock(mask)261cc0207dcSpendry int sigblock(mask)
262cc0207dcSpendry int mask;
263cc0207dcSpendry {
264cc0207dcSpendry     int sig;
265cc0207dcSpendry     int m;
266cc0207dcSpendry     int oldmask;
267cc0207dcSpendry 
268cc0207dcSpendry     oldmask = current_mask;
269cc0207dcSpendry     for ( sig = 1, m = 1; sig <= MAXSIG; sig++, m <<= 1 ) {
270cc0207dcSpendry         if (mask & m)  {
271cc0207dcSpendry 	    sighold(sig);
272cc0207dcSpendry             current_mask |= m;
273cc0207dcSpendry         }
274cc0207dcSpendry     }
275cc0207dcSpendry     return oldmask;
276cc0207dcSpendry }
277cc0207dcSpendry 
sigsetmask(mask)278cc0207dcSpendry int sigsetmask(mask)
279cc0207dcSpendry int mask;
280cc0207dcSpendry {
281cc0207dcSpendry     int sig;
282cc0207dcSpendry     int m;
283cc0207dcSpendry     int oldmask;
284cc0207dcSpendry 
285cc0207dcSpendry     oldmask = current_mask;
286cc0207dcSpendry     for ( sig = 1, m = 1; sig <= MAXSIG; sig++, m <<= 1 ) {
287cc0207dcSpendry         if (mask & m)  {
288cc0207dcSpendry             sighold(sig);
289cc0207dcSpendry             current_mask |= m;
290cc0207dcSpendry         }
291cc0207dcSpendry         else  {
292cc0207dcSpendry             sigrelse(sig);
293cc0207dcSpendry             current_mask &= ~m;
294cc0207dcSpendry         }
295cc0207dcSpendry     }
296cc0207dcSpendry     return oldmask;
297cc0207dcSpendry }
298cc0207dcSpendry 
299cc0207dcSpendry #endif /* HAS_SVR3_SIGNALS */
300