diff options
-rw-r--r-- | share/man/man9/at_exit.9 | 4 | ||||
-rw-r--r-- | share/man/man9/at_fork.9 | 4 | ||||
-rw-r--r-- | sys/kern/kern_exit.c | 57 | ||||
-rw-r--r-- | sys/kern/kern_fork.c | 58 |
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); } |