Date: Fri, 27 Feb 1998 02:47:29 -0500 (EST) From: walter@fortean.com To: FreeBSD-gnats-submit@FreeBSD.ORG Subject: kern/5863: Kernel support for sorted SHUTDOWN : SHUTDOWN_POWEROFF queues Message-ID: <199802270747.CAA24164@callisto.fortean.com>
next in thread | raw e-mail | index | archive | help
>Number: 5863 >Category: kern >Synopsis: Kernel support for sorted SHUTDOWN & SHUTDOWN_POWEROFF queues >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Thu Feb 26 23:50:00 PST 1998 >Last-Modified: >Originator: Bruce M. Walter >Organization: Fortean Technologies, Inc >Release: FreeBSD 2.2-STABLE i386 >Environment: FreeBSD 2.2-STABLE >Description: The attached patches add support for a SHUTDOWN_POWEROFF queue which is run after the SHUTDOWN_POST_SYNC queue. This provides a safe place for callouts which want to poweroff the system by whatever means they have available (UPS and APM would be logical consumers). The patches also implement ordering all three SHUTDOWN_* queues. An patch for the at_shutdown.9 man page is also included. These patches have been tested locally for some time, and are also under review by Mike Smith. >How-To-Repeat: N/A >Fix: *** sys/kern/kern_shutdown.c.orig Sun Aug 10 22:04:14 1997 --- sys/kern/kern_shutdown.c Wed Feb 11 01:56:25 1998 *************** *** 110,115 **** --- 110,116 ---- struct shutdown_list_element *next; bootlist_fn function; void *arg; + int priority; } *sle_p; /* *************** *** 118,123 **** --- 119,125 ---- */ static sle_p shutdown_list1; static sle_p shutdown_list2; + static sle_p shutdown_list3; static void dumpsys(void); *************** *** 248,253 **** --- 250,266 ---- ep = ep->next; } splhigh(); + + /* + * Ok, now do any last things we need to before cpu death + */ + ep = shutdown_list3; + while (ep) { + shutdown_list3 = ep->next; + (*ep->function)(howto, ep->arg); + ep = ep->next; + } + if (howto & RB_HALT) { printf("\n"); printf("The operating system has halted.\n"); *************** *** 391,397 **** } /* ! * Two routines to handle adding/deleting items on the * shutdown callout lists * * at_shutdown(): --- 404,410 ---- } /* ! * Three routines to handle adding/deleting items on the * shutdown callout lists * * at_shutdown(): *************** *** 402,408 **** int at_shutdown(bootlist_fn function, void *arg, int position) { ! sle_p ep, *epp; switch(position) { case SHUTDOWN_PRE_SYNC: --- 415,436 ---- int at_shutdown(bootlist_fn function, void *arg, int position) { ! return (at_shutdown_pri(function,arg,position,SHUTDOWN_PRI_DEFAULT)); ! } ! ! /* ! * Three routines to handle adding/deleting items on the ! * shutdown callout lists ! * ! * at_shutdown_pri(): ! * Take the arguments given and put them onto the shutdown callout list with ! * the given execution priority. ! * returns 0 on success. ! */ ! int ! at_shutdown_pri(bootlist_fn function, void *arg, int position, int priority) ! { ! sle_p ep, ip, lp, *epp; switch(position) { case SHUTDOWN_PRE_SYNC: *************** *** 411,429 **** case SHUTDOWN_POST_SYNC: epp = &shutdown_list2; break; default: printf("bad exit callout list specified\n"); return (EINVAL); } if (rm_at_shutdown(function, arg)) printf("exit callout entry already present\n"); ep = malloc(sizeof(*ep), M_TEMP, M_NOWAIT); if (ep == NULL) return (ENOMEM); - ep->next = *epp; ep->function = function; ep->arg = arg; ! *epp = ep; return (0); } --- 439,482 ---- case SHUTDOWN_POST_SYNC: epp = &shutdown_list2; break; + case SHUTDOWN_POWEROFF: + epp = &shutdown_list3; + break; default: printf("bad exit callout list specified\n"); return (EINVAL); } + if ((priority < SHUTDOWN_PRI_MAX) || (priority > SHUTDOWN_PRI_MIN)) { + printf("bad callout priority specified\n"); + return (EINVAL); + } if (rm_at_shutdown(function, arg)) printf("exit callout entry already present\n"); ep = malloc(sizeof(*ep), M_TEMP, M_NOWAIT); if (ep == NULL) return (ENOMEM); ep->function = function; ep->arg = arg; ! ep->priority = priority; ! ! lp = NULL; ! ip = *epp; ! if (*epp) { ! while (ip) { ! if (ip->priority >= priority) ! break; ! lp = ip; ! ip = ip->next; ! } ! } ! if (lp) { ! ep->next = lp->next; ! lp->next = ep; ! } else { ! ep->next = ip; ! *epp = ep; ! } ! return (0); } *************** *** 451,456 **** --- 504,521 ---- ep = *epp; } epp = &shutdown_list2; + ep = *epp; + while (ep) { + if ((ep->function == function) && (ep->arg == arg)) { + *epp = ep->next; + free(ep, M_TEMP); + count++; + } else { + epp = &ep->next; + } + ep = *epp; + } + epp = &shutdown_list3; ep = *epp; while (ep) { if ((ep->function == function) && (ep->arg == arg)) { *** sys/sys/systm.h.orig Sun Aug 10 22:04:12 1997 --- sys/sys/systm.h Wed Feb 11 01:56:41 1998 *************** *** 168,176 **** --- 168,181 ---- /* shutdown callout list definitions */ typedef void (*bootlist_fn)(int,void *); int at_shutdown(bootlist_fn function, void *arg, int); + int at_shutdown_pri(bootlist_fn function, void *arg, int, int); int rm_at_shutdown(bootlist_fn function, void *arg); #define SHUTDOWN_PRE_SYNC 0 #define SHUTDOWN_POST_SYNC 1 + #define SHUTDOWN_POWEROFF 2 + #define SHUTDOWN_PRI_MAX 1 + #define SHUTDOWN_PRI_MIN 10000 + #define SHUTDOWN_PRI_DEFAULT 5000 /* forking */ /* XXX not yet */ typedef void (*forklist_fn)(struct proc *parent,struct proc *child,int flags); *** share/man/man9/at_shutdown.9.orig Fri Feb 14 02:53:01 1997 --- share/man/man9/at_shutdown.9 Wed Feb 18 11:35:59 1998 *************** *** 25,35 **** .\" .\" $Id: at_shutdown.9,v 1.4.2.1 1997/02/14 07:53:01 mpp Exp $ .\" " ! .Dd August 15, 1996 .Os .Dt AT_SHUTDOWN 9 .Sh NAME .Nm at_shutdown , .Nm rm_at_shutdown .Nd ask that a function be run at shutdown. .Sh SYNOPSIS --- 25,36 ---- .\" .\" $Id: at_shutdown.9,v 1.4.2.1 1997/02/14 07:53:01 mpp Exp $ .\" " ! .Dd February 18, 1998 .Os .Dt AT_SHUTDOWN 9 .Sh NAME .Nm at_shutdown , + .Nm at_shutdown_pri , .Nm rm_at_shutdown .Nd ask that a function be run at shutdown. .Sh SYNOPSIS *************** *** 41,58 **** .Ft int .Fn at_shutdown "bootlist_fn func" "void *arg" "int when" .Ft int .Fn rm_at_shutdown "bootlist_fn func" "void *arg" .Sh DESCRIPTION The .Nm at_shutdown ! facility allows a kernel module to ensure that it is notified ! at system shutdown. The function .Fa func is called with the flags indicating boot type, and the opaque argument .Fa arg when the system is shut down. .Pp If the requirement for notification is removed, then the function .Fn rm_at_shutdown must be called with the exact --- 42,95 ---- .Ft int .Fn at_shutdown "bootlist_fn func" "void *arg" "int when" .Ft int + .Fn at_shutdown_pri "bootlist_fn func" "void *arg" "int when" "int priority" + .Ft int .Fn rm_at_shutdown "bootlist_fn func" "void *arg" .Sh DESCRIPTION The .Nm at_shutdown ! and ! .Nm at_shutdown_pri ! facilities allows a kernel module to ensure that it is notified at system ! shutdown. There are three ordered shutdown queues, one run before the ! final sync, one run after, and one run with the intent of powering off the ! system (if possible). ! .Pp The function .Fa func is called with the flags indicating boot type, and the opaque argument .Fa arg when the system is shut down. .Pp + The argument + .Fa when + should be one of + .Dv SHUTDOWN_PRE_SYNC , + .Dv SHUTDOWN_POST_SYNC + or + .Dv SHUTDOWN_POWEROFF + to specify which queue should be used. + .Pp + The + .Fa priority + argument is an integer value between + .Dv SHUTDOWN_PRI_MAX + and + .Dv SHUTDOWN_PRI_MIN + by which the shutdown queue is sorted. Smaller + .Fa priority + values are executed first. Functions with identical priorities are + executed on a last-added, first-executed basis. + .Pp + For backwards compatibility any functions added via the + .Fn at_shutdown + interface will be added with a priority of + .Dv SHUTDOWN_PRI_DEFAULT + which represents a midpoint between + .Dv SHUTDOWN_PRI_MAX + and + .Dv SHUTDOWN_PRI_MIN . + .Pp If the requirement for notification is removed, then the function .Fn rm_at_shutdown must be called with the exact *************** *** 60,80 **** and .Fa arg arguments as the corresponding call to ! .Fn at_shutdown . ! There are two shutdown queues, one run before the final sync and one after. ! The last argument to ! .Fa at_shutdown ! should be one of ! .Dv SHUTDOWN_PRE_SYNC or ! .Dv SHUTDOWN_POST_SYNC ! to specify which queue should be used. .Fn rm_at_shutdown ! will remove an entry from either queue. .Pp .Sh RETURN VALUES .Fn at_shutdown ! returns an error code, 0 meaning success. .Fn rm_at_shutdown returns the number of items removed (should be 0 or 1). .Sh SEE ALSO --- 97,114 ---- and .Fa arg arguments as the corresponding call to ! .Fn at_shutdown or ! .Fn at_shutdown_pri . .Fn rm_at_shutdown ! will remove an entry from any of the queues. .Pp .Sh RETURN VALUES .Fn at_shutdown ! and ! .Fn at_shutdown_pri ! both return an error code, 0 meaning success. ! .Fn rm_at_shutdown returns the number of items removed (should be 0 or 1). .Sh SEE ALSO *************** *** 88,98 **** functions appeared in .Fx 2.2 . .Sh BUGS ! Since the shutdown 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 ! .ie t Julian Elischer (julian@freebsd.org) .el Julian Elischer (julian@freebsd.org) --- 122,142 ---- functions appeared in .Fx 2.2 . + .Pp + The + .Fn at_shutdown_pri + function appeared in + .Fx 2.2.6 . .Sh BUGS ! Although the shutdown queues are ordered by ! .Fa priority ! this priority is assigned by the interface consumers and may not ! reflect sanity. .Sh AUTHORS The function was written by ! .ie t Julian Elischer (julian@freebsd.org) .el Julian Elischer (julian@freebsd.org) + .Pp + Ordered execution added by + .ie t Bruce Walter (walter@fortean.com) + .el Bruce Walter (walter@fortean.com) >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199802270747.CAA24164>