4 * Copyright (c) 1997-2009 Erez Zadok
5 * Copyright (c) 1990 Jan-Simon Pendry
6 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
7 * Copyright (c) 1990 The Regents of the University of California.
10 * This code is derived from software contributed to Berkeley by
11 * Jan-Simon Pendry at Imperial College, London.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. All advertising materials mentioning features or use of this software
22 * must display the following acknowledgment:
23 * This product includes software developed by the University of
24 * California, Berkeley and its contributors.
25 * 4. Neither the name of the University nor the names of its contributors
26 * may be used to endorse or promote products derived from this software
27 * without specific prior written permission.
29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 * File: am-utils/amd/sched.c
52 #endif /* HAVE_CONFIG_H */
57 typedef struct pjob pjob
;
60 qelem hdr
; /* Linked list */
61 int pid
; /* Process ID of job */
62 cb_fun
*cb_fun
; /* Callback function */
63 opaque_t cb_arg
; /* Argument for callback */
64 int w
; /* everyone these days uses int, not a "union wait" */
65 wchan_t wchan
; /* Wait channel */
69 qelem proc_list_head
= {&proc_list_head
, &proc_list_head
};
70 qelem proc_wait_list
= {&proc_wait_list
, &proc_wait_list
};
75 ins_que(qelem
*elem
, qelem
*pred
)
77 qelem
*p
= pred
->q_forw
;
89 qelem
*p
= elem
->q_forw
;
90 qelem
*p2
= elem
->q_back
;
98 sched_job(cb_fun
*cf
, opaque_t ca
)
100 pjob
*p
= ALLOC(struct pjob
);
106 * Now place on wait queue
108 ins_que(&p
->hdr
, &proc_wait_list
);
115 * tf: The task to execute (ta is its arguments)
116 * cf: Continuation function (ca is its arguments)
119 run_task(task_fun
*tf
, opaque_t ta
, cb_fun
*cf
, opaque_t ca
)
121 pjob
*p
= sched_job(cf
, ca
);
122 #ifdef HAVE_SIGACTION
124 #else /* not HAVE_SIGACTION */
126 #endif /* not HAVE_SIGACTION */
128 p
->wchan
= (wchan_t
) p
;
130 #ifdef HAVE_SIGACTION
131 sigemptyset(&new); /* initialize signal set we wish to block */
132 sigaddset(&new, SIGCHLD
); /* only block on SIGCHLD */
133 sigprocmask(SIG_BLOCK
, &new, &mask
);
134 #else /* not HAVE_SIGACTION */
135 mask
= sigblock(sigmask(SIGCHLD
));
136 #endif /* not HAVE_SIGACTION */
138 if ((p
->pid
= background())) {
139 #ifdef HAVE_SIGACTION
140 sigprocmask(SIG_SETMASK
, &mask
, NULL
);
141 #else /* not HAVE_SIGACTION */
143 #endif /* not HAVE_SIGACTION */
147 /* child code runs here, parent has returned to caller */
156 * Schedule a task to be run when woken up
159 sched_task(cb_fun
*cf
, opaque_t ca
, wchan_t wchan
)
162 * Allocate a new task
164 pjob
*p
= sched_job(cf
, ca
);
166 dlog("SLEEP on %p", wchan
);
169 p
->w
= 0; /* was memset (when ->w was union) */
177 ins_que(&p
->hdr
, &proc_list_head
);
183 wakeup(wchan_t wchan
)
191 * Can't use ITER() here because
192 * wakeupjob() juggles the list.
194 for (p
= AM_FIRST(pjob
, &proc_wait_list
);
195 p2
= NEXT(pjob
, p
), p
!= HEAD(pjob
, &proc_wait_list
);
197 if (p
->wchan
== wchan
) {
205 wakeup_task(int rc
, int term
, wchan_t wchan
)
212 get_mntfs_wchan(mntfs
*mf
)
216 mf
->mf_ops
->get_wchan
)
217 return mf
->mf_ops
->get_wchan(mf
);
223 * Run any pending tasks.
224 * This must be called with SIGCHLD disabled
230 * Keep taking the first item off the list and processing it.
232 * Done this way because the callback can, quite reasonably,
233 * queue a new task, so no local reference into the list can be
236 while (AM_FIRST(pjob
, &proc_list_head
) != HEAD(pjob
, &proc_list_head
)) {
237 pjob
*p
= AM_FIRST(pjob
, &proc_list_head
);
240 * This job has completed
245 * Do callback if it exists
248 /* these two trigraphs will ensure compatibility with strict POSIX.1 */
249 p
->cb_fun(WIFEXITED(p
->w
) ? WEXITSTATUS(p
->w
) : 0,
250 WIFSIGNALED(p
->w
) ? WTERMSIG(p
->w
) : 0,
261 int w
; /* everyone these days uses int, not a "union wait" */
265 while ((pid
= waitpid((pid_t
) -1, &w
, WNOHANG
)) > 0) {
266 #else /* not HAVE_WAITPID */
267 while ((pid
= wait3( &w
, WNOHANG
, (struct rusage
*) NULL
)) > 0) {
268 #endif /* not HAVE_WAITPID */
272 plog(XLOG_ERROR
, "Process %d exited with signal %d",
275 dlog("Process %d exited with status %d",
276 pid
, WEXITSTATUS(w
));
278 for (p
= AM_FIRST(pjob
, &proc_wait_list
);
279 p2
= NEXT(pjob
, p
), p
!= HEAD(pjob
, &proc_wait_list
);
286 } /* end of for loop */
288 if (p
== HEAD(pjob
, &proc_wait_list
))
289 dlog("can't locate task block for pid %d", pid
);
292 * Must count down children inside the while loop, otherwise we won't
293 * count them all, and NumChildren (and later backoff) will be set
294 * incorrectly. SH/RUNIT 940519.
296 if (--NumChildren
< 0)
298 } /* end of "while wait..." loop */
300 #ifdef REINSTALL_SIGNAL_HANDLER
301 signal(sig
, sigchld
);
302 #endif /* REINSTALL_SIGNAL_HANDLER */
304 if (select_intr_valid
)
305 longjmp(select_intr
, sig
);