2 * Copyright (c) 1997-2006 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
40 * File: am-utils/amd/sched.c
50 #endif /* HAVE_CONFIG_H */
55 typedef struct pjob pjob;
58 qelem hdr; /* Linked list */
59 int pid; /* Process ID of job */
60 cb_fun *cb_fun; /* Callback function */
61 opaque_t cb_arg; /* Argument for callback */
62 int w; /* everyone these days uses int, not a "union wait" */
63 wchan_t wchan; /* Wait channel */
67 qelem proc_list_head = {&proc_list_head, &proc_list_head};
68 qelem proc_wait_list = {&proc_wait_list, &proc_wait_list};
73 ins_que(qelem *elem, qelem *pred)
75 qelem *p = pred->q_forw;
87 qelem *p = elem->q_forw;
88 qelem *p2 = elem->q_back;
96 sched_job(cb_fun *cf, opaque_t ca)
98 pjob *p = ALLOC(struct pjob);
104 * Now place on wait queue
106 ins_que(&p->hdr, &proc_wait_list);
113 * tf: The task to execute (ta is its arguments)
114 * cf: Continuation function (ca is its arguments)
117 run_task(task_fun *tf, opaque_t ta, cb_fun *cf, opaque_t ca)
119 pjob *p = sched_job(cf, ca);
120 #ifdef HAVE_SIGACTION
122 #else /* not HAVE_SIGACTION */
124 #endif /* not HAVE_SIGACTION */
126 p->wchan = (wchan_t) p;
128 #ifdef HAVE_SIGACTION
129 sigemptyset(&new); /* initialize signal set we wish to block */
130 sigaddset(&new, SIGCHLD); /* only block on SIGCHLD */
131 sigprocmask(SIG_BLOCK, &new, &mask);
132 #else /* not HAVE_SIGACTION */
133 mask = sigblock(sigmask(SIGCHLD));
134 #endif /* not HAVE_SIGACTION */
136 if ((p->pid = background())) {
137 #ifdef HAVE_SIGACTION
138 sigprocmask(SIG_SETMASK, &mask, NULL);
139 #else /* not HAVE_SIGACTION */
141 #endif /* not HAVE_SIGACTION */
145 /* child code runs here, parent has returned to caller */
154 * Schedule a task to be run when woken up
157 sched_task(cb_fun *cf, opaque_t ca, wchan_t wchan)
160 * Allocate a new task
162 pjob *p = sched_job(cf, ca);
164 dlog("SLEEP on %p", wchan);
167 p->w = 0; /* was memset (when ->w was union) */
175 ins_que(&p->hdr, &proc_list_head);
181 wakeup(wchan_t wchan)
189 * Can't use ITER() here because
190 * wakeupjob() juggles the list.
192 for (p = AM_FIRST(pjob, &proc_wait_list);
193 p2 = NEXT(pjob, p), p != HEAD(pjob, &proc_wait_list);
195 if (p->wchan == wchan) {
203 wakeup_task(int rc, int term, wchan_t wchan)
210 get_mntfs_wchan(mntfs *mf)
214 mf->mf_ops->get_wchan)
215 return mf->mf_ops->get_wchan(mf);
221 * Run any pending tasks.
222 * This must be called with SIGCHLD disabled
228 * Keep taking the first item off the list and processing it.
230 * Done this way because the callback can, quite reasonably,
231 * queue a new task, so no local reference into the list can be
234 while (AM_FIRST(pjob, &proc_list_head) != HEAD(pjob, &proc_list_head)) {
235 pjob *p = AM_FIRST(pjob, &proc_list_head);
238 * This job has completed
243 * Do callback if it exists
246 /* these two trigraphs will ensure compatibility with strict POSIX.1 */
247 p->cb_fun(WIFEXITED(p->w) ? WEXITSTATUS(p->w) : 0,
248 WIFSIGNALED(p->w) ? WTERMSIG(p->w) : 0,
259 int w; /* everyone these days uses int, not a "union wait" */
263 while ((pid = waitpid((pid_t) -1, &w, WNOHANG)) > 0) {
264 #else /* not HAVE_WAITPID */
265 while ((pid = wait3( &w, WNOHANG, (struct rusage *) 0)) > 0) {
266 #endif /* not HAVE_WAITPID */
270 plog(XLOG_ERROR, "Process %d exited with signal %d",
273 dlog("Process %d exited with status %d",
274 pid, WEXITSTATUS(w));
276 for (p = AM_FIRST(pjob, &proc_wait_list);
277 p2 = NEXT(pjob, p), p != HEAD(pjob, &proc_wait_list);
284 } /* end of for loop */
286 if (p == HEAD(pjob, &proc_wait_list))
287 dlog("can't locate task block for pid %d", pid);
290 * Must count down children inside the while loop, otherwise we won't
291 * count them all, and NumChildren (and later backoff) will be set
292 * incorrectly. SH/RUNIT 940519.
294 if (--NumChildren < 0)
296 } /* end of "while wait..." loop */
298 #ifdef REINSTALL_SIGNAL_HANDLER
299 signal(sig, sigchld);
300 #endif /* REINSTALL_SIGNAL_HANDLER */
302 if (select_intr_valid)
303 longjmp(select_intr, sig);