summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/man/man9/at_exit.94
-rw-r--r--share/man/man9/at_fork.94
-rw-r--r--sys/kern/kern_exit.c57
-rw-r--r--sys/kern/kern_fork.c58
4 files changed, 54 insertions, 69 deletions
diff --git a/share/man/man9/at_exit.9 b/share/man/man9/at_exit.9
index 352e6b2..234ef45 100644
--- a/share/man/man9/at_exit.9
+++ b/share/man/man9/at_exit.9
@@ -70,10 +70,6 @@ The
.Fn at_exit
function appeared in
.Fx 2.2 .
-.Sh BUGS
-Since the exit queue is not sorted
-and items are added to the head, order of execution
-is reversed to that of insertion.
.Sh AUTHORS
The function was written by
.An Julian Elischer Aq julian@FreeBSD.org .
diff --git a/share/man/man9/at_fork.9 b/share/man/man9/at_fork.9
index 369bc54..f9ea282 100644
--- a/share/man/man9/at_fork.9
+++ b/share/man/man9/at_fork.9
@@ -72,10 +72,6 @@ The
.Fn at_fork
function appeared in
.Fx 2.2 .
-.Sh BUGS
-Since the fork queue is not sorted
-and items are added to the head, order of execution
-is reversed to that of insertion.
.Sh AUTHORS
The function was written by
.An Julian Elischer Aq julian@FreeBSD.org .
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 6c00e43..abbe9de 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -75,17 +75,20 @@
/* Required to be non-static for SysVR4 emulator */
MALLOC_DEFINE(M_ZOMBIE, "zombie", "zombie proc status");
+static MALLOC_DEFINE(M_ATEXIT, "atexit", "atexit callback");
+
static int wait1 __P((struct proc *, struct wait_args *, int));
/*
* callout list for things to do at exit time
*/
-typedef struct exit_list_element {
- struct exit_list_element *next;
+struct exitlist {
exitlist_fn function;
-} *ele_p;
+ TAILQ_ENTRY(exitlist) next;
+};
-static ele_p exit_list;
+TAILQ_HEAD(exit_list_head, exitlist);
+static struct exit_list_head exit_list = TAILQ_HEAD_INITIALIZER(exit_list);
/*
* exit --
@@ -115,7 +118,7 @@ exit1(p, rv)
{
register struct proc *q, *nq;
register struct vmspace *vm;
- ele_p ep = exit_list;
+ struct exitlist *ep;
if (p->p_pid == 1) {
printf("init died (signal %d, exit %d)\n",
@@ -154,10 +157,8 @@ exit1(p, rv)
* e.g. SYSV IPC stuff
* XXX what if one of these generates an error?
*/
- while (ep) {
+ TAILQ_FOREACH(ep, &exit_list, next)
(*ep->function)(p);
- ep = ep->next;
- }
if (p->p_flag & P_PROFIL)
stopprofclock(p);
@@ -580,49 +581,45 @@ proc_reparent(child, parent)
* However first make sure that it's not already there.
* returns 0 on success.
*/
+
int
at_exit(function)
exitlist_fn function;
{
- ele_p ep;
+ struct exitlist *ep;
+#ifdef INVARIANTS
/* Be noisy if the programmer has lost track of things */
if (rm_at_exit(function))
- printf("exit callout entry already present\n");
- ep = malloc(sizeof(*ep), M_TEMP, M_NOWAIT);
+ printf("WARNING: exit callout entry (%p) already present\n",
+ function);
+#endif
+ ep = malloc(sizeof(*ep), M_ATEXIT, M_NOWAIT);
if (ep == NULL)
return (ENOMEM);
- ep->next = exit_list;
ep->function = function;
- exit_list = ep;
+ TAILQ_INSERT_TAIL(&exit_list, ep, next);
return (0);
}
+
/*
- * Scan the exit callout list for the given items and remove them.
- * Returns the number of items removed.
- * Logically this can only be 0 or 1.
+ * Scan the exit callout list for the given item and remove it.
+ * Returns the number of items removed (0 or 1)
*/
int
rm_at_exit(function)
exitlist_fn function;
{
- ele_p *epp, ep;
- int count;
+ struct exitlist *ep;
- count = 0;
- epp = &exit_list;
- ep = *epp;
- while (ep) {
+ TAILQ_FOREACH(ep, &exit_list, next) {
if (ep->function == function) {
- *epp = ep->next;
- free(ep, M_TEMP);
- count++;
- } else {
- epp = &ep->next;
+ TAILQ_REMOVE(&exit_list, ep, next);
+ free(ep, M_ATEXIT);
+ return(1);
}
- ep = *epp;
- }
- return (count);
+ }
+ return (0);
}
void check_sigacts (void)
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 9268592..c12c965 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -65,6 +65,8 @@
#include <sys/user.h>
+static MALLOC_DEFINE(M_ATFORK, "atfork", "atfork callback");
+
static int fast_vfork = 1;
SYSCTL_INT(_kern, OID_AUTO, fast_vfork, CTLFLAG_RW, &fast_vfork, 0, "");
@@ -72,12 +74,13 @@ SYSCTL_INT(_kern, OID_AUTO, fast_vfork, CTLFLAG_RW, &fast_vfork, 0, "");
* These are the stuctures used to create a callout list for things to do
* when forking a process
*/
-typedef struct fork_list_element {
- struct fork_list_element *next;
+struct forklist {
forklist_fn function;
-} *fle_p;
+ TAILQ_ENTRY(forklist) next;
+};
-static fle_p fork_list;
+TAILQ_HEAD(forklist_head, forklist);
+static struct forklist_head fork_list = TAILQ_HEAD_INITIALIZER(fork_list);
#ifndef _SYS_SYSPROTO_H_
struct fork_args {
@@ -150,9 +153,7 @@ fork1(p1, flags, procp)
struct proc *newproc;
int count;
static int pidchecked = 0;
- fle_p ep ;
-
- ep = fork_list;
+ struct forklist *ep;
if ((flags & (RFFDG|RFCFDG)) == (RFFDG|RFCFDG))
return (EINVAL);
@@ -461,9 +462,8 @@ again:
* to adjust anything.
* What if they have an error? XXX
*/
- while (ep) {
+ TAILQ_FOREACH(ep, &fork_list, next) {
(*ep->function)(p1, p2, flags);
- ep = ep->next;
}
/*
@@ -505,48 +505,44 @@ again:
* However first make sure that it's not already there.
* Returns 0 on success or a standard error number.
*/
+
int
at_fork(function)
forklist_fn function;
{
- fle_p ep;
+ struct forklist *ep;
+#ifdef INVARIANTS
/* let the programmer know if he's been stupid */
if (rm_at_fork(function))
- printf("fork callout entry already present\n");
- ep = malloc(sizeof(*ep), M_TEMP, M_NOWAIT);
+ printf("WARNING: fork callout entry (%p) already present\n",
+ function);
+#endif
+ ep = malloc(sizeof(*ep), M_ATFORK, M_NOWAIT);
if (ep == NULL)
return (ENOMEM);
- ep->next = fork_list;
ep->function = function;
- fork_list = ep;
+ TAILQ_INSERT_TAIL(&fork_list, ep, next);
return (0);
}
/*
- * Scan the exit callout list for the given items and remove them.
- * Returns the number of items removed.
- * Theoretically this value can only be 0 or 1.
+ * Scan the exit callout list for the given item and remove it..
+ * Returns the number of items removed (0 or 1)
*/
+
int
rm_at_fork(function)
forklist_fn function;
{
- fle_p *epp, ep;
- int count;
+ struct forklist *ep;
- count= 0;
- epp = &fork_list;
- ep = *epp;
- while (ep) {
+ TAILQ_FOREACH(ep, &fork_list, next) {
if (ep->function == function) {
- *epp = ep->next;
- free(ep, M_TEMP);
- count++;
- } else {
- epp = &ep->next;
+ TAILQ_REMOVE(&fork_list, ep, next);
+ free(ep, M_ATFORK);
+ return(1);
}
- ep = *epp;
- }
- return (count);
+ }
+ return (0);
}
OpenPOWER on IntegriCloud