2 * Copyright (c) 1997-1999 Erez Zadok
3 * Copyright (c) 1990 Jan-Simon Pendry
4 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
5 * Copyright (c) 1990 The Regents of the University of California.
8 * This code is derived from software contributed to Berkeley by
9 * Jan-Simon Pendry at Imperial College, London.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgment:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 * $Id: sched.c,v 1.3 1999/01/13 23:31:01 ezk Exp $
51 #endif /* HAVE_CONFIG_H */
56 typedef struct pjob pjob
;
59 qelem hdr
; /* Linked list */
60 int pid
; /* Process ID of job */
61 cb_fun cb_fun
; /* Callback function */
62 voidp cb_closure
; /* Closure for callback */
63 int w
; /* everyone these days uses int, not a "union wait" */
64 voidp wchan
; /* Wait channel */
68 qelem proc_list_head
= {&proc_list_head
, &proc_list_head
};
69 qelem proc_wait_list
= {&proc_wait_list
, &proc_wait_list
};
74 ins_que(qelem
*elem
, qelem
*pred
)
76 qelem
*p
= pred
->q_forw
;
88 qelem
*p
= elem
->q_forw
;
89 qelem
*p2
= elem
->q_back
;
97 sched_job(cb_fun cf
, voidp ca
)
99 pjob
*p
= ALLOC(struct pjob
);
105 * Now place on wait queue
107 ins_que(&p
->hdr
, &proc_wait_list
);
114 * tf: The task to execute (ta is its arguments)
115 * cf: Continuation function (ca is its arguments)
118 run_task(task_fun tf
, voidp ta
, cb_fun cf
, voidp ca
)
120 pjob
*p
= sched_job(cf
, ca
);
121 #ifdef HAVE_SIGACTION
123 #else /* not HAVE_SIGACTION */
125 #endif /* not HAVE_SIGACTION */
127 p
->wchan
= (voidp
) p
;
129 #ifdef HAVE_SIGACTION
130 sigemptyset(&new); /* initialize signal set we wish to block */
131 sigaddset(&new, SIGCHLD
); /* only block on SIGCHLD */
132 sigprocmask(SIG_BLOCK
, &new, &mask
);
133 #else /* not HAVE_SIGACTION */
134 mask
= sigblock(sigmask(SIGCHLD
));
135 #endif /* not HAVE_SIGACTION */
137 if ((p
->pid
= background())) {
138 #ifdef HAVE_SIGACTION
139 sigprocmask(SIG_SETMASK
, &mask
, NULL
);
140 #else /* not HAVE_SIGACTION */
142 #endif /* not HAVE_SIGACTION */
146 /* child code runs here, parent have returned to caller */
155 * Schedule a task to be run when woken up
158 sched_task(cb_fun cf
, voidp ca
, voidp wchan
)
161 * Allocate a new task
163 pjob
*p
= sched_job(cf
, ca
);
166 dlog("SLEEP on %#lx", (unsigned long) wchan
);
170 memset((voidp
) &p
->w
, 0, sizeof(p
->w
));
178 ins_que(&p
->hdr
, &proc_list_head
);
192 * Can't user ITER() here because
193 * wakeupjob() juggles the list.
195 for (p
= AM_FIRST(pjob
, &proc_wait_list
);
196 p2
= NEXT(pjob
, p
), p
!= HEAD(pjob
, &proc_wait_list
);
198 if (p
->wchan
== wchan
) {
206 wakeup_task(int rc
, int term
, voidp cl
)
213 * Run any pending tasks.
214 * This must be called with SIGCHLD disabled
220 * Keep taking the first item off the list and processing it.
222 * Done this way because the the callback can, quite reasonably,
223 * queue a new task, so no local reference into the list can be
226 while (AM_FIRST(pjob
, &proc_list_head
) != HEAD(pjob
, &proc_list_head
)) {
227 pjob
*p
= AM_FIRST(pjob
, &proc_list_head
);
230 * This job has completed
235 * Do callback if it exists
238 /* these two trigraphs will ensure compatibility with strict POSIX.1 */
239 (*p
->cb_fun
) (WIFEXITED(p
->w
) ? WEXITSTATUS(p
->w
) : 0,
240 WIFSIGNALED(p
->w
) ? WTERMSIG(p
->w
) : 0,
251 int w
; /* everyone these days uses int, not a "union wait" */
255 while ((pid
= waitpid((pid_t
) -1, &w
, WNOHANG
)) > 0) {
256 #else /* not HAVE_WAITPID */
257 while ((pid
= wait3( &w
, WNOHANG
, (struct rusage
*) 0)) > 0) {
258 #endif /* not HAVE_WAITPID */
262 plog(XLOG_ERROR
, "Process %d exited with signal %d",
266 dlog("Process %d exited with status %d",
267 pid
, WEXITSTATUS(w
));
270 for (p
= AM_FIRST(pjob
, &proc_wait_list
);
271 p2
= NEXT(pjob
, p
), p
!= HEAD(pjob
, &proc_wait_list
);
278 } /* end of for loop */
282 dlog("can't locate task block for pid %d", pid
);
286 * Must count down children inside the while loop, otherwise we won't
287 * count them all, and NumChild (and later backoff) will be set
288 * incorrectly. SH/RUNIT 940519.
292 } /* end of "while wait..." loop */
294 #ifdef REINSTALL_SIGNAL_HANDLER
295 signal(sig
, sigchld
);
296 #endif /* REINSTALL_SIGNAL_HANDLER */
298 if (select_intr_valid
)
299 longjmp(select_intr
, sig
);