[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Sync() and Shutdown() system call



Hello every1!

Here is a patch for a Sync and a Shutdown system call, relative to
MiNT 1.11 h2.
For Sync(), the FILESYS structure had to be extended by a function which
does the sync... (a patch for the minixfs will follow).
And MiNT now spawn off a system update daemon, whose update time can
be set in mint.cnf.
The shutdown() call has two modes, one to set the system to a halt,
the other to reboot. Of course, Sync() is called interally after terminating
all processes.

ok, here is the patch:

diff -uw old/debug.c ./debug.c
--- old/debug.c	Tue Nov  1 22:23:10 1994
+++ ./debug.c	Tue Nov  1 22:23:46 1994
@@ -523,6 +523,71 @@
 }
 
 
+/* uk: a normal halt() function without an error message. This function
+ *     may only be called if all processes are shut down and the file
+ *     systems are synced.
+ */
+
+static const char *haltmsg[MAXLANG] = {
+"System halted.\r\n",
+"System angehalten.\r\n",	/* German */
+"System halted.\r\n",		/* French */
+"System halted.\r\n",		/* UK */
+"System halted.\r\n",		/* Spanish */
+"System halted.\r\n"		/* Italian */
+};
+
+
+EXITING
+void halt()
+{
+	long r;
+	long key;
+	int scan;
+	extern long tosssp;	/* in main.c */
+#ifdef PROFILING
+	extern EXITING _exit P_((int)) NORETURN;
+#endif
+	restr_intr();	/* restore interrupts to normal */
+#ifdef DEBUG_INFO
+	debug_ws("halt() called, system halting...\r\n");
+#else
+	debug_ws(haltmsg[gl_lang]);
+#endif
+	sys_q[READY_Q] = 0;	/* prevent context switches */
+
+	for(;;) {
+		/* get a key; if ctl-alt then do it, else halt */
+		key = Bconin(out_device);
+		if ((key & 0x0c000000L) == 0x0c000000L) {
+			scan = (int) ((key >> 16) & 0xff);
+			do_func_key(scan);
+		}
+		else {
+			break;
+		}
+	}
+	for(;;) {
+		debug_ws(haltmsg[gl_lang]);
+		r = Bconin(2);
+
+		if ((r & 0x0ff) == 'x') {
+			extern int no_mem_prot;
+			if (!no_mem_prot)
+				restr_mmu();
+			restr_screen();
+			(void)Super((void *)tosssp);	/* gratuitous (void *) for Lattice */
+#ifdef PROFILING
+			_exit(0);
+#else
+			Pterm0();
+#endif
+		}
+	}
+}
+
+
+
 static const char *rebootmsg[MAXLANG] = {
 "FATAL ERROR. You must reboot the system.\r\n",
 "FATALER FEHLER. Das System mu? neu gestartet werden.\r\n",	/* German */
@@ -565,9 +630,17 @@
 		debug_ws(rebootmsg[gl_lang]);
 		r = Bconin(2);
 
-		if ( (r & 0x0ff) == 'x' ) {
+		if ( ((r & 0x0ff) == 'x') || ((r & 0xff) == 's') ) {
 			extern int no_mem_prot;
 			close_filesys();
+
+			/* if the user pressed 's', try to sync before halting the system */
+			if ((r & 0xff) == 's')
+			{
+				debug_ws("Syncing...");
+				s_ync();
+				debug_ws("done.\r\n");
+			}
 			if (!no_mem_prot)
 				restr_mmu();
 			restr_screen();
@@ -595,7 +668,7 @@
 
 	switch (scan) {
 	case DEL:
-		reboot();
+		s_hutdown(1);
 		break;
 	case UNDO:
 		killgroup(con_tty.pgrp, SIGQUIT, 1);
diff -uw old/dos.c ./dos.c
--- old/dos.c	Tue Nov  1 22:23:10 1994
+++ ./dos.c	Tue Nov  1 22:26:42 1994
@@ -8,7 +8,7 @@
 
 #include "mint.h"
 
-#define DOS_MAX 0x150
+#define DOS_MAX 0x160
 
 Func dos_tab[DOS_MAX];
 short dos_max = DOS_MAX;
@@ -829,6 +829,91 @@
 	return 0;
 }
 
+/* uk: shutdown function
+ *     if the parameter is nonzero, reboot the machine, otherwise
+ *     halt it after syncing the file systems.
+ */
+
+/* this is mostly from main.c:
+ * shut down processes; this involves waking them all up, and sending
+ * them SIGTERM to give them a chance to clean up after themselves
+ */
+
+static void
+shutmedown(p)
+	PROC *p;
+{
+	wake(WAIT_Q, (long)s_hutdown);
+	p->wait_cond = 0;
+}
+
+long ARGS_ON_STACK
+s_hutdown(long restart)
+{
+	/* only root may shut down the system */
+	if ((curproc->euid == 0) || (curproc->ruid == 0))
+	{
+		PROC *p;
+		int proc_left = 0;
+
+		DEBUG(("Shutting processes down..."));
+		DEBUG(("This is pid %d", curproc->pid));
+		curproc->sighandle[SIGCHLD] = SIG_IGN;
+		for (p = proclist; p; p = p->gl_next) {
+			if (p->pid == 0) continue;
+			if (p == curproc) continue;  /* curproc is trapped in this code */
+			if (p->wait_q != ZOMBIE_Q && p->wait_q != TSR_Q) {
+				if (p->wait_q != READY_Q) {
+	 				short sr = spl7();
+					rm_q(p->wait_q, p);
+					add_q(READY_Q, p);
+					spl(sr);
+				}
+				DEBUG(("Posting SIGTERM for pid %d", p->pid));
+				post_sig(p, SIGTERM);
+				proc_left++;
+			}
+		}
+
+		if (proc_left) {
+			/* sleep a little while, to give the other processes a chance to
+			   shut down
+			 */
+
+			if (addtimeout(1000, shutmedown))
+				do {
+					DEBUG(("Sleeping..."));
+					sleep(WAIT_Q, (long)s_hutdown);
+				} while (curproc->wait_cond == (long)s_hutdown);
+
+			DEBUG(("Killing all processes..."));
+			for (p = proclist; p; p = p->gl_next)
+			{
+				if ((p->pid == 0) || (p == curproc))
+					continue;
+				DEBUG(("Posting SIGKILL for pid %d", p->pid));
+				post_sig(p, SIGKILL);
+			}
+		}
+		sys_q[READY_Q] = 0;
+		DEBUG(("Syncing file systems..."));
+		close_filesys();
+		s_ync();   /* additional sync() */
+		if (restart)
+		{
+			DEBUG(("Rebooting..."));
+			reboot();
+		}
+		else
+		{
+			DEBUG(("Halting system..."));
+			halt();
+		}
+	}
+	return EACCDN;	
+}
+
+
 /*
  * routine for initializing DOS
  *
@@ -975,4 +1060,6 @@
 		dos_tab[0x14a] = s_cookie;
  	dos_tab[0x14e] = p_setreuid;
  	dos_tab[0x14f] = p_setregid;
+		dos_tab[0x150] = s_ync;
+		dos_tab[0x151] = s_hutdown;
 }
diff -uw old/file.h ./file.h
--- old/file.h	Tue Nov  1 22:23:10 1994
+++ ./file.h	Tue Nov  1 22:28:12 1994
@@ -186,6 +186,7 @@
 #define	FS_LONGPATH	0x08	/* file system understands "size" argument to
 				   "getname" */
 #define FS_NO_C_CACHE	0x10	/* don't cache cookies for this filesystem */
+#define FS_DO_SYNC    0x20  /* file system has a sync function */
 	long	ARGS_ON_STACK (*root) P_((int drv, fcookie *fc));
 	long	ARGS_ON_STACK (*lookup) P_((fcookie *dir, const char *name, fcookie *fc));
 	long	ARGS_ON_STACK (*creat) P_((fcookie *dir, const char *name, unsigned mode,
@@ -218,6 +219,7 @@
 	long	ARGS_ON_STACK (*dskchng) P_((int drv));
 	long	ARGS_ON_STACK (*release) P_((fcookie *));
 	long	ARGS_ON_STACK (*dupcookie) P_((fcookie *new, fcookie *old));
+	long	ARGS_ON_STACK (*sync) P_((void));
 } FILESYS;
 
 /*
diff -uw old/filesys.c ./filesys.c
--- old/filesys.c	Tue Nov  1 22:23:10 1994
+++ ./filesys.c	Tue Nov  1 22:23:54 1994
@@ -124,6 +124,26 @@
 	unifs_init();
 }
 
+
+/* uk: go through the list of file systems and call their sync() function
+ *     if they wish to.
+ */
+long
+s_ync()
+{
+	FILESYS *fs;
+
+	TRACE(("Syncing file systems..."));
+	for (fs = active_fs;  fs;  fs = fs->next)
+	{
+		if (fs->fsflags & FS_DO_SYNC)
+			(*fs->sync)();
+	}
+	TRACE(("Syncing done."));
+	return 0;
+}
+
+
 /*
  * load file systems from disk
  * this routine is called after process 0 is set up, but before any user
diff -uw old/main.c ./main.c
--- old/main.c	Tue Nov  1 22:23:10 1994
+++ ./main.c	Tue Nov  1 22:23:58 1994
@@ -184,6 +184,8 @@
 
 extern Func bios_tab[], dos_tab[];
 
+extern long sync_time;
+
 /* kernel info that is passed to loaded file systems and device drivers */
 
 struct kerinfo kernelinfo = {
@@ -565,6 +567,8 @@
 			sleep(WAIT_Q, (long)shutdown);
 		} while (curproc->wait_cond == (long)shutdown);
 	}
+	/* uk: do an additional sync for the file systems */
+	s_ync();
 }
 
 #ifndef MULTITOS
@@ -596,6 +600,8 @@
 	long yn;
 	FILEPTR *f;
 
+	extern void start_sysupdate();
+	
 #if defined(__GNUC__) || defined(__MINT__)
 	UNUSED(envp);
 #endif
@@ -872,6 +878,9 @@
 /* load the configuration file */
 	load_config();
 
+/* start system update daemon */
+	start_sysupdate();
+
 	*((long *)0x4c2L) |= PSEUDODRVS;
 
 	if (init_env == 0)
@@ -1173,6 +1182,7 @@
  * DEBUG_DEVNO=n	-- set debug device number to (decimal number) n
  * HARDSCROLL=n		-- set hard-scroll size to n, range 0-99.
  * SLICES=nnn		-- set multitasking granularity
+ * UPDATE=n   -- set the sync time in seconds for the system update daemon
  * echo message		-- print a message on the screen
  * alias drive path	-- make a fake drive pointing at a path
  * cd dir		-- change directory/drive
@@ -1324,6 +1334,14 @@
 	if (!strcmp(name, "PSEUDODRIVES")) {
 		FORCE("PSEUDODRIVES= no longer supported");
 		return;
+	}
+
+	/* uk: set update time for system update daemon */
+	if (!strcmp(name, "UPDATE")) {
+		extern long sync_time;
+
+		sync_time = atol(val);
+		return;
 	}
 	FORCE("Unknown variable `%s'", name);
 }
diff -uw old/makefile ./makefile
--- old/makefile	Tue Nov  1 22:23:12 1994
+++ ./makefile	Tue Nov  1 22:32:24 1994
@@ -61,12 +61,14 @@
 COBJS = bios.o xbios.o console.o dos.o dosdir.o dosfile.o dosmem.o dossig.o \
 	filesys.o main.o mem.o proc.o signal.o timeout.o tty.o util.o \
 	biosfs.o pipefs.o procfs.o tosfs.o debug.o rendez.o cookie.o \
-	unifs.o shmfs.o fasttext.o welcome.o nalloc2.o memprot.o realloc.o
+	unifs.o shmfs.o fasttext.o welcome.o nalloc2.o memprot.o realloc.o \
+	update.o
 
 COBJS030 = bios.o0 xbios.o0 console.o0 dos.o0 dosdir.o0 dosfile.o0 dosmem.o0 dossig.o0 \
 	filesys.o0 main.o0 mem.o0 proc.o0 signal.o0 timeout.o0 tty.o0 util.o0 \
 	biosfs.o0 pipefs.o0 procfs.o0 tosfs.o0 debug.o0 rendez.o0 cookie.o0 \
-	unifs.o0 shmfs.o0 fasttext.o0 welcome.o0 nalloc2.o0 memprot.o realloc.o0
+	unifs.o0 shmfs.o0 fasttext.o0 welcome.o0 nalloc2.o0 memprot.o realloc.o0 \
+	update.o0
 
 CFILES = bios.c xbios.c console.c dos.c dosdir.c dosfile.c dosmem.c dossig.c \
 	filesys.c main.c mem.c proc.c signal.c timeout.c tty.c util.c \
diff -uw old/proto.h ./proto.h
--- old/proto.h	Tue Nov  1 22:23:18 1994
+++ ./proto.h	Tue Nov  1 22:24:04 1994
@@ -107,6 +107,7 @@
 long ARGS_ON_STACK s_ysconf P_((int which));
 long ARGS_ON_STACK s_alert P_((char *msg));
 long ARGS_ON_STACK s_uptime P_((unsigned long *cur_uptim, unsigned long loadave[3]));
+long ARGS_ON_STACK s_hutdown P_((long restart));
 void init_dos P_((void));
 
 /* dosdir.c */
@@ -200,6 +201,7 @@
 void load_filesys P_((void));
 void load_devdriver P_((void));
 void close_filesys P_((void));
+long s_ync P_((void));
 void ARGS_ON_STACK changedrv P_((unsigned drv));
 int disk_changed P_((int drv));
 long relpath2cookie
@@ -398,6 +400,7 @@
 void ARGS_ON_STACK FORCE P_((const char *s, ...));
 void PAUSE P_((void));
 EXITING void ARGS_ON_STACK FATAL P_((const char *s, ...)) NORETURN;
+EXITING void halt P_((void)) NORETURN;
 EXITING void HALT P_((void)) NORETURN;
 void DUMPLOG P_((void));
 void do_func_key P_((int));


I hope you will like it. Unfortunately, the keyboard drivers of newer
TOSes do a warmboot by themselves when ctrl-alt-del is pressed, so
MiNT has NO chance to sync the file system, sorry.

Regards,
Ulrich

--
+---------------+----------------------------+-----------------------+
| Ulrich Kuehn  | Internet:                  | Life is uncertain --  |
| Cand.Math.Inf | kuehn@math.uni-muenster.de | eat the dessert first |
+---------------+----------------------------+-----------------------+