]> Zhao Yanbai Git Server - minix.git/commitdiff
New RS and new signal handling for system processes.
authorCristiano Giuffrida <cristiano@minix3.org>
Wed, 17 Mar 2010 01:15:29 +0000 (01:15 +0000)
committerCristiano Giuffrida <cristiano@minix3.org>
Wed, 17 Mar 2010 01:15:29 +0000 (01:15 +0000)
UPDATING INFO:
20100317:
        /usr/src/etc/system.conf updated to ignore default kernel calls: copy
        it (or merge it) to /etc/system.conf.
        The hello driver (/dev/hello) added to the distribution:
        # cd /usr/src/commands/scripts && make clean install
        # cd /dev && MAKEDEV hello

KERNEL CHANGES:
- Generic signal handling support. The kernel no longer assumes PM as a signal
manager for every process. The signal manager of a given process can now be
specified in its privilege slot. When a signal has to be delivered, the kernel
performs the lookup and forwards the signal to the appropriate signal manager.
PM is the default signal manager for user processes, RS is the default signal
manager for system processes. To enable ptrace()ing for system processes, it
is sufficient to change the default signal manager to PM. This will temporarily
disable crash recovery, though.
- sys_exit() is now split into sys_exit() (i.e. exit() for system processes,
which generates a self-termination signal), and sys_clear() (i.e. used by PM
to ask the kernel to clear a process slot when a process exits).
- Added a new kernel call (i.e. sys_update()) to swap two process slots and
implement live update.

PM CHANGES:
- Posix signal handling is no longer allowed for system processes. System
signals are split into two fixed categories: termination and non-termination
signals. When a non-termination signaled is processed, PM transforms the signal
into an IPC message and delivers the message to the system process. When a
termination signal is processed, PM terminates the process.
- PM no longer assumes itself as the signal manager for system processes. It now
makes sure that every system signal goes through the kernel before being
actually processes. The kernel will then dispatch the signal to the appropriate
signal manager which may or may not be PM.

SYSLIB CHANGES:
- Simplified SEF init and LU callbacks.
- Added additional predefined SEF callbacks to debug crash recovery and
live update.
- Fixed a temporary ack in the SEF init protocol. SEF init reply is now
completely synchronous.
- Added SEF signal event type to provide a uniform interface for system
processes to deal with signals. A sef_cb_signal_handler() callback is
available for system processes to handle every received signal. A
sef_cb_signal_manager() callback is used by signal managers to process
system signals on behalf of the kernel.
- Fixed a few bugs with memory mapping and DS.

VM CHANGES:
- Page faults and memory requests coming from the kernel are now implemented
using signals.
- Added a new VM call to swap two process slots and implement live update.
- The call is used by RS at update time and in turn invokes the kernel call
sys_update().

RS CHANGES:
- RS has been reworked with a better functional decomposition.
- Better kernel call masks. com.h now defines the set of very basic kernel calls
every system service is allowed to use. This makes system.conf simpler and
easier to maintain. In addition, this guarantees a higher level of isolation
for system libraries that use one or more kernel calls internally (e.g. printf).
- RS is the default signal manager for system processes. By default, RS
intercepts every signal delivered to every system process. This makes crash
recovery possible before bringing PM and friends in the loop.
- RS now supports fast rollback when something goes wrong while initializing
the new version during a live update.
- Live update is now implemented by keeping the two versions side-by-side and
swapping the process slots when the old version is ready to update.
- Crash recovery is now implemented by keeping the two versions side-by-side
and cleaning up the old version only when the recovery process is complete.

DS CHANGES:
- Fixed a bug when the process doing ds_publish() or ds_delete() is not known
by DS.
- Fixed the completely broken support for strings. String publishing is now
implemented in the system library and simply wraps publishing of memory ranges.
Ideally, we should adopt a similar approach for other data types as well.
- Test suite fixed.

DRIVER CHANGES:
- The hello driver has been added to the Minix distribution to demonstrate basic
live update and crash recovery functionalities.
- Other drivers have been adapted to conform the new SEF interface.

148 files changed:
commands/dhcpd/dhcpd.c
commands/scripts/DESCRIBE.sh
commands/scripts/MAKEDEV.sh
commands/scripts/readclock.sh
docs/UPDATING
drivers/Makefile
drivers/amddev/amddev.c
drivers/at_wini/at_wini.c
drivers/at_wini/liveupdate.c
drivers/atl2/atl2.c
drivers/audio/framework/audio_fw.c
drivers/audio/framework/liveupdate.c
drivers/bios_wini/bios_wini.c
drivers/dec21140A/dec21140A.c
drivers/dp8390/dp8390.c
drivers/dpeth/dp.c
drivers/e1000/e1000.c
drivers/filter/main.c
drivers/filter/util.c
drivers/floppy/floppy.c
drivers/floppy/liveupdate.c
drivers/fxp/fxp.c
drivers/hello/Makefile [new file with mode: 0644]
drivers/hello/hello.c [new file with mode: 0644]
drivers/hello/hello.h [new file with mode: 0644]
drivers/lance/lance.c
drivers/libdriver/driver.c
drivers/libdriver/driver.h
drivers/log/liveupdate.c
drivers/log/log.c
drivers/memory/memory.c
drivers/memory/ramdisk/rc
drivers/orinoco/orinoco.c
drivers/pci/main.c
drivers/pci/pci.c
drivers/printer/liveupdate.c
drivers/printer/printer.c
drivers/random/main.c
drivers/readclock/readclock.c
drivers/rtl8139/liveupdate.c
drivers/rtl8139/rtl8139.c
drivers/rtl8169/rtl8169.c
drivers/sb16/sb16_dsp.c
drivers/sb16/sb16_dsp_liveupdate.c
drivers/tty/console.c
drivers/tty/tty.c
drivers/tty/tty.h
etc/rs.inet
etc/system.conf
include/errno.h
include/minix/callnr.h
include/minix/com.h
include/minix/dmap.h
include/minix/ds.h
include/minix/rs.h
include/minix/safecopies.h
include/minix/sef.h
include/minix/syslib.h
include/minix/vm.h
include/signal.h
kernel/arch/i386/exception.c
kernel/arch/i386/memory.c
kernel/config.h
kernel/interrupt.c
kernel/main.c
kernel/priv.h
kernel/proc.h
kernel/system.c
kernel/system.h
kernel/system/Makefile
kernel/system/do_abort.c
kernel/system/do_clear.c [new file with mode: 0644]
kernel/system/do_endksig.c
kernel/system/do_exit.c
kernel/system/do_getksig.c
kernel/system/do_kill.c
kernel/system/do_privctl.c
kernel/system/do_runctl.c
kernel/system/do_safemap.c
kernel/system/do_update.c [new file with mode: 0644]
lib/libc/ansi/errlist.c
lib/libc/other/Makefile.inc
lib/libc/other/_vm_update.c [new file with mode: 0644]
lib/libc/syscall/Makefile.inc
lib/libc/syscall/vm_update.S [new file with mode: 0644]
lib/libsys/Makefile
lib/libsys/ds.c
lib/libsys/sef.c
lib/libsys/sef_init.c
lib/libsys/sef_liveupdate.c
lib/libsys/sef_ping.c
lib/libsys/sef_signal.c [new file with mode: 0644]
lib/libsys/sys_clear.c [new file with mode: 0644]
lib/libsys/sys_exit.c
lib/libsys/sys_update.c [new file with mode: 0644]
man/man2/intro.2
servers/ds/inc.h
servers/ds/main.c
servers/ds/store.c
servers/ds/store.h
servers/hgfs/main.c
servers/inet/inet.c
servers/inet/mnx_eth.c
servers/ipc/inc.h
servers/ipc/main.c
servers/is/dmp_ds.c
servers/is/dmp_pm.c
servers/is/dmp_rs.c
servers/is/main.c
servers/iso9660fs/main.c
servers/mfs/main.c
servers/pfs/main.c
servers/pm/exec.c
servers/pm/forkexit.c
servers/pm/main.c
servers/pm/mproc.h
servers/pm/proto.h
servers/pm/signal.c
servers/pm/table.c
servers/rs/Makefile
servers/rs/const.h
servers/rs/error.c [new file with mode: 0644]
servers/rs/exec.c
servers/rs/glo.h
servers/rs/inc.h
servers/rs/main.c
servers/rs/manager.c
servers/rs/proto.h
servers/rs/request.c [new file with mode: 0755]
servers/rs/service.c
servers/rs/table.c
servers/rs/type.h
servers/rs/utility.c
servers/vfs/dmap.c
servers/vfs/main.c
servers/vfs/table.c
servers/vm/exit.c
servers/vm/main.c
servers/vm/map_mem.c
servers/vm/pagefaults.c
servers/vm/proto.h
servers/vm/rs.c
test/ds/dstest.c
test/ds/subs.c
test/ds/system.conf
test/safecopy/system.conf
test/safemap/system.conf
test/safeperf/system.conf

index 05b315a41ad2e800076549c1d0c3f878a47614aa..bd43077ae13aabfd76f424d6cca4f6e24f0a0253 100644 (file)
@@ -673,10 +673,13 @@ int main(int argc, char **argv)
     int i;
     network_t *np;
     struct sigaction sa;
-    ssize_t r= -1;
-    buf_t *bp= nil;
+    ssize_t r;
+    buf_t *bp;
     static struct timeval eventtv;
 
+main:
+    r = -1;
+    bp = nil;
     program= argv[0];
     start= now= time(nil);
 
@@ -1403,6 +1406,9 @@ int main(int argc, char **argv)
            }
        }
     }
-    if (debug >= 1) printf("Nothing more to do! Bailing out...\n");
+    if (debug >= 1) printf("Nothing more to do! Starting over...\n");
+    sleep(2);
+    goto main;
+
     return 0;
 }
index 2edba7d95b67dfc43818e10561f117e5d498455c..93b1be3472f33303d9311d6ad6e3ed253264e507 100755 (executable)
@@ -190,6 +190,9 @@ do
     16,0)
        des="pseudo random number generator" dev=urandom
        ;;
+    17,0)
+       des="hello" dev=hello
+       ;;
     BAD,BAD)
        des= dev=
        ;;
index 915f0f127fa69af65095d13b8f091d40537e8b0c..a35149864e5537b4403c2557cb7028ed86196d25 100755 (executable)
@@ -23,7 +23,7 @@ case $#:$1 in
        ttypa ttypb ttypc ttypd ttype ttypf \
        ttyq0 ttyq1 ttyq2 ttyq3 ttyq4 ttyq5 ttyq6 ttyq7 ttyq8 ttyq9 \
        ttyqa ttyqb ttyqc ttyqd ttyqe ttyqf \
-       eth klog random filter
+       eth klog random filter hello
     ;;
 0:|1:-\?)
     cat >&2 <<EOF
@@ -48,6 +48,7 @@ Where key is one of the following:
   kbd                     # Make /dev/kbd
   kbdaux                  # Make /dev/kbdaux
   filter                  # Make /dev/filter
+  hello                   # Make /dev/hello
   video                   # Make /dev/video
   std                    # All standard devices
 EOF
@@ -259,6 +260,11 @@ do
        $e mknod filter b 11 0
        $e chmod 644 filter
        ;;
+    hello)
+       # hello driver
+       $e mknod hello c 17 0
+       $e chmod 644 hello
+       ;;
     *)
        echo "$0: don't know about $dev" >&2
        ex=1
index f53e0d259f055fee1d86e56f1fe7a0009fb1dc4c..97c94c3ef8b21406f60e56a56efdfa4467205616 100644 (file)
@@ -2,4 +2,4 @@
 if [ $# -gt 0 ]
 then   ARGS="-args $@"
 fi
-/bin/service up /sbin/readclock.drv -config /etc/system.conf -script /etc/rs.single $ARGS
+/bin/service up /sbin/readclock.drv -config /etc/system.conf -period 5HZ -script /etc/rs.single $ARGS
index 609cb3dd48baf6315826289a11f68eb457b7902d..59261ce8a39c2bb10d5305168d562876f29e4461 100644 (file)
@@ -1,27 +1,3 @@
-20100316:
-        /usr/man/man9 is required
-       # mkdir /usr/man/man9
-20100308:
-        Include directory reorganization:
-        # mv /usr/include/ibm /usr/include/i386
-        # ln -s /usr/include/i386 /usr/include/machine
-        Install(1) updates:
-        # cd commands/simple && make /bin/install
-20100303:
-        Gas2ack updates: Run 'make install' in commands/i386/gas2ack
-20100215:
-        Make(1) has been replaced: Run 'make install' in commands/make
-        Mkdep updates: Copy commands/scripts/mkdep.sh to /usr/bin/mkdep
-        Make(1) needs mkfiles: Copy files in etc/mk to /etc/mk
-        ACK update: Copy commands/i386/acd.descr to /usr/lib/descr
-        End.a renamed:
-           -Copy /usr/lib/i86/end.a to /usr/lib/i86/libend.a
-           -Copy /usr/lib/i386/end.a to /usr/lib/i386/libend.a
-           -Copy /usr/gnu/lib/end.a to /usr/gnu/lib/libend.a
-        Asmconv updates: Run 'make install' in commands/i386/asmconv
-20091212:
-        /etc/drivers.conf has been renamed to /etc/system.conf.
-        user "service" has been added to password file /etc/passwd.
 20060818:
        You need flex in your $PATH, which has become part of the base
        system. This needs bigger binaries.
 20091006 (r5422):
        OSS requires an improved make to be compiled; run "make install"
        in /usr/src/commands/make before running "make world".
+20091212:
+        /etc/drivers.conf has been renamed to /etc/system.conf.
+        user "service" has been added to password file /etc/passwd.
+20100215:
+        Make(1) has been replaced: Run 'make install' in commands/make
+        Mkdep updates: Copy commands/scripts/mkdep.sh to /usr/bin/mkdep
+        Make(1) needs mkfiles: Copy files in etc/mk to /etc/mk
+        ACK update: Copy commands/i386/acd.descr to /usr/lib/descr
+        End.a renamed:
+           -Copy /usr/lib/i86/end.a to /usr/lib/i86/libend.a
+           -Copy /usr/lib/i386/end.a to /usr/lib/i386/libend.a
+           -Copy /usr/gnu/lib/end.a to /usr/gnu/lib/libend.a
+        Asmconv updates: Run 'make install' in commands/i386/asmconv
+20100303:
+        Gas2ack updates: Run 'make install' in commands/i386/gas2ack
+20100308:
+        Include directory reorganization:
+        # mv /usr/include/ibm /usr/include/i386
+        # ln -s /usr/include/i386 /usr/include/machine
+        Install(1) updates:
+        # cd commands/simple && make /bin/install
+20100316:
+        /usr/man/man9 is required
+       # mkdir /usr/man/man9
+20100317:
+        /usr/src/etc/system.conf updated to ignore default kernel calls: copy
+        it (or merge it) to /etc/system.conf.
+        The hello driver (/dev/hello) added to the distribution:
+        # cd /usr/src/commands/scripts && make clean install
+        # cd /dev && MAKEDEV hello
+
index c3e9eeeaf4899222525426d3c64567898fb2e8ee..b72054051556f027c1729ed0f3b1b0ea86de3609 100644 (file)
@@ -32,6 +32,7 @@ all install depend clean:
        cd ./log && $(MAKE) $@
        cd ./bios_wini && $(MAKE) $@
        cd ./filter && $(MAKE) $@
+       cd ./hello && $(MAKE) $@
        cd ./random && $(MAKE) $@
        cd ./readclock && $(MAKE) $@
        cd ./dp8390 && $(MAKE) $@
index fa2f65c68e0e18c9bd4bee3b7fc3f6e013ca9e39..16bd92acbe48dc29f5500771bb96f51fbf1b6f28 100644 (file)
@@ -16,6 +16,7 @@ Driver for the AMD Device Exclusion Vector (DEV)
 #include <string.h>
 #include <unistd.h>
 #include <machine/vm.h>
+#include <signal.h>
 #include <minix/com.h>
 #include <minix/const.h>
 #include <minix/ipc.h>
@@ -57,12 +58,12 @@ static void init_map(unsigned int ix);
 static int do_add4pci(message *m);
 static void add_range(u32_t busaddr, u32_t size);
 static void del_range(u32_t busaddr, u32_t size);
-static void do_pm_notify(message *m);
 static void report_exceptions(void);
 
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
+FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
 
 int main(void)
 {
@@ -79,13 +80,7 @@ int main(void)
                r= sef_receive(ANY, &m);
                if (r != OK)
                        panic("sef_receive failed: %d", r);
-               if (is_notify(m.m_type)) {
-                       if (_ENDPOINT_P(m.m_source) == PM_PROC_NR) {
-                               do_pm_notify(&m);
-                               continue;
-                       }
-               }
-               else if (m.m_type == IOMMU_MAP) {
+               if (m.m_type == IOMMU_MAP) {
                        r= do_add4pci(&m);
                        m.m_type= r;
                        send(m.m_source, &m);
@@ -109,6 +104,9 @@ PRIVATE void sef_local_startup()
   sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready);
   sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard);
 
+  /* Register signal callbacks. */
+  sef_setcb_signal_handler(sef_cb_signal_handler);
+
   /* Let SEF perform startup. */
   sef_startup();
 }
@@ -156,6 +154,47 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
        return(OK);
 }
 
+
+/*===========================================================================*
+ *                        sef_cb_signal_handler                             *
+ *===========================================================================*/
+PRIVATE void sef_cb_signal_handler(int signo)
+{
+       int r;
+       endpoint_t proc_e;
+       phys_bytes base, size;
+
+       /* Only check for termination signal, ignore anything else. */
+       if (signo != SIGTERM) return;
+
+       for (;;)
+       {
+               r= getdma(&proc_e, &base, &size);
+               if (r == -1)
+               {
+                       if (errno != -EAGAIN)
+                       {
+                               printf(
+                               "amddev: getdma failed: %d\n",
+                                       errno);
+                       }
+                       break;
+               }
+
+               printf(
+               "amddev: deleting 0x%x@0x%x for proc %d\n",
+                       size, base, proc_e);
+               del_range(base, size);
+               r= deldma(proc_e, base, size);
+               if (r == -1)
+               {
+                       printf("amddev: deldma failed: %d\n",
+                               errno);
+                       break;
+               }
+       }
+}
+
 /* Returns 0 if no device found, or 1 if a device is found. */
 static int find_dev(devindp, capaddrp)
 int *devindp;
@@ -419,47 +458,6 @@ static void del_range(u32_t busaddr, u32_t size)
        }
 }
 
-static void do_pm_notify(message *m)
-{
-       int r;
-       endpoint_t proc_e;
-       phys_bytes base, size;
-
-       if (m->m_source != PM_PROC_NR)
-       {
-               printf("amddev`do_pm_notify: notify not from PM (from %d)\n",
-                       m->m_source);
-               return;
-       }
-
-       for (;;)
-       {
-               r= getdma(&proc_e, &base, &size);
-               if (r == -1)
-               {
-                       if (errno != -EAGAIN)
-                       {
-                               printf(
-                               "amddev`do_pm_notify: getdma failed: %d\n",
-                                       errno);
-                       }
-                       break;
-               }
-
-               printf(
-               "amddev`do_pm_notify: deleting 0x%x@0x%x for proc %d\n",
-                       size, base, proc_e);
-               del_range(base, size);
-               r= deldma(proc_e, base, size);
-               if (r == -1)
-               {
-                       printf("amddev`do_pm_notify: deldma failed: %d\n",
-                               errno);
-                       break;
-               }
-       }
-}
-
 static void report_exceptions(void)
 {
        u32_t status;
index e168642cee0e7f69665d0a8e9b46ccf55749719b..47ed78d3cb6e255c932c9263585dfa5910eb14cb 100644 (file)
@@ -202,7 +202,6 @@ PRIVATE struct driver w_dtab = {
   w_transfer,          /* do the I/O */
   nop_cleanup,         /* nothing to clean up */
   w_geometry,          /* tell the geometry of the disk */
-  nop_signal,          /* no cleanup needed on shutdown */
   nop_alarm,           /* ignore leftover alarms */
   nop_cancel,          /* ignore CANCELs */
   nop_select,          /* ignore selects */
@@ -213,7 +212,7 @@ PRIVATE struct driver w_dtab = {
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
-EXTERN _PROTOTYPE( void sef_cb_lu_prepare, (int state) );
+EXTERN _PROTOTYPE( int sef_cb_lu_prepare, (int state) );
 EXTERN _PROTOTYPE( int sef_cb_lu_state_isvalid, (int state) );
 EXTERN _PROTOTYPE( void sef_cb_lu_state_dump, (int state) );
 
@@ -257,9 +256,6 @@ PRIVATE void sef_local_startup()
 PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
 {
 /* Initialize the at_wini driver. */
-  struct sigaction sa;
-  
-  /* Install signal handlers. Ask PM to transform signal into message. */
   system_hz = sys_hz();
 
   init_buffer();
@@ -267,14 +263,8 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
   w_identify_wakeup_ticks = WAKEUP_TICKS;
   wakeup_ticks = WAKEUP_TICKS;
 
-  sa.sa_handler = SIG_MESS;
-  sigemptyset(&sa.sa_mask);
-  sa.sa_flags = 0;
-  if (sigaction(SIGTERM,&sa,NULL)<0) panic("sigaction failed: %d", errno);
-
   /* Set special disk parameters. */
   init_params();
-  signal(SIGTERM, SIG_IGN);
 
   return(OK);
 }
index 188736886695cdf1f5dcf3e86bddb55d714fe46a..a048c22b48d257866230015b419829ea128ac393 100644 (file)
@@ -19,7 +19,7 @@ EXTERN int w_command;
 /*===========================================================================*
  *                              sef_cb_lu_prepare                           *
  *===========================================================================*/
-PUBLIC void sef_cb_lu_prepare(int state)
+PUBLIC int sef_cb_lu_prepare(int state)
 {
   int is_ready;
 
@@ -43,9 +43,7 @@ PUBLIC void sef_cb_lu_prepare(int state)
   }
 
   /* Tell SEF if we are ready. */
-  if(is_ready) {
-      sef_lu_ready(OK);
-  }
+  return is_ready ? OK : ENOTREADY;
 }
 
 /*===========================================================================*
index cd41be48d1099534bb37bb78aa6c72f6bd507edf..8e8f6f2d442b81f8e36e7b0bb6010aca12b0843b 100644 (file)
@@ -6,7 +6,6 @@
 
 #include "../drivers.h"
 
-#include <signal.h>
 #include <sys/mman.h>
 #include <minix/ds.h>
 #include <minix/vm.h>
@@ -1122,33 +1121,6 @@ PRIVATE void atl2_getname(message *m, int instance)
                printf("ATL2: unable to send reply (%d)\n", r);
 }
 
-/*===========================================================================*
- *                             atl2_shutdown                                *
- *===========================================================================*/
-PRIVATE void atl2_shutdown(void)
-{
-       /* Shut down this driver. Stop the device, and deallocate resources
-        * as proof of concept.
-        */
-       int r;
-
-       atl2_stop();
-
-       if ((r = sys_irqrmpolicy(&state.hook_id)) != OK)
-               panic("unable to deregister IRQ: %d", r);
-
-       free_contig(state.txd_base, ATL2_TXD_BUFSIZE);
-       free_contig(state.txs_base, ATL2_TXS_COUNT * sizeof(u32_t));
-       free_contig(state.rxd_base_u,
-               state.rxd_align + ATL2_RXD_COUNT * ATL2_RXD_SIZE);
-
-       vm_unmap_phys(SELF, state.base, ATL2_MMAP_SIZE);
-
-       /* We cannot free the PCI device at this time. */
-
-       exit(0);
-}
-
 /*===========================================================================*
  *                             atl2_dump_link                               *
  *===========================================================================*/
@@ -1275,6 +1247,36 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
        return(OK);
 }
 
+/*===========================================================================*
+ *                         sef_cb_signal_handler                            *
+ *===========================================================================*/
+PRIVATE void sef_cb_signal_handler(int signo)
+{
+       /* In case of a termination signal, shut down this driver.
+        * Stop the device, and deallocate resources as proof of concept.
+        */
+       int r;
+
+       /* Only check for termination signal, ignore anything else. */
+       if (signo != SIGTERM) return;
+
+       atl2_stop();
+
+       if ((r = sys_irqrmpolicy(&state.hook_id)) != OK)
+               panic("unable to deregister IRQ: %d", r);
+
+       free_contig(state.txd_base, ATL2_TXD_BUFSIZE);
+       free_contig(state.txs_base, ATL2_TXS_COUNT * sizeof(u32_t));
+       free_contig(state.rxd_base_u,
+               state.rxd_align + ATL2_RXD_COUNT * ATL2_RXD_SIZE);
+
+       vm_unmap_phys(SELF, state.base, ATL2_MMAP_SIZE);
+
+       /* We cannot free the PCI device at this time. */
+
+       exit(0);
+}
+
 /*===========================================================================*
  *                             sef_local_startup                            *
  *===========================================================================*/
@@ -1289,6 +1291,9 @@ PRIVATE void sef_local_startup(void)
 
        /* No support for live update yet. */
 
+       /* Register signal callbacks. */
+       sef_setcb_signal_handler(sef_cb_signal_handler);
+
        /* Let SEF perform startup. */
        sef_startup();
 }
@@ -1319,14 +1324,6 @@ int main(int argc, char **argv)
 
                                break;
 
-                       case PM_PROC_NR:        /* signal */
-                               if (getsigset(&set) != 0) break;
-
-                               if (sigismember(&set, SIGTERM))
-                                       atl2_shutdown();
-
-                               break;
-
                        case TTY_PROC_NR:       /* function key */
                                atl2_dump();
 
index 0d275ed83489a3d95097283f1213c9f7039973b4..e4d83e71e0fefedcc67491c76486a20a502cb348 100644 (file)
@@ -53,7 +53,6 @@ FORWARD _PROTOTYPE( int msg_ioctl, (message *m_ptr) );
 FORWARD _PROTOTYPE( void msg_write, (message *m_ptr) );
 FORWARD _PROTOTYPE( void msg_read, (message *m_ptr) );
 FORWARD _PROTOTYPE( void msg_hardware, (void) );
-FORWARD _PROTOTYPE( void msg_sig_stop, (void) );
 FORWARD _PROTOTYPE( void msg_status, (message *m_ptr) );
 FORWARD _PROTOTYPE( int init_driver, (void) );
 FORWARD _PROTOTYPE( int open_sub_dev, (int sub_dev_nr, int operation) );
@@ -78,7 +77,8 @@ PRIVATE int device_available = 0;/*todo*/
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
-EXTERN _PROTOTYPE( void sef_cb_lu_prepare, (int state) );
+FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
+EXTERN _PROTOTYPE( int sef_cb_lu_prepare, (int state) );
 EXTERN _PROTOTYPE( int sef_cb_lu_state_isvalid, (int state) );
 EXTERN _PROTOTYPE( void sef_cb_lu_state_dump, (int state) );
 PUBLIC int is_status_msg_expected = FALSE;
@@ -104,9 +104,6 @@ PUBLIC void main(void)
                                case HARDWARE:
                                        msg_hardware();
                                        break;
-                               case PM_PROC_NR:
-                                       msg_sig_stop();
-                                       break;
                                default:
                                        dprint("%s: %d uncaught notify!\n",
                                                drv.DriverName, mess.m_type);
@@ -191,6 +188,9 @@ PRIVATE void sef_local_startup()
   sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid);
   sef_setcb_lu_state_dump(sef_cb_lu_state_dump);
 
+  /* Register signal callbacks. */
+  sef_setcb_signal_handler(sef_cb_signal_handler);
+
   /* Let SEF perform startup. */
   sef_startup();
 }
@@ -248,10 +248,38 @@ PRIVATE int init_driver(void) {
                error("%s: init driver couldn't set IRQ policy", drv.DriverName, i);
                return EIO;
        }
-       irq_hook_set = TRUE; /* now msg_sig_stop knows it must unregister policy*/
+       irq_hook_set = TRUE; /* now signal handler knows it must unregister policy*/
        return OK;
 }
 
+/*===========================================================================*
+ *                        sef_cb_signal_handler                             *
+ *===========================================================================*/
+PRIVATE void sef_cb_signal_handler(int signo)
+{
+       int i;
+       char irq;
+
+       /* Only check for termination signal, ignore anything else. */
+       if (signo != SIGTERM) return;
+
+       for (i = 0; i < drv.NrOfSubDevices; i++) {
+               drv_stop(i); /* stop all sub devices */
+       }
+       if (irq_hook_set) {
+               if (sys_irqdisable(&irq_hook_id) != OK) {
+                       error("Could not disable IRQ\n");
+               }
+               /* get irq from device driver*/
+               if (drv_get_irq(&irq) != OK) {
+                       error("Msg SIG_STOP Couldn't get IRQ");
+               }
+               /* remove the policy */
+               if (sys_irqrmpolicy(&irq_hook_id) != OK) {
+                       error("%s: Could not disable IRQ\n",drv.DriverName);
+               }
+       }
+}
 
 PRIVATE int msg_open (int minor_dev_nr) {
        int r, read_chan, write_chan, io_ctl;
@@ -627,29 +655,6 @@ PRIVATE void msg_status(message *m_ptr)
        is_status_msg_expected = FALSE;
 }
 
-
-PRIVATE void msg_sig_stop(void) 
-{
-       int i; char irq;
-       for (i = 0; i < drv.NrOfSubDevices; i++) {
-               drv_stop(i); /* stop all sub devices */
-       }
-       if (irq_hook_set) {
-               if (sys_irqdisable(&irq_hook_id) != OK) {
-                       error("Could not disable IRQ\n");
-               }
-               /* get irq from device driver*/
-               if (drv_get_irq(&irq) != OK) {
-                       error("Msg SIG_STOP Couldn't get IRQ");
-               }
-               /* remove the policy */
-               if (sys_irqrmpolicy(&irq_hook_id) != OK) {
-                       error("%s: Could not disable IRQ\n",drv.DriverName);
-               }
-       }
-}
-
-
 /* handle interrupt for specified sub device; DmaMode == DEV_WRITE_S*/
 PRIVATE void handle_int_write(int sub_dev_nr) 
 {
index 62ee35236cfbe44cae70b60682d3c81c8c352a26..58aa449ec84b65fda30f23d79c0e1d7744538511 100644 (file)
@@ -44,7 +44,7 @@ PRIVATE void load_state_info(void)
 /*===========================================================================*
  *                              sef_cb_lu_prepare                           *
  *===========================================================================*/
-PUBLIC void sef_cb_lu_prepare(int state)
+PUBLIC int sef_cb_lu_prepare(int state)
 {
   int is_ready;
 
@@ -75,9 +75,7 @@ PUBLIC void sef_cb_lu_prepare(int state)
   }
 
   /* Tell SEF if we are ready. */
-  if(is_ready) {
-      sef_lu_ready(OK);
-  }
+  return is_ready ? OK : ENOTREADY;
 }
 
 /*===========================================================================*
index be34a68a98bada05321642f69889a3e4f4d71fbf..4088f607f271fd2d3447fd412d77b9ce264a4a9a 100644 (file)
@@ -80,7 +80,6 @@ PRIVATE struct driver w_dtab = {
   w_transfer,  /* do the I/O */
   nop_cleanup, /* no cleanup needed */
   w_geometry,  /* tell the geometry of the disk */
-  nop_signal,          /* no cleanup needed on shutdown */
   nop_alarm,           /* ignore leftover alarms */
   nop_cancel,          /* ignore CANCELs */
   nop_select,          /* ignore selects */
index 40c19876e820de938535e72ec80fc8c7d4d6950a..cf5589dbe63202c294174b7ccd6ac907905be21c 100644 (file)
@@ -64,25 +64,10 @@ static char str_DevName[]     = "dec21140A:eth#?";
 PRIVATE dpeth_t de_table[DE_PORT_NR];
 PRIVATE const char *progname;
 
-int sef_cb_init(int type, sef_init_info_t *info)
-{
-  int r;
-  int fkeys, sfkeys;
-  endpoint_t tasknr;
-  /* Request function key for debug dumps */
-  fkeys = sfkeys = 0; bit_set(sfkeys, DE_FKEY);
-  if ((fkey_map(&fkeys, &sfkeys)) != OK) 
-    printf("%s: error using Shift+F%d key(%d)\n", str_DevName, DE_FKEY, errno);
-
-  /* Try to notify inet that we are present (again) */
-  r = ds_retrieve_label_num("inet", &tasknr);
-  if (r == OK)
-    notify(tasknr);
-  else if(r != ESRCH)
-    printf("%s unable to notify inet: %d\n", str_DevName, r);
-
-  return OK;
-}
+/* SEF functions and variables. */
+FORWARD _PROTOTYPE( void sef_local_startup, (void) );
+FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
+EXTERN char **env_argv;
 
 /*===========================================================================*
  *                             main                                         *
@@ -93,13 +78,9 @@ int main(int argc, char *argv[])
   message m;
   int r;
 
-  (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
-
+  /* SEF local startup. */
   env_setargs(argc, argv);
-
-  sef_setcb_init_fresh(sef_cb_init);
-  sef_setcb_init_restart(sef_cb_init);
-  sef_startup();
+  sef_local_startup();
   
   while (TRUE)
     {
@@ -125,9 +106,6 @@ int main(int argc, char *argv[])
            }
          }
          break;
-        case PM_PROC_NR:
-               exit(0);
-               break;
         default:
                printf("ignoring notify from %d\n", m.m_source);
                break;
@@ -152,6 +130,51 @@ int main(int argc, char *argv[])
     }
 }
 
+/*===========================================================================*
+ *                            sef_local_startup                             *
+ *===========================================================================*/
+PRIVATE void sef_local_startup()
+{
+  /* Register init callbacks. */
+  sef_setcb_init_fresh(sef_cb_init_fresh);
+  sef_setcb_init_restart(sef_setcb_init_fresh);
+
+  /* No support for live update yet. */
+
+  /* Register signal callbacks. */
+  sef_setcb_signal_handler(sef_cb_signal_handler_term);
+
+  /* Let SEF perform startup. */
+  sef_startup();
+}
+
+/*===========================================================================*
+ *                         sef_cb_init_fresh                                *
+ *===========================================================================*/
+PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
+{
+/* Initialize the DEC 21140A driver. */
+  int r;
+  int fkeys, sfkeys;
+  endpoint_t tasknr;
+
+  (progname=strrchr(env_argv[0],'/')) ? progname++ : (progname=env_argv[0]);
+
+  /* Request function key for debug dumps */
+  fkeys = sfkeys = 0; bit_set(sfkeys, DE_FKEY);
+  if ((fkey_map(&fkeys, &sfkeys)) != OK) 
+    printf("%s: error using Shift+F%d key(%d)\n", str_DevName, DE_FKEY, errno);
+
+  /* Try to notify inet that we are present (again) */
+  r = ds_retrieve_label_num("inet", &tasknr);
+  if (r == OK)
+    notify(tasknr);
+  else if(r != ESRCH)
+    printf("%s unable to notify inet: %d\n", str_DevName, r);
+
+  return OK;
+}
+
 PRIVATE void do_get_stat_s(message * mp)
 {
   int port, rc;
index 7e65e741ae5525fb99b8393266660d1377be3268..08d4588760040b248b822171242cc89fe3e2031f 100644 (file)
@@ -134,7 +134,6 @@ _PROTOTYPE( static void dp_reset, (dpeth_t *dep)                    );
 _PROTOTYPE( static void dp_check_ints, (dpeth_t *dep)                  );
 _PROTOTYPE( static void dp_recv, (dpeth_t *dep)                                );
 _PROTOTYPE( static void dp_send, (dpeth_t *dep)                                );
-_PROTOTYPE( static void dp8390_stop, (void)                            );
 _PROTOTYPE( static void dp_getblock, (dpeth_t *dep, int page,
                                size_t offset, size_t size, void *dst)  );
 _PROTOTYPE( static void dp_pio8_getblock, (dpeth_t *dep, int page,
@@ -232,6 +231,7 @@ PRIVATE int handle_hw_intr(void)
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
+FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
 EXTERN int env_argc;
 EXTERN char **env_argv;
 
@@ -257,17 +257,6 @@ int main(int argc, char *argv[])
                                case HARDWARE:
                                        r = handle_hw_intr();
                                        break;
-                               case PM_PROC_NR:
-                               {
-                                       sigset_t set;
-
-                                       if (getsigset(&set) != 0) break;
-
-                                       if (sigismember(&set, SIGTERM))
-                                               dp8390_stop();
-
-                                       break;
-                               }
                                case CLOCK:
                                        printf("dp8390: notify from CLOCK\n");
                                        break;
@@ -310,6 +299,9 @@ PRIVATE void sef_local_startup()
 
   /* No live update support for now. */
 
+  /* Register signal callbacks. */
+  sef_setcb_signal_handler(sef_cb_signal_handler);
+
   /* Let SEF perform startup. */
   sef_startup();
 }
@@ -350,6 +342,27 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
        return(OK);
 }
 
+/*===========================================================================*
+ *                        sef_cb_signal_handler                             *
+ *===========================================================================*/
+PRIVATE void sef_cb_signal_handler(int signo)
+{
+       message mess;
+       int i;
+
+       /* Only check for termination signal, ignore anything else. */
+       if (signo != SIGTERM) return;
+
+       for (i= 0; i<DE_PORT_NR; i++)
+       {
+               if (de_table[i].de_mode != DEM_ENABLED)
+                       continue;
+               mess.m_type= DL_STOP;
+               mess.DL_PORT= i;
+               do_stop(&mess);
+       }
+}
+
 #if 0
 /*===========================================================================*
  *                             dp8390_dump                                  *
@@ -403,24 +416,6 @@ void dp8390_dump()
 }
 #endif
 
-/*===========================================================================*
- *                             dp8390_stop                                  *
- *===========================================================================*/
-static void dp8390_stop()
-{
-       message mess;
-       int i;
-
-       for (i= 0; i<DE_PORT_NR; i++)
-       {
-               if (de_table[i].de_mode != DEM_ENABLED)
-                       continue;
-               mess.m_type= DL_STOP;
-               mess.DL_PORT= i;
-               do_stop(&mess);
-       }
-}
-
 #if ENABLE_PCI
 /*===========================================================================*
  *                             pci_conf                                     *
index c4bb20c616f4c2c914bb1ea17f9bdd2b17f2d8eb..3f1eef2071adf34f9db7c48a0fde28f23f002526 100644 (file)
@@ -544,24 +544,6 @@ static void do_watchdog(void *message)
   return;
 }
 
-PRIVATE void handle_system_signal(message *m)
-{
-       sigset_t set;
-       int port;
-
-       if (getsigset(&set) != 0) return;
-
-       if (sigismember(&set, SIGTERM)) {       /* Shut down */
-               for (port = 0; port < DE_PORT_NR; port += 1) {
-                       if (de_table[port].de_mode == DEM_ENABLED) {
-                               m->m_type = DL_STOP;
-                               m->DL_PORT = port;
-                               do_stop(m);
-                       }
-               }
-       }
-}
-
 PRIVATE void handle_hw_intr(void)
 {
        dpeth_t *dep;
@@ -582,6 +564,7 @@ PRIVATE void handle_hw_intr(void)
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
+FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
 EXTERN char **env_argv;
 
 /*
@@ -619,9 +602,6 @@ PUBLIC int main(int argc, char **argv)
                                /* Function key pressed */
                                do_dump(&m);
                                break;
-                       case PM_PROC_NR:
-                               handle_system_signal(&m);
-                               break;
                        default:        
                                /* Invalid message type */
                                panic(TypeErrMsg, m.m_type);
@@ -669,6 +649,9 @@ PRIVATE void sef_local_startup()
 
   /* No live update support for now. */
 
+  /* Register signal callbacks. */
+  sef_setcb_signal_handler(sef_cb_signal_handler);
+
   /* Let SEF perform startup. */
   sef_startup();
 }
@@ -706,4 +689,24 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
   return(OK);
 }
 
+/*===========================================================================*
+ *                         sef_cb_signal_handler                            *
+ *===========================================================================*/
+PRIVATE void sef_cb_signal_handler(int signo)
+{
+  int port;
+  message m;
+
+  /* Only check for termination signal, ignore anything else. */
+  if (signo != SIGTERM) return;
+
+  for (port = 0; port < DE_PORT_NR; port += 1) {
+      if (de_table[port].de_mode == DEM_ENABLED) {
+          m.m_type = DL_STOP;
+          m.DL_PORT = port;
+          do_stop(&m);
+      }
+  }
+}
+
 /** dp.c **/
index cd14b4d9086712e918b4596a96c167f193e8282b..117784a99f50ac94193ed6d0a833710670b9d236 100644 (file)
@@ -42,7 +42,6 @@ _PROTOTYPE( PRIVATE void e1000_readv_s, (message *mp, int from_int)   );
 _PROTOTYPE( PRIVATE void e1000_getstat_s, (message *mp)                        );
 _PROTOTYPE( PRIVATE void e1000_getname, (message *mp)                  );
 _PROTOTYPE( PRIVATE void e1000_interrupt, (message *mp)                        );
-_PROTOTYPE( PRIVATE void e1000_signal, (void)                           );
 _PROTOTYPE( PRIVATE int  e1000_link_changed, (e1000_t *e)              );
 _PROTOTYPE( PRIVATE void e1000_stop, (void)                             );
 _PROTOTYPE( PRIVATE e1000_t * e1000_port, (int port)                    );
@@ -63,6 +62,7 @@ _PROTOTYPE( PRIVATE void mess_reply, (message *req, message *reply)   );
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
+FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
 EXTERN int env_argc;
 EXTERN char **env_argv;
 
@@ -94,11 +94,7 @@ int main(int argc, char *argv[])
                 case HARDWARE:
                    e1000_interrupt(&m);
                    break;
-                
-               case PM_PROC_NR:
-                   e1000_signal();
-                   break;
-                
+
                case CLOCK:
                     break;
            }
@@ -129,6 +125,9 @@ PRIVATE void sef_local_startup()
 
   /* No live update support for now. */
 
+  /* Register signal callbacks. */
+  sef_setcb_signal_handler(sef_cb_signal_handler);
+
   /* Let SEF perform startup. */
   sef_startup();
 }
@@ -172,6 +171,19 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
     return(OK);
 }
 
+/*===========================================================================*
+ *                        sef_cb_signal_handler                             *
+ *===========================================================================*/
+PRIVATE void sef_cb_signal_handler(int signo)
+{
+    E1000_DEBUG(3, ("e1000: got signal\n"));
+
+    /* Only check for termination signal, ignore anything else. */
+    if (signo != SIGTERM) return;
+
+    e1000_stop();
+}
+
 /*===========================================================================*
  *                             e1000_init                                   *
  *===========================================================================*/
@@ -851,27 +863,6 @@ message *mp;
     }
 }
 
-/*===========================================================================*
- *                             e1000_signal                                 *
- *===========================================================================*/
-PRIVATE void e1000_signal(void)
-{
-    sigset_t sigset;
-
-    E1000_DEBUG(3, ("e1000: signal()\n"));
-
-    /* Try to obtain signal set from PM. */
-    if (getsigset(&sigset) != 0)
-    {
-        return;
-    }
-    /* Check for known signals. */
-    if (sigismember(&sigset, SIGTERM))
-    {
-       e1000_stop();
-    }
-}
-
 /*===========================================================================*
  *                             e1000_link_changed                           *
  *===========================================================================*/
index d13e2db8389b909fa106a76aa2b47a0fa3dcd1b0..6d62a85df9f88ef2abf7f484ceb82d3b854e1ffe 100644 (file)
@@ -76,6 +76,7 @@ static char *buf_array, *buffer;              /* contiguous buffer */
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
+FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
 EXTERN int env_argc;
 EXTERN char **env_argv;
 
@@ -368,28 +369,6 @@ static int parse_arguments(int argc, char *argv[])
        return OK;
 }
 
-/*===========================================================================*
- *                             got_signal                                   *
- *===========================================================================*/
-static void got_signal(void)
-{
-       sigset_t set;
-
-       /* See if PM sent us a SIGTERM. */
-       if (getsigset(&set) != 0) return;
-
-       if (!sigismember(&set, SIGTERM)) return;
-
-       /* If so, shut down this driver. */
-#if DEBUG
-       printf("Filter: shutdown...\n");
-#endif
-
-       driver_shutdown();
-
-       exit(0);
-}
-
 /*===========================================================================*
  *                             main                                         *
  *===========================================================================*/
@@ -413,9 +392,6 @@ int main(int argc, char *argv[])
                        m_in.m_type, m_in.m_source);
 #endif
 
-               if (is_notify(m_in.m_type) && m_in.m_source == PM_PROC_NR)
-                       got_signal();
-
                who_e = m_in.m_source;
                proc_e = m_in.IO_ENDPT;
                grant_id = (cp_grant_id_t) m_in.IO_GRANT;
@@ -461,6 +437,9 @@ PRIVATE void sef_local_startup(void)
 
        /* No live update support for now. */
 
+       /* Register signal callbacks. */
+       sef_setcb_signal_handler(sef_cb_signal_handler);
+
        /* Let SEF perform startup. */
        sef_startup();
 }
@@ -489,3 +468,21 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
        return(OK);
 }
 
+/*===========================================================================*
+ *                        sef_cb_signal_handler                             *
+ *===========================================================================*/
+PRIVATE void sef_cb_signal_handler(int signo)
+{
+       /* Only check for termination signal, ignore anything else. */
+       if (signo != SIGTERM) return;
+
+       /* If so, shut down this driver. */
+#if DEBUG
+       printf("Filter: shutdown...\n");
+#endif
+
+       driver_shutdown();
+
+       exit(0);
+}
+
index a0f8144cf01e82b74cfede15d10f664cb7cb81cb..ba43eb8eb04a12f8c6c2713cabf3ed2f7e30292a 100644 (file)
@@ -96,13 +96,10 @@ static void got_alarm(int sig)
  *===========================================================================*/
 void flt_sleep(int secs)
 {
-       /* Sleep for the given number of seconds. Don't use sleep(), as that
-        * will end up calling select() to VFS. This implementation could be
-        * improved.
-        */
-
-       signal(SIGALRM, got_alarm);
-       alarm(secs);
+       u32_t system_hz;
 
-       pause();
+       /* Sleep for the given number of seconds. */
+       system_hz = sys_hz();
+       tickdelay(system_hz * secs);
 }
+
index 9e0d1d49e2d2b5f734414969a8c40fe85a043762..6457591b6d3afd8c4a7eac733688809835e3d0ff 100644 (file)
@@ -264,7 +264,6 @@ FORWARD _PROTOTYPE( void f_reset, (void)                            );
 FORWARD _PROTOTYPE( int f_intr_wait, (void)                            );
 FORWARD _PROTOTYPE( int read_id, (void)                                );
 FORWARD _PROTOTYPE( int f_do_open, (struct driver *dp, message *m_ptr)         );
-FORWARD _PROTOTYPE( void floppy_stop, (struct driver *dp, sigset_t *set));
 FORWARD _PROTOTYPE( int test_read, (int density)                       );
 FORWARD _PROTOTYPE( void f_geometry, (struct partition *entry)         );
 
@@ -278,7 +277,6 @@ PRIVATE struct driver f_dtab = {
   f_transfer,  /* do the I/O */
   f_cleanup,   /* cleanup before sending reply to user process */
   f_geometry,  /* tell the geometry of the diskette */
-  floppy_stop, /* floppy cleanup on shutdown */
   f_expire_tmrs,/* expire all alarm timers */
   nop_cancel,
   nop_select,
@@ -292,7 +290,8 @@ static phys_bytes floppy_buf_phys;
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
-EXTERN _PROTOTYPE( void sef_cb_lu_prepare, (int state) );
+FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
+EXTERN _PROTOTYPE( int sef_cb_lu_prepare, (int state) );
 EXTERN _PROTOTYPE( int sef_cb_lu_state_isvalid, (int state) );
 EXTERN _PROTOTYPE( void sef_cb_lu_state_dump, (int state) );
 PUBLIC int last_transfer_opcode;
@@ -326,6 +325,9 @@ PRIVATE void sef_local_startup(void)
   sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid);
   sef_setcb_lu_state_dump(sef_cb_lu_state_dump);
 
+  /* Register signal callbacks. */
+  sef_setcb_signal_handler(sef_cb_signal_handler);
+
   /* Let SEF perform startup. */
   sef_startup();
 }
@@ -365,12 +367,25 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
   if ((s=sys_irqenable(&irq_hook_id)) != OK)
        panic("Couldn't enable IRQs: %d", s);
 
-  /* Ignore signals */
-  signal(SIGHUP, SIG_IGN);
-
   return(OK);
 }
 
+/*===========================================================================*
+ *                        sef_cb_signal_handler                             *
+ *===========================================================================*/
+PRIVATE void sef_cb_signal_handler(int signo)
+{
+  int s;
+
+  /* Only check for termination signal, ignore anything else. */
+  if (signo != SIGTERM) return;
+
+  /* Stop all activity and cleanly exit with the system. */
+  if ((s=sys_outb(DOR, ENABLE_INT)) != OK)
+      panic("Sys_outb failed: %d", s);
+  exit(0);
+}
+
 /*===========================================================================*
  *                             f_expire_tmrs                                *
  *===========================================================================*/
@@ -745,7 +760,7 @@ PRIVATE int dma_setup(
 
   /* First check the DMA memory address not to exceed maximum. */
   if (floppy_buf_phys != (floppy_buf_phys & DMA_ADDR_MASK)) {
-       printf("floppy: DMA denied because address out of range");
+       printf("floppy: DMA denied because address out of range\n");
        return(EIO);
   }
 
@@ -834,20 +849,6 @@ PRIVATE void stop_motor(timer_t *tp)
        panic("Sys_outb in stop_motor() failed: %d", s);
 }
 
-/*===========================================================================*
- *                             floppy_stop                                  *
- *===========================================================================*/
-PRIVATE void floppy_stop(struct driver *dp, sigset_t *set)
-{
-/* Stop all activity and cleanly exit with the system. */
-  int s;
-  if (sigismember(set, SIGTERM)) {
-      if ((s=sys_outb(DOR, ENABLE_INT)) != OK)
-               panic("Sys_outb in floppy_stop() failed: %d", s);
-      exit(0); 
-  }
-}
-
 /*===========================================================================*
  *                             seek                                         *
  *===========================================================================*/
index 0d4d1421a89c3b0a853a7a466705cf12c45c5dc3..870a9049af2bba211bd65b71f1f089ae0cf14d16 100644 (file)
@@ -22,7 +22,7 @@ EXTERN int last_transfer_opcode;
 /*===========================================================================*
  *                              sef_cb_lu_prepare                           *
  *===========================================================================*/
-PUBLIC void sef_cb_lu_prepare(int state)
+PUBLIC int sef_cb_lu_prepare(int state)
 {
   int is_ready;
 
@@ -43,9 +43,7 @@ PUBLIC void sef_cb_lu_prepare(int state)
   }
 
   /* Tell SEF if we are ready. */
-  if(is_ready) {
-      sef_lu_ready(OK);
-  }
+  return is_ready ? OK : ENOTREADY;
 }
 
 /*===========================================================================*
index 59430bb5bb2a5f0096c72db65475fca0dc9181dc..d7e943db3e1ccd1e892ff25701c7907d7de7626e 100644 (file)
@@ -250,7 +250,6 @@ _PROTOTYPE( static void fxp_check_ints, (fxp_t *fp)                 );
 _PROTOTYPE( static void fxp_watchdog_f, (timer_t *tp)                  );
 _PROTOTYPE( static int fxp_link_changed, (fxp_t *fp)                   );
 _PROTOTYPE( static void fxp_report_link, (fxp_t *fp)                   );
-_PROTOTYPE( static void fxp_stop, (void));
 _PROTOTYPE( static void reply, (fxp_t *fp, int err, int may_block)     );
 _PROTOTYPE( static void mess_reply, (message *req, message *reply)     );
 _PROTOTYPE( static u16_t eeprom_read, (fxp_t *fp, int reg)             );
@@ -292,6 +291,7 @@ PRIVATE void handle_hw_intr(void)
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
+FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
 EXTERN int env_argc;
 EXTERN char **env_argv;
 
@@ -317,17 +317,6 @@ int main(int argc, char *argv[])
                                case HARDWARE:
                                        handle_hw_intr();
                                        break;
-                               case PM_PROC_NR:
-                               {
-                                       sigset_t set;
-
-                                       if (getsigset(&set) != 0) break;
-
-                                       if (sigismember(&set, SIGTERM))
-                                               fxp_stop();
-
-                                       break;
-                               }
                                case CLOCK:
                                        fxp_expire_timers();
                                        break;
@@ -368,6 +357,9 @@ PRIVATE void sef_local_startup()
 
   /* No live update support for now. */
 
+  /* Register signal callbacks. */
+  sef_setcb_signal_handler(sef_cb_signal_handler);
+
   /* Let SEF perform startup. */
   sef_startup();
 }
@@ -415,6 +407,34 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
        return(OK);
 }
 
+/*===========================================================================*
+ *                        sef_cb_signal_handler                             *
+ *===========================================================================*/
+PRIVATE void sef_cb_signal_handler(int signo)
+{
+       int i;
+       port_t port;
+       fxp_t *fp;
+
+       /* Only check for termination signal, ignore anything else. */
+       if (signo != SIGTERM) return;
+
+       for (i= 0, fp= &fxp_table[0]; i<FXP_PORT_NR; i++, fp++)
+       {
+               if (fp->fxp_mode != FM_ENABLED)
+                       continue;
+               if (!(fp->fxp_flags & FF_ENABLED))
+                       continue;
+               port= fp->fxp_base_port;
+
+               /* Reset device */
+               if (debug)
+                       printf("%s: resetting device\n", fp->fxp_name);
+               fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET);
+       }
+       exit(0);
+}
+
 /*===========================================================================*
  *                             fxp_init                                     *
  *===========================================================================*/
@@ -2604,31 +2624,6 @@ resspeed:
        ;
 }
 
-/*===========================================================================*
- *                             fxp_stop                                     *
- *===========================================================================*/
-static void fxp_stop()
-{
-       int i;
-       port_t port;
-       fxp_t *fp;
-
-       for (i= 0, fp= &fxp_table[0]; i<FXP_PORT_NR; i++, fp++)
-       {
-               if (fp->fxp_mode != FM_ENABLED)
-                       continue;
-               if (!(fp->fxp_flags & FF_ENABLED))
-                       continue;
-               port= fp->fxp_base_port;
-
-               /* Reset device */
-               if (debug)
-                       printf("%s: resetting device\n", fp->fxp_name);
-               fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET);
-       }
-       exit(0);
-}
-
 /*===========================================================================*
  *                             reply                                        *
  *===========================================================================*/
diff --git a/drivers/hello/Makefile b/drivers/hello/Makefile
new file mode 100644 (file)
index 0000000..addbc5f
--- /dev/null
@@ -0,0 +1,44 @@
+#
+# Makefile for the hello driver.
+#
+DRIVER = hello
+
+#
+# Directories.
+#
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+d = ..
+
+#
+# Build Programs, Flags and Variables.
+#
+CC      = exec cc
+CFLAGS  = -I$i $(CPROFILE)
+LDFLAGS = -i -L../libdriver
+LIBS    = -ldriver -lsys
+OBJ     = hello.o
+
+# build local binary
+all build:      $(DRIVER)
+$(DRIVER):      $(OBJ)
+       $(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
+       install -S 128k $(DRIVER)
+
+# install with other drivers
+install:        /usr/sbin/$(DRIVER)
+/usr/sbin/$(DRIVER):    $(DRIVER)
+       install -o root -cs $? $@
+
+# clean up local files
+clean:
+       rm -f *.o $(DRIVER)
+
+depend:
+       mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
\ No newline at end of file
diff --git a/drivers/hello/hello.c b/drivers/hello/hello.c
new file mode 100644 (file)
index 0000000..129bceb
--- /dev/null
@@ -0,0 +1,214 @@
+#include "../drivers.h"
+#include "../libdriver/driver.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <minix/ds.h>
+#include "hello.h"
+
+/*
+ * Function prototypes for the hello driver.
+ */
+FORWARD _PROTOTYPE( char * hello_name,   (void) );
+FORWARD _PROTOTYPE( int hello_open,      (struct driver *d, message *m) );
+FORWARD _PROTOTYPE( int hello_close,     (struct driver *d, message *m) );
+FORWARD _PROTOTYPE( struct device * hello_prepare, (int device) );
+FORWARD _PROTOTYPE( int hello_transfer,  (int procnr, int opcode,
+                                          u64_t position, iovec_t *iov,
+                                          unsigned nr_req) );
+FORWARD _PROTOTYPE( void hello_geometry, (struct partition *entry) );
+
+/* SEF functions and variables. */
+FORWARD _PROTOTYPE( void sef_local_startup, (void) );
+FORWARD _PROTOTYPE( int sef_cb_init, (int type, sef_init_info_t *info) );
+FORWARD _PROTOTYPE( int sef_cb_lu_state_save, (int) );
+FORWARD _PROTOTYPE( int lu_state_restore, (void) );
+
+/* Entry points to the hello driver. */
+PRIVATE struct driver hello_tab =
+{
+    hello_name,
+    hello_open,
+    hello_close,
+    nop_ioctl,
+    hello_prepare,
+    hello_transfer,
+    nop_cleanup,
+    hello_geometry,
+    nop_alarm,
+    nop_cancel,
+    nop_select,
+    nop_ioctl,
+    do_nop,
+};
+
+/** Represents the /dev/hello device. */
+PRIVATE struct device hello_device;
+
+/** State variable to count the number of times the device has been opened. */
+PRIVATE int open_counter;
+
+PRIVATE char * hello_name(void)
+{
+    printf("hello_name()\n");
+    return "hello";
+}
+
+PRIVATE int hello_open(d, m)
+    struct driver *d;
+    message *m;
+{
+    printf("hello_open(). Called %d time(s).\n", ++open_counter);
+    return OK;
+}
+
+PRIVATE int hello_close(d, m)
+    struct driver *d;
+    message *m;
+{
+    printf("hello_close()\n");
+    return OK;
+}
+
+PRIVATE struct device * hello_prepare(dev)
+    int dev;
+{
+    hello_device.dv_base.lo = 0;
+    hello_device.dv_base.hi = 0;
+    hello_device.dv_size.lo = strlen(HELLO_MESSAGE);
+    hello_device.dv_size.hi = 0;
+    return &hello_device;
+}
+
+PRIVATE int hello_transfer(proc_nr, opcode, position, iov, nr_req)
+    int proc_nr;
+    int opcode;
+    u64_t position;
+    iovec_t *iov;
+    unsigned nr_req;
+{
+    int bytes, ret;
+
+    printf("hello_transfer()\n");
+
+    bytes = strlen(HELLO_MESSAGE) - position.lo < iov->iov_size ?
+            strlen(HELLO_MESSAGE) - position.lo : iov->iov_size;
+
+    if (bytes <= 0)
+    {
+        return OK;
+    }
+    switch (opcode)
+    {
+        case DEV_GATHER_S:
+            ret = sys_safecopyto(proc_nr, iov->iov_addr, 0,
+                                (vir_bytes) (HELLO_MESSAGE + position.lo),
+                                 bytes, D);
+            iov->iov_size -= bytes;
+            break;
+
+        default:
+            return EINVAL;
+    }
+    return ret;
+}
+
+PRIVATE void hello_geometry(entry)
+    struct partition *entry;
+{
+    printf("hello_geometry()\n");
+    entry->cylinders = 0;
+    entry->heads     = 0;
+    entry->sectors   = 0;
+}
+
+PRIVATE int sef_cb_lu_state_save(int state) {
+/* Save the state. */
+    ds_publish_u32("open_counter", open_counter, DSF_OVERWRITE);
+
+    return OK;
+}
+
+PRIVATE int lu_state_restore() {
+/* Restore the state. */
+    u32_t value;
+
+    ds_retrieve_u32("open_counter", &value);
+    ds_delete_u32("open_counter");
+    open_counter = (int) value;
+
+    return OK;
+}
+
+PRIVATE void sef_local_startup()
+{
+    /*
+     * Register init callbacks. Use the same function for all event types
+     */
+    sef_setcb_init_fresh(sef_cb_init);
+    sef_setcb_init_lu(sef_cb_init);
+    sef_setcb_init_restart(sef_cb_init);
+
+    /*
+     * Register live update callbacks.
+     */
+    /* - Agree to update immediately when LU is requested in a valid state. */
+    sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready);
+    /* - Support live update starting from any standard state. */
+    sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard);
+    /* - Register a custom routine to save the state. */
+    sef_setcb_lu_state_save(sef_cb_lu_state_save);
+
+    /* Let SEF perform startup. */
+    sef_startup();
+}
+
+PRIVATE int sef_cb_init(int type, sef_init_info_t *info)
+{
+/* Initialize the hello driver. */
+    int do_mapdriver = TRUE;
+
+    open_counter = 0;
+    switch(type) {
+        case SEF_INIT_FRESH:
+            printf("%s", HELLO_MESSAGE);
+        break;
+
+        case SEF_INIT_LU:
+            /* Restore the state. */
+            lu_state_restore();
+            do_mapdriver = FALSE;
+
+            printf("%sHey, I'm a new version!\n", HELLO_MESSAGE);
+        break;
+
+        case SEF_INIT_RESTART:
+            printf("%sHey, I've just been restarted!\n", HELLO_MESSAGE);
+        break;
+    }
+
+    /* Map major number to our process. */
+    if (do_mapdriver && mapdriver("hello", HELLO_MAJOR, STYLE_DEV, TRUE) != OK)
+    {
+        printf("hello: mapdriver() failed: %s\n",
+                strerror(errno));
+        return EINVAL;
+    }
+
+    /* Initialization completed successfully. */
+    return OK;
+}
+
+PUBLIC int main(int argc, char **argv)
+{
+    /*
+     * Perform initialization.
+     */
+    sef_local_startup();
+
+    /*
+     * Run the main loop.
+     */
+    driver_task(&hello_tab, DRIVER_STD);
+    return OK;
+}
+
diff --git a/drivers/hello/hello.h b/drivers/hello/hello.h
new file mode 100644 (file)
index 0000000..5725b3d
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __HELLO_H
+#define __HELLO_H
+
+/** The Hello, World! message. */
+#define HELLO_MESSAGE "Hello, World!\n"
+
+#endif /* __HELLO_H */
index 9b12b2d7f813bb270d2b0d4ab785f4aefd17c443..26d5456c89ed7a68d062eebc1741a4eef6550220 100644 (file)
@@ -121,7 +121,6 @@ _PROTOTYPE( static void do_stop, (message *mp)                          );
 _PROTOTYPE( static void do_getname, (message *mp)                       );
 
 _PROTOTYPE( static void lance_dump, (void)            );
-_PROTOTYPE( static void lance_stop, (void)            );
 _PROTOTYPE( static void getAddressing, (int devind, ether_card_t *ec)   );
 
 /* probe+init LANCE cards */
@@ -264,6 +263,7 @@ phys_bytes lance_buf_phys;
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
+FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
 EXTERN char **env_argv;
 
 /*===========================================================================*
@@ -317,17 +317,6 @@ void main( int argc, char **argv )
                                      }
                              }
                              break;
-                     case PM_PROC_NR:
-                     {
-                             sigset_t set;
-
-                             if (getsigset(&set) != 0) break;
-
-                             if (sigismember(&set, SIGTERM))
-                                     lance_stop();
-
-                             break;
-                     }
                      default:
                              panic("illegal notify source: %d", m.m_source);
              }
@@ -373,6 +362,9 @@ PRIVATE void sef_local_startup()
 
   /* No live update support for now. */
 
+  /* Register signal callbacks. */
+  sef_setcb_signal_handler(sef_cb_signal_handler);
+
   /* Let SEF perform startup. */
   sef_startup();
 }
@@ -410,7 +402,34 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
    else if (r != ESRCH)
       printf("lance: ds_retrieve_label_num failed for 'inet': %d\n", r);
 
-  return(OK);
+   return OK;
+}
+
+/*===========================================================================*
+ *                        sef_cb_signal_handler                             *
+ *===========================================================================*/
+PRIVATE void sef_cb_signal_handler(int signo)
+{
+   message mess;
+   int i;
+
+   /* Only check for termination signal, ignore anything else. */
+   if (signo != SIGTERM) return;
+
+   for (i= 0; i<EC_PORT_NR_MAX; i++)
+   {
+      if (ec_table[i].mode != EC_ENABLED)
+         continue;
+      mess.m_type= DL_STOP;
+      mess.DL_PORT= i;
+      do_stop(&mess);
+   }
+
+#if VERBOSE
+   printf("LANCE driver stopped.\n");
+#endif
+
+   exit(0);
 }
 
 /*===========================================================================*
@@ -478,31 +497,6 @@ static void lance_dump()
    }
 }
 
-/*===========================================================================*
- *                              lance_stop                                   *
- *===========================================================================*/
-static void lance_stop()
-{
-   message mess;
-   int i;
-
-   for (i= 0; i<EC_PORT_NR_MAX; i++)
-   {
-      if (ec_table[i].mode != EC_ENABLED)
-         continue;
-      mess.m_type= DL_STOP;
-      mess.DL_PORT= i;
-      do_stop(&mess);
-   }
-
-#if VERBOSE
-   printf("LANCE driver stopped.\n");
-#endif
-
-   exit( 0 );
-}
-
-
 /*===========================================================================*
  *                              do_init                                      *
  *===========================================================================*/
index 5d1c2f32d39ce5bed47114b7904bc92adc72f0d9..8e3f7385bb8277d7e078171cd7bedb55c66c573c 100644 (file)
@@ -161,14 +161,6 @@ int type;          /* Driver type (DRIVER_STD or DRIVER_ASYN) */
                                        (*dp->dr_hw_int)(dp, &mess);
                                }
                                break;
-                       case PM_PROC_NR:
-                               if (getsigset(&set) != 0) break;
-                               (*dp->dr_signal)(dp, &set);
-                               break;
-                       case SYSTEM:
-                               set = mess.NOTIFY_ARG;
-                               (*dp->dr_signal)(dp, &set);
-                               break;
                        case CLOCK:
                                (*dp->dr_alarm)(dp, &mess);     
                                break;
@@ -380,16 +372,6 @@ message *mp;
   return(ENOTTY);
 }
 
-/*============================================================================*
- *                             nop_signal                                    *
- *============================================================================*/
-PUBLIC void nop_signal(dp, set)
-struct driver *dp;
-sigset_t *set;
-{
-/* Default action for signal is to ignore. */
-}
-
 /*============================================================================*
  *                             nop_alarm                                     *
  *============================================================================*/
index 565be666a9c17aa80f9dd0ff925cc16aa138169e..f2956929fd305490bb6f30b602a0acbd70f72784 100644 (file)
@@ -37,7 +37,6 @@ struct driver {
                                        iovec_t *iov, unsigned nr_req) );
   _PROTOTYPE( void (*dr_cleanup), (void) );
   _PROTOTYPE( void (*dr_geometry), (struct partition *entry) );
-  _PROTOTYPE( void (*dr_signal), (struct driver *dp, sigset_t *set) );
   _PROTOTYPE( void (*dr_alarm), (struct driver *dp, message *m_ptr) );
   _PROTOTYPE( int (*dr_cancel), (struct driver *dp, message *m_ptr) );
   _PROTOTYPE( int (*dr_select), (struct driver *dp, message *m_ptr) );
@@ -63,7 +62,6 @@ _PROTOTYPE( int do_nop, (struct driver *dp, message *m_ptr) );
 _PROTOTYPE( struct device *nop_prepare, (int device) );
 _PROTOTYPE( void nop_cleanup, (void) );
 _PROTOTYPE( void nop_task, (void) );
-_PROTOTYPE( void nop_signal, (struct driver *dp, sigset_t *set) );
 _PROTOTYPE( void nop_alarm, (struct driver *dp, message *m_ptr) );
 _PROTOTYPE( int nop_cancel, (struct driver *dp, message *m_ptr) );
 _PROTOTYPE( int nop_select, (struct driver *dp, message *m_ptr) );
index 793b415d776ca1126dd5e2332d83454a23b0a7ec..474c36655481c60018c2bcfabeb163bac04b8b7b 100644 (file)
@@ -36,7 +36,7 @@ PRIVATE void load_state_info(void)
 /*===========================================================================*
  *                              sef_cb_lu_prepare                           *
  *===========================================================================*/
-PUBLIC void sef_cb_lu_prepare(int state)
+PUBLIC int sef_cb_lu_prepare(int state)
 {
   int is_ready;
 
@@ -62,9 +62,7 @@ PUBLIC void sef_cb_lu_prepare(int state)
   }
 
   /* Tell SEF if we are ready. */
-  if(is_ready) {
-      sef_lu_ready(OK);
-  }
+  return is_ready ? OK : ENOTREADY;
 }
 
 /*===========================================================================*
index 524253da8f91a9ee77c18f01c71ed383c3a286e3..1d553f2193d29d2c0ecdf277b92e0619d83d22d6 100644 (file)
@@ -29,7 +29,6 @@ FORWARD _PROTOTYPE( int log_transfer, (int proc_nr, int opcode, u64_t position,
 FORWARD _PROTOTYPE( int log_do_open, (struct driver *dp, message *m_ptr) );
 FORWARD _PROTOTYPE( int log_cancel, (struct driver *dp, message *m_ptr) );
 FORWARD _PROTOTYPE( int log_select, (struct driver *dp, message *m_ptr) );
-FORWARD _PROTOTYPE( void log_signal, (struct driver *dp, sigset_t *set) );
 FORWARD _PROTOTYPE( int log_other, (struct driver *dp, message *m_ptr) );
 FORWARD _PROTOTYPE( void log_geometry, (struct partition *entry) );
 FORWARD _PROTOTYPE( int subread, (struct logdevice *log, int count, int proc_nr, vir_bytes user_vir, size_t) );
@@ -44,7 +43,6 @@ PRIVATE struct driver log_dtab = {
   log_transfer,        /* do the I/O */
   nop_cleanup, /* no need to clean up */
   log_geometry,        /* geometry */
-  log_signal,  /* handle system signal */
   nop_alarm,   /* no alarm */
   log_cancel,  /* CANCEL request */
   log_select,  /* DEV_SELECT request */
@@ -57,9 +55,10 @@ extern int device_caller;
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
-EXTERN _PROTOTYPE( void sef_cb_lu_prepare, (int state) );
+EXTERN _PROTOTYPE( int sef_cb_lu_prepare, (int state) );
 EXTERN _PROTOTYPE( int sef_cb_lu_state_isvalid, (int state) );
 EXTERN _PROTOTYPE( void sef_cb_lu_state_dump, (int state) );
+FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
 
 /*===========================================================================*
  *                                main                                      *
@@ -90,6 +89,9 @@ PRIVATE void sef_local_startup()
   sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid);
   sef_setcb_lu_state_dump(sef_cb_lu_state_dump);
 
+  /* Register signal callbacks. */
+  sef_setcb_signal_handler(sef_cb_signal_handler);
+
   /* Let SEF perform startup. */
   sef_startup();
 }
@@ -118,6 +120,17 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
   return(OK);
 }
 
+/*===========================================================================*
+ *                        sef_cb_signal_handler                             *
+ *===========================================================================*/
+PRIVATE void sef_cb_signal_handler(int signo)
+{
+  /* Only check for a pending message from the kernel, ignore anything else. */
+  if (signo != SIGKMESS) return;
+
+  do_new_kmess(SYSTEM);
+}
+
 /*===========================================================================*
  *                              log_name                                    *
  *===========================================================================*/
@@ -395,20 +408,6 @@ message *m_ptr;
   return(OK);
 }
 
-
-/*============================================================================*
- *                             log_signal                                    *
- *============================================================================*/
-PRIVATE void log_signal(dp, set)
-struct driver *dp;
-sigset_t *set;
-{
-  if (sigismember(set, SIGKMESS)) {
-       do_new_kmess(SYSTEM);
-  }    
-}
-
-       
 /*============================================================================*
  *                             log_other                                     *
  *============================================================================*/
index 3edf779077e83bd46594c04d7e9054506a6ad715..8eaad90e26edf9df56c1ddd78e29ab108ad7fb04 100644 (file)
@@ -64,7 +64,6 @@ PRIVATE struct driver m_dtab = {
   m_transfer,  /* do the I/O */
   nop_cleanup, /* no need to clean up */
   m_geometry,  /* memory device "geometry" */
-  nop_signal,  /* system signals */
   nop_alarm,
   nop_cancel,
   nop_select,
@@ -121,15 +120,9 @@ PRIVATE void sef_local_startup()
 PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
 {
 /* Initialize the memory driver. */
-  struct sigaction sa;
   u32_t ramdev_size;
   int i, s;
 
-  sa.sa_handler = SIG_MESS;
-  sigemptyset(&sa.sa_mask);
-  sa.sa_flags = 0;
-  if (sigaction(SIGTERM,&sa,NULL)<0) panic("sigaction failed: %d", errno);
-
   /* Initialize all minor devices one by one. */
   if (OK != (s=sys_getkinfo(&kinfo))) {
       panic("Couldn't get kernel information: %d", s);
index a03e4a914de0f9afea6ee28bd0ee48802744a732..6e23c4a1359069475000e3108c1b220473b08e9f 100644 (file)
@@ -5,7 +5,7 @@ exec >/dev/log
 exec 2>/dev/log
 exec </dev/null
 
-/bin/service up /bin/pci -config /etc/system.conf
+/bin/service -c up /bin/pci -config /etc/system.conf
 /bin/service -c up /bin/floppy -config /etc/system.conf -dev /dev/fd0
 if [ X`/bin/sysenv bios_wini` = Xyes ]
 then
index c57a3dfb58ddc6e5208d7d85e0cd049c57cf009e..79638899e08a4ca018654b5c522084de6fbe34bf 100644 (file)
@@ -207,7 +207,6 @@ _PROTOTYPE (static void or_getstat_s, (message * mp));
 _PROTOTYPE (static void print_linkstatus, (t_or * orp, u16_t status));
 _PROTOTYPE (static int  or_get_recvd_packet, (t_or *orp, u16_t rxfid, 
                                        u8_t *databuf));
-_PROTOTYPE (static void orinoco_stop, (void));
 _PROTOTYPE (static void or_reset, (void));
 _PROTOTYPE (static void or_watchdog_f, (timer_t *tp) );
 _PROTOTYPE (static void setup_wepkey, (t_or *orp, char *wepkey0) );
@@ -231,6 +230,7 @@ PRIVATE const char *progname;
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
+FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
 EXTERN char **env_argv;
 
 /*****************************************************************************
@@ -263,17 +263,6 @@ int main(int argc, char *argv[]) {
                                case TTY_PROC_NR: 
                                        or_dump(&m);    
                                        break;
-                               case PM_PROC_NR:
-                               {
-                                       sigset_t set;
-
-                                       if (getsigset(&set) != 0) break;
-
-                                       if (sigismember(&set, SIGTERM))
-                                               orinoco_stop();
-
-                                       break;
-                               }
                                default:
                                        panic("orinoco: illegal notify from: %d",
                                                m.m_source);
@@ -331,6 +320,9 @@ PRIVATE void sef_local_startup()
 
   /* No live update support for now. */
 
+  /* Register signal callbacks. */
+  sef_setcb_signal_handler(sef_cb_signal_handler);
+
   /* Let SEF perform startup. */
   sef_startup();
 }
@@ -366,6 +358,25 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
        return(OK);
 }
 
+/*===========================================================================*
+ *                        sef_cb_signal_handler                             *
+ *===========================================================================*/
+PRIVATE void sef_cb_signal_handler(int signo)
+{
+       int i;
+       t_or *orp;
+
+       /* Only check for termination signal, ignore anything else. */
+       if (signo != SIGTERM) return;
+
+       for (i= 0, orp= &or_table[0]; i<OR_PORT_NR; i++, orp++) {
+               if (orp->or_mode != OR_M_ENABLED)
+                       continue;
+               /* TODO: send a signal to the card to shut it down */
+       }
+       exit(0);
+}
+
 /*****************************************************************************
  *                    check_int_events                                       *
  *                                                                           *
@@ -432,25 +443,6 @@ static int do_hard_int(void) {
        }
 }
 
-
-
-/*****************************************************************************
- *                orinoco_stop                                               *
- *                                                                           *
- * Stops the card. The signal to the card itself is not implemented yet.     *
- *****************************************************************************/
-static void orinoco_stop () {
-       int i;
-       t_or *orp;
-
-       for (i= 0, orp= &or_table[0]; i<OR_PORT_NR; i++, orp++) {
-               if (orp->or_mode != OR_M_ENABLED)
-                       continue;
-               /* TODO: send a signal to the card to shut it down */
-       }
-       exit(0);
-}
-
 /*****************************************************************************
  *                or_reset                                                   *
  *                                                                           *
index 982aff1e5b24f0746db47568bbb6f2f9c4ea1e8d..f96349dac3c4eec702b9fe4623d938c6cccdda26 100644 (file)
@@ -55,14 +55,7 @@ int main(void)
                }
 
                if (is_notify(m.m_type)) {
-                       switch (_ENDPOINT_P(m.m_source)) {
-                               case PM_PROC_NR:
-                                       break;
-                               default:
-                                       printf("PCI: got notify from %d\n",
-                                                               m.m_source);
-                                       break;
-                       }
+                       printf("PCI: got notify from %d\n", m.m_source);
 
                        /* done, get a new message */
                        continue;
index 3ac5bcd7a52ecf2c22f09034f2b26ea7852b4d32..5c8485c6ec8e5d484a16b336c9b353005bc2bd38 100644 (file)
@@ -365,7 +365,7 @@ endpoint_t proc;
                printf("pci:pci_reserve2: bad devind: %d\n", devind);
                return EINVAL;
        }
-       if(pcidev[devind].pd_inuse)
+       if(pcidev[devind].pd_inuse && pcidev[devind].pd_proc != proc)
                return EBUSY;
        pcidev[devind].pd_inuse= 1;
        pcidev[devind].pd_proc= proc;
index b65d61b017790bcd31132d13aa935226016e3427..de040947ef2e1219608a48ba78cdbd0e6dd075e9 100644 (file)
@@ -11,7 +11,7 @@ EXTERN int is_status_msg_expected;
 /*===========================================================================*
  *                              sef_cb_lu_prepare                           *
  *===========================================================================*/
-PUBLIC void sef_cb_lu_prepare(int state)
+PUBLIC int sef_cb_lu_prepare(int state)
 {
   int is_ready;
 
@@ -34,9 +34,7 @@ PUBLIC void sef_cb_lu_prepare(int state)
   }
 
   /* Tell SEF if we are ready. */
-  if(is_ready) {
-      sef_lu_ready(OK);
-  }
+  return is_ready ? OK : ENOTREADY;
 }
 
 /*===========================================================================*
index 92447c37cd0bb816a68945e240e0c96e3ee038a8..152310a7d141a55332947199c69fd040d9ced9a5 100644 (file)
@@ -111,12 +111,10 @@ FORWARD _PROTOTYPE( void prepare_output, (void) );
 FORWARD _PROTOTYPE( void do_initialize, (void) );
 FORWARD _PROTOTYPE( void reply, (int code,int replyee,int proc,int status));
 FORWARD _PROTOTYPE( void do_printer_output, (void) );
-FORWARD _PROTOTYPE( void do_signal, (void) );
 
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
-FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
-EXTERN _PROTOTYPE( void sef_cb_lu_prepare, (int state) );
+EXTERN _PROTOTYPE( int sef_cb_lu_prepare, (int state) );
 EXTERN _PROTOTYPE( int sef_cb_lu_state_isvalid, (int state) );
 EXTERN _PROTOTYPE( void sef_cb_lu_state_dump, (int state) );
 PUBLIC int is_status_msg_expected = FALSE;
@@ -140,9 +138,6 @@ PUBLIC void main(void)
                        case HARDWARE:
                                do_printer_output();
                                break;
-                       case PM_PROC_NR:
-                               do_signal();
-                               break;
                        default:
                                reply(TASK_REPLY, pr_mess.m_source,
                                                pr_mess.IO_ENDPT, EINVAL);
@@ -171,53 +166,20 @@ PUBLIC void main(void)
  *===========================================================================*/
 PRIVATE void sef_local_startup()
 {
-  /* Register init callbacks. */
-  sef_setcb_init_fresh(sef_cb_init_fresh);
-  sef_setcb_init_lu(sef_cb_init_fresh);
-  sef_setcb_init_restart(sef_cb_init_fresh);
+  /* Nothing to on initialization. */
 
   /* Register live update callbacks. */
   sef_setcb_lu_prepare(sef_cb_lu_prepare);
   sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid);
   sef_setcb_lu_state_dump(sef_cb_lu_state_dump);
 
+  /* Register signal callbacks. */
+  sef_setcb_signal_handler(sef_cb_signal_handler_term);
+
   /* Let SEF perform startup. */
   sef_startup();
 }
 
-/*===========================================================================*
- *                         sef_cb_init_fresh                                *
- *===========================================================================*/
-PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
-{
-/* Initialize the printer driver. */
-  struct sigaction sa;
-
-  /* Install signal handlers. Ask PM to transform signal into message. */
-  sa.sa_handler = SIG_MESS;
-  sigemptyset(&sa.sa_mask);
-  sa.sa_flags = 0;
-  if (sigaction(SIGTERM,&sa,NULL)<0) panic("sigaction failed: %d", errno);
-
-  return(OK);
-}
-
-/*===========================================================================*
- *                              do_signal                                   *
- *===========================================================================*/
-PRIVATE void do_signal()
-{
-  sigset_t sigset;
-
-  if (getsigset(&sigset) != 0) return;
-  
-  /* Expect a SIGTERM signal when this server must shutdown. */
-  if (sigismember(&sigset, SIGTERM)) {
-       exit(0);
-  } 
-  /* Ignore all other signals. */
-}
-
 /*===========================================================================*
  *                             do_write                                     *
  *===========================================================================*/
index 4e383a677cc90f83837b486d01744b811978489e..773e378480d6d8b837845088a683e650d1c665ca 100644 (file)
@@ -40,7 +40,6 @@ PRIVATE struct driver r_dtab = {
   r_transfer,  /* do the I/O */
   nop_cleanup, /* no need to clean up */
   r_geometry,  /* device "geometry" */
-  nop_signal,  /* system signals */
   r_random,    /* get randomness from kernel (alarm) */
   nop_cancel,
   nop_select,
index 140aca50d6c77d89183fb82de5beed016018ecbb..c5c30a073886059af64955075b5c71d8a954cead 100644 (file)
@@ -45,7 +45,6 @@
 #include <stdio.h>
 #include <time.h>
 #include <errno.h>
-#include <signal.h>
 #include <minix/type.h>
 #include <minix/const.h>
 #include <minix/syslib.h>
@@ -229,32 +228,15 @@ void errmsg(char *s)
 /*                                                                     */
 /***********************************************************************/
 
-int dead;
-void timeout(int sig) { dead= 1; }
-
 void get_time(struct tm *t)
 {
   int osec, n;
   unsigned long i;
-  struct sigaction sa;
-
-  /* Start a timer to keep us from getting stuck on a dead clock. */
-  sigemptyset(&sa.sa_mask);
-  sa.sa_flags = 0;
-  sa.sa_handler = timeout;
-  sigaction(SIGALRM, &sa, NULL);
-  dead = 0;
-  alarm(5);
 
   do {
        osec = -1;
        n = 0;
        do {
-               if (dead) {
-                       printf("readclock: CMOS clock appears dead\n");
-                       exit(1);
-               }
-
                /* Clock update in progress? */
                if (read_register(RTC_REG_A) & RTC_A_UIP) continue;
 
index 19e064132edcd8b708711f02567083a714d3fa11..d6af2684feab4b5bba809113781bc7301eac01bc 100644 (file)
@@ -39,7 +39,7 @@ PRIVATE void load_state_info(void)
 /*===========================================================================*
  *                              sef_cb_lu_prepare                           *
  *===========================================================================*/
-PUBLIC void sef_cb_lu_prepare(int state)
+PUBLIC int sef_cb_lu_prepare(int state)
 {
   int is_ready;
 
@@ -69,9 +69,7 @@ PUBLIC void sef_cb_lu_prepare(int state)
   }
 
   /* Tell SEF if we are ready. */
-  if(is_ready) {
-      sef_lu_ready(OK);
-  }
+  return is_ready ? OK : ENOTREADY;
 }
 
 /*===========================================================================*
index fddf454b15bc8bda116f223a7932e870500bfbcb..fe3f87fabc1ab621ffa06d1703d38a59256fa60c 100644 (file)
@@ -171,7 +171,6 @@ _PROTOTYPE( static void rl_getstat_s, (message *mp)                 );
 _PROTOTYPE( static void rl_getname, (message *mp)                      );
 _PROTOTYPE( static void reply, (re_t *rep, int err, int may_block)     );
 _PROTOTYPE( static void mess_reply, (message *req, message *reply)     );
-_PROTOTYPE( static void rtl8139_stop, (void)                           );
 _PROTOTYPE( static void check_int_events, (void)                               );
 _PROTOTYPE( static int do_hard_int, (void)                             );
 _PROTOTYPE( static void rtl8139_dump, (message *m)                             );
@@ -195,7 +194,8 @@ PRIVATE u32_t system_hz;
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
-EXTERN _PROTOTYPE( void sef_cb_lu_prepare, (int state) );
+FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
+EXTERN _PROTOTYPE( int sef_cb_lu_prepare, (int state) );
 EXTERN _PROTOTYPE( int sef_cb_lu_state_isvalid, (int state) );
 EXTERN _PROTOTYPE( void sef_cb_lu_state_dump, (int state) );
 EXTERN int env_argc;
@@ -243,17 +243,6 @@ int main(int argc, char *argv[])
                                case TTY_PROC_NR:
                                        rtl8139_dump(&m);
                                        break;
-                               case PM_PROC_NR:
-                               {
-                                       sigset_t set;
-
-                                       if (getsigset(&set) != 0) break;
-
-                                       if (sigismember(&set, SIGTERM))
-                                               rtl8139_stop();
-
-                                       break;
-                               }
                                default:
                                        panic("illegal notify from: %d",
                                        m.m_source);
@@ -299,6 +288,9 @@ PRIVATE void sef_local_startup()
   sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid);
   sef_setcb_lu_state_dump(sef_cb_lu_state_dump);
 
+  /* Register signal callbacks. */
+  sef_setcb_signal_handler(sef_cb_signal_handler);
+
   /* Let SEF perform startup. */
   sef_startup();
 }
@@ -351,6 +343,26 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
        return(OK);
 }
 
+/*===========================================================================*
+ *                        sef_cb_signal_handler                             *
+ *===========================================================================*/
+PRIVATE void sef_cb_signal_handler(int signo)
+{
+       int i;
+       re_t *rep;
+
+       /* Only check for termination signal, ignore anything else. */
+       if (signo != SIGTERM) return;
+
+       for (i= 0, rep= &re_table[0]; i<RE_PORT_NR; i++, rep++)
+       {
+               if (rep->re_mode != REM_ENABLED)
+                       continue;
+               rl_outb(rep->re_base_port, RL_CR, 0);
+       }
+       exit(0);
+}
+
 /*===========================================================================*
  *                             check_int_events                             *
  *===========================================================================*/
@@ -370,23 +382,6 @@ static void check_int_events(void)
                        }
 }
 
-/*===========================================================================*
- *                             rtl8139_stop                                 *
- *===========================================================================*/
-static void rtl8139_stop()
-{
-       int i;
-       re_t *rep;
-
-       for (i= 0, rep= &re_table[0]; i<RE_PORT_NR; i++, rep++)
-       {
-               if (rep->re_mode != REM_ENABLED)
-                       continue;
-               rl_outb(rep->re_base_port, RL_CR, 0);
-       }
-       exit(0);
-}
-
 /*===========================================================================*
  *                             rtl8139_dump                                 *
  *===========================================================================*/
index deacc912afda7188116b93df62cb207ef5d8a863..0dd7992b762704f53a56ae28de7f510321488314 100644 (file)
@@ -259,7 +259,6 @@ _PROTOTYPE( static void rl_getstat_s, (message *mp)                 );
 _PROTOTYPE( static void rl_getname, (message *mp)                      );
 _PROTOTYPE( static void reply, (re_t *rep, int err, int may_block)     );
 _PROTOTYPE( static void mess_reply, (message *req, message *reply)     );
-_PROTOTYPE( static void rtl8169_stop, (void)                           );
 _PROTOTYPE( static void check_int_events, (void)                       );
 _PROTOTYPE( static void do_hard_int, (void)                            );
 _PROTOTYPE( static void rtl8169_dump, (void)                           );
@@ -280,6 +279,7 @@ u32_t system_hz;
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
+FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
 EXTERN int env_argc;
 EXTERN char **env_argv;
 
@@ -321,17 +321,6 @@ int main(int argc, char *argv[])
                                        check_int_events();
                                }
                                break ;
-                       case PM_PROC_NR:
-                       {
-                               sigset_t set;
-
-                               if (getsigset(&set) != 0) break;
-
-                               if (sigismember(&set, SIGTERM))
-                                       rtl8169_stop();
-
-                               break;
-                       }
                        default:
                                panic("illegal notify from: %d",        m.m_type);
                        }
@@ -364,6 +353,9 @@ PRIVATE void sef_local_startup()
 
   /* No live update support for now. */
 
+  /* Register signal callbacks. */
+  sef_setcb_signal_handler(sef_cb_signal_handler);
+
   /* Let SEF perform startup. */
   sef_startup();
 }
@@ -409,6 +401,26 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
        return(OK);
 }
 
+/*===========================================================================*
+ *                        sef_cb_signal_handler                             *
+ *===========================================================================*/
+PRIVATE void sef_cb_signal_handler(int signo)
+{
+       int i;
+       re_t *rep;
+
+       /* Only check for termination signal, ignore anything else. */
+       if (signo != SIGTERM) return;
+
+       for (i = 0, rep = &re_table[0]; i < RE_PORT_NR; i++, rep++) {
+               if (rep->re_mode != REM_ENABLED)
+                       continue;
+               rl_outb(rep->re_base_port, RL_CR, 0);
+       }
+
+       exit(0);
+}
+
 static void mdio_write(U16_t port, int regaddr, int value)
 {
        int i;
@@ -466,23 +478,6 @@ static void check_int_events(void)
        }
 }
 
-/*===========================================================================*
- *                             rtl8169_stop                                 *
- *===========================================================================*/
-static void rtl8169_stop()
-{
-       int i;
-       re_t *rep;
-
-       for (i = 0, rep = &re_table[0]; i < RE_PORT_NR; i++, rep++) {
-               if (rep->re_mode != REM_ENABLED)
-                       continue;
-               rl_outb(rep->re_base_port, RL_CR, 0);
-       }
-
-       exit(0);
-}
-
 static void rtl8169_update_stat(re_t *rep)
 {
        port_t port;
index 26722e66198e2902f71e53952ecb7ffaedacac9f..7e9a1bf41e00e4727696fa7b160b4f0d3899e9a9 100644 (file)
@@ -79,7 +79,7 @@ PRIVATE int reviveProcNr;
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
-EXTERN _PROTOTYPE( void sef_cb_lu_prepare, (int state) );
+EXTERN _PROTOTYPE( int sef_cb_lu_prepare, (int state) );
 EXTERN _PROTOTYPE( int sef_cb_lu_state_isvalid, (int state) );
 EXTERN _PROTOTYPE( void sef_cb_lu_state_dump, (int state) );
 PUBLIC int is_processing = FALSE;
@@ -108,8 +108,6 @@ PUBLIC void main()
                                case HARDWARE:
                                        dsp_hardware_msg();
                                        continue; /* don't reply */
-                               case SYSTEM:
-                                       continue; /* don't reply */
                                default:
                                        r = EINVAL;
                        }
index 83f915c563e7fda17fa87caddc685962ef085382..94a3583b9510f65dac8e0898cbf928e808ac5663 100644 (file)
@@ -12,7 +12,7 @@ EXTERN int is_status_msg_expected;
 /*===========================================================================*
  *                      sef_cb_lu_prepare                                   *
  *===========================================================================*/
-PUBLIC void sef_cb_lu_prepare(int state)
+PUBLIC int sef_cb_lu_prepare(int state)
 {
   int is_ready;
 
@@ -35,9 +35,7 @@ PUBLIC void sef_cb_lu_prepare(int state)
   }
 
   /* Tell SEF if we are ready. */
-  if(is_ready) {
-      sef_lu_ready(OK);
-  }
+  return is_ready ? OK : ENOTREADY;
 }
 
 /*===========================================================================*
index 8e1cbcb30363fcda4a47153893da19c8454801f0..816bd62834fa815e17a609b189d4fd8a9aa26883 100644 (file)
@@ -1063,8 +1063,7 @@ PUBLIC void kputc(int c)
 /*===========================================================================*
  *                             do_new_kmess                                 *
  *===========================================================================*/
-PUBLIC void do_new_kmess(m)
-message *m;
+PUBLIC void do_new_kmess()
 {
 /* Notification for a new kernel message. */
   static struct kmessages kmess;               /* kmessages structure */
index dbe45080627240bfa027915669ac675eea42b6fb..3cbec48e6dd592b00a12d3104d16531a1d208db5 100644 (file)
@@ -100,7 +100,6 @@ unsigned long rs_irq_set = 0;
 
 struct kmessages kmess;
 
-FORWARD _PROTOTYPE( void got_signal, (void)                            );
 FORWARD _PROTOTYPE( void tty_timed_out, (timer_t *tp)                  );
 FORWARD _PROTOTYPE( void expire_timers, (void)                         );
 FORWARD _PROTOTYPE( void settimer, (tty_t *tty_ptr, int enable)                );
@@ -144,6 +143,7 @@ PUBLIC u32_t system_hz;
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
+FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
 
 /*===========================================================================*
  *                             tty_task                                     *
@@ -203,16 +203,6 @@ PUBLIC int main(void)
                                /* run watchdogs of expired timers */
                                expire_timers();
                                break;
-                       case PM_PROC_NR:
-                               /* signal */
-                               got_signal();
-                               break;
-                       case SYSTEM:
-                               /* system signal */
-                               if (sigismember((sigset_t*)&tty_mess.NOTIFY_ARG,
-                                                               SIGKMESS))
-                                       do_new_kmess(&tty_mess);
-                               break;
                        default:
                                /* do nothing */
                                break;
@@ -328,6 +318,9 @@ PRIVATE void sef_local_startup()
 
   /* No live update support for now. */
 
+  /* Register signal callbacks. */
+  sef_setcb_signal_handler(sef_cb_signal_handler);
+
   /* Let SEF perform startup. */
   sef_startup();
 }
@@ -355,21 +348,21 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
 }
 
 /*===========================================================================*
- *                             got_signal                                   *
+ *                        sef_cb_signal_handler                             *
  *===========================================================================*/
-PRIVATE void got_signal()
+PRIVATE void sef_cb_signal_handler(int signo)
 {
-/* PM notified us that we have received a signal. If it is a SIGTERM, assume
- * that the system is shutting down.
- */
-  sigset_t set;
-
-  if (getsigset(&set) != 0) return;
-
-  if (!sigismember(&set, SIGTERM)) return;
-
-  /* switch to primary console */
-  cons_stop();
+  /* Check for known signals, ignore anything else. */
+  switch(signo) {
     /* There is a pending message from the kernel. */
+      case SIGKMESS:
+          do_new_kmess();
+      break;
+      /* Switch to primary console on termination. */
+      case SIGTERM:
+          cons_stop();
+      break;
+  }
 }
 
 /*===========================================================================*
index e609781090ca648b9900177bedead332ac829f3e..71d0bd4109ef18eab64200021b221ab6a26f0ca6 100644 (file)
@@ -165,7 +165,7 @@ _PROTOTYPE( void rs_interrupt, (message *m)                         );
 /* console.c */
 _PROTOTYPE( void kputc, (int c)                                                );
 _PROTOTYPE( void cons_stop, (void)                                     );
-_PROTOTYPE( void do_new_kmess, (message *m)                            );
+_PROTOTYPE( void do_new_kmess, (void)                                  );
 _PROTOTYPE( void do_diagnostics, (message *m, int safe)                        );
 _PROTOTYPE( void do_get_kmess, (message *m)                            );
 _PROTOTYPE( void do_get_kmess_s, (message *m)                          );
index c0d1058c99899f9f1c69d3cfda5973266ebbf7aa..9ebb3af62815e905c98c92a25dd07b8a76b4115f 100755 (executable)
@@ -56,12 +56,13 @@ disabled()
 exec > /dev/console
 echo "Arguments: $@"
 
+service down "$1"
 kill_by_name dhcpd
 kill_by_name nonamed
 kill_by_name syslogd
-sleep 1
-service restart "$1"
-sleep 1
+sleep 3
+service up /usr/sbin/inet -script /etc/rs.inet
 daemonize dhcpd
 daemonize nonamed -L
 daemonize syslogd
+
index 7123e51b448f2c904fe45641c29da51c7edde0c6..d99d97d0255b35d2e27f36f0290adbacd68d3e54 100644 (file)
@@ -10,13 +10,6 @@ service floppy
                IRQCTL          # 19
                DEVIO           # 21
                VDEVIO          # 23
-               SETALARM        # 24
-               TIMES           # 25
-               GETINFO         # 26
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               PROFBUF         # 38
-               SYSCTL          # 44
                ;
 };
 
@@ -26,14 +19,6 @@ service dp8390
                IRQCTL          # 19
                DEVIO           # 21
                SDEVIO          # 22
-               SETALARM        # 24
-               TIMES           # 25
-               GETINFO         # 26
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               SETGRANT        # 34
-               PROFBUF         # 38
-               SYSCTL          # 44
        ;
        pci device      10ec/8029;
        uid     0;
@@ -45,14 +30,6 @@ service dpeth
                IRQCTL          # 19
                DEVIO           # 21
                SDEVIO          # 22
-               SETALARM        # 24
-               TIMES           # 25
-               GETINFO         # 26
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               SETGRANT        # 34
-               PROFBUF         # 38
-               SYSCTL          # 44
        ;
        uid     0;
 };
@@ -63,14 +40,6 @@ service lance
                UMAP            # 14
                IRQCTL          # 19
                DEVIO           # 21
-               #SDEVIO         # 22
-               TIMES           # 25
-               GETINFO         # 26
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               SETGRANT        # 34
-               PROFBUF         # 38
-               SYSCTL          # 44
        ;
        pci device      1022/2000;
        uid     0;
@@ -82,15 +51,6 @@ service rtl8139
                UMAP            # 14
                IRQCTL          # 19
                DEVIO           # 21
-               #SDEVIO         # 22
-               SETALARM        # 24
-               TIMES           # 25
-               GETINFO         # 26
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               SETGRANT        # 34
-               PROFBUF         # 38
-               SYSCTL          # 44
        ;
        pci device      10ec/8139;
        pci device      02ac/1012;
@@ -121,15 +81,6 @@ service fxp
                UMAP            # 14
                IRQCTL          # 19
                DEVIO           # 21
-               #SDEVIO         # 22
-               SETALARM        # 24
-               TIMES           # 25
-               GETINFO         # 26
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               SETGRANT        # 34
-               PROFBUF         # 38
-               SYSCTL          # 44
        ;
        pci device      8086/103d;
        pci device      8086/1064;
@@ -143,61 +94,26 @@ service fxp
 
 service inet
 {
-       system
-               SETALARM        # 24
-               TIMES           # 25
-               GETINFO         # 26
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               VSAFECOPY       # 33
-               SETGRANT        # 34
-               PROFBUF         # 38
-               SYSCTL          # 44
-       ;
        uid 0;
 };
 
 service random
 {
-       system
-               UMAP            # 14
-               SETALARM        # 24
-               TIMES           # 25
-               GETINFO         # 26
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               SETGRANT        # 34
-               PROFBUF         # 38
-               SYSCTL          # 44
-       ;
 };
 
 service readclock.drv
 {
        io      70:2;
        system
+               UMAP            # 14
                DEVIO           # 21
-               TIMES           # 25
-               GETINFO         # 26
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               SETGRANT        # 34
                READBIOS        # 35
-               PROFBUF         # 38
-               SYSCTL          # 44
        ;
        uid 0;
 };
 
 service is
 {
-       system
-               TIMES           # 25
-               GETINFO         # 26
-               SETGRANT        # 34
-               PROFBUF         # 38
-               SYSCTL          # 44
-       ;
        vm
                INFO
        ;
@@ -212,13 +128,6 @@ service pci
        system
                PRIVCTL         #  4
                DEVIO           # 21
-               TIMES           # 25
-               GETINFO         # 26
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               SETGRANT        # 34
-               PROFBUF         # 38
-               SYSCTL          # 44
        ;
        uid 0;
 };
@@ -240,15 +149,7 @@ service at_wini
                DEVIO           # 21
                SDEVIO          # 22
                VDEVIO          # 23
-               SETALARM        # 24
-               TIMES           # 25
-               GETINFO         # 26
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               SETGRANT        # 34
                READBIOS        # 35
-               PROFBUF         # 38
-               SYSCTL          # 44
        ;
        pci class       
                1/1             # Mass storage / IDE
@@ -261,58 +162,25 @@ service bios_wini
        system
                UMAP            # 14
                INT86           # 20
-               SETALARM        # 24
-               TIMES           # 25
-               GETINFO         # 26
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               SETGRANT        # 34
                READBIOS        # 35
-               PROFBUF         # 38
-               SYSCTL          # 44
        ;
 };
 
 service mfs
 {
-       system
-               TIMES           # 25
-               GETINFO         # 26
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               SETGRANT        # 34
-               PROFBUF         # 38
-               SYSCTL          # 44
-               ;
        uid     0;
 };
 
 service isofs
 {
        system
-                UMAP            # 14
-               TIMES           # 25
-               GETINFO         # 26
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               SETGRANT        # 34
-               PROFBUF         # 38
-               SYSCTL          # 44
+               UMAP            # 14
                ;
        uid     0;
 };
 
 service hgfs
 {
-       system
-               TIMES           # 25
-               GETINFO         # 26
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               SETGRANT        # 34
-               PROFBUF         # 38
-               SYSCTL          # 44
-       ;
        ipc
                SYSTEM PM VFS RS VM
        ;
@@ -333,13 +201,6 @@ service printer
                IRQCTL          # 19
                DEVIO           # 21
                VDEVIO          # 23
-               TIMES           # 25
-               GETINFO         # 26
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               SETGRANT        # 34
-               PROFBUF         # 38
-               SYSCTL          # 44
        ;
 };
 
@@ -350,16 +211,7 @@ service orinoco
                UMAP            # 14
                IRQCTL          # 19
                DEVIO           # 21
-               #SDEVIO         # 22
-               SETALARM        # 24
-               TIMES           # 25
-               GETINFO         # 26
                VM_MAP          # 30
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               SETGRANT        # 34
-               PROFBUF         # 38
-               SYSCTL          # 44
        ;
        pci device      1260/3873;
        pci device      1186/1300;
@@ -372,13 +224,6 @@ service es1370
                UMAP            # 14
                IRQCTL          # 19
                DEVIO           # 21
-               TIMES           # 25
-                GETINFO                # 26
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               SETGRANT        # 34
-               PROFBUF         # 38
-               SYSCTL          # 44
        ;
        pci device 1274/5000;
 };
@@ -386,16 +231,9 @@ service es1370
 service es1371
 {
        system
-               SAFECOPYFROM
-               SAFECOPYTO
-               UMAP
-               SETGRANT
-               TIMES           # 25
-                GETINFO
+               UMAP            # 14
                IRQCTL          # 19
                DEVIO           # 21
-               PROFBUF         # 38
-               SYSCTL
        ;
        pci device 1274/1371;
 };
@@ -405,12 +243,6 @@ service amddev
        pci device      1022/1103;
        system
                UMAP            # 14
-               TIMES           # 25
-                GETINFO                # 26
-               SETGRANT        # 34
-               PROFBUF         # 38
-               REGDEV          # 40
-               SYSCTL          # 44
        ;
        uid     0;
 };
@@ -419,14 +251,7 @@ service ipc
 {
        system
                UMAP            # 14
-               VIRCOPY         # 15
-               TIMES           # 25
-               GETINFO         # 26
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               SETGRANT        # 34
-               PROFBUF         # 38
-               SYSCTL          # 44
+               VIRCOPY         # 15
                ;
        uid     0;
        ipc
@@ -456,14 +281,6 @@ service osscore
                IRQCTL          # 19
                DEVIO           # 21
                SDEVIO          # 22
-               SETALARM        # 24
-               TIMES           # 25
-               GETINFO         # 26
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               SETGRANT        # 34
-               PROFBUF         # 38
-               SYSCTL          # 44
        ;
        pci class       
                4/1             # Multimedia / Audio device
@@ -481,15 +298,6 @@ service rtl8169
                UMAP            # 14
                IRQCTL          # 19
                DEVIO           # 21
-               #SDEVIO         # 22
-               SETALARM        # 24
-               TIMES           # 25
-               GETINFO         # 26
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               SETGRANT        # 34
-               PROFBUF         # 38
-               SYSCTL          # 44
        ;
        pci device      10ec/8129;
        pci device      10ec/8167;
@@ -507,15 +315,6 @@ service rtl8169
 
 service filter
 {
-       system
-               SETALARM        # 24
-               TIMES           # 25
-               GETINFO         # 26
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               SETGRANT        # 34
-               SYSCTL          # 44
-       ;
        ipc
                SYSTEM PM VFS RS DS VM
                at_wini
@@ -533,13 +332,6 @@ service e1000
                UMAP            # 14
                IRQCTL          # 19
                DEVIO           # 21
-               SETALARM        # 24
-               TIMES           # 25
-               GETINFO         # 26
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               SETGRANT        # 34
-               SYSCTL          # 44
        ;
        pci device      8086/100e;
        pci device      8086/107c;
@@ -554,13 +346,6 @@ service atl2
        system
                UMAP            # 14
                IRQCTL          # 19
-               SETALARM        # 24
-               TIMES           # 25
-               GETINFO         # 26
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               SETGRANT        # 34
-               SYSCTL          # 44
        ;
        pci device      1969/2048;
        ipc
@@ -575,15 +360,6 @@ service dec21140A
                UMAP            # 14
                IRQCTL          # 19
                DEVIO           # 21
-               #SDEVIO         # 22
-               SETALARM        # 24
-               TIMES           # 25
-               GETINFO         # 26
-               SAFECOPYFROM    # 31
-               SAFECOPYTO      # 32
-               SETGRANT        # 34
-               PROFBUF         # 38
-               SYSCTL
        ;
        pci device      1011/0009;
        ipc
@@ -591,3 +367,17 @@ service dec21140A
                pci inet
                ;
 };
+
+service hello
+{
+        system
+                IRQCTL          # 19
+                DEVIO           # 21
+        ;
+        ipc
+                SYSTEM PM RS LOG TTY DS VM VFS
+                pci inet amddev
+                ;
+    uid 0;
+};
+
index 3a252cae619247a30f15832ded2b2a05edc818ac..9903f86390432ba2a7bab89eaace53d376344564 100644 (file)
@@ -74,7 +74,7 @@ extern int errno;               /* place where the error numbers go */
 #define ENOSYS        (_SIGN 38)  /* function not implemented */
 #define ENOTEMPTY     (_SIGN 39)  /* directory not empty */
 #define ELOOP         (_SIGN 40)  /* too many levels of symlinks detected */
-#define ERESTART      (_SIGN 41)  /* driver restarted */
+#define ERESTART      (_SIGN 41)  /* service restarted */
 #define EIDRM         (_SIGN 43)  /* Identifier removed */
 #define EILSEQ        (_SIGN 44)  /* illegal byte sequence */
 
index a4d28ef0a551f1891568485c3c7ca563b12f0869..3dcd8311f7ebf322e763f97eba636b6979064650 100644 (file)
@@ -1,4 +1,4 @@
-#define NCALLS          111    /* number of system calls allowed */
+#define NCALLS          112    /* number of system calls allowed */
 
 #define EXIT              1 
 #define FORK              2 
@@ -93,7 +93,7 @@
 #define EXEC_NEWMEM    100     /* from FS or RS to PM: new memory map for
                                 * exec
                                 */
-#define FORK_NB                101     /* to PM: special fork call for RS */
+#define SRV_FORK       101     /* to PM: special fork call for RS */
 #define EXEC_RESTART   102     /* to PM: final part of exec for RS */
 #define PROCSTAT       103     /* to PM */
 #define GETPROCNR      104     /* to PM */
                                 * that should not be used for bus-master DMA
                                 * any longer
                                 */
+#define SRV_KILL       111     /* to PM: special kill call for RS */
 
 #define TASK_REPLY     121     /* to FS: reply code from drivers, not 
                                 * really a standalone call.
index 3642e3fac922936da10b6b704f5a06ea867feb08..3a13fcb55513e8114a6d3db086166370e676a4f8 100644 (file)
@@ -19,6 +19,7 @@
  *    0xB00 -  0xBFF   Requests from VM to VFS
  *    0xC00 -  0xCFF   Virtual Memory (VM) requests
  *    0xD00 -  0xDFF   IPC server requests
+ *    0xE00 -  0xEFF   Common system messages (e.g. system signals)
  *   0x1000 - 0x10FF   Notify messages
  *
  * Zero and negative values are widely used for OK and error responses.
 
 #  define SYS_FORK       (KERNEL_CALL + 0)     /* sys_fork() */
 #  define SYS_EXEC       (KERNEL_CALL + 1)     /* sys_exec() */
-#  define SYS_EXIT      (KERNEL_CALL + 2)      /* sys_exit() */
+#  define SYS_CLEAR     (KERNEL_CALL + 2)      /* sys_clear() */
 #  define SYS_NICE       (KERNEL_CALL + 3)     /* sys_nice() */
 #  define SYS_PRIVCTL    (KERNEL_CALL + 4)     /* sys_privctl() */
 #  define SYS_TRACE      (KERNEL_CALL + 5)     /* sys_trace() */
 #  define SYS_GETMCONTEXT (KERNEL_CALL + 50)    /* sys_getmcontext() */
 #  define SYS_SETMCONTEXT (KERNEL_CALL + 51)    /* sys_setmcontext() */
 
-#define NR_SYS_CALLS   52      /* number of system calls */ 
+#  define SYS_UPDATE    (KERNEL_CALL + 52)     /* sys_update() */
+#  define SYS_EXIT      (KERNEL_CALL + 53)     /* sys_exit() */
+
+/* Total */
+#define NR_SYS_CALLS   54      /* number of system calls */ 
+
 #define SYS_CALL_MASK_SIZE BITMAP_CHUNKS(NR_SYS_CALLS)
 
+/* Basic kernel calls allowed to every system process. */
+#define SYS_BASIC_CALLS \
+    SYS_EXIT, SYS_SAFECOPYFROM, SYS_SAFECOPYTO, SYS_VSAFECOPY, SYS_GETINFO, \
+    SYS_TIMES, SYS_SETALARM, SYS_SETGRANT, SYS_SAFEMAP, SYS_SAFEREVMAP, \
+    SYS_SAFEUNMAP, SYS_PROFBUF, SYS_SYSCTL
+
 /* Field names for SYS_MEMSET. */
 #define MEM_PTR                m2_p1   /* base */
 #define MEM_COUNT      m2_l1   /* count */
 #define RC_FLAGS       m1_i3   /* request flags */
 #  define RC_DELAY          1  /* delay stop if process is sending */
 
+/* Field names for SYS_UPDATE. */
+#define SYS_UPD_SRC_ENDPT      m1_i1   /* source endpoint */
+#define SYS_UPD_DST_ENDPT      m1_i2   /* destination endpoint */
+
 /*===========================================================================*
  *                Messages for the Reincarnation Server                     *
  *===========================================================================*/
 #  define DS_VAL               m2_l1           /* data (u32, char *, etc.) */
 #  define DS_VAL_LEN           m2_l2           /* data length */
 #  define DS_NR_SNAPSHOT       m2_i3           /* number of snapshot */
-#  define DS_STRING            m2_i3           /* inline string */
 
 /*===========================================================================*
  *                Miscellaneous messages used by TTY                        *
 #define PM_DUMPCORE    (PM_RQ_BASE + 5)        /* Process is to dump core */
 #define PM_EXEC                (PM_RQ_BASE + 6)        /* Forwarded exec call */
 #define PM_FORK                (PM_RQ_BASE + 7)        /* Newly forked process */
-#define PM_FORK_NB     (PM_RQ_BASE + 8)        /* Non-blocking fork */
+#define PM_SRV_FORK    (PM_RQ_BASE + 8)        /* fork for system services */
 #define PM_UNPAUSE     (PM_RQ_BASE + 9)        /* Interrupt process call */
 #define PM_REBOOT      (PM_RQ_BASE + 10)       /* System reboot */
 #define PM_SETGROUPS   (PM_RQ_BASE + 11)       /* Tell VFS about setgroups */
 #define PM_CORE_REPLY  (PM_RS_BASE + 5)
 #define PM_EXEC_REPLY  (PM_RS_BASE + 6)
 #define PM_FORK_REPLY  (PM_RS_BASE + 7)
-#define PM_FORK_NB_REPLY       (PM_RS_BASE + 8)
+#define PM_SRV_FORK_REPLY      (PM_RS_BASE + 8)
 #define PM_UNPAUSE_REPLY       (PM_RS_BASE + 9)
 #define PM_REBOOT_REPLY        (PM_RS_BASE + 10)
 #define PM_SETGROUPS_REPLY     (PM_RS_BASE + 11)
 
 /* Additional parameters for PM_INIT */
 #  define PM_SLOT              m1_i2   /* process slot number */
-#  define PM_PID               m2_i3   /* process pid */
+#  define PM_PID               m1_i3   /* process pid */
 
 /* Additional parameters for PM_SETUID and PM_SETGID */
 #  define PM_EID               m1_i2   /* effective user/group id */
 /* Additional parameters for PM_EXEC_REPLY and PM_CORE_REPLY */
 #  define PM_STATUS            m1_i2   /* OK or failure */
 
-/* Additional parameters for PM_FORK and PM_FORK_NB */
+/* Additional parameters for PM_FORK and PM_SRV_FORK */
 #  define PM_PPROC             m1_i2   /* parent process endpoint */
 #  define PM_CPID              m1_i3   /* child pid */
 
  *                Miscellaneous field names                                 *
  *===========================================================================*/
 
+#define COMMON_RQ_BASE         0xE00
+
 /* PM field names */
 /* BRK */
 #define PMBRK_ADDR                             m1_p1
 #define SEL_ERRORFDS   m8_p3
 #define SEL_TIMEOUT    m8_p4
 
+/* Field names for system signals (sent by a signal manager). */
+#define SIGS_SIGNAL_RECEIVED (COMMON_RQ_BASE+0)
+#      define SIGS_SIG_NUM      m2_i1
+
 /*===========================================================================*
  *                Messages for VM server                                    *
  *===========================================================================*/
 #define VMIW_USAGE                     2
 #define VMIW_REGION                    3
 
+#define VM_RS_UPDATE           (VM_RQ_BASE+41)
+#      define VM_RS_SRC_ENDPT          m1_i1
+#      define VM_RS_DST_ENDPT          m1_i2
+
 /* Total. */
-#define NR_VM_CALLS                            41
+#define NR_VM_CALLS                            42
 #define VM_CALL_MASK_SIZE                      BITMAP_CHUNKS(NR_VM_CALLS)
 
 /* Basic vm calls allowed to every process. */
index 11598ad8471e71a7b1575e3e6eb85f86a901cfd5..5e44b4a06be25e9239aa25c5af7214bc25fa9599 100644 (file)
@@ -45,4 +45,6 @@ enum dev_style { STYLE_DEV, STYLE_NDEV, STYLE_TTY, STYLE_CLONE };
 #define LOG_MAJOR                15    /* major device for log driver */
 #  define IS_KLOG_DEV             0    /* minor device for /dev/klog */
 
+#define HELLO_MAJOR              17    /* major device for hello driver */
+
 #endif /* _DMAP_H */
index fd9f42296c595385e25cded63bc0ccfd366a3688..e33743a007f4fdeae87634959a4cfc473f9253bf 100644 (file)
@@ -29,7 +29,6 @@
 
 /* DS constants. */
 #define DS_MAX_KEYLEN 80        /* Max length of a key, including '\0'. */
-#define DS_MAX_STRLEN 16        /* Max length of string, including '\0'. */
 
 /* ds.c */
 
index ae784485af15604c6b18bd047d4c70f19c9da331..a508de847b16e8d0244ae9d2814999ab9f662ecb 100644 (file)
@@ -22,7 +22,6 @@ Interface to the reincarnation server
 #define RSS_REUSE      0x04    /* Try to reuse previously copied binary */
 
 /* Common definitions. */
-#define RS_SYS_CALL_MASK_SIZE   2
 #define RS_NR_CONTROL           8
 #define RS_NR_PCI_DEVICE       32
 #define RS_NR_PCI_CLASS                 4
@@ -55,7 +54,7 @@ struct rs_start
        struct { u16_t vid; u16_t did; } rss_pci_id[RS_NR_PCI_DEVICE];
        int rss_nr_pci_class;
        struct { u32_t class; u32_t mask; } rss_pci_class[RS_NR_PCI_CLASS];
-       u32_t rss_system[RS_SYS_CALL_MASK_SIZE];
+       bitchunk_t rss_system[SYS_CALL_MASK_SIZE];
        struct rss_label rss_label;
        char *rss_ipc;
        size_t rss_ipclen;
index 0f237844b50d5925981ecd88dd481991cb3794dd..4f0c92c8fb3a92b321ac90ecf6f65052e5d53ad0 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <minix/sys_config.h>
 #include <minix/types.h>
+#include <minix/vm.h>
 #include <stdint.h>
 
 typedef struct {
@@ -47,13 +48,6 @@ struct vscp_vec {
         size_t          v_bytes;        /* no. of bytes */
 };
 
-/* Types on VM invocation. */
-#define VMPTYPE_NONE           0
-#define VMPTYPE_CHECK          1
-#define VMPTYPE_COWMAP         2
-#define VMPTYPE_SMAP           3
-#define VMPTYPE_SUNMAP         4
-
 /* Invalid grant number. */
 #define GRANT_INVALID  ((cp_grant_id_t) -1)
 #define GRANT_VALID(g) ((g) > GRANT_INVALID)
index 7c07adf0728ce68cd6d30b2d740e8b56d49527bc..9883f92b9fed6fc3a84ab4eed0a373b7fd3f243f 100644 (file)
@@ -8,6 +8,7 @@
 /* SEF entry points for system processes. */
 _PROTOTYPE( void sef_startup, (void) );
 _PROTOTYPE( int sef_receive, (endpoint_t src, message *m_ptr) );
+_PROTOTYPE( void sef_exit, (int status) );
 
 /* SEF Debug. */
 #include <stdio.h>
@@ -29,30 +30,27 @@ typedef struct {
 } sef_init_info_t;
 
 /* Callback type definitions. */
-typedef int(*sef_cb_init_fresh_t)(int type, sef_init_info_t *info);
-typedef int(*sef_cb_init_lu_t)(int type, sef_init_info_t *info);
-typedef int(*sef_cb_init_restart_t)(int type, sef_init_info_t *info);
+typedef int(*sef_cb_init_t)(int type, sef_init_info_t *info);
 
 /* Callback registration helpers. */
-_PROTOTYPE( void sef_setcb_init_fresh, (sef_cb_init_fresh_t cb));
-_PROTOTYPE( void sef_setcb_init_lu, (sef_cb_init_lu_t cb));
-_PROTOTYPE( void sef_setcb_init_restart, (sef_cb_init_restart_t cb));
+_PROTOTYPE( void sef_setcb_init_fresh, (sef_cb_init_t cb));
+_PROTOTYPE( void sef_setcb_init_lu, (sef_cb_init_t cb));
+_PROTOTYPE( void sef_setcb_init_restart, (sef_cb_init_t cb));
 
 /* Predefined callback implementations. */
-_PROTOTYPE( int sef_cb_init_fresh_null, (int type, sef_init_info_t *info) );
-_PROTOTYPE( int sef_cb_init_lu_null, (int type, sef_init_info_t *info) );
-_PROTOTYPE( int sef_cb_init_restart_null, (int type, sef_init_info_t *info) );
+_PROTOTYPE( int sef_cb_init_null, (int type, sef_init_info_t *info) );
 
-_PROTOTYPE( int sef_cb_init_restart_fail, (int type, sef_init_info_t *info) );
+_PROTOTYPE( int sef_cb_init_fail, (int type, sef_init_info_t *info) );
+_PROTOTYPE( int sef_cb_init_crash, (int type, sef_init_info_t *info) );
 
 /* Macros for predefined callback implementations. */
-#define SEF_CB_INIT_FRESH_NULL          sef_cb_init_fresh_null
-#define SEF_CB_INIT_LU_NULL             sef_cb_init_lu_null
-#define SEF_CB_INIT_RESTART_NULL        sef_cb_init_restart_null
+#define SEF_CB_INIT_FRESH_NULL          sef_cb_init_null
+#define SEF_CB_INIT_LU_NULL             sef_cb_init_null
+#define SEF_CB_INIT_RESTART_NULL        sef_cb_init_null
 
-#define SEF_CB_INIT_FRESH_DEFAULT       sef_cb_init_fresh_null
-#define SEF_CB_INIT_LU_DEFAULT          sef_cb_init_lu_null
-#define SEF_CB_INIT_RESTART_DEFAULT     sef_cb_init_restart_null
+#define SEF_CB_INIT_FRESH_DEFAULT       sef_cb_init_null
+#define SEF_CB_INIT_LU_DEFAULT          sef_cb_init_null
+#define SEF_CB_INIT_RESTART_DEFAULT     sef_cb_init_null
 
 /* Init types. */
 #define SEF_INIT_FRESH                  0    /* init fresh */
@@ -79,15 +77,15 @@ _PROTOTYPE( int sef_cb_init_restart_fail, (int type, sef_init_info_t *info) );
     && (mp)->m_source == RS_PROC_NR)
 
 /* Callback type definitions. */
-typedef void(*sef_cb_ping_reply_t)(message *m_ptr);
+typedef void(*sef_cb_ping_reply_t)(endpoint_t source);
 
 /* Callback registration helpers. */
 _PROTOTYPE( void sef_setcb_ping_reply, (sef_cb_ping_reply_t cb));
 
 /* Predefined callback implementations. */
-_PROTOTYPE( void sef_cb_ping_reply_null, (message *m_ptr) );
+_PROTOTYPE( void sef_cb_ping_reply_null, (endpoint_t source) );
 
-_PROTOTYPE( void sef_cb_ping_reply_pong, (message *m_ptr) );
+_PROTOTYPE( void sef_cb_ping_reply_pong, (endpoint_t source) );
 
 /* Macros for predefined callback implementations. */
 #define SEF_CB_PING_REPLY_NULL          sef_cb_ping_reply_null
@@ -113,31 +111,30 @@ _PROTOTYPE( void sef_cb_ping_reply_pong, (message *m_ptr) );
 #define IS_SEF_LU_REQUEST(mp) ((mp)->m_type == RS_LU_PREPARE \
     && (mp)->m_source == RS_PROC_NR)
 
-/* Global helpers. */
-_PROTOTYPE( void sef_lu_ready, (int result) );
-
 /* Callback type definitions. */
-typedef void(*sef_cb_lu_prepare_t)(int);
+typedef  int(*sef_cb_lu_prepare_t)(int);
 typedef  int(*sef_cb_lu_state_isvalid_t)(int);
 typedef void(*sef_cb_lu_state_changed_t)(int, int);
 typedef void(*sef_cb_lu_state_dump_t)(int);
-typedef  int(*sef_cb_lu_ready_pre_t)(int);
+typedef  int(*sef_cb_lu_state_save_t)(int);
 
 /* Callback registration helpers. */
 _PROTOTYPE( void sef_setcb_lu_prepare, (sef_cb_lu_prepare_t cb) );
 _PROTOTYPE( void sef_setcb_lu_state_isvalid, (sef_cb_lu_state_isvalid_t cb) );
 _PROTOTYPE( void sef_setcb_lu_state_changed, (sef_cb_lu_state_changed_t cb) );
 _PROTOTYPE( void sef_setcb_lu_state_dump, (sef_cb_lu_state_dump_t cb) );
-_PROTOTYPE( void sef_setcb_lu_ready_pre, (sef_cb_lu_ready_pre_t cb) );
+_PROTOTYPE( void sef_setcb_lu_state_save, (sef_cb_lu_state_save_t cb) );
 
 /* Predefined callback implementations. */
-_PROTOTYPE( void sef_cb_lu_prepare_null, (int state) );
+_PROTOTYPE(  int sef_cb_lu_prepare_null, (int state) );
 _PROTOTYPE(  int sef_cb_lu_state_isvalid_null, (int state) );
 _PROTOTYPE( void sef_cb_lu_state_changed_null, (int old_state, int state) );
 _PROTOTYPE( void sef_cb_lu_state_dump_null, (int state) );
-_PROTOTYPE(  int sef_cb_lu_ready_pre_null, (int result) );
+_PROTOTYPE(  int sef_cb_lu_state_save_null, (int state) );
 
-_PROTOTYPE( void sef_cb_lu_prepare_always_ready, (int state) );
+_PROTOTYPE(  int sef_cb_lu_prepare_always_ready, (int state) );
+_PROTOTYPE(  int sef_cb_lu_prepare_never_ready, (int state) );
+_PROTOTYPE(  int sef_cb_lu_prepare_crash, (int state) );
 _PROTOTYPE(  int sef_cb_lu_state_isvalid_standard, (int state) );
 
 /* Macros for predefined callback implementations. */
@@ -145,13 +142,13 @@ _PROTOTYPE(  int sef_cb_lu_state_isvalid_standard, (int state) );
 #define SEF_CB_LU_STATE_ISVALID_NULL    sef_cb_lu_state_isvalid_null
 #define SEF_CB_LU_STATE_CHANGED_NULL    sef_cb_lu_state_changed_null
 #define SEF_CB_LU_STATE_DUMP_NULL       sef_cb_lu_state_dump_null
-#define SEF_CB_LU_READY_PRE_NULL        sef_cb_lu_ready_pre_null
+#define SEF_CB_LU_STATE_SAVE_NULL       sef_cb_lu_state_save_null
 
 #define SEF_CB_LU_PREPARE_DEFAULT       sef_cb_lu_prepare_null
 #define SEF_CB_LU_STATE_ISVALID_DEFAULT sef_cb_lu_state_isvalid_null
 #define SEF_CB_LU_STATE_CHANGED_DEFAULT sef_cb_lu_state_changed_null
 #define SEF_CB_LU_STATE_DUMP_DEFAULT    sef_cb_lu_state_dump_null
-#define SEF_CB_LU_READY_PRE_DEFAULT     sef_cb_lu_ready_pre_null
+#define SEF_CB_LU_STATE_SAVE_DEFAULT    sef_cb_lu_state_save_null
 
 /* Standard live update states. */
 #define SEF_LU_STATE_NULL               0    /* null state */
@@ -173,5 +170,47 @@ _PROTOTYPE(  int sef_cb_lu_state_isvalid_standard, (int state) );
 #define sef_lu_debug_begin      sef_debug_begin
 #define sef_lu_debug_end        sef_debug_end
 
+/*===========================================================================*
+ *                               SEF Signal                                 *
+ *===========================================================================*/
+/* What to intercept. */
+#define INTERCEPT_SEF_SIGNAL_REQUESTS 1
+#define IS_SEF_SIGNAL_REQUEST(mp) \
+    (((mp)->m_type == SIGS_SIGNAL_RECEIVED && (mp)->m_source < INIT_PROC_NR) \
+    || (is_notify((mp)->m_type) && (mp)->m_source == SYSTEM))
+
+/* Callback type definitions. */
+typedef void(*sef_cb_signal_handler_t)(int signo);
+typedef  int(*sef_cb_signal_manager_t)(endpoint_t target, int signo);
+
+/* Callback registration helpers. */
+_PROTOTYPE( void sef_setcb_signal_handler, (sef_cb_signal_handler_t cb));
+_PROTOTYPE( void sef_setcb_signal_manager, (sef_cb_signal_manager_t cb));
+
+/* Predefined callback implementations. */
+_PROTOTYPE( void sef_cb_signal_handler_null, (int signo) );
+_PROTOTYPE(  int sef_cb_signal_manager_null, (endpoint_t target, int signo) );
+
+_PROTOTYPE( void sef_cb_signal_handler_term, (int signo) );
+_PROTOTYPE( void sef_cb_signal_handler_posix_default, (int signo) );
+
+/* Macros for predefined callback implementations. */
+#define SEF_CB_SIGNAL_HANDLER_NULL      sef_cb_signal_handler_null
+#define SEF_CB_SIGNAL_MANAGER_NULL      sef_cb_signal_manager_null
+
+#define SEF_CB_SIGNAL_HANDLER_DEFAULT   sef_cb_signal_handler_null
+#define SEF_CB_SIGNAL_MANAGER_DEFAULT   sef_cb_signal_manager_null
+
+/* Debug. */
+#define SEF_SIGNAL_DEBUG_DEFAULT 0
+
+#ifndef SEF_SIGNAL_DEBUG
+#define SEF_SIGNAL_DEBUG                SEF_SIGNAL_DEBUG_DEFAULT
+#endif
+
+#define sef_signal_dprint               sef_dprint
+#define sef_signal_debug_begin          sef_debug_begin
+#define sef_signal_debug_end            sef_debug_end
+
 #endif /* _SEF_H */
 
index a11b821598200682392c2d72eb7e03f47b95fcb3..bfad9ff6e4d02808a75952fbbe68fd74edee394c 100644 (file)
@@ -40,7 +40,8 @@ _PROTOTYPE( int sys_exec, (endpoint_t proc_ep, char *ptr,
 _PROTOTYPE( int sys_fork, (endpoint_t parent, endpoint_t child, endpoint_t *,
        struct mem_map *ptr, u32_t vm, vir_bytes *));
 _PROTOTYPE( int sys_newmap, (endpoint_t proc_ep, struct mem_map *ptr));
-_PROTOTYPE( int sys_exit, (endpoint_t proc_ep));
+_PROTOTYPE( int sys_clear, (endpoint_t proc_ep));
+_PROTOTYPE( int sys_exit, (void));
 _PROTOTYPE( int sys_trace, (int req, endpoint_t proc_ep, long addr, long *data_p));
 
 /* Shorthands for sys_runctl() system call. */
@@ -49,6 +50,7 @@ _PROTOTYPE( int sys_trace, (int req, endpoint_t proc_ep, long addr, long *data_p
 #define sys_resume(proc_ep) sys_runctl(proc_ep, RC_RESUME, 0)
 _PROTOTYPE( int sys_runctl, (endpoint_t proc_ep, int action, int flags));
 
+_PROTOTYPE( int sys_update, (endpoint_t src_ep, endpoint_t dst_ep));
 _PROTOTYPE( int sys_privctl, (endpoint_t proc_ep, int req, void *p));
 _PROTOTYPE( int sys_privquery_mem, (endpoint_t proc_ep,
        phys_bytes physstart, phys_bytes physlen));
index 3755dfa96de4567ed00ad9fe74b3e9a4c727cf8f..121acd0147f444299e0a6ce1abe5d9c87205ec37 100644 (file)
@@ -25,8 +25,16 @@ _PROTOTYPE( int vm_unmap_phys, (endpoint_t who, void *vaddr, size_t len));
 _PROTOTYPE( int vm_notify_sig, (endpoint_t ep, endpoint_t ipc_ep));
 _PROTOTYPE( int vm_ctl, (int what, int param));
 _PROTOTYPE( int vm_set_priv, (int procnr, void *buf));
+_PROTOTYPE( int vm_update, (endpoint_t src_e, endpoint_t dst_e));
 _PROTOTYPE( int vm_query_exit, (int *endpt));
 
+/* VM kernel request types. */
+#define VMPTYPE_NONE           0
+#define VMPTYPE_CHECK          1
+#define VMPTYPE_COWMAP         2
+#define VMPTYPE_SMAP           3
+#define VMPTYPE_SUNMAP         4
+
 struct vm_stats_info {
   int vsi_pagesize;            /* page size */
   int vsi_total;               /* total number of memory pages */
index 5d701e6590f69792bb74f9e15acba72a50865a2f..642b41ff73691c07dc610d2ae65baef952764b21 100644 (file)
@@ -63,10 +63,26 @@ typedef unsigned long sigset_t;
 
 /* MINIX specific signals. These signals are not used by user proceses, 
  * but meant to inform system processes, like the PM, about system events.
+ * The order here determines the order signals are processed by system
+ * processes in user-space. Higher-priority signals should be first.
  */
-#define SIGKMESS         29    /* new kernel message */
+#define SIGKPF           26    /* kernel page fault request pending */
+#define SIGKMEM                  27    /* kernel memory request pending */
+#define SIGKMESS         28    /* new kernel message */
+#define SIGKSIGSM        29    /* kernel signal pending for signal manager */
 #define SIGKSIG          30    /* kernel signal pending */
-#define SIGNDELAY        31    /* end of delay for signal delivery */
+#define SIGKNDELAY       31    /* end of delay for signal delivery */
+
+#define SIGK_FIRST       SIGKPF      /* first kernel signal */
+#define SIGK_LAST        SIGKNDELAY   /* last kernel signal */
+#define IS_SIGK(signo)    (signo>=SIGK_FIRST && signo<=SIGK_LAST)
+
+/* Termination signals for Minix system processes. */
+#define SIGS_IS_LETHAL(sig) \
+    (sig == SIGILL || sig == SIGBUS || sig == SIGFPE || sig == SIGSEGV \
+    || sig == SIGEMT || sig == SIGABRT)
+#define SIGS_IS_TERMINATION(sig) (SIGS_IS_LETHAL(sig) \
+    || (sig == SIGKILL || sig == SIGPIPE))
 
 #endif
 
@@ -79,7 +95,6 @@ typedef void _PROTOTYPE( (*__sighandler_t), (int) );
 #define SIG_IGN           ((__sighandler_t)  1)        /* ignore signal */
 #define SIG_HOLD   ((__sighandler_t)  2)       /* block signal */
 #define SIG_CATCH  ((__sighandler_t)  3)       /* catch signal */
-#define SIG_MESS   ((__sighandler_t)  4)       /* pass as message (MINIX) */
 
 #ifdef _POSIX_SOURCE
 struct sigaction {
index 7e9538300d76e6149da0cecbbc25ed7dc562ce04..b1e22a85ca15ee479c90b09c97d4ba1d49730ff5 100644 (file)
@@ -91,7 +91,7 @@ void pagefault( struct proc *pr,
        pr->p_nextpagefault = pagefaults;
        pagefaults = pr;
                
-       mini_notify(proc_addr(HARDWARE), VM_PROC_NR);
+       send_sig(VM_PROC_NR, SIGKPF);
 
        return;
 }
index 1a6b2e11ab10b63dc71e6601411406ce9c1b2a56..2da9f17322b0a0cec974dc81045db9b3c3c363e9 100644 (file)
@@ -9,6 +9,7 @@
 #include <minix/cpufeature.h>
 #include <string.h>
 #include <assert.h>
+#include <signal.h>
 
 #include <machine/vm.h>
 
@@ -577,7 +578,7 @@ PRIVATE void vm_suspend(struct proc *caller, struct proc *target,
                                                        
        /* Connect caller on vmrequest wait queue. */   
        if(!(caller->p_vmrequest.nextrequestor = vmrequest))
-               mini_notify(proc_addr(SYSTEM), VM_PROC_NR);
+               send_sig(VM_PROC_NR, SIGKMEM);
        vmrequest = caller;
 }
 
index ef6f2897ea97776de2e42f95c854c42b70a8ae6b..02834ea72eaa3986fb6e7060e905ce31d33216e4 100644 (file)
@@ -18,7 +18,8 @@
 #define USE_FORK                  1    /* fork a new process */
 #define USE_NEWMAP                1    /* set a new memory map */
 #define USE_EXEC                  1    /* update process after execute */
-#define USE_EXIT          1    /* clean up after process exit */
+#define USE_CLEAR         1    /* clean up after process exit */
+#define USE_EXIT          1    /* a system process wants to exit */
 #define USE_TRACE                 1    /* process information and tracing */
 #define USE_GETKSIG               1    /* retrieve pending kernel signals */
 #define USE_ENDKSIG               1    /* finish pending kernel signals */
@@ -42,6 +43,7 @@
 #define USE_PHYSCOPY      1    /* copy using physical addressing */
 #define USE_MEMSET        1    /* write char to a given memory area */
 #define USE_RUNCTL         1   /* control stop flags of a process */
+#define USE_UPDATE         1   /* update a process into another */
 #define USE_MCONTEXT       1    /* enable getting and setting of mach context*/
 
 /* Length of program names stored in the process table. This is only used
index a61331a52e8b6a9846518efa8f44b6cf0418768a..328a404fba58c56757233713aae49ee6f09f0248 100644 (file)
@@ -56,7 +56,7 @@ PUBLIC void put_irq_handler( irq_hook_t* hook, int irq, irq_handler_t handler)
   hook->id = id;
   *line = hook;
   irq_use |= 1 << irq;  /* this does not work for irq >= 32 */
-  
+
   /* And as last enable the irq at the hardware.
    *
    * Internal this activates the line or source of the given interrupt.
@@ -78,25 +78,30 @@ PUBLIC void rm_irq_handler( irq_hook_t* hook ) {
   if( irq < 0 || irq >= NR_IRQ_VECTORS ) 
        panic("invalid call to rm_irq_handler: %d",  irq);
 
-  /* disable the irq.  */
-  irq_actids[hook->irq] |= hook->id;
-  hw_intr_mask(hook->irq);
-    
-  /* remove the hook.  */
+  /* remove the hook  */
   line = &irq_handlers[irq];
-  
   while( (*line) != NULL ) {
-       if((*line)->id == id) {      
-               (*line) = (*line)->next;      
+       if((*line)->id == id) {
+               (*line) = (*line)->next;
                if(!irq_handlers[irq])
                        irq_use &= ~(1 << irq);
                if (irq_actids[irq] & id)
                        irq_actids[irq] &= ~id;
-               return;
-       }          
-       line = &(*line)->next;
+       }
+       else {
+               line = &(*line)->next;
+       }
+  }
+
+  /* Disable the irq if there are no other handlers registered.
+   * If the irq is shared, reenable it if there is no active handler.
+   */
+  if (irq_handlers[irq] == NULL) {
+       hw_intr_mask(irq);
+  }
+  else if (irq_actids[irq] == 0) {
+       hw_intr_unmask(irq);
   }
-  /* When the handler is not found, normally return here. */
 }
 
 /*===========================================================================*
@@ -115,6 +120,13 @@ PUBLIC void irq_handle(int irq)
   hw_intr_mask(irq);
   hook = irq_handlers[irq];
 
+  /* Sanity check. */
+  if(hook == NULL) {
+      printf("%s: irq_handle:no handler registered, masking the IRQ...\n",
+          __FILE__);
+      return;
+  }
+
   /* Call list of handlers for an IRQ. */
   while( hook != NULL ) {
     /* For each handler in the list, mark it active by setting its ID bit,
index 450f5a70406787017c1dc67d2a7ed3eee03b8eb2..daf0989c2923f18ccd479c40e5cc9f7cb0b4e5d2 100644 (file)
@@ -114,6 +114,7 @@ PUBLIC void main()
                 priv(rp)->s_trap_mask= RSYS_T;     /* allowed traps */
                 ipc_to_m = RSYS_M;                 /* allowed targets */
                 kcalls = RSYS_KC;                  /* allowed kernel calls */
+                priv(rp)->s_sig_mgr = RSYS_SM;     /* signal manager */
             }
             /* Priviliges for ordinary process. */
             else {
index b4bd9c886f82da86db18a7a25ef0be97ca45d7d1..42e62698621bb46579cc375c1402a123e53848cf 100644 (file)
@@ -41,8 +41,9 @@ struct priv {
   sys_map_t s_ipc_to;          /* allowed destination processes */
 
   /* allowed kernel calls */
-  bitchunk_t s_k_call_mask[SYS_CALL_MASK_SIZE];  
+  bitchunk_t s_k_call_mask[SYS_CALL_MASK_SIZE];
 
+  endpoint_t s_sig_mgr;                /* signal manager for system signals */
   sys_map_t s_notify_pending;          /* bit map with pending notifications */
   irq_id_t s_int_pending;      /* pending hardware interrupts */
   sigset_t s_sig_pending;      /* pending signals */
@@ -150,4 +151,8 @@ EXTERN struct priv *ppriv_addr[NR_SYS_PROCS];       /* direct slot pointers */
 #define RSYS_KC    ALL_C                                /* root system proc */
 #define DEF_SYS_KC RSYS_KC                              /* default sys proc */
 
+/* signal manager */
+#define RSYS_SM    ROOT_SYS_PROC_NR                     /* root system proc */
+#define DEF_SYS_SM ROOT_SYS_PROC_NR                     /* default sys proc */
+
 #endif /* PRIV_H */
index 8f67988ad572424e6c0de4ddbb62dbc28803d566..319dadd5e1f91e670e04318c36c938e840b64830 100644 (file)
@@ -45,8 +45,8 @@ struct proc {
   struct proc *p_nextready;    /* pointer to next ready process */
   struct proc *p_caller_q;     /* head of list of procs wishing to send */
   struct proc *p_q_link;       /* link to next proc wishing to send */
-  int p_getfrom_e;             /* from whom does process want to receive? */
-  int p_sendto_e;              /* to whom does process want to send? */
+  endpoint_t p_getfrom_e;      /* from whom does process want to receive? */
+  endpoint_t p_sendto_e;       /* to whom does process want to send? */
 
   sigset_t p_pending;          /* bit map for pending kernel signals */
 
index e7e4bea5c5e99f875b936570d206455a27d17c1f..deb2dae1b9a1d4db52747928cac843e61f435b83 100644 (file)
@@ -15,7 +15,7 @@
  *   set_sendto_bit:   allow a process to send messages to a new target
  *   unset_sendto_bit: disallow a process from sending messages to a target
  *   send_sig:         send a signal directly to a system process
- *   cause_sig:                take action to cause a signal to occur via PM
+ *   cause_sig:                take action to cause a signal to occur via a signal mgr
  *   sig_delay_done:   tell PM that a process is not sending
  *   umap_bios:                map virtual address in BIOS_SEG to physical 
  *   get_randomness:   accumulate randomness in a buffer
@@ -176,17 +176,19 @@ PUBLIC void system_init(void)
   /* Process management. */
   map(SYS_FORK, do_fork);              /* a process forked a new process */
   map(SYS_EXEC, do_exec);              /* update process after execute */
-  map(SYS_EXIT, do_exit);              /* clean up after process exit */
+  map(SYS_CLEAR, do_clear);            /* clean up after process exit */
+  map(SYS_EXIT, do_exit);              /* a system process wants to exit */
   map(SYS_NICE, do_nice);              /* set scheduling priority */
   map(SYS_PRIVCTL, do_privctl);                /* system privileges control */
   map(SYS_TRACE, do_trace);            /* request a trace operation */
   map(SYS_SETGRANT, do_setgrant);      /* get/set own parameters */
   map(SYS_RUNCTL, do_runctl);          /* set/clear stop flag of a process */
+  map(SYS_UPDATE, do_update);          /* update a process into another */
 
   /* Signal handling. */
   map(SYS_KILL, do_kill);              /* cause a process to be signaled */
-  map(SYS_GETKSIG, do_getksig);                /* PM checks for pending signals */
-  map(SYS_ENDKSIG, do_endksig);                /* PM finished processing signal */
+  map(SYS_GETKSIG, do_getksig);                /* signal manager checks for signals */
+  map(SYS_ENDKSIG, do_endksig);                /* signal manager finished signal */
   map(SYS_SIGSEND, do_sigsend);                /* start POSIX-style signal */
   map(SYS_SIGRETURN, do_sigreturn);    /* return from POSIX-style signal */
 
@@ -347,27 +349,38 @@ int sig_nr;                       /* signal to be sent */
  *  - HARDWARE wanting to cause a SIGSEGV after a CPU exception
  *  - TTY wanting to cause SIGINT upon getting a DEL
  *  - FS wanting to cause SIGPIPE for a broken pipe 
- * Signals are handled by sending a message to PM.  This function handles the 
- * signals and makes sure the PM gets them by sending a notification. The 
- * process being signaled is blocked while PM has not finished all signals 
- * for it. 
+ * Signals are handled by sending a message to the signal manager assigned to
+ * the process. This function handles the signals and makes sure the signal
+ * manager gets them by sending a notification. The process being signaled
+ * is blocked while the signal manager has not finished all signals for it.
  * Race conditions between calls to this function and the system calls that
  * process pending kernel signals cannot exist. Signal related functions are
  * only called when a user process causes a CPU exception and from the kernel 
  * process level, which runs to completion.
  */
   register struct proc *rp;
+  endpoint_t sig_mgr;
 
-  if (proc_nr == PM_PROC_NR)
-       panic("cause_sig: PM gets signal");
+  /* Lookup signal manager. */
+  rp = proc_addr(proc_nr);
+  sig_mgr = priv(rp)->s_sig_mgr;
+
+  /* If the target is the signal manager of itself, send the signal directly. */
+  if(rp->p_endpoint == sig_mgr) {
+       if(SIGS_IS_LETHAL(sig_nr)) {
+           panic("cause_sig: signal manager gets lethal signal for itself");
+       }
+       sigaddset(&priv(rp)->s_sig_pending, sig_nr);
+       send_sig(rp->p_endpoint, SIGKSIGSM);
+       return;
+  }
 
   /* Check if the signal is already pending. Process it otherwise. */
-  rp = proc_addr(proc_nr);
   if (! sigismember(&rp->p_pending, sig_nr)) {
       sigaddset(&rp->p_pending, sig_nr);
       if (! (RTS_ISSET(rp, RTS_SIGNALED))) {           /* other pending */
          RTS_SET(rp, RTS_SIGNALED | RTS_SIG_PENDING);
-          send_sig(PM_PROC_NR, SIGKSIG);
+          send_sig(sig_mgr, SIGKSIG);
       }
   }
 }
@@ -385,7 +398,7 @@ struct proc *rp;
 
   rp->p_misc_flags &= ~MF_SIG_DELAY;
 
-  cause_sig(proc_nr(rp), SIGNDELAY);
+  cause_sig(proc_nr(rp), SIGKNDELAY);
 }
 
 #if _MINIX_CHIP == _CHIP_INTEL
index 951b4ea6a16d8f839cd6494be734bd979387471e..8c31c504f7490a6b515cbcc930292e39866f2c95 100644 (file)
@@ -8,6 +8,7 @@
  * into a message with type SYS_CALL that is handled in a function do_call(). 
  * 
  * Changes:
+ *   Mar 01, 2010   SYS_CLEAR and SYS_EXIT split (Cristiano Giuffrida)
  *   Jul 30, 2005   created SYS_INT86 to support BIOS driver  (Philip Homburg) 
  *   Jul 13, 2005   created SYS_PRIVCTL to manage services  (Jorrit N. Herder) 
  *   Jul 09, 2005   updated SYS_KILL to signal services  (Jorrit N. Herder) 
@@ -53,9 +54,9 @@ _PROTOTYPE( int do_newmap, (struct proc * caller, message *m_ptr) );
 #define do_newmap do_unused
 #endif
 
-_PROTOTYPE( int do_exit, (struct proc * caller, message *m_ptr) );
-#if ! USE_EXIT
-#define do_exit do_unused
+_PROTOTYPE( int do_clear, (struct proc * caller, message *m_ptr) );
+#if ! USE_CLEAR
+#define do_clear do_unused
 #endif
 
 _PROTOTYPE( int do_trace, (struct proc * caller, message *m_ptr) );
@@ -73,6 +74,16 @@ _PROTOTYPE( int do_runctl, (struct proc * caller, message *m_ptr) );
 #define do_runctl do_unused
 #endif
 
+_PROTOTYPE( int do_update, (struct proc * caller, message *m_ptr) );
+#if ! USE_UPDATE
+#define do_update do_unused
+#endif
+
+_PROTOTYPE( int do_exit, (struct proc * caller, message *m_ptr) );
+#if ! USE_EXIT
+#define do_exit do_unused
+#endif
+
 _PROTOTYPE( int do_copy, (struct proc * caller, message *m_ptr) );
 #define do_vircopy     do_copy
 #if ! (USE_VIRCOPY || USE_PHYSCOPY)
index 8ddd1af7abf08d082b879ec9f81199409a9873ac..0269471591cdda7ae0272b0c28a0e91fffba0227 100644 (file)
@@ -27,10 +27,12 @@ OBJECTS     = \
        do_fork.o \
        do_exec.o \
        do_newmap.o \
+       do_clear.o \
        do_exit.o \
        do_trace.o \
        do_nice.o \
        do_runctl.o \
+       do_update.o \
        do_times.o \
        do_setalarm.o \
        do_stime.o \
index 935568b2be8f38f5269692cb4b54ec2e0a433ab1..60676515b5b13d1034a8042600487a485c32c72c 100644 (file)
@@ -19,7 +19,7 @@
 PUBLIC int do_abort(struct proc * caller, message * m_ptr)
 {
 /* Handle sys_abort. MINIX is unable to continue. This can originate e.g.
- * in the PM (normal abort or panic) or TTY (after CTRL-ALT-DEL).
+ * in the PM (normal abort) or TTY (after CTRL-ALT-DEL).
  */
   int how = m_ptr->ABRT_HOW;
 
diff --git a/kernel/system/do_clear.c b/kernel/system/do_clear.c
new file mode 100644 (file)
index 0000000..31682b3
--- /dev/null
@@ -0,0 +1,75 @@
+/* The kernel call implemented in this file:
+ *   m_type:   SYS_CLEAR
+ *
+ * The parameters for this kernel call are:
+ *    m1_i1:   PR_ENDPT                (endpoint of process to clean up)
+ */
+
+#include "../system.h"
+
+#include <minix/endpoint.h>
+
+#if USE_CLEAR
+
+/*===========================================================================*
+ *                             do_clear                                     *
+ *===========================================================================*/
+PUBLIC int do_clear(struct proc * caller, message * m_ptr)
+{
+/* Handle sys_clear. Only the PM can request other process slots to be cleared
+ * when a process has exited.
+ * The routine to clean up a process table slot cancels outstanding timers, 
+ * possibly removes the process from the message queues, and resets certain 
+ * process table fields to the default values.
+ */
+  struct proc *rc;
+  int exit_p;
+  int i;
+
+  if(!isokendpt(m_ptr->PR_ENDPT, &exit_p)) { /* get exiting process */
+      return EINVAL;
+  }
+  rc = proc_addr(exit_p);      /* clean up */
+
+  /* Don't clear if already cleared. */
+  if(isemptyp(rc)) return;
+
+  /* Check the table with IRQ hooks to see if hooks should be released. */
+  for (i=0; i < NR_IRQ_HOOKS; i++) {
+      if (rc->p_endpoint == irq_hooks[i].proc_nr_e) {
+        rm_irq_handler(&irq_hooks[i]); /* remove interrupt handler */
+        irq_hooks[i].proc_nr_e = NONE; /* mark hook as free */
+      } 
+  }
+
+  /* Remove the process' ability to send and receive messages */
+  clear_endpoint(rc);
+
+  /* Turn off any alarm timers at the clock. */   
+  reset_timer(&priv(rc)->s_alarm_timer);
+
+  /* Make sure that the exiting process is no longer scheduled,
+   * and mark slot as FREE. Also mark saved fpu contents as not significant.
+   */
+  RTS_SETFLAGS(rc, RTS_SLOT_FREE);
+  rc->p_misc_flags &= ~MF_FPU_INITIALIZED;
+
+  /* Release the process table slot. If this is a system process, also
+   * release its privilege structure.  Further cleanup is not needed at
+   * this point. All important fields are reinitialized when the 
+   * slots are assigned to another, new process. 
+   */
+  if (priv(rc)->s_flags & SYS_PROC) priv(rc)->s_proc_nr = NONE;
+
+#if 0
+  /* Clean up virtual memory */
+  if (rc->p_misc_flags & MF_VM) {
+       vm_map_default(rc);
+  }
+#endif
+
+  return OK;
+}
+
+#endif /* USE_CLEAR */
+
index 1b09b894c9315632f7b3070b8ca1b6bcedefe158..cd1acaf62e92edb04a833fbcebe5df6a16cf61cb 100644 (file)
@@ -15,8 +15,8 @@
 PUBLIC int do_endksig(struct proc * caller, message * m_ptr)
 {
 /* Finish up after a kernel type signal, caused by a SYS_KILL message or a 
- * call to cause_sig by a task. This is called by the PM after processing a
- * signal it got with SYS_GETKSIG.
+ * call to cause_sig by a task. This is called by a signal manager after
+ * processing a signal it got with SYS_GETKSIG.
  */
   register struct proc *rp;
   int proc_nr;
@@ -28,9 +28,10 @@ PUBLIC int do_endksig(struct proc * caller, message * m_ptr)
        return EINVAL;
 
   rp = proc_addr(proc_nr);
+  if (caller->p_endpoint != priv(rp)->s_sig_mgr) return(EPERM);
   if (!RTS_ISSET(rp, RTS_SIG_PENDING)) return(EINVAL);
 
-  /* PM has finished one kernel signal. Perhaps process is ready now? */
+  /* The signal manager has finished one kernel signal. Is the process ready? */
   if (!RTS_ISSET(rp, RTS_SIGNALED))            /* new signal arrived */
        RTS_UNSET(rp, RTS_SIG_PENDING); /* remove pending flag */
   return(OK);
index 277333a0ff09da926d806d9b340dacb9b8692c3f..2970a7eb53df9e129e71a9aab00eb69ba3447181 100644 (file)
@@ -1,91 +1,27 @@
 /* The kernel call implemented in this file:
  *   m_type:   SYS_EXIT
- *
- * The parameters for this kernel call are:
- *    m1_i1:   PR_ENDPT                (slot number of exiting process)
  */
 
 #include "../system.h"
 
 #include <minix/endpoint.h>
+#include <signal.h>
 
 #if USE_EXIT
 
-FORWARD _PROTOTYPE( void clear_proc, (register struct proc *rc));
-
 /*===========================================================================*
- *                             do_exit                                      *
+ *                              do_exit                                     *
  *===========================================================================*/
 PUBLIC int do_exit(struct proc * caller, message * m_ptr)
 {
-/* Handle sys_exit. A user process has exited or a system process requests 
- * to exit. Only the PM can request other process slots to be cleared.
- * The routine to clean up a process table slot cancels outstanding timers, 
- * possibly removes the process from the message queues, and resets certain 
- * process table fields to the default values.
+/* Handle sys_exit. A system process has requested to exit. Generate a
+ * self-termination signal.
  */
-  int exit_e;                          
-
-  /* Determine what process exited. User processes are handled here. */
-  if (PM_PROC_NR == caller->p_endpoint) {
-      if (m_ptr->PR_ENDPT != SELF) {           /* PM tries to exit self */
-          if(!isokendpt(m_ptr->PR_ENDPT, &exit_e)) /* get exiting process */
-            return EINVAL;
-          clear_proc(proc_addr(exit_e));       /* exit a user process */
-          return(OK);                          /* report back to PM */
-      }
-  } 
-
-  /* The PM or some other system process requested to be exited. */
-  clear_proc(caller);
-  return(EDONTREPLY);
-}
-
-/*===========================================================================*
- *                              clear_proc                                  *
- *===========================================================================*/
-PRIVATE void clear_proc(rc)
-register struct proc *rc;              /* slot of process to clean up */
-{
-  int i;
-
-  /* Don't clear if already cleared. */
-  if(isemptyp(rc)) return;
-
-  /* Check the table with IRQ hooks to see if hooks should be released. */
-  for (i=0; i < NR_IRQ_HOOKS; i++) {
-      if (rc->p_endpoint == irq_hooks[i].proc_nr_e) {
-        rm_irq_handler(&irq_hooks[i]); /* remove interrupt handler */
-        irq_hooks[i].proc_nr_e = NONE; /* mark hook as free */
-      } 
-  }
-
-  /* Remove the process' ability to send and receive messages */
-  clear_endpoint(rc);
-
-
-  /* Turn off any alarm timers at the clock. */   
-  reset_timer(&priv(rc)->s_alarm_timer);
-
-  /* Make sure that the exiting process is no longer scheduled,
-   * and mark slot as FREE. Also mark saved fpu contents as not significant.
-   */
-  RTS_SETFLAGS(rc, RTS_SLOT_FREE);
-  rc->p_misc_flags &= ~MF_FPU_INITIALIZED;
+  int sig_nr = SIGABRT;
 
-  /* Release the process table slot. If this is a system process, also
-   * release its privilege structure.  Further cleanup is not needed at
-   * this point. All important fields are reinitialized when the 
-   * slots are assigned to another, new process. 
-   */
-  if (priv(rc)->s_flags & SYS_PROC) priv(rc)->s_proc_nr = NONE;
+  cause_sig(caller->p_nr, sig_nr);      /* send a signal to the caller */
 
-#if 0
-  /* Clean up virtual memory */
-  if (rc->p_misc_flags & MF_VM) {
-       vm_map_default(rc);
-  }
-#endif
+  return(EDONTREPLY);                  /* don't reply */
 }
 
 #endif /* USE_EXIT */
index 7c05c83b85eb2d93962988917587bb9ba3b4a89b..1416113dbd9c47634a13078b02ab70d6440be69d 100644 (file)
  *===========================================================================*/
 PUBLIC int do_getksig(struct proc * caller, message * m_ptr)
 {
-/* PM is ready to accept signals and repeatedly does a kernel call to get 
- * one. Find a process with pending signals. If no signals are available, 
- * return NONE in the process number field.
- * It is not sufficient to ready the process when PM is informed, because 
- * PM can block waiting for FS to do a core dump.
+/* The signal manager is ready to accept signals and repeatedly does a kernel
+ * call to get one. Find a process with pending signals. If no signals are
+ * available, return NONE in the process number field.
  */
   register struct proc *rp;
 
   /* Find the next process with pending signals. */
   for (rp = BEG_USER_ADDR; rp < END_PROC_ADDR; rp++) {
       if (RTS_ISSET(rp, RTS_SIGNALED)) {
+          if (caller->p_endpoint != priv(rp)->s_sig_mgr) continue;
          /* store signaled process' endpoint */
           m_ptr->SIG_ENDPT = rp->p_endpoint;
           m_ptr->SIG_MAP = rp->p_pending;      /* pending signals map */
-          sigemptyset(&rp->p_pending);                 /* ball is in PM's court */
+          sigemptyset(&rp->p_pending);                 /* clear map in the kernel */
          RTS_UNSET(rp, RTS_SIGNALED);          /* blocked by SIG_PENDING */
           return(OK);
       }
index 04758a8605709951d47e19f2b948ddafc407ca5c..c6ace6842f877fddd75f86bb3cdf2a1eb197ccf6 100644 (file)
  *===========================================================================*/
 PUBLIC int do_kill(struct proc * caller, message * m_ptr)
 {
-/* Handle sys_kill(). Cause a signal to be sent to a process. The PM is the
- * central server where all signals are processed and handler policies can
- * be registered. Any request, except for PM requests, is added to the map
- * of pending signals and the PM is informed about the new signal.
- * Since system servers cannot use normal POSIX signal handlers (because they
- * are usually blocked on a RECEIVE), they can request the PM to transform 
- * signals into messages. This is done by the PM with a call to sys_kill(). 
+/* Handle sys_kill(). Cause a signal to be sent to a process. Any request
+ * is added to the map of pending signals and the signal manager
+ * associated to the process is informed about the new signal. The signal
+ * is then delivered using POSIX signal handlers for user processes, or
+ * translated into an IPC message for system services.
  */
   proc_nr_t proc_nr, proc_nr_e;
   int sig_nr = m_ptr->SIG_NUMBER;
@@ -33,10 +31,9 @@ PUBLIC int do_kill(struct proc * caller, message * m_ptr)
   if (sig_nr >= _NSIG) return(EINVAL);
   if (iskerneln(proc_nr)) return(EPERM);
 
-  /* Set pending signal to be processed by the PM. */
+  /* Set pending signal to be processed by the signal manager. */
   cause_sig(proc_nr, sig_nr);
-  if (sig_nr == SIGKILL)
-       clear_endpoint(proc_addr(proc_nr));
+
   return(OK);
 }
 
index 11568811ddc56cd593fdf773f514ba1b5aed31db..0fcdaba674f261c879d398f2e7dd6f41309583f7 100644 (file)
@@ -111,6 +111,9 @@ PUBLIC int do_privctl(struct proc * caller, message * m_ptr)
                priv(rp)->s_k_call_mask[i] = (kcalls == NO_C ? 0 : (~0));
        }
 
+       /* Set the default signal manager. */
+       priv(rp)->s_sig_mgr = DEF_SYS_SM;
+
        /* Set defaults for resources: no I/O resources, no memory resources,
         * no IRQs, no grant table
         */
@@ -123,8 +126,9 @@ PUBLIC int do_privctl(struct proc * caller, message * m_ptr)
        /* Override defaults if the caller has supplied a privilege structure. */
        if (m_ptr->CTL_ARG_PTR)
        {
-               /* Copy s_flags. */
+               /* Copy s_flags and signal manager. */
                priv(rp)->s_flags = priv.s_flags;
+               priv(rp)->s_sig_mgr = priv.s_sig_mgr;
 
                /* Copy IRQs */
                if(priv.s_flags & CHECK_IRQ) {
index d3ba0890d0c5e905dab91dd94c480ef68f971f3a..fb0a7055849ced646f11d6a4d749a4750445dec6 100644 (file)
@@ -19,7 +19,7 @@ PUBLIC int do_runctl(struct proc * caller, message * m_ptr)
 /* Control a process's RTS_PROC_STOP flag. Used for process management.
  * If the process is queued sending a message or stopped for system call
  * tracing, and the RC_DELAY request flag is given, set MF_SIG_DELAY instead
- * of RTS_PROC_STOP, and send a SIGNDELAY signal later when the process is done
+ * of RTS_PROC_STOP, and send a SIGKNDELAY signal later when the process is done
  * sending (ending the delay). Used by PM for safe signal delivery.
  */
   int proc_nr, action, flags, delayed;
index f442293bc941ff3cb3d478077b441712ee60e54d..32dc2ebe91ef2833c334281520754c9cb874ce63 100644 (file)
 
 #include <assert.h>
 
+#include <minix/type.h>
 #include <minix/type.h>
 #include <minix/safecopies.h>
 
 #include "../system.h"
 
+#include <signal.h>
 
 struct map_info_s {
        int flag;
@@ -161,7 +163,7 @@ PUBLIC int map_invoke_vm(struct proc * caller,
 
        /* Connect caller on vmrequest wait queue. */
        if(!(caller->p_vmrequest.nextrequestor = vmrequest))
-               mini_notify(proc_addr(SYSTEM), VM_PROC_NR);
+               send_sig(VM_PROC_NR, SIGKMEM);
        vmrequest = caller;
 
        return OK;
diff --git a/kernel/system/do_update.c b/kernel/system/do_update.c
new file mode 100644 (file)
index 0000000..ef43407
--- /dev/null
@@ -0,0 +1,165 @@
+/* The kernel call implemented in this file:
+ *   m_type:   SYS_UPDATE
+ *
+ * The parameters for this kernel call are:
+ *    m2_i1:   SYS_UPD_SRC_ENDPT       (source process endpoint)
+ *    m2_i2:   SYS_UPD_DST_ENDPT       (destination process endpoint)
+ */
+
+#include "../system.h"
+#include "../ipc.h"
+#include <string.h>
+
+#if USE_UPDATE
+
+#define DEBUG 0
+
+#define proc_is_updatable(p) \
+    (RTS_ISSET(p, RTS_NO_PRIV) || RTS_ISSET(p, RTS_SIG_PENDING) \
+    || (RTS_ISSET(p, RTS_RECEIVING) && !RTS_ISSET(p, RTS_SENDING)))
+
+FORWARD _PROTOTYPE(void adjust_proc_slot, (struct proc *rp,
+    struct proc *from_rp));
+FORWARD _PROTOTYPE(void adjust_priv_slot, (struct priv *privp,
+    struct priv *from_privp));
+FORWARD _PROTOTYPE(void swap_proc_slot_pointer, (struct proc **rpp,
+    struct proc *src_rp, struct proc *dst_rp));
+
+/*===========================================================================*
+ *                             do_update                                    *
+ *===========================================================================*/
+PUBLIC int do_update(struct proc * caller, message * m_ptr)
+{
+/* Handle sys_update(). Update a process into another by swapping their process
+ * slots.
+ */
+  endpoint_t src_e, dst_e;
+  int src_p, dst_p;
+  struct proc *src_rp, *dst_rp, *rp;
+  struct priv *src_privp, *dst_privp;
+  struct proc orig_src_proc;
+  struct proc orig_dst_proc;
+  struct priv orig_src_priv;
+  struct priv orig_dst_priv;
+  int r;
+  reg_t src_vbp, dst_vbp;
+
+  /* Lookup slots for source and destination process. */
+  src_e = m_ptr->SYS_UPD_SRC_ENDPT;
+  if(!isokendpt(src_e, &src_p)) {
+      return EINVAL;
+  }
+  src_rp = proc_addr(src_p);
+  src_privp = priv(src_rp);
+  if(!(src_privp->s_flags & SYS_PROC)) {
+      return EPERM;
+  }
+
+  dst_e = m_ptr->SYS_UPD_DST_ENDPT;
+  if(!isokendpt(dst_e, &dst_p)) {
+      return EINVAL;
+  }
+  dst_rp = proc_addr(dst_p);
+  dst_privp = priv(dst_rp);
+  if(!(dst_privp->s_flags & SYS_PROC)) {
+      return EPERM;
+  }
+
+  /* Check if processes are updatable. */
+  if(!proc_is_updatable(src_rp) || !proc_is_updatable(dst_rp)) {
+      return EBUSY;
+  }
+
+#if DEBUG
+  printf("do_update: updating %d (%s, %d, %d) into %d (%s, %d, %d)\n",
+      src_rp->p_endpoint, src_rp->p_name, src_rp->p_nr, priv(src_rp)->s_proc_nr,
+      dst_rp->p_endpoint, dst_rp->p_name, dst_rp->p_nr, priv(dst_rp)->s_proc_nr);
+
+  proc_stacktrace(src_rp);
+  proc_stacktrace(dst_rp);
+  printf("do_update: curr ptproc %d\n", ptproc->p_endpoint);
+#endif
+
+  /* Save existing data. */
+  orig_src_proc = *src_rp;
+  orig_src_priv = *(priv(src_rp));
+  orig_dst_proc = *dst_rp;
+  orig_dst_priv = *(priv(dst_rp));
+
+  /* Swap slots. */
+  *src_rp = orig_dst_proc;
+  *src_privp = orig_dst_priv;
+  *dst_rp = orig_src_proc;
+  *dst_privp = orig_src_priv;
+
+  /* Adjust process slots. */
+  adjust_proc_slot(src_rp, &orig_src_proc);
+  adjust_proc_slot(dst_rp, &orig_dst_proc);
+
+  /* Adjust privilege slots. */
+  adjust_priv_slot(priv(src_rp), &orig_src_priv);
+  adjust_priv_slot(priv(dst_rp), &orig_dst_priv);
+
+  /* Swap global process slot addresses. */
+  swap_proc_slot_pointer(&ptproc, src_rp, dst_rp);
+
+  /* Fix segments. */
+  alloc_segments(src_rp);
+  alloc_segments(dst_rp);
+  prot_init();
+
+#if DEBUG
+  printf("do_update: updated %d (%s, %d, %d) into %d (%s, %d, %d)\n",
+      src_rp->p_endpoint, src_rp->p_name, src_rp->p_nr, priv(src_rp)->s_proc_nr,
+      dst_rp->p_endpoint, dst_rp->p_name, dst_rp->p_nr, priv(dst_rp)->s_proc_nr);
+
+  proc_stacktrace(src_rp);
+  proc_stacktrace(dst_rp);
+  printf("do_update: curr ptproc %d\n", ptproc->p_endpoint);
+#endif
+
+  return OK;
+}
+
+/*===========================================================================*
+ *                          adjust_proc_slot                                *
+ *===========================================================================*/
+PRIVATE void adjust_proc_slot(struct proc *rp, struct proc *from_rp)
+{
+  /* Preserve endpoints, slot numbers, priv structure. */
+  rp->p_endpoint = from_rp->p_endpoint;
+  rp->p_nr = from_rp->p_nr;
+  rp->p_priv = from_rp->p_priv;
+  priv(rp)->s_proc_nr = from_rp->p_nr;
+}
+
+/*===========================================================================*
+ *                          adjust_priv_slot                                *
+ *===========================================================================*/
+PRIVATE void adjust_priv_slot(struct priv *privp, struct priv *from_privp)
+{
+  /* Preserve privilege ids and non-privilege stuff in the priv structure. */
+  privp->s_id = from_privp->s_id;
+  privp->s_notify_pending = from_privp->s_notify_pending;
+  privp->s_int_pending = from_privp->s_int_pending;
+  privp->s_sig_pending = from_privp->s_sig_pending;
+  privp->s_alarm_timer = from_privp->s_alarm_timer;
+  memcpy(privp->s_farmem, from_privp->s_farmem, sizeof(privp->s_farmem));
+}
+
+/*===========================================================================*
+ *                        swap_proc_slot_pointer                            *
+ *===========================================================================*/
+PRIVATE void swap_proc_slot_pointer(struct proc **rpp, struct proc *src_rp,
+    struct proc *dst_rp)
+{
+  if(*rpp == src_rp) {
+      *rpp = dst_rp;
+  }
+  else if(*rpp == dst_rp) {
+      *rpp = src_rp;
+  }
+}
+
+#endif /* USE_UPDATE */
+
index 605a2f7cab2a050334f6ad356ec837b9bb405dea..1bdec1a220979ad37d8d3fd704f1ce1025afff13 100644 (file)
@@ -48,7 +48,7 @@ const char *_sys_errlist[] = {
        "Function not implemented",     /* ENOSYS */
        "Directory not empty",          /* ENOTEMPTY */
        "Too many levels of symbolic links",    /* ELOOP */
-       "Driver restarted",             /* ERESTART */
+       "Service restarted",            /* ERESTART */
        unknown,                        /* 42 */
        "Identifier removed",           /* EIDRM */
        "Illegal byte sequence",        /* EILSEQ */
index 04e56303db3a56f6b646f875011ff4a87a139bd3..56f6da8f92610b73a4ef8905a65818274b9f2a39 100644 (file)
@@ -33,6 +33,7 @@ SRCS+=  \
        _sysuname.c \
        _vm_dmacalls.c \
        _vm_set_priv.c \
+       _vm_update.c \
        _vm_query_exit.c \
        asynchio.c \
        basename.c \
diff --git a/lib/libc/other/_vm_update.c b/lib/libc/other/_vm_update.c
new file mode 100644 (file)
index 0000000..12b6231
--- /dev/null
@@ -0,0 +1,12 @@
+#include <lib.h>
+#define vm_update _vm_update
+#include <unistd.h>
+
+PUBLIC int vm_update(endpoint_t src_e, endpoint_t dst_e)
+{
+       message m;
+       m.VM_RS_SRC_ENDPT = src_e;
+       m.VM_RS_DST_ENDPT = dst_e;
+
+       return _syscall(VM_PROC_NR, VM_RS_UPDATE, &m);
+}
index b67470550d67791112d83acf8f76a3ee9b194d95..f4993c4f104e0ad40f6937172beda8506c6ddf1a 100644 (file)
@@ -74,6 +74,7 @@ SRCS+=  \
        vm_remap.S \
        vm_unmap.S \
        vm_set_priv.S \
+       vm_update.S \
        vm_query_exit.S \
        mount.S \
        nanosleep.S \
diff --git a/lib/libc/syscall/vm_update.S b/lib/libc/syscall/vm_update.S
new file mode 100644 (file)
index 0000000..3f8c714
--- /dev/null
@@ -0,0 +1,7 @@
+.text
+.extern        __vm_update
+.globl _vm_update
+.balign        2
+
+_vm_update:
+       jmp     __vm_update
index dc408dbc1000d012ea4aad42bf2d10e83cca3936..0965e732a8b86661b773aa9db8b8afd75c38f52b 100644 (file)
@@ -29,10 +29,12 @@ SRCS=  \
        pci_slot_name.c \
        safecopies.c \
        sef.c \
+       sef_init.c \
        sef_liveupdate.c \
        sef_ping.c \
-       sef_init.c \
+       sef_signal.c \
        sys_abort.c \
+       sys_clear.c \
        sys_mcontext.c \
        sys_cprof.c \
        sys_endsig.c \
@@ -53,6 +55,7 @@ SRCS=  \
        sys_physcopy.c \
        sys_readbios.c \
        sys_runctl.c \
+       sys_update.c \
        sys_safecopy.c \
        sys_safemap.c \
        sys_sysctl.c \
index 491a61785d8c836b7fe9a4fb13cff7a8c13a3760..948579a87dd2766d6bae5a324ed0dbe6dbabf735 100644 (file)
@@ -49,16 +49,8 @@ int ds_publish_u32(const char *ds_name, u32_t value, int flags)
        return do_invoke_ds(DS_PUBLISH, ds_name);
 }
 
-int ds_publish_str(const char *ds_name, char *value, int flags)
-{
-       if(strlen(value) >= DS_MAX_STRLEN)
-               return EINVAL;
-       strcpy((char *)(&m.DS_STRING), value);
-       m.DS_FLAGS = DSF_TYPE_STR | flags;
-       return do_invoke_ds(DS_PUBLISH, ds_name);
-}
-
-int ds_publish_mem(const char *ds_name, void *vaddr, size_t length, int flags)
+static int ds_publish_raw(const char *ds_name, void *vaddr, size_t length,
+       int flags)
 {
        cp_grant_id_t gid;
        int r;
@@ -70,7 +62,7 @@ int ds_publish_mem(const char *ds_name, void *vaddr, size_t length, int flags)
 
        m.DS_VAL = gid;
        m.DS_VAL_LEN = length;
-       m.DS_FLAGS = DSF_TYPE_MEM | flags;
+       m.DS_FLAGS = flags;
 
        r = do_invoke_ds(DS_PUBLISH, ds_name);
        cpf_revoke(gid);
@@ -78,6 +70,19 @@ int ds_publish_mem(const char *ds_name, void *vaddr, size_t length, int flags)
        return r;
 }
 
+int ds_publish_str(const char *ds_name, char *value, int flags)
+{
+       size_t length;
+       length = strlen(value) + 1;
+       value[length - 1] = '\0';
+       return ds_publish_raw(ds_name, value, length, flags | DSF_TYPE_STR);
+}
+
+int ds_publish_mem(const char *ds_name, void *vaddr, size_t length, int flags)
+{
+       return ds_publish_raw(ds_name, vaddr, length, flags | DSF_TYPE_MEM);
+}
+
 int ds_publish_map(const char *ds_name, void *vaddr, size_t length, int flags)
 {
        cp_grant_id_t gid;
@@ -97,7 +102,6 @@ int ds_publish_map(const char *ds_name, void *vaddr, size_t length, int flags)
        m.DS_FLAGS = DSF_TYPE_MAP | flags;
 
        r = do_invoke_ds(DS_PUBLISH, ds_name);
-       cpf_revoke(gid);
 
        return r;
 }
@@ -136,17 +140,8 @@ int ds_retrieve_u32(const char *ds_name, u32_t *value)
        return r;
 }
 
-int ds_retrieve_str(const char *ds_name, char *value, size_t len_str)
-{
-       int r;
-       m.DS_FLAGS = DSF_TYPE_STR;
-       r = do_invoke_ds(DS_RETRIEVE, ds_name);
-       strncpy(value, (char *)(&m.DS_STRING), DS_MAX_STRLEN);
-       value[DS_MAX_STRLEN - 1] = '\0';
-       return r;
-}
-
-int ds_retrieve_mem(const char *ds_name, char *vaddr, size_t *length)
+static int ds_retrieve_raw(const char *ds_name, char *vaddr, size_t *length,
+       int flags)
 {
        cp_grant_id_t gid;
        int r;
@@ -158,7 +153,7 @@ int ds_retrieve_mem(const char *ds_name, char *vaddr, size_t *length)
 
        m.DS_VAL = gid;
        m.DS_VAL_LEN = *length;
-       m.DS_FLAGS = DSF_TYPE_MEM;
+       m.DS_FLAGS = flags;
        r = do_invoke_ds(DS_RETRIEVE, ds_name);
        *length = m.DS_VAL_LEN;
        cpf_revoke(gid);
@@ -166,6 +161,20 @@ int ds_retrieve_mem(const char *ds_name, char *vaddr, size_t *length)
        return r;
 }
 
+int ds_retrieve_str(const char *ds_name, char *value, size_t len_str)
+{
+       int r;
+       size_t length = len_str + 1;
+       r = ds_retrieve_raw(ds_name, value, &length, DSF_TYPE_STR);
+       value[length - 1] = '\0';
+       return r;
+}
+
+int ds_retrieve_mem(const char *ds_name, char *vaddr, size_t *length)
+{
+       return ds_retrieve_raw(ds_name, vaddr, length, DSF_TYPE_MEM);
+}
+
 int ds_retrieve_map(const char *ds_name, char *vaddr, size_t *length,
                int nr_snapshot, int flags)
 {
index 50e1eeb4897051549f76dfb2c46fab12decfdf47..7dd78494025a425da4d16b8de4a6e798451b7be4 100644 (file)
@@ -5,8 +5,8 @@
 
 /* Self variables. */
 #define SEF_SELF_NAME_MAXLEN 20
-PRIVATE char sef_self_name[SEF_SELF_NAME_MAXLEN];
-PRIVATE endpoint_t sef_self_endpoint;
+PUBLIC char sef_self_name[SEF_SELF_NAME_MAXLEN];
+PUBLIC endpoint_t sef_self_endpoint;
 
 /* Debug. */
 #define SEF_DEBUG_HEADER_MAXLEN 32
@@ -22,19 +22,22 @@ PUBLIC _PROTOTYPE( char* sef_debug_header, (void) );
 EXTERN _PROTOTYPE( int do_sef_rs_init, (void) );
 EXTERN _PROTOTYPE( int do_sef_init_request, (message *m_ptr) );
 
+/* SEF Ping prototypes. */
+EXTERN _PROTOTYPE( int do_sef_ping_request, (message *m_ptr) );
+
 /* SEF Live update prototypes. */
 EXTERN _PROTOTYPE( void do_sef_lu_before_receive, (void) );
 EXTERN _PROTOTYPE( int do_sef_lu_request, (message *m_ptr) );
 
-/* SEF Ping prototypes. */
-EXTERN _PROTOTYPE( int do_sef_ping_request, (message *m_ptr) );
+/* SEF Signal prototypes. */
+EXTERN _PROTOTYPE( int do_sef_signal_request, (message *m_ptr) );
 
 /*===========================================================================*
  *                             sef_startup                                  *
  *===========================================================================*/
 PUBLIC void sef_startup()
 {
-/* SEF startup interface for system processes. */
+/* SEF startup interface for system services. */
   int r;
 
   /* Get information about self. */
@@ -63,7 +66,7 @@ PUBLIC void sef_startup()
           }
       }
       else {
-          panic("unable to receive init request");
+          panic("got an unexpected message type %d", m.m_type);
       }
   }
 #endif
@@ -74,7 +77,7 @@ PUBLIC void sef_startup()
  *===========================================================================*/
 PUBLIC int sef_receive(endpoint_t src, message *m_ptr)
 {
-/* SEF receive() interface for system processes. */
+/* SEF receive() interface for system services. */
   int r;
 
   while(TRUE) {
@@ -108,6 +111,15 @@ PUBLIC int sef_receive(endpoint_t src, message *m_ptr)
       }
 #endif
 
+#if INTERCEPT_SEF_SIGNAL_REQUESTS
+      /* Intercept SEF Signal requests. */
+      if(IS_SEF_SIGNAL_REQUEST(m_ptr)) {
+          if(do_sef_signal_request(m_ptr) == OK) {
+              continue;
+          }
+      }
+#endif
+
       /* If we get this far, this is not a valid SEF request, return and
        * let the caller deal with that.
        */
@@ -117,6 +129,46 @@ PUBLIC int sef_receive(endpoint_t src, message *m_ptr)
   return r;
 }
 
+/*===========================================================================*
+ *                               sef_exit                                   *
+ *===========================================================================*/
+PUBLIC void sef_exit(int status)
+{
+/* System services use a special version of exit() that generates a
+ * self-termination signal.
+ */
+  message m;
+
+  /* Ask the kernel to exit. */
+  sys_exit();
+
+  /* If sys_exit() fails, this is not a system service. Exit through PM. */
+  m.m1_i1 = status;
+  _syscall(PM_PROC_NR, EXIT, &m);
+
+  /* If everything else fails, hang. */
+  printf("Warning: system service %d couldn't exit\n", sef_self_endpoint);
+  for(;;) { }
+}
+
+/*===========================================================================*
+ *                                  _exit                                   *
+ *===========================================================================*/
+PUBLIC void _exit(int status)
+{
+/* Make exit() an alias for sef_exit() for system services. */
+  sef_exit(status);
+}
+
+/*===========================================================================*
+ *                                 __exit                                   *
+ *===========================================================================*/
+PUBLIC void __exit(int status)
+{
+/* Make exit() an alias for sef_exit() for system services. */
+  sef_exit(status);
+}
+
 /*===========================================================================*
  *                         sef_debug_refresh_params                         *
  *===========================================================================*/
index 4b1671a0222863878374751850fb67072cb28b7b..1c7904a7d125c6d16cb95796db6b1114c76530e5 100644 (file)
@@ -4,9 +4,9 @@
 
 /* SEF Init callbacks. */
 PRIVATE struct sef_cbs {
-    sef_cb_init_fresh_t                 sef_cb_init_fresh;
-    sef_cb_init_lu_t                    sef_cb_init_lu;
-    sef_cb_init_restart_t               sef_cb_init_restart;
+    sef_cb_init_t                       sef_cb_init_fresh;
+    sef_cb_init_t                       sef_cb_init_lu;
+    sef_cb_init_t                       sef_cb_init_restart;
 } sef_cbs = {
     SEF_CB_INIT_FRESH_DEFAULT,
     SEF_CB_INIT_LU_DEFAULT,
@@ -67,11 +67,9 @@ PUBLIC int do_sef_init_request(message *m_ptr)
       break;
   }
 
-  /* Report back to RS. XXX FIXME: we should use send, but this would cause
-   * a deadlock due to the current blocking nature of mapdriver().
-   */
+  /* Report back to RS. */
   m_ptr->RS_INIT_RESULT = r;
-  r = asynsend(RS_PROC_NR, m_ptr);
+  r = sendrec(RS_PROC_NR, m_ptr);
 
   return r;
 }
@@ -79,7 +77,7 @@ PUBLIC int do_sef_init_request(message *m_ptr)
 /*===========================================================================*
  *                         sef_setcb_init_fresh                              *
  *===========================================================================*/
-PUBLIC void sef_setcb_init_fresh(sef_cb_init_fresh_t cb)
+PUBLIC void sef_setcb_init_fresh(sef_cb_init_t cb)
 {
   assert(cb != NULL);
   sef_cbs.sef_cb_init_fresh = cb;
@@ -88,7 +86,7 @@ PUBLIC void sef_setcb_init_fresh(sef_cb_init_fresh_t cb)
 /*===========================================================================*
  *                            sef_setcb_init_lu                              *
  *===========================================================================*/
-PUBLIC void sef_setcb_init_lu(sef_cb_init_lu_t cb)
+PUBLIC void sef_setcb_init_lu(sef_cb_init_t cb)
 {
   assert(cb != NULL);
   sef_cbs.sef_cb_init_lu = cb;
@@ -97,44 +95,36 @@ PUBLIC void sef_setcb_init_lu(sef_cb_init_lu_t cb)
 /*===========================================================================*
  *                         sef_setcb_init_restart                            *
  *===========================================================================*/
-PUBLIC void sef_setcb_init_restart(sef_cb_init_restart_t cb)
+PUBLIC void sef_setcb_init_restart(sef_cb_init_t cb)
 {
   assert(cb != NULL);
   sef_cbs.sef_cb_init_restart = cb;
 }
 
 /*===========================================================================*
- *                         sef_cb_init_fresh_null                           *
+ *                           sef_cb_init_null                               *
  *===========================================================================*/
-PUBLIC int sef_cb_init_fresh_null(int UNUSED(type),
+PUBLIC int sef_cb_init_null(int UNUSED(type),
    sef_init_info_t *UNUSED(info))
 {
-  return(OK);
+  return OK;
 }
 
 /*===========================================================================*
- *                           sef_cb_init_lu_null                            *
+ *                           sef_cb_init_fail                               *
  *===========================================================================*/
-PUBLIC int sef_cb_init_lu_null(int UNUSED(type), sef_init_info_t *UNUSED(info))
+PUBLIC int sef_cb_init_fail(int UNUSED(type), sef_init_info_t *UNUSED(info))
 {
-  return(OK);
+  return ENOSYS;
 }
 
 /*===========================================================================*
- *                         sef_cb_init_restart_null                         *
+ *                           sef_cb_init_crash                              *
  *===========================================================================*/
-PUBLIC int sef_cb_init_restart_null(int UNUSED(type),
-     sef_init_info_t *UNUSED(info))
+PUBLIC int sef_cb_init_crash(int UNUSED(type), sef_init_info_t *UNUSED(info))
 {
-  return(OK);
-}
+  panic("Simulating a crash at initialization time...");
 
-/*===========================================================================*
- *                         sef_cb_init_restart_fail                         *
- *===========================================================================*/
-PUBLIC int sef_cb_init_restart_fail(int UNUSED(type),
-   sef_init_info_t *UNUSED(info))
-{
-  return(ENOSYS);
+  return OK;
 }
 
index 4bf894492f25f5e044917b582bf2bb611570bc88..553447f61c6e5607ae12c080b0132d2fae583073 100644 (file)
@@ -11,19 +11,22 @@ PRIVATE struct sef_cbs {
     sef_cb_lu_state_isvalid_t           sef_cb_lu_state_isvalid;
     sef_cb_lu_state_changed_t           sef_cb_lu_state_changed;
     sef_cb_lu_state_dump_t              sef_cb_lu_state_dump;
-    sef_cb_lu_ready_pre_t               sef_cb_lu_ready_pre;
+    sef_cb_lu_state_save_t              sef_cb_lu_state_save;
 } sef_cbs = {
     SEF_CB_LU_PREPARE_DEFAULT,
     SEF_CB_LU_STATE_ISVALID_DEFAULT,
     SEF_CB_LU_STATE_CHANGED_DEFAULT,
     SEF_CB_LU_STATE_DUMP_DEFAULT,
-    SEF_CB_LU_READY_PRE_DEFAULT,
+    SEF_CB_LU_STATE_SAVE_DEFAULT,
 };
 
 /* SEF Live update prototypes for sef_receive(). */
 PUBLIC _PROTOTYPE( void do_sef_lu_before_receive, (void) );
 PUBLIC _PROTOTYPE( int do_sef_lu_request, (message *m_ptr) );
 
+/* SEF Live update helpers. */
+PRIVATE _PROTOTYPE( void sef_lu_ready, (int result) );
+
 /* Debug. */
 EXTERN _PROTOTYPE( char* sef_debug_header, (void) );
 PRIVATE int sef_lu_debug_cycle = 0;
@@ -34,6 +37,7 @@ PRIVATE int sef_lu_debug_cycle = 0;
 PUBLIC void do_sef_lu_before_receive()
 {
 /* Handle SEF Live update before receive events. */
+  int r;
 
   /* Nothing to do if we are not preparing for a live update. */
   if(sef_lu_state == SEF_LU_STATE_NULL) {
@@ -53,11 +57,12 @@ PUBLIC void do_sef_lu_before_receive()
   /* Let the callback code handle the event.
    * For SEF_LU_STATE_WORK_FREE, we're always ready, tell immediately.
    */
-  if(sef_lu_state == SEF_LU_STATE_WORK_FREE) {
-      sef_lu_ready(OK);
+  r = OK;
+  if(sef_lu_state != SEF_LU_STATE_WORK_FREE) {
+      r = sef_cbs.sef_cb_lu_prepare(sef_lu_state);
   }
-  else {
-      sef_cbs.sef_cb_lu_prepare(sef_lu_state);
+  if(r == OK) {
+      sef_lu_ready(OK);
   }
 }
 
@@ -67,19 +72,28 @@ PUBLIC void do_sef_lu_before_receive()
 PUBLIC int do_sef_lu_request(message *m_ptr)
 {
 /* Handle a SEF Live update request. */
-  int old_state, is_valid_state;
+  int state, old_state, is_valid_state;
 
   sef_lu_debug_cycle = 0;
   old_state = sef_lu_state;
+  state = m_ptr->RS_LU_STATE;
 
-  /* Only accept live update requests with a valid state. */
-  is_valid_state = sef_cbs.sef_cb_lu_state_isvalid(m_ptr->RS_LU_STATE);
+  /* Deal with prepare cancel requests first. */
+  is_valid_state = (state == SEF_LU_STATE_NULL);
+
+  /* Otherwise only accept live update requests with a valid state. */
+  is_valid_state = is_valid_state || sef_cbs.sef_cb_lu_state_isvalid(state);
   if(!is_valid_state) {
-      sef_lu_ready(EINVAL);
+      if(sef_cbs.sef_cb_lu_state_isvalid == SEF_CB_LU_STATE_ISVALID_NULL) {
+          sef_lu_ready(ENOSYS);
+      }
+      else {
+          sef_lu_ready(EINVAL);
+      }
   }
   else {
       /* Set the new live update state. */
-      sef_lu_state = m_ptr->RS_LU_STATE;
+      sef_lu_state = state;
 
       /* If the live update state changed, let the callback code
        * handle the rest.
@@ -96,10 +110,10 @@ PUBLIC int do_sef_lu_request(message *m_ptr)
 /*===========================================================================*
  *                               sef_lu_ready                               *
  *===========================================================================*/
-PUBLIC void sef_lu_ready(int result)
+PRIVATE void sef_lu_ready(int result)
 {
   message m;
-  int old_state, r;
+  int old_state, rs_result, r;
 
 #if SEF_LU_DEBUG
   sef_lu_debug_begin();
@@ -109,28 +123,33 @@ PUBLIC void sef_lu_ready(int result)
   sef_lu_debug_end();
 #endif
 
-  /* Let the callback code perform any pre-ready operations. */
-  r = sef_cbs.sef_cb_lu_ready_pre(result);
-  if(r != OK) {
-      /* Abort update if callback returned error. */
-      result = r;
-  }
-  else {
-      /* Inform RS that we're ready with the given result. */
-      m.m_type = RS_LU_PREPARE;
-      m.RS_LU_STATE = sef_lu_state;
-      m.RS_LU_RESULT = result;
-      r = sendrec(RS_PROC_NR, &m);
-      if ( r != OK) {
-          panic("sendrec failed: %d", r);
+  /* If result is OK, let the callback code save
+   * any state that must be carried over to the new version.
+   */
+  if(result == OK) {
+      r = sef_cbs.sef_cb_lu_state_save(sef_lu_state);
+      if(r != OK) {
+          /* Abort update if callback returned error. */
+          result = r;
       }
   }
 
+  /* Inform RS that we're ready with the given result. */
+  m.m_type = RS_LU_PREPARE;
+  m.RS_LU_STATE = sef_lu_state;
+  m.RS_LU_RESULT = result;
+  r = sendrec(RS_PROC_NR, &m);
+  if ( r != OK) {
+      panic("sendrec failed: %d", r);
+  }
+
 #if SEF_LU_DEBUG
+  rs_result = m.m_type == RS_LU_PREPARE ? EINTR : m.m_type;
   sef_lu_debug_begin();
-  sef_lu_dprint("%s, cycle=%d. The %s aborted the update!\n",
+  sef_lu_dprint("%s, cycle=%d. The %s aborted the update with result %d!\n",
       sef_debug_header(), sef_lu_debug_cycle,
-      (result == OK ? "server" : "client"));
+      (result == OK ? "server" : "client"),
+      (result == OK ? rs_result : result)); /* EINTR if update was canceled. */
   sef_lu_debug_end();
 #endif
 
@@ -181,19 +200,20 @@ PUBLIC void sef_setcb_lu_state_dump(sef_cb_lu_state_dump_t cb)
 }
 
 /*===========================================================================*
- *                          sef_setcb_lu_ready_pre                           *
+ *                          sef_setcb_lu_state_save                           *
  *===========================================================================*/
-PUBLIC void sef_setcb_lu_ready_pre(sef_cb_lu_ready_pre_t cb)
+PUBLIC void sef_setcb_lu_state_save(sef_cb_lu_state_save_t cb)
 {
   assert(cb != NULL);
-  sef_cbs.sef_cb_lu_ready_pre = cb;
+  sef_cbs.sef_cb_lu_state_save = cb;
 }
 
 /*===========================================================================*
  *                         sef_cb_lu_prepare_null                           *
  *===========================================================================*/
-PUBLIC void sef_cb_lu_prepare_null(int UNUSED(state))
+PUBLIC int sef_cb_lu_prepare_null(int UNUSED(state))
 {
+  return ENOTREADY;
 }
 
 /*===========================================================================*
@@ -221,19 +241,44 @@ PUBLIC void sef_cb_lu_state_dump_null(int UNUSED(state))
 }
 
 /*===========================================================================*
- *                       sef_cb_lu_ready_pre_null                           *
+ *                       sef_cb_lu_state_save_null                          *
  *===========================================================================*/
-PUBLIC int sef_cb_lu_ready_pre_null(int UNUSED(result))
+PUBLIC int sef_cb_lu_state_save_null(int UNUSED(result))
 {
-  return(OK);
+  return OK;
 }
 
 /*===========================================================================*
  *                    sef_cb_lu_prepare_always_ready                        *
  *===========================================================================*/
-PUBLIC void sef_cb_lu_prepare_always_ready(int UNUSED(state))
+PUBLIC int sef_cb_lu_prepare_always_ready(int UNUSED(state))
+{
+  return OK;
+}
+
+/*===========================================================================*
+ *                    sef_cb_lu_prepare_never_ready                         *
+ *===========================================================================*/
+PUBLIC int sef_cb_lu_prepare_never_ready(int UNUSED(state))
 {
-  sef_lu_ready(OK);
+#if SEF_LU_DEBUG
+  sef_lu_debug_begin();
+  sef_lu_dprint("%s, cycle=%d. Simulating a service never ready to update...\n",
+      sef_debug_header(), sef_lu_debug_cycle);
+  sef_lu_debug_end();
+#endif
+
+  return ENOTREADY;
+}
+
+/*===========================================================================*
+ *                      sef_cb_lu_prepare_crash                             *
+ *===========================================================================*/
+PUBLIC int sef_cb_lu_prepare_crash(int UNUSED(state))
+{
+  panic("Simulating a crash at update prepare time...");
+
+  return OK;
 }
 
 /*===========================================================================*
index 648ccb1c8778af4e8d5a36d71791a08949f203f4..6c30a6172191633d8379c76704902b7e3fccf7f0 100644 (file)
@@ -31,7 +31,7 @@ PUBLIC int do_sef_ping_request(message *m_ptr)
 #endif
 
   /* Let the callback code handle the request. */
-  sef_cbs.sef_cb_ping_reply(m_ptr);
+  sef_cbs.sef_cb_ping_reply(m_ptr->m_source);
 
   /* Return OK not to let anybody else intercept the request. */
   return(OK);
@@ -49,15 +49,15 @@ PUBLIC void sef_setcb_ping_reply(sef_cb_ping_reply_t cb)
 /*===========================================================================*
  *                        sef_cb_ping_reply_null                            *
  *===========================================================================*/
-PUBLIC void sef_cb_ping_reply_null(message *UNUSED(m_ptr))
+PUBLIC void sef_cb_ping_reply_null(endpoint_t UNUSED(source))
 {
 }
 
 /*===========================================================================*
  *                        sef_cb_ping_reply_pong                            *
  *===========================================================================*/
-PUBLIC void sef_cb_ping_reply_pong(message *m_ptr)
+PUBLIC void sef_cb_ping_reply_pong(endpoint_t source)
 {
-  notify(m_ptr->m_source);
+  notify(source);
 }
 
diff --git a/lib/libsys/sef_signal.c b/lib/libsys/sef_signal.c
new file mode 100644 (file)
index 0000000..9d88938
--- /dev/null
@@ -0,0 +1,196 @@
+#include "syslib.h"
+#include <assert.h>
+#include <signal.h>
+#include <minix/sysutil.h>
+
+/* SEF Signal callbacks. */
+PRIVATE struct sef_cbs {
+    sef_cb_signal_handler_t             sef_cb_signal_handler;
+    sef_cb_signal_manager_t             sef_cb_signal_manager;
+} sef_cbs = {
+    SEF_CB_SIGNAL_HANDLER_DEFAULT,
+    SEF_CB_SIGNAL_MANAGER_DEFAULT
+};
+
+/* SEF Signal prototypes for sef_receive(). */
+PUBLIC _PROTOTYPE( int do_sef_signal_request, (message *m_ptr) );
+
+/* Debug. */
+EXTERN _PROTOTYPE( char* sef_debug_header, (void) );
+
+/* Information about SELF. */
+EXTERN endpoint_t sef_self_endpoint;
+
+/*===========================================================================*
+ *                         process_sigmgr_signals                           *
+ *===========================================================================*/
+PRIVATE void process_sigmgr_signals(void)
+{
+/* A signal manager has pending signals in the kernel. Process them. */
+  endpoint_t target;
+  sigset_t sigset;
+  int signo, r;
+
+  while (TRUE) {
+      /* Get an arbitrary pending signal. */
+      if((r=sys_getksig(&target, &sigset)) != OK)
+          panic("SEF", "sys_getksig failed", r);
+
+      if (target == NONE) {
+          /* Stop if there are no more pending signals. */
+          break;
+      } else {
+          /* Process every signal in the signal set. */
+          r = OK;
+          for(signo = 1; signo < _NSIG; signo++) {
+              if(sigismember(&sigset, signo)) {
+                  /* Let the callback code process the signal. */
+                  r = sef_cbs.sef_cb_signal_manager(target, signo);
+
+                  /* Stop if process is gone. */
+                  if(r == EDEADSRCDST) {
+                      break;
+                  }
+              }
+          }
+          /* Tell the kernel we are done if the target is still alive. */
+          if(r == OK) {
+              if((r=sys_endksig(target)) != OK)
+                  panic("SEF","sys_endksig failed", r);
+          }
+      }
+  }
+}
+
+/*===========================================================================*
+ *                         process_sigmgr_self_signals                      *
+ *===========================================================================*/
+PRIVATE void process_sigmgr_self_signals(sigset_t sigset)
+{
+/* A signal manager has pending signals for itself. Process them. */
+  int signo;
+
+  for(signo = 1; signo < _NSIG; signo++) {
+      if(sigismember(&sigset, signo)) {
+          /* Let the callback code process the signal. */
+          sef_cbs.sef_cb_signal_handler(signo);
+      }
+  }
+}
+
+/*===========================================================================*
+ *                           do_sef_signal_request                                  *
+ *===========================================================================*/
+PUBLIC int do_sef_signal_request(message *m_ptr)
+{
+/* Handle a SEF Signal request. */
+  int signo;
+  sigset_t sigset;
+
+  if(m_ptr->m_source == SYSTEM) {
+      /* Handle kernel signals. */
+      sigset = m_ptr->NOTIFY_ARG;
+      for (signo = SIGK_FIRST; signo <= SIGK_LAST; signo++) {
+          if (sigismember(&sigset, signo)) {
+              /* Let the callback code handle the kernel signal. */
+              sef_cbs.sef_cb_signal_handler(signo);
+
+              /* Handle SIGKSIG for a signal manager. */
+              if(signo == SIGKSIG) {
+                  process_sigmgr_signals();
+              }
+              /* Handle SIGKSIGSM for a signal manager. */
+              else if(signo == SIGKSIGSM) {
+                  process_sigmgr_self_signals(sigset);
+              }
+          }
+      }
+  }
+  else {
+      /* Handle system signals from a signal manager. */
+      signo = m_ptr->SIGS_SIG_NUM;
+
+      /* Debug. */
+#if SEF_SIGNAL_DEBUG
+      sef_signal_debug_begin();
+      sef_signal_dprint("%s. Got a SEF Signal request for signal %d! About to handle signal.\n", 
+          sef_debug_header(), signo);
+      sef_signal_debug_end();
+#endif
+
+      /* Let the callback code handle the signal. */
+      sef_cbs.sef_cb_signal_handler(signo);
+  }
+
+  /* Return OK not to let anybody else intercept the request. */
+  return OK;
+}
+
+/*===========================================================================*
+ *                        sef_setcb_signal_handler                           *
+ *===========================================================================*/
+PUBLIC void sef_setcb_signal_handler(sef_cb_signal_handler_t cb)
+{
+  assert(cb != NULL);
+  sef_cbs.sef_cb_signal_handler = cb;
+}
+
+/*===========================================================================*
+ *                        sef_setcb_signal_manager                           *
+ *===========================================================================*/
+PUBLIC void sef_setcb_signal_manager(sef_cb_signal_manager_t cb)
+{
+  assert(cb != NULL);
+  sef_cbs.sef_cb_signal_manager = cb;
+}
+
+/*===========================================================================*
+ *                       sef_cb_signal_handler_null                         *
+ *===========================================================================*/
+PUBLIC void sef_cb_signal_handler_null(int signo)
+{
+}
+
+/*===========================================================================*
+ *                       sef_cb_signal_manager_null                         *
+ *===========================================================================*/
+PUBLIC int sef_cb_signal_manager_null(endpoint_t target, int signo)
+{
+  return OK;
+}
+
+/*===========================================================================*
+ *                       sef_cb_signal_handler_term                         *
+ *===========================================================================*/
+PUBLIC void sef_cb_signal_handler_term(int signo)
+{
+  /* Terminate in case of SIGTERM, ignore other signals. */
+  if(signo == SIGTERM) {
+      sef_exit(1);
+  }
+}
+
+/*===========================================================================*
+ *                   sef_cb_signal_handler_posix_default                    *
+ *===========================================================================*/
+PUBLIC void sef_cb_signal_handler_posix_default(int signo)
+{
+  switch(signo) {
+      /* Ignore when possible. */
+      case SIGCHLD:
+      case SIGWINCH:
+      case SIGCONT:
+      case SIGTSTP:
+      case SIGTTIN:
+      case SIGTTOU:
+      break;
+
+      /* Terminate in any other case unless it is a kernel signal. */
+      default:
+          if(!IS_SIGK(signo)) {
+              sef_exit(1);
+          }
+      break;
+  }
+}
+
diff --git a/lib/libsys/sys_clear.c b/lib/libsys/sys_clear.c
new file mode 100644 (file)
index 0000000..68a6a72
--- /dev/null
@@ -0,0 +1,15 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                                sys_clear                                 *
+ *===========================================================================*/
+PUBLIC int sys_clear(proc_ep)
+endpoint_t proc_ep;                    /* which process has exited */
+{
+/* A process has exited. PM tells the kernel.
+ */
+  message m;
+
+  m.PR_ENDPT = proc_ep;
+  return(_kernel_call(SYS_CLEAR, &m));
+}
index bc1acad8a176cdc205e8ba6571c52a3296bfbe45..88e95acd4d814395c7d572fbbbd911c7c374d615 100644 (file)
@@ -3,15 +3,10 @@
 /*===========================================================================*
  *                                sys_exit                                  *
  *===========================================================================*/
-PUBLIC int sys_exit(proc_ep)
-endpoint_t proc_ep;                    /* which process has exited */
+PUBLIC int sys_exit()
 {
-/* A process has exited. PM tells the kernel. In addition this call can be
- * used by system processes to directly exit without passing through the
- * PM. This should be used with care to prevent inconsistent PM tables. 
- */
+/* A system process requests to exit. */
   message m;
 
-  m.PR_ENDPT = proc_ep;
   return(_kernel_call(SYS_EXIT, &m));
 }
diff --git a/lib/libsys/sys_update.c b/lib/libsys/sys_update.c
new file mode 100644 (file)
index 0000000..c93845b
--- /dev/null
@@ -0,0 +1,11 @@
+#include "syslib.h"
+
+int sys_update(endpoint_t src_ep, endpoint_t dst_ep)
+{
+  message m;
+
+  m.SYS_UPD_SRC_ENDPT = src_ep;
+  m.SYS_UPD_DST_ENDPT = dst_ep;
+
+  return _kernel_call(SYS_UPDATE, &m);
+}
index a7d1f4639d9f42162dbd146bdafbef510275927c..e16b2039d4233fc94182b70834ec6025aed54d20 100644 (file)
@@ -229,7 +229,7 @@ A directory with entries other than \*(lq.\*(rq and \*(lq..\*(rq
 was supplied to a remove directory or rename call.
 .en 40 ELOOP "Too many symbolic links"
 A path name lookup involved too many symbolic links.
-.en 41 ERESTART "Device driver restarted
+.en 41 ERESTART "Service restarted
 .en 43 EIDRM "Identifier removed
 .en 44 EILSEQ "Illegal byte sequence
 .en 50 EPACKSIZE "Invalid packet size
index 6f433e72752c6ba7052c447be3f2707b8b2a1fbc..c1bf05acef21bd10350ed3a8d7385ace4bfa9e77 100644 (file)
@@ -3,8 +3,9 @@
 
 /* Header file including all needed system headers. */
 
-#define _SYSTEM            1    /* get OK and negative error codes */
+#define _POSIX_SOURCE      1   /* tell headers to include POSIX stuff */
 #define _MINIX             1   /* tell headers to include MINIX stuff */
+#define _SYSTEM            1    /* get OK and negative error codes */
 
 #include <ansi.h>
 #include <sys/types.h>
index 64f7c521b449c616f618adb56464906976193cf0..1efe805854b081416d640dba8682420838f8c64f 100644 (file)
@@ -16,8 +16,6 @@ PRIVATE endpoint_t who_e;     /* caller's proc number */
 PRIVATE int callnr;            /* system call number */
 
 /* Declare some local functions. */
-FORWARD _PROTOTYPE(void exit_server, (void)                            );
-FORWARD _PROTOTYPE(void sig_handler, (void)                            );
 FORWARD _PROTOTYPE(void get_work, (message *m_ptr)                     );
 FORWARD _PROTOTYPE(void reply, (int whom, message *m_ptr)              );
 
@@ -47,18 +45,9 @@ PUBLIC int main(int argc, char **argv)
       get_work(&m);
 
       if (is_notify(callnr)) {
-             switch (_ENDPOINT_P(who_e)) {
-                     case PM_PROC_NR:
-                             sig_handler();
-                             break;
-                     default:
-                             printf("DS: warning, got illegal notify from: %d\n",
-                                                                m.m_source);
-                             result = EINVAL;
-                             goto send_reply;
-             }
-
-             /* done, get a new message */
+          printf("DS: warning, got illegal notify from: %d\n", m.m_source);
+          result = EINVAL;
+          goto send_reply;
       }
 
       switch (callnr) {
@@ -108,7 +97,7 @@ PRIVATE void sef_local_startup()
 {
   /* Register init callbacks. */
   sef_setcb_init_fresh(sef_cb_init_fresh);
-  sef_setcb_init_restart(sef_cb_init_restart_fail);
+  sef_setcb_init_restart(sef_cb_init_fail);
 
   /* No live update support for now. */
 
@@ -116,34 +105,6 @@ PRIVATE void sef_local_startup()
   sef_startup();
 }
 
-/*===========================================================================*
- *                              sig_handler                                 *
- *===========================================================================*/
-PRIVATE void sig_handler()
-{
-/* Signal handler. */
-  sigset_t sigset;
-
-  /* Try to obtain signal set from PM. */
-  if (getsigset(&sigset) != 0) return;
-
-  /* Check for known signals. */
-  if (sigismember(&sigset, SIGTERM)) {
-      exit_server();
-  }
-}
-
-/*===========================================================================*
- *                             exit_server                                  *
- *===========================================================================*/
-PRIVATE void exit_server()
-{
-/* Shut down the information service. */
-
-  /* Done. Now exit. */
-  exit(0);
-}
-
 /*===========================================================================*
  *                             get_work                                     *
  *===========================================================================*/
index 2adf376fe5bd87b2c636b88104b49181f0cd620f..76e1efde470fc51f290636cf3810da0dce935cd0 100644 (file)
@@ -129,10 +129,13 @@ PRIVATE endpoint_t ds_getprocep(char *s)
 PRIVATE int check_auth(struct data_store *p, endpoint_t ep, int perm)
 {
 /* Check authorization for a given type of permission. */
+       char *source;
+
        if(!(p->flags & perm))
                return 1;
 
-       return !strcmp(p->owner, ds_getprocname(ep));
+       source = ds_getprocname(ep);
+       return source && !strcmp(p->owner, source);
 }
 
 /*===========================================================================*
@@ -237,7 +240,7 @@ PRIVATE int map_service(struct rprocpub *rpub)
   /* Set attributes. */
   strcpy(dsp->key, rpub->label);
   dsp->u.u32 = (u32_t) rpub->endpoint;
-  strcpy(dsp->owner, ds_getprocname(DS_PROC_NR));
+  strcpy(dsp->owner, "rs");
   dsp->flags = DSF_IN_USE | DSF_TYPE_LABEL;
 
   /* Update subscribers having a matching subscription. */
@@ -286,10 +289,16 @@ PUBLIC int do_publish(message *m_ptr)
 {
   struct data_store *dsp;
   char key_name[DS_MAX_KEYLEN];
+  char *source;
   int flags = m_ptr->DS_FLAGS;
   size_t length;
   int r;
 
+  /* Lookup the source. */
+  source = ds_getprocname(m_ptr->m_source);
+  if(source == NULL)
+         return EPERM;
+
   /* MAP should not be overwritten. */
   if((flags & DSF_TYPE_MAP) && (flags & DSF_OVERWRITE))
        return EINVAL;
@@ -324,9 +333,6 @@ PUBLIC int do_publish(message *m_ptr)
        dsp->u.u32 = m_ptr->DS_VAL;
        break;
   case DSF_TYPE_STR:
-       strncpy(dsp->u.string, (char *)(&m_ptr->DS_STRING), DS_MAX_STRLEN);
-       dsp->u.string[DS_MAX_STRLEN - 1] = '\0';
-       break;
   case DSF_TYPE_MEM:
        length = m_ptr->DS_VAL_LEN;
        /* Allocate a new data buffer if necessary. */
@@ -351,6 +357,9 @@ PUBLIC int do_publish(message *m_ptr)
                return r;
        }
        dsp->u.mem.length = length;
+       if(flags & DSF_TYPE_STR) {
+               ((char*)dsp->u.mem.data)[length-1] = '\0';
+       }
        break;
   case DSF_TYPE_MAP:
        /* Allocate buffer, the address should be aligned by CLICK_SIZE. */
@@ -377,7 +386,7 @@ PUBLIC int do_publish(message *m_ptr)
 
   /* Set attributes. */
   strcpy(dsp->key, key_name);
-  strcpy(dsp->owner, ds_getprocname(m_ptr->m_source));
+  strcpy(dsp->owner, source);
   dsp->flags = DSF_IN_USE | (flags & DSF_MASK_INTERNAL);
 
   /* Update subscribers having a matching subscription. */
@@ -416,8 +425,6 @@ PUBLIC int do_retrieve(message *m_ptr)
        m_ptr->DS_VAL = dsp->u.u32;
        break;
   case DSF_TYPE_STR:
-       strncpy((char *)(&m_ptr->DS_STRING), dsp->u.string, DS_MAX_STRLEN);
-       break;
   case DSF_TYPE_MEM:
        length = MIN(m_ptr->DS_VAL_LEN, dsp->u.mem.length);
        r = sys_safecopyto(m_ptr->m_source, (cp_grant_id_t) m_ptr->DS_VAL, 0,
@@ -631,9 +638,15 @@ PUBLIC int do_delete(message *m_ptr)
 {
   struct data_store *dsp;
   char key_name[DS_MAX_KEYLEN];
+  char *source;
   int type = m_ptr->DS_FLAGS & DSF_MASK_TYPE;
   int top, i, r;
 
+  /* Lookup the source. */
+  source = ds_getprocname(m_ptr->m_source);
+  if(source == NULL)
+         return EPERM;
+
   /* Get key name. */
   if((r = get_key_name(m_ptr, key_name)) != OK)
        return r;
@@ -643,14 +656,14 @@ PUBLIC int do_delete(message *m_ptr)
        return ESRCH;
 
   /* Only the owner can delete. */
-  if(strcmp(dsp->owner, ds_getprocname(m_ptr->m_source)))
+  if(strcmp(dsp->owner, source))
        return EPERM;
 
   switch(type) {
   case DSF_TYPE_U32:
-  case DSF_TYPE_STR:
   case DSF_TYPE_LABEL:
        break;
+  case DSF_TYPE_STR:
   case DSF_TYPE_MEM:
        free(dsp->u.mem.data);
        break;
@@ -658,7 +671,7 @@ PUBLIC int do_delete(message *m_ptr)
        /* Unmap the mapped data. */
        r = sys_safeunmap(D, (vir_bytes)dsp->u.map.data);
        if(r != OK)
-               return r;
+               printf("DS: sys_safeunmap failed. Grant already revoked?\n");
 
        /* Revoke all the mapped grants. */
        r = sys_saferevmap_addr((vir_bytes)dsp->u.map.data);
index 6653318ff6b04236974dea417d90d8a10980e2c2..1ef27172921a14fe7f86ea2ef0b7701d7c001fa1 100644 (file)
@@ -20,7 +20,6 @@ struct data_store {
 
        union {
                unsigned u32;
-               char string[DS_MAX_STRLEN];
                struct {
                        void *data;
                        size_t length;
index 89e1e3c64dcb0ffd76162f74510ba6d21cf9165d..78c212d6bb08f3fd26991021561b2019d68c43fd 100644 (file)
 
 #include <signal.h>
 #include <unistd.h>
+#include <stdlib.h>
 
-FORWARD _PROTOTYPE( int init, (int type, sef_init_info_t *info)                );
-FORWARD _PROTOTYPE( void sef_local_startup, (void)                     );
-FORWARD _PROTOTYPE( void cleanup, (void)                               );
 FORWARD _PROTOTYPE( int get_work, (endpoint_t *who_e)                  );
 FORWARD _PROTOTYPE( void send_reply, (int err)                         );
-FORWARD _PROTOTYPE( int proc_event, (void)                             );
 
 PRIVATE struct optset optset_table[] = {
   { "prefix",   OPT_STRING, opt.prefix,       sizeof(opt.prefix) },
@@ -32,13 +29,17 @@ PRIVATE struct optset optset_table[] = {
   { NULL                                                         }
 };
 
+/* SEF functions and variables. */
+FORWARD _PROTOTYPE( void sef_local_startup, (void) );
+FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
+FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
 EXTERN int env_argc;
 EXTERN char **env_argv;
 
 /*===========================================================================*
- *                             init                                         *
+ *                           sef_cb_init_fresh                              *
  *===========================================================================*/
-PRIVATE int init(type, info)
+PRIVATE int sef_cb_init_fresh(type, info)
 int type;
 sef_init_info_t *info;
 {
@@ -87,31 +88,43 @@ sef_init_info_t *info;
 }
 
 /*===========================================================================*
- *                             sef_local_startup                            *
+ *                        sef_cb_signal_handler                             *
  *===========================================================================*/
-PRIVATE void sef_local_startup()
+PRIVATE void sef_cb_signal_handler(int signo)
 {
-/* Specify initialization routines and start the SEF framework.
- */
+  sigset_t set;
+  int r;
 
-  sef_setcb_init_fresh(init);
-  sef_setcb_init_restart(init);
+  /* Only check for termination signal, ignore anything else. */
+  if (signo != SIGTERM) return;
 
-  /* No live update support yet. */
+  if (state.mounted) {
+      dprintf(("HGFS: got SIGTERM, still mounted\n"));
+  }
+  else {
+      dprintf(("HGFS: got SIGTERM, shutting down\n"));
 
-  sef_startup();
+      /* Pass on the cleanup request to the HGFS library. */
+      hgfs_cleanup();
+      exit(0);
+  }
 }
 
 /*===========================================================================*
- *                             cleanup                                      *
+ *                             sef_local_startup                            *
  *===========================================================================*/
-PRIVATE void cleanup()
+PRIVATE void sef_local_startup()
 {
-/* Clean up any resources in use by this file server. Called at shutdown time.
- */
+  /* Register init callbacks. */
+  sef_setcb_init_fresh(sef_cb_init_fresh);
+  sef_setcb_init_restart(sef_cb_init_fresh);
+
+  /* No live update support yet. */
 
-  /* Pass on the cleanup request to the HGFS library. */
-  hgfs_cleanup();
+  /* Register signal callbacks. */
+  sef_setcb_signal_handler(sef_cb_signal_handler);
+
+  sef_startup();
 }
 
 /*===========================================================================*
@@ -135,10 +148,6 @@ char *argv[];
        call_nr = get_work(&who_e);
 
        if (who_e != FS_PROC_NR) {
-               /* Is this PM telling us to shut down? */
-               if (who_e == PM_PROC_NR && is_notify(call_nr))
-                       if (proc_event()) break;
-
                continue;
        }
 
@@ -160,8 +169,6 @@ char *argv[];
        send_reply(err);
   }
 
-  cleanup();
-
   return 0;
 }
 
@@ -199,34 +206,3 @@ int err;                           /* resulting error code */
        printf("HGFS: send failed (%d)\n", r);
 }
 
-/*===========================================================================*
- *                             proc_event                                   *
- *===========================================================================*/
-PRIVATE int proc_event()
-{
-/* We got a notification from PM; see what it's about. Return TRUE if this
- * server has been told to shut down.
- */
-  sigset_t set;
-  int r;
-
-  if ((r = getsigset(&set)) != OK) {
-       printf("HGFS: unable to get pending signals from PM (%d)\n", r);
-
-       return FALSE;
-  }
-
-  if (sigismember(&set, SIGTERM)) {
-       if (state.mounted) {
-               dprintf(("HGFS: got SIGTERM, still mounted\n"));
-
-               return FALSE;
-       }
-
-       dprintf(("HGFS: got SIGTERM, shutting down\n"));
-
-       return TRUE;
-  }
-
-  return FALSE;
-}
index 4ee2cec230c02ab2381d3c21cbdebe3224476c9e..364c251eec228a7fca54313182c45be914800e2d 100644 (file)
@@ -189,7 +189,7 @@ PRIVATE void sef_local_startup()
 {
   /* Register init callbacks. */
   sef_setcb_init_fresh(sef_cb_init_fresh);
-  sef_setcb_init_restart(sef_cb_init_restart_fail);
+  sef_setcb_init_restart(sef_cb_init_fresh);
 
   /* No live update support for now. */
 
@@ -205,10 +205,11 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
 /* Initialize the inet server. */
        int r;
        int timerand, fd;
-       u32_t tasknr;
+       endpoint_t tasknr;
        struct fssignon device;
        u8_t randbits[32];
        struct timeval tv;
+       char my_name[32];
 
 #if DEBUG
        printf("Starting inet...\n");
@@ -257,9 +258,9 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
        init_rand256(randbits);
 
        /* Our new identity as a server. */
-       r= ds_retrieve_label_num("inet", &tasknr);
+       r = sys_whoami(&tasknr, my_name, sizeof(my_name));
        if (r != OK)
-               ip_panic(("inet: ds_retrieve_label_num failed for 'inet': %d", r));
+               ip_panic(("inet: sys_whoami failed for 'inet': %d", r));
        this_proc= tasknr;
 
        /* Register the device group. */
index 2f9055095c3dcba5500e3dd2bb467162f304e894..0ffd969be2abb8d2456ea529347a47c1a8115037 100644 (file)
@@ -462,7 +462,9 @@ PUBLIC void eth_rec(message *m)
        }
        if (loc_port->etp_osdep.etp_flags & OEPF_NEED_CONF)
        {
+#if 0
                printf("eth_rec: OEPF_NEED_CONF is set\n");
+#endif
        }
        if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
                (loc_port->etp_osdep.etp_flags & OEPF_NEED_STAT))
@@ -899,12 +901,6 @@ int tasknr;
                        eth_port->etp_osdep.etp_port);
        }
 
-       if (eth_port->etp_osdep.etp_task == tasknr)
-       {
-               printf(
-               "eth_restart: task number did not change. Aborting restart\n");
-               return;
-       }
        eth_port->etp_osdep.etp_task= tasknr;
 
        switch(eth_port->etp_osdep.etp_state)
index 38138a4115cfdff695ba116d4ed09f8ee55600bd..7a2829b272c0b8c4cd809a15e553bb366d484fc5 100644 (file)
@@ -1,5 +1,6 @@
-#define _SYSTEM        1
-#define _MINIX 1
+#define _POSIX_SOURCE      1   /* tell headers to include POSIX stuff */
+#define _MINIX             1   /* tell headers to include MINIX stuff */
+#define _SYSTEM            1    /* get OK and negative error codes */
 
 #include <minix/callnr.h>
 #include <minix/com.h>
@@ -25,6 +26,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <errno.h>
+#include <signal.h>
 
 _PROTOTYPE( int do_shmget, (message *)                                   );
 _PROTOTYPE( int do_shmat, (message *)                                    );
index 2800a74c98b0049a925f03ce28ff9d32aa422c30..e88b700a9ac7e2fbc8b0f578304188cbe1311a3b 100644 (file)
@@ -26,6 +26,7 @@ PRIVATE int verbose = 0;
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
+FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
 
 PUBLIC int main(int argc, char *argv[])
 {
@@ -49,14 +50,6 @@ PUBLIC int main(int argc, char *argv[])
 
                if (call_type & NOTIFY_MESSAGE) {
                        switch (who_e) {
-                       case PM_PROC_NR:
-                               /* PM sends a notify() on shutdown,
-                                * checkout if there are still IPC keys,
-                                * give warning messages.
-                                */
-                               if (!is_sem_nil() || !is_shm_nil())
-                                       printf("IPC: exit with un-clean states.\n");
-                               break;
                        case VM_PROC_NR:
                                /* currently, only semaphore needs such information. */
                                sem_process_vm_notify();
@@ -114,6 +107,9 @@ PRIVATE void sef_local_startup()
 
   /* No live update support for now. */
 
+  /* Register signal callbacks. */
+  sef_setcb_signal_handler(sef_cb_signal_handler);
+
   /* Let SEF perform startup. */
   sef_startup();
 }
@@ -133,3 +129,16 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
   return(OK);
 }
 
+/*===========================================================================*
+ *                         sef_cb_signal_handler                            *
+ *===========================================================================*/
+PRIVATE void sef_cb_signal_handler(int signo)
+{
+  /* Only check for termination signal, ignore anything else. */
+  if (signo != SIGTERM) return;
+
+  /* Checkout if there are still IPC keys. Inform the user in that case. */
+  if (!is_sem_nil() || !is_shm_nil())
+      printf("IPC: exit with un-clean states.\n");
+}
+
index 8d6769078f814bb98cd645fd9c035659e4bd8cb0..89802e9abe4c228e14707266dfa157bacfd4302f 100644 (file)
@@ -29,7 +29,7 @@ PUBLIC void data_store_dmp()
                printf("%-10s %12u\n", "U32", p->u.u32);
                break;
        case DSF_TYPE_STR:
-               printf("%-10s %12s\n", "STR", p->u.string);
+               printf("%-10s %12s\n", "STR", (char*) p->u.mem.data);
                break;
        case DSF_TYPE_MEM:
                printf("%-10s %12u\n", "MEM", p->u.mem.length);
index b566f559563825b72b19dcae2f341509ad1fdb64..4022f086da5e78600629981ef3a8d1cf3e8ca45e 100644 (file)
@@ -82,14 +82,14 @@ PUBLIC void sigaction_dmp()
   getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc);
   getuptime(&uptime);
 
-  printf("-process- -nr- --ignore- --catch- --block- -tomess- -pending- -alarm---\n");
+  printf("-process- -nr- --ignore- --catch- --block- -pending- -alarm---\n");
   for (i=prev_i; i<NR_PROCS; i++) {
        mp = &mproc[i];
        if (mp->mp_pid == 0 && i != PM_PROC_NR) continue;
        if (++n > 22) break;
        printf("%8.8s  %3d  ", mp->mp_name, i);
-       printf(" %08x %08x %08x %08x  ", 
-               mp->mp_ignore, mp->mp_catch, mp->mp_sigmask, mp->mp_sig2mess); 
+       printf(" %08x %08x %08x ", 
+               mp->mp_ignore, mp->mp_catch, mp->mp_sigmask); 
        printf("%08x  ", mp->mp_sigpending);
        if (mp->mp_flags & ALARM_ON) printf("%8u", mp->mp_timer.tmr_exp_time-uptime);
        else printf("       -");
index aa81fca05f3cd775238f7f53cf6f6c6fd13a72c0..96341456cc9be0672a11852246ed4a3a20f2afc6 100644 (file)
@@ -43,7 +43,7 @@ PUBLIC void rproc_dmp()
                rpub->label, rpub->endpoint, rp->r_pid,
                s_flags_str(rp->r_flags), rpub->dev_nr, rpub->dev_style,
                rpub->period, rp->r_alive_tm, rp->r_restarts,
-               rp->r_cmd
+               rp->r_args
        );
        printf("\n");
   }
@@ -56,9 +56,9 @@ PUBLIC void rproc_dmp()
 PRIVATE char *s_flags_str(int flags)
 {
        static char str[10];
-       str[0] = (flags & RS_IN_USE)        ? 'U' : '-';
+       str[0] = (flags & RS_ACTIVE)        ? 'A' : '-';
        str[1] = (flags & RS_INITIALIZING)  ? 'I' : '-';
-       str[2] = (flags & RS_UPDATING)      ? 'u' : '-';
+       str[2] = (flags & RS_UPDATING)      ? 'U' : '-';
        str[3] = (flags & RS_EXITING)       ? 'E' : '-';
        str[4] = (flags & RS_NOPINGREPLY)   ? 'N' : '-';
        str[5] = '\0';
index 773798004e8ab6d096423195902f6f216c47bcdc..f65c648e9f6a8e5c5c41aa689942bd42220a3336 100644 (file)
@@ -19,13 +19,13 @@ int callnr;         /* system call number */
 extern int errno;      /* error number set by system library */
 
 /* Declare some local functions. */
-FORWARD _PROTOTYPE(void sig_handler, (void)                            );
 FORWARD _PROTOTYPE(void get_work, (void)                               );
 FORWARD _PROTOTYPE(void reply, (int whom, int result)                  );
 
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
+FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
 
 /*===========================================================================*
  *                             main                                         *
@@ -50,17 +50,6 @@ PUBLIC int main(int argc, char **argv)
 
       if (is_notify(callnr)) {
              switch (_ENDPOINT_P(who_e)) {
-                     case SYSTEM:
-                             printf("got message from SYSTEM\n");
-                             sigset = m_in.NOTIFY_ARG;
-                             for ( result=0; result< _NSIG; result++) {
-                                     if (sigismember(&sigset, result))
-                                             printf("signal %d found\n", result);
-                             }
-                             continue;
-                     case PM_PROC_NR:
-                             sig_handler();
-                             continue;
                      case TTY_PROC_NR:
                              result = do_fkey_pressed(&m_in);
                              break;
@@ -98,6 +87,9 @@ PRIVATE void sef_local_startup()
   sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready);
   sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard);
 
+  /* Register signal callbacks. */
+  sef_setcb_signal_handler(sef_cb_signal_handler);
+
   /* Let SEF perform startup. */
   sef_startup();
 }
@@ -108,14 +100,6 @@ PRIVATE void sef_local_startup()
 PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
 {
 /* Initialize the information server. */
-  struct sigaction sigact;
-
-  /* Install signal handler. Ask PM to transform signal into message. */
-  sigact.sa_handler = SIG_MESS;
-  sigact.sa_mask = ~0;                 /* block all other signals */
-  sigact.sa_flags = 0;                 /* default behaviour */
-  if (sigaction(SIGTERM, &sigact, NULL) < 0) 
-      printf("IS: warning, sigaction() failed: %d\n", errno);
 
   /* Set key mappings. */
   map_unmap_fkeys(TRUE /*map*/);
@@ -124,17 +108,12 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
 }
 
 /*===========================================================================*
- *                             sig_handler                                  *
+ *                         sef_cb_signal_handler                            *
  *===========================================================================*/
-PRIVATE void sig_handler()
+PRIVATE void sef_cb_signal_handler(int signo)
 {
-  sigset_t sigset;
-
-  /* Try to obtain signal set from PM. */
-  if (getsigset(&sigset) != 0) return;
-
-  /* Only check for termination signal. */
-  if (!sigismember(&sigset, SIGTERM)) return;
+  /* Only check for termination signal, ignore anything else. */
+  if (signo != SIGTERM) return;
 
   /* Shutting down. Unset key mappings, and quit. */
   map_unmap_fkeys(FALSE /*map*/);
index c948445aaad73b854a6f5ba2c761b09b6c1dbebe..74abfe5680a0f693ad16e3ec0dc477beee549d7a 100644 (file)
@@ -68,7 +68,7 @@ PRIVATE void sef_local_startup()
 {
   /* Register init callbacks. */
   sef_setcb_init_fresh(sef_cb_init_fresh);
-  sef_setcb_init_restart(sef_cb_init_restart_fail);
+  sef_setcb_init_restart(sef_cb_init_fail);
 
   /* No live update support for now. */
 
index 426114e099a94831d0f0f94e42f1471b38590677..835432594fe253b4682b3cf8043d2f5abc6f2100 100644 (file)
@@ -16,6 +16,7 @@ FORWARD _PROTOTYPE(void cch_check, (void)                             );
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
+FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
 
 /*===========================================================================*
  *                             main                                         *
@@ -44,13 +45,6 @@ PUBLIC int main(int argc, char *argv[])
        caller_uid = -1;        /* To trap errors */
        caller_gid = -1;
 
-       /* Exit request? */
-       if(src == PM_PROC_NR) {
-               exitsignaled = 1;
-               fs_sync();
-               continue;
-       }
-
        /* This must be a regular VFS request. */
        assert(src == VFS_PROC_NR && !unmountdone);
 
@@ -79,7 +73,6 @@ PUBLIC int main(int argc, char *argv[])
   }
 }
 
-
 /*===========================================================================*
  *                            sef_local_startup                             *
  *===========================================================================*/
@@ -87,10 +80,13 @@ PRIVATE void sef_local_startup()
 {
   /* Register init callbacks. */
   sef_setcb_init_fresh(sef_cb_init_fresh);
-  sef_setcb_init_restart(sef_cb_init_restart_fail);
+  sef_setcb_init_restart(sef_cb_init_fail);
 
   /* No live update support for now. */
 
+  /* Register signal callbacks. */
+  sef_setcb_signal_handler(sef_cb_signal_handler);
+
   /* Let SEF perform startup. */
   sef_startup();
 }
@@ -128,6 +124,17 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
   return(OK);
 }
 
+/*===========================================================================*
+ *                        sef_cb_signal_handler                             *
+ *===========================================================================*/
+PRIVATE void sef_cb_signal_handler(int signo)
+{
+  /* Only check for termination signal, ignore anything else. */
+  if (signo != SIGTERM) return;
+
+  exitsignaled = 1;
+  fs_sync();
+}
 
 /*===========================================================================*
  *                             get_work                                     *
@@ -143,15 +150,7 @@ message *m_in;                             /* pointer to message */
                panic("sef_receive failed: %d", r);
        src = fs_m_in.m_source;
 
-       if (src != FS_PROC_NR) {
-               if(src == PM_PROC_NR) {
-                       if(is_notify(fs_m_in.m_type))
-                               srcok = 1;      /* Normal exit request. */
-                       else
-                               printf("MFS: unexpected message from PM\n");
-               } else
-                       printf("MFS: unexpected source %d\n", src);
-       } else if(src == FS_PROC_NR) {
+       if(src == FS_PROC_NR) {
                if(unmountdone) 
                        printf("MFS: unmounted: unexpected message from FS\n");
                else 
@@ -161,8 +160,7 @@ message *m_in;                              /* pointer to message */
                printf("MFS: unexpected source %d\n", src);
   } while(!srcok);
 
-   assert((src == FS_PROC_NR && !unmountdone) || 
-       (src == PM_PROC_NR && is_notify(fs_m_in.m_type)));
+   assert((src == FS_PROC_NR && !unmountdone));
 }
 
 
index aa36d28c1099e9bf09872bf5c151b1ec219e6610..16b1ffdd814c9f4f5daa26af49d0e22829e52fd5 100644 (file)
@@ -1,5 +1,6 @@
 #include "fs.h"
 #include <assert.h>
+#include <signal.h>
 #include <minix/dmap.h>
 #include <minix/endpoint.h>
 #include <minix/vfsif.h>
@@ -12,6 +13,7 @@ FORWARD _PROTOTYPE(void get_work, (message *m_in)                     );
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
+FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
 
 /*===========================================================================*
  *                             main                                         *
@@ -40,7 +42,6 @@ PUBLIC int main(int argc, char *argv[])
        caller_uid = -1;        /* To trap errors */
        caller_gid = -1;
 
-       if (src == PM_PROC_NR) continue; /* Exit signal */
        assert(src == VFS_PROC_NR); /* Otherwise this must be VFS talking */
        req_nr = fs_m_in.m_type;
        if (req_nr < VFS_BASE) {
@@ -71,10 +72,13 @@ PRIVATE void sef_local_startup()
 {
   /* Register init callbacks. */
   sef_setcb_init_fresh(sef_cb_init_fresh);
-  sef_setcb_init_restart(sef_cb_init_restart_fail);
+  sef_setcb_init_restart(sef_cb_init_fail);
 
   /* No live update support for now. */
 
+  /* Register signal callbacks. */
+  sef_setcb_signal_handler(sef_cb_signal_handler);
+
   /* Let SEF perform startup. */
   sef_startup();
 }
@@ -109,6 +113,16 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
   return(OK);
 }
 
+/*===========================================================================*
+ *                        sef_cb_signal_handler                             *
+ *===========================================================================*/
+PRIVATE void sef_cb_signal_handler(int signo)
+{
+  /* Only check for termination signal, ignore anything else. */
+  if (signo != SIGTERM) return;
+
+  exitsignaled = 1;
+}
 
 /*===========================================================================*
  *                             get_work                                     *
@@ -124,24 +138,13 @@ message *m_in;                            /* pointer to message */
                panic("sef_receive failed: %d", r);
        src = fs_m_in.m_source;
 
-       if (src != VFS_PROC_NR) {
-               if(src == PM_PROC_NR) {
-                       if(is_notify(fs_m_in.m_type)) {
-                               exitsignaled = 1; /* Normal exit request. */
-                               srcok = 1;      
-                       } else
-                               printf("PFS: unexpected message from PM\n");
-               } else
-                       printf("PFS: unexpected source %d\n", src);
-       } else if(src == VFS_PROC_NR) {
+       if(src == VFS_PROC_NR) {
                srcok = 1;              /* Normal FS request. */
        } else
                printf("PFS: unexpected source %d\n", src);
   } while(!srcok);
 
-   assert( src == VFS_PROC_NR || 
-         (src == PM_PROC_NR && is_notify(fs_m_in.m_type))
-        );
+   assert( src == VFS_PROC_NR );
 }
 
 
index d464ad21cdbcf886f543a80acb0f7868a60b913b..77198ce6b5201e9e8c75071d74c58e228dc164ac 100644 (file)
@@ -152,9 +152,8 @@ int result;
        {
                if (rmp->mp_flags & PARTIAL_EXEC)
                {
-                       /* Use SIGILL signal that something went wrong */
-                       rmp->mp_sigstatus = SIGILL;
-                       exit_proc(rmp, 0, FALSE /*dump_core*/);
+                       /* Use SIGKILL to signal that something went wrong */
+                       sys_kill(rmp->mp_endpoint, SIGKILL);
                        return;
                }
                setreply(rmp-mproc, result);
index cb87baaf15f36faeb70e8183c51509757269bd76..dc29656dae1325af50d299a6018008dd3143f41a 100644 (file)
@@ -8,7 +8,7 @@
  *
  * The entry points into this file are:
  *   do_fork:          perform the FORK system call
- *   do_fork_nb:       special nonblocking version of FORK, for RS
+ *   do_srv_fork:      special FORK, used by RS to create sys services
  *   do_exit:          perform the EXIT system call (by calling exit_proc())
  *   exit_proc:                actually do the exiting, and tell FS about it
  *   exit_restart:     continue exiting a process after FS has replied
@@ -91,8 +91,8 @@ PUBLIC int do_fork()
        rmc->mp_trace_flags = 0;
        sigemptyset(&rmc->mp_sigtrace);
   }
-  /* inherit only these flags */
-  rmc->mp_flags &= (IN_USE|PRIV_PROC|DELAY_CALL);
+  /* Inherit only these flags. In normal fork(), PRIV_PROC is not inherited. */
+  rmc->mp_flags &= (IN_USE|DELAY_CALL);
   rmc->mp_child_utime = 0;             /* reset administration */
   rmc->mp_child_stime = 0;             /* reset administration */
   rmc->mp_exitstatus = 0;
@@ -123,9 +123,9 @@ PUBLIC int do_fork()
 }
 
 /*===========================================================================*
- *                             do_fork_nb                                   *
+ *                             do_srv_fork                                  *
  *===========================================================================*/
-PUBLIC int do_fork_nb()
+PUBLIC int do_srv_fork()
 {
 /* The process pointed to by 'mp' has forked.  Create a child process. */
   register struct mproc *rmp;  /* pointer to parent */
@@ -137,8 +137,8 @@ PUBLIC int do_fork_nb()
   endpoint_t child_ep;
   message m;
 
-  /* Only system processes are allowed to use fork_nb */
-  if (!(mp->mp_flags & PRIV_PROC))
+  /* Only RS is allowed to use srv_fork. */
+  if (mp->mp_endpoint != RS_PROC_NR)
        return EPERM;
 
  /* If tables might fill up during FORK, don't even start since recovery half
@@ -192,7 +192,7 @@ PUBLIC int do_fork_nb()
   new_pid = get_free_pid();
   rmc->mp_pid = new_pid;       /* assign pid to child */
 
-  m.m_type = PM_FORK_NB;
+  m.m_type = PM_SRV_FORK;
   m.PM_PROC = rmc->mp_endpoint;
   m.PM_PPROC = rmp->mp_endpoint;
   m.PM_CPID = rmc->mp_pid;
@@ -214,10 +214,19 @@ PUBLIC int do_fork_nb()
  *===========================================================================*/
 PUBLIC int do_exit()
 {
-/* Perform the exit(status) system call. The real work is done by exit_proc(),
- * which is also called when a process is killed by a signal.
- */
-  exit_proc(mp, m_in.status, FALSE /*dump_core*/);
+ /* Perform the exit(status) system call. The real work is done by exit_proc(),
+  * which is also called when a process is killed by a signal. System processes
+  * do not use PM's exit() to terminate. If they try to, we warn the user
+  * and send a SIGKILL signal to the system process.
+  */
+  if(mp->mp_flags & PRIV_PROC) {
+      printf("PM: system process %d (%s) tries to exit(), sending SIGKILL\n",
+          mp->mp_endpoint, mp->mp_name);
+      sys_kill(mp->mp_endpoint, SIGKILL);
+  }
+  else {
+      exit_proc(mp, m_in.status, FALSE /*dump_core*/);
+  }
   return(SUSPEND);             /* can't communicate from beyond the grave */
 }
 
@@ -280,7 +289,6 @@ int dump_core;                      /* flag indicating whether to dump core */
        panic("exit_proc: vm_willexit failed: %d", r);
   }
   vm_notify_sig_wrapper(rmp->mp_endpoint);
-
   if (proc_nr_e == INIT_PROC_NR)
   {
        printf("PM: INIT died\n");
@@ -303,8 +311,8 @@ int dump_core;                      /* flag indicating whether to dump core */
         * needed because the system process might be a block device
         * driver that FS is blocked waiting on.
         */
-       if((r= sys_exit(rmp->mp_endpoint)) != OK)
-               panic("exit_proc: sys_exit failed: %d", r);
+       if((r= sys_clear(rmp->mp_endpoint)) != OK)
+               panic("exit_proc: sys_clear failed: %d", r);
   }
 
   /* Clean up most of the flags describing the process's state before the exit,
@@ -363,8 +371,8 @@ int dump_core;                      /* flag indicating whether to dump core */
   if (!(rmp->mp_flags & PRIV_PROC))
   {
        /* destroy the (user) process */
-       if((r=sys_exit(rmp->mp_endpoint)) != OK)
-               panic("exit_restart: sys_exit failed: %d", r);
+       if((r=sys_clear(rmp->mp_endpoint)) != OK)
+               panic("exit_restart: sys_clear failed: %d", r);
   }
 
   /* Release the memory occupied by the child. */
@@ -667,12 +675,3 @@ register struct mproc *rmp;        /* tells which process is exiting */
   procs_in_use--;
 }
 
-PUBLIC void _exit(int code)
-{
-       sys_exit(SELF);
-}
-
-PUBLIC void __exit(int code)
-{
-       sys_exit(SELF);
-}
index e5cef3ad7096af706b8199ed63729f6db3905a4f..a11480338ff28394f79b80b9797e90f837a40869 100644 (file)
@@ -39,6 +39,7 @@
 EXTERN unsigned long calls_stats[NCALLS];
 #endif
 
+FORWARD _PROTOTYPE( void sendreply, (void)                             );
 FORWARD _PROTOTYPE( void get_work, (void)                              );
 FORWARD _PROTOTYPE( int get_nice_value, (int queue)                    );
 FORWARD _PROTOTYPE( void handle_fs_reply, (void)                       );
@@ -51,6 +52,7 @@ extern int unmap_ok;
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
+FORWARD _PROTOTYPE( int sef_cb_signal_manager, (endpoint_t target, int signo) );
 
 /*===========================================================================*
  *                             main                                         *
@@ -80,19 +82,14 @@ PUBLIC int main()
                                pm_expire_timers(m_in.NOTIFY_TIMESTAMP);
                                result = SUSPEND;       /* don't reply */
                                break;
-                       case SYSTEM:                    /* signals pending */
-                               sigset = m_in.NOTIFY_ARG;
-                               if (sigismember(&sigset, SIGKSIG))  {
-                                       (void) ksig_pending();
-                               } 
-                               result = SUSPEND;       /* don't reply */
-                               break;
                        default :
                                result = ENOSYS;
                }
 
                /* done, send reply and continue */
-               goto send_reply;
+               if (result != SUSPEND) setreply(who_p, result);
+               sendreply();
+               continue;
        }
 
        switch(call_nr)
@@ -104,7 +101,7 @@ PUBLIC int main()
        case PM_EXIT_REPLY:
        case PM_CORE_REPLY:
        case PM_FORK_REPLY:
-       case PM_FORK_NB_REPLY:
+       case PM_SRV_FORK_REPLY:
        case PM_UNPAUSE_REPLY:
        case PM_REBOOT_REPLY:
        case PM_SETGROUPS_REPLY:
@@ -133,29 +130,9 @@ PUBLIC int main()
                break;
        }
 
-send_reply:
-       /* Send the results back to the user to indicate completion. */
+       /* Send reply. */
        if (result != SUSPEND) setreply(who_p, result);
-
-       /* Send out all pending reply messages, including the answer to
-        * the call just made above.
-        */
-       for (proc_nr=0, rmp=mproc; proc_nr < NR_PROCS; proc_nr++, rmp++) {
-               /* In the meantime, the process may have been killed by a
-                * signal (e.g. if a lethal pending signal was unblocked)
-                * without the PM realizing it. If the slot is no longer in
-                * use or the process is exiting, don't try to reply.
-                */
-               if ((rmp->mp_flags & (REPLY | IN_USE | EXITING)) ==
-                  (REPLY | IN_USE)) {
-                       s=sendnb(rmp->mp_endpoint, &rmp->mp_reply);
-                       if (s != OK) {
-                               printf("PM can't reply to %d (%s): %d\n",
-                                       rmp->mp_endpoint, rmp->mp_name, s);
-                       }
-                       rmp->mp_flags &= ~REPLY;
-               }
-       }
+       sendreply();
   }
   return(OK);
 }
@@ -167,10 +144,13 @@ PRIVATE void sef_local_startup()
 {
   /* Register init callbacks. */
   sef_setcb_init_fresh(sef_cb_init_fresh);
-  sef_setcb_init_restart(sef_cb_init_restart_fail);
+  sef_setcb_init_restart(sef_cb_init_fail);
 
   /* No live update support for now. */
 
+  /* Register signal callbacks. */
+  sef_setcb_signal_manager(sef_cb_signal_manager);
+
   /* Let SEF perform startup. */
   sef_startup();
 }
@@ -203,6 +183,7 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
                                SIGBUS, SIGSEGV };
   register struct mproc *rmp;
   register char *sig_ptr;
+  register int signo;
   message mess;
 
   /* Initialize process table, including timers. */
@@ -246,7 +227,6 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
                rmp = &mproc[ip->proc_nr];      
                strncpy(rmp->mp_name, ip->proc_name, PROC_NAME_LEN); 
                rmp->mp_nice = get_nice_value(ip->priority);
-               sigemptyset(&rmp->mp_sig2mess);
                sigemptyset(&rmp->mp_ignore);   
                sigemptyset(&rmp->mp_sigmask);
                sigemptyset(&rmp->mp_catch);
@@ -268,11 +248,7 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
                                rmp->mp_parent = RS_PROC_NR;
                        }
                        rmp->mp_pid = get_free_pid();
-                       rmp->mp_flags |= IN_USE | PRIV_PROC; 
-                       for (sig_ptr = mess_sigs; 
-                               sig_ptr < mess_sigs+sizeof(mess_sigs); 
-                               sig_ptr++)
-                       sigaddset(&rmp->mp_sig2mess, *sig_ptr);
+                       rmp->mp_flags |= IN_USE | PRIV_PROC;
                }
 
                /* Get kernel endpoint identifier. */
@@ -288,9 +264,6 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
        }
   }
 
-  /* Override some details for PM. */
-  sigfillset(&mproc[PM_PROC_NR].mp_ignore);    /* guard against signals */
-
   /* Tell FS that no more system processes follow and synchronize. */
   mess.PR_ENDPT = NONE;
   if (sendrec(FS_PROC_NR, &mess) != OK || mess.m_type != OK)
@@ -317,6 +290,20 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
   return(OK);
 }
 
+/*===========================================================================*
+ *                         sef_cb_signal_manager                            *
+ *===========================================================================*/
+PRIVATE int sef_cb_signal_manager(endpoint_t target, int signo)
+{
+/* Process signal on behalf of the kernel. */
+  int r;
+
+  r = process_ksig(target, signo);
+  sendreply();
+
+  return r;
+}
+
 /*===========================================================================*
  *                             get_work                                     *
  *===========================================================================*/
@@ -360,6 +347,36 @@ int result;                        /* result of call (usually OK or error #) */
   rmp->mp_flags |= REPLY;      /* reply pending */
 }
 
+/*===========================================================================*
+ *                             sendreply                                    *
+ *===========================================================================*/
+PRIVATE void sendreply()
+{
+  int proc_nr;
+  int s;
+  struct mproc *rmp;
+
+  /* Send out all pending reply messages, including the answer to
+   * the call just made above.
+   */
+  for (proc_nr=0, rmp=mproc; proc_nr < NR_PROCS; proc_nr++, rmp++) {
+      /* In the meantime, the process may have been killed by a
+       * signal (e.g. if a lethal pending signal was unblocked)
+       * without the PM realizing it. If the slot is no longer in
+       * use or the process is exiting, don't try to reply.
+       */
+      if ((rmp->mp_flags & (REPLY | IN_USE | EXITING)) ==
+          (REPLY | IN_USE)) {
+          s=sendnb(rmp->mp_endpoint, &rmp->mp_reply);
+          if (s != OK) {
+              printf("PM can't reply to %d (%s): %d\n",
+                  rmp->mp_endpoint, rmp->mp_name, s);
+          }
+          rmp->mp_flags &= ~REPLY;
+      }
+  }
+}
+
 /*===========================================================================*
  *                             get_nice_value                               *
  *===========================================================================*/
@@ -485,7 +502,7 @@ PRIVATE void handle_fs_reply()
 
        break;
 
-  case PM_FORK_NB_REPLY:
+  case PM_SRV_FORK_REPLY:
        /* Nothing to do */
 
        break;
index 7da8d8b0a32ef03744bc778ee35370d001710968..ae614b2282d05ee1821c4d85c0f6a9de098f9948 100644 (file)
@@ -38,7 +38,6 @@ EXTERN struct mproc {
   /* Signal handling information. */
   sigset_t mp_ignore;          /* 1 means ignore the signal, 0 means don't */
   sigset_t mp_catch;           /* 1 means catch the signal, 0 means don't */
-  sigset_t mp_sig2mess;                /* 1 means transform into notify message */
   sigset_t mp_sigmask;         /* signals to be blocked */
   sigset_t mp_sigmask2;                /* saved copy of mp_sigmask */
   sigset_t mp_sigpending;      /* pending signals to be handled */
index 2d3d32811130104c6b4177075bc35a40a48eb070..8ff58eac392483e41a099819c69dd598c3b49cf4 100644 (file)
@@ -29,7 +29,7 @@ _PROTOTYPE( void exec_restart, (struct mproc *rmp, int result)                );
 
 /* forkexit.c */
 _PROTOTYPE( int do_fork, (void)                                                );
-_PROTOTYPE( int do_fork_nb, (void)                                     );
+_PROTOTYPE( int do_srv_fork, (void)                                    );
 _PROTOTYPE( int do_exit, (void)                                                );
 _PROTOTYPE( void exit_proc, (struct mproc *rmp, int exit_status,
        int dump_core)                                                  );
@@ -66,7 +66,8 @@ _PROTOTYPE( int do_cprofile, (void)                                   );
 
 /* signal.c */
 _PROTOTYPE( int do_kill, (void)                                                );
-_PROTOTYPE( int ksig_pending, (void)                                   );
+_PROTOTYPE( int do_srv_kill, (void)                                    );
+_PROTOTYPE( int process_ksig, (endpoint_t proc_nr_e, int signo)                );
 _PROTOTYPE( int do_pause, (void)                                       );
 _PROTOTYPE( int check_sig, (pid_t proc_id, int signo, int ksig)                );
 _PROTOTYPE( void sig_proc, (struct mproc *rmp, int signo, int trace,
index f4d3c6ca0e2a3ba263d959f196dfa936b953ce26..33ca55d62feffa57d13b1f1b3b3d41be886fe7f3 100644 (file)
@@ -12,7 +12,7 @@
  *   do_sigsuspend:    perform the SIGSUSPEND system call
  *   do_kill:          perform the KILL system call
  *   do_pause:         perform the PAUSE system call
- *   ksig_pending:     the kernel notified about pending signals
+ *   process_ksig:     process a signal an behalf of the kernel
  *   sig_proc:         interrupt or terminate a signaled process
  *   check_sig:                check which processes to signal with sig_proc()
  *   check_pending:    check if a pending signal can now be delivered
@@ -34,8 +34,8 @@
 #include "param.h"
 
 FORWARD _PROTOTYPE( void unpause, (struct mproc *rmp)                  );
-FORWARD _PROTOTYPE( void handle_ksig, (int proc_nr, sigset_t sig_map)  );
 FORWARD _PROTOTYPE( int sig_send, (struct mproc *rmp, int signo)       );
+FORWARD _PROTOTYPE( void sig_proc_exit, (struct mproc *rmp, int signo) );
 
 /*===========================================================================*
  *                             do_sigaction                                 *
@@ -48,6 +48,7 @@ PUBLIC int do_sigaction()
 
   if (m_in.sig_nr == SIGKILL) return(OK);
   if (m_in.sig_nr < 1 || m_in.sig_nr >= _NSIG) return(EINVAL);
+
   svp = &mp->mp_sigact[m_in.sig_nr];
   if ((struct sigaction *) m_in.sig_osa != (struct sigaction *) NULL) {
        r = sys_datacopy(PM_PROC_NR,(vir_bytes) svp,
@@ -67,20 +68,12 @@ PUBLIC int do_sigaction()
        sigaddset(&mp->mp_ignore, m_in.sig_nr);
        sigdelset(&mp->mp_sigpending, m_in.sig_nr);
        sigdelset(&mp->mp_catch, m_in.sig_nr);
-       sigdelset(&mp->mp_sig2mess, m_in.sig_nr);
   } else if (svec.sa_handler == SIG_DFL) {
        sigdelset(&mp->mp_ignore, m_in.sig_nr);
        sigdelset(&mp->mp_catch, m_in.sig_nr);
-       sigdelset(&mp->mp_sig2mess, m_in.sig_nr);
-  } else if (svec.sa_handler == SIG_MESS) {
-       if (! (mp->mp_flags & PRIV_PROC)) return(EPERM);
-       sigdelset(&mp->mp_ignore, m_in.sig_nr);
-       sigaddset(&mp->mp_sig2mess, m_in.sig_nr);
-       sigdelset(&mp->mp_catch, m_in.sig_nr);
   } else {
        sigdelset(&mp->mp_ignore, m_in.sig_nr);
        sigaddset(&mp->mp_catch, m_in.sig_nr);
-       sigdelset(&mp->mp_sig2mess, m_in.sig_nr);
   }
   mp->mp_sigact[m_in.sig_nr].sa_handler = svec.sa_handler;
   sigdelset(&svec.sa_mask, SIGKILL);
@@ -200,67 +193,42 @@ PUBLIC int do_kill()
 }
 
 /*===========================================================================*
- *                             ksig_pending                                 *
+ *                           do_srv_kill                                    *
  *===========================================================================*/
-PUBLIC int ksig_pending()
+PUBLIC int do_srv_kill()
 {
-/* Certain signals, such as segmentation violations originate in the kernel.
- * When the kernel detects such signals, it notifies the PM to take further 
- * action. The PM requests the kernel to send messages with the process
- * slot and bit map for all signaled processes. The File System, for example,
- * uses this mechanism to signal writing on broken pipes (SIGPIPE). 
- *
- * The kernel has notified the PM about pending signals. Request pending
- * signals until all signals are handled. If there are no more signals,
- * NONE is returned in the process number field.
- */ 
- endpoint_t proc_nr_e;
- sigset_t sig_map;
-
- while (TRUE) {
-   int r;
-   /* get an arbitrary pending signal */
-   if((r=sys_getksig(&proc_nr_e, &sig_map)) != OK)
-       panic("sys_getksig failed: %d", r);
-   if (NONE == proc_nr_e) {            /* stop if no more pending signals */
-       break;
-   } else {
-       int proc_nr_p;
-       if(pm_isokendpt(proc_nr_e, &proc_nr_p) != OK)
-               panic("sys_getksig strange process: %d", proc_nr_e);
-       handle_ksig(proc_nr_e, sig_map);        /* handle the received signal */
-       /* If the process still exists to the kernel after the signal
-        * has been handled ...
-        */
-        if ((mproc[proc_nr_p].mp_flags & (IN_USE | EXITING)) == IN_USE)
-       {
-          if((r=sys_endksig(proc_nr_e)) != OK) /* ... tell kernel it's done */
-               panic("sys_endksig failed: %d", r);
-       }
-   }
- } 
- return(SUSPEND);                      /* prevents sending reply */
+/* Perform the srv_kill(pid, signo) system call. */
+
+  /* Only RS is allowed to use srv_kill. */
+  if (mp->mp_endpoint != RS_PROC_NR)
+       return EPERM;
+
+  /* Pretend the signal comes from the kernel when RS wants to deliver a signal
+   * to a system process. RS sends a SIGKILL when it wants to perform cleanup.
+   * In that case, ksig == TRUE forces PM to exit the process immediately.
+   */
+  return check_sig(m_in.pid, m_in.sig_nr, TRUE /* ksig */);
 }
 
 /*===========================================================================*
- *                             handle_ksig                                  *
+ *                             process_ksig                                 *
  *===========================================================================*/
-PRIVATE void handle_ksig(proc_nr_e, sig_map)
+PUBLIC int process_ksig(proc_nr_e, signo)
 int proc_nr_e;
-sigset_t sig_map;
+int signo;
 {
   register struct mproc *rmp;
-  int i, proc_nr;
+  int proc_nr;
   pid_t proc_id, id;
 
   if(pm_isokendpt(proc_nr_e, &proc_nr) != OK || proc_nr < 0) {
-       printf("PM: handle_ksig: %d?? not ok\n", proc_nr_e);
+       printf("PM: process_ksig: %d?? not ok\n", proc_nr_e);
        return;
   }
   rmp = &mproc[proc_nr];
   if ((rmp->mp_flags & (IN_USE | EXITING)) != IN_USE) {
 #if 0
-       printf("PM: handle_ksig: %d?? exiting / not in use\n", proc_nr_e);
+       printf("PM: process_ksig: %d?? exiting / not in use\n", proc_nr_e);
 #endif
        return;
   }
@@ -268,54 +236,52 @@ sigset_t sig_map;
   mp = &mproc[0];                      /* pretend signals are from PM */
   mp->mp_procgrp = rmp->mp_procgrp;    /* get process group right */
 
-  /* Check each bit in turn to see if a signal is to be sent.  Unlike
-   * kill(), the kernel may collect several unrelated signals for a
-   * process and pass them to PM in one blow.  Thus loop on the bit
-   * map. For SIGVTALRM and SIGPROF, see if we need to restart a
+  /* For SIGVTALRM and SIGPROF, see if we need to restart a
    * virtual timer. For SIGINT, SIGWINCH and SIGQUIT, use proc_id 0
    * to indicate a broadcast to the recipient's process group.  For
    * SIGKILL, use proc_id -1 to indicate a systemwide broadcast.
    */
-  for (i = 1; i < _NSIG; i++) {
-       if (!sigismember(&sig_map, i)) continue;
-#if 0
-       printf("PM: sig %d for %d from kernel\n", 
-               i, proc_nr_e);
-#endif
-       switch (i) {
-           case SIGINT:
-           case SIGQUIT:
-           case SIGWINCH:
-               id = 0; break;  /* broadcast to process group */
-           case SIGVTALRM:
-           case SIGPROF:
-               check_vtimer(proc_nr, i);
-               /* fall-through */
-           default:
-               id = proc_id;
-               break;
-       }
-       check_sig(id, i, TRUE /* ksig */);
+  switch (signo) {
+      case SIGINT:
+      case SIGQUIT:
+      case SIGWINCH:
+       id = 0; break;  /* broadcast to process group */
+      case SIGVTALRM:
+      case SIGPROF:
+       check_vtimer(proc_nr, signo);
+       /* fall-through */
+      default:
+       id = proc_id;
+       break;
   }
+  check_sig(id, signo, TRUE /* ksig */);
 
-  /* If SIGNDELAY is set, an earlier sys_stop() failed because the process was
+  /* If SIGKNDELAY is set, an earlier sys_stop() failed because the process was
    * still sending, and the kernel hereby tells us that the process is now done
    * with that. We can now try to resume what we planned to do in the first
    * place: set up a signal handler. However, the process's message may have
    * been a call to PM, in which case the process may have changed any of its
    * signal settings. The process may also have forked, exited etcetera.
    */
-  if (sigismember(&sig_map, SIGNDELAY) && (rmp->mp_flags & DELAY_CALL)) {
+  if (signo == SIGKNDELAY && (rmp->mp_flags & DELAY_CALL)) {
        rmp->mp_flags &= ~DELAY_CALL;
 
        if (rmp->mp_flags & (FS_CALL | PM_SIG_PENDING))
-               panic("handle_ksig: bad process state");
+               panic("process_ksig: bad process state");
 
        /* Process as many normal signals as possible. */
        check_pending(rmp);
 
        if (rmp->mp_flags & DELAY_CALL)
-               panic("handle_ksig: multiple delay calls?");
+               panic("process_ksig: multiple delay calls?");
+  }
+  
+  /* See if the process is still alive */
+  if ((mproc[proc_nr].mp_flags & (IN_USE | EXITING)) == IN_USE)  {
+      return OK; /* signal has been delivered */
+  }
+  else {
+      return EDEADSRCDST; /* process is gone */
   }
 }
 
@@ -388,11 +354,34 @@ int ksig;                 /* non-zero means signal comes from kernel  */
        return;
   }
 
-  /* some signals cannot be safely ignored */
+  /* Handle system signals for system processes first. */
+  if(rmp->mp_flags & PRIV_PROC) {
+       /* System signals have always to go through the kernel first to let it
+        * pick the right signal manager. If PM is the assigned signal manager,
+        * the signal will come back and will actually be processed.
+        */
+       if(!ksig) {
+               sys_kill(rmp->mp_endpoint, signo);
+               return;
+       }
+       if(!SIGS_IS_TERMINATION(signo)) {
+               /* Translate every non-termination sys signal into a message. */
+               message m;
+               m.m_type = SIGS_SIGNAL_RECEIVED;
+               m.SIGS_SIG_NUM = signo;
+               asynsend3(rmp->mp_endpoint, &m, AMF_NOREPLY);
+       }
+       else {
+               /* Exit the process in case of termination system signal. */
+               sig_proc_exit(rmp, signo);
+       }
+       return;
+  }
+
+  /* Handle user processes now. See if the signal cannot be safely ignored. */
   badignore = ksig && sigismember(&noign_sset, signo) && (
          sigismember(&rmp->mp_ignore, signo) ||
-         sigismember(&rmp->mp_sigmask, signo) ||
-         sigismember(&rmp->mp_sig2mess, signo));
+         sigismember(&rmp->mp_sigmask, signo));
 
   if (!badignore && sigismember(&rmp->mp_ignore, signo)) { 
        /* Signal should be ignored. */
@@ -403,12 +392,6 @@ int ksig;                  /* non-zero means signal comes from kernel  */
        sigaddset(&rmp->mp_sigpending, signo);
        return;
   }
-  if (!badignore && sigismember(&rmp->mp_sig2mess, signo)) {
-       /* Mark event pending in process slot and send notification. */
-       sigaddset(&rmp->mp_sigpending, signo);
-       notify(rmp->mp_endpoint);
-       return;
-  }
 
   if ((rmp->mp_flags & STOPPED) && signo != SIGKILL) {
        /* If the process is stopped for a debugger, do not deliver any signals
@@ -418,7 +401,6 @@ int ksig;                   /* non-zero means signal comes from kernel  */
        sigaddset(&rmp->mp_sigpending, signo);
        return;
   }
-
   if (!badignore && sigismember(&rmp->mp_catch, signo)) {
        /* Signal is caught. First interrupt the process's current call, if
         * applicable. This may involve a roundtrip to FS, in which case we'll
@@ -449,6 +431,16 @@ int ksig;                  /* non-zero means signal comes from kernel  */
   }
 
   /* Terminate process */
+  sig_proc_exit(rmp, signo);
+}
+
+/*===========================================================================*
+ *                             sig_proc_exit                                *
+ *===========================================================================*/
+PRIVATE void sig_proc_exit(rmp, signo)
+struct mproc *rmp;             /* process that must exit */
+int signo;                     /* signal that caused termination */
+{
   rmp->mp_sigstatus = (char) signo;
   if (sigismember(&core_sset, signo)) {
        printf("PM: coredump signal %d for %d / %s\n", signo, rmp->mp_pid,
@@ -482,12 +474,17 @@ int ksig;                 /* non-zero means signal comes from kernel  */
   /* Return EINVAL for attempts to send SIGKILL to INIT alone. */
   if (proc_id == INIT_PID && signo == SIGKILL) return(EINVAL);
 
-  /* Search the proc table for processes to signal.  
+  /* Signal RS first when broadcasting SIGTERM. */
+  if (proc_id == -1 && signo == SIGTERM)
+      sys_kill(RS_PROC_NR, signo);
+
+  /* Search the proc table for processes to signal. Start from the end of the
+   * table to analyze core system processes at the end when broadcasting.
    * (See forkexit.c about pid magic.)
    */
   count = 0;
   error_code = ESRCH;
-  for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
+  for (rmp = &mproc[NR_PROCS-1]; rmp >= &mproc[0]; rmp--) {
        if (!(rmp->mp_flags & IN_USE)) continue;
 
        /* Check for selection. */
@@ -500,6 +497,12 @@ int ksig;                  /* non-zero means signal comes from kernel  */
        if (proc_id == -1 && signo == SIGKILL &&
                (rmp->mp_flags & PRIV_PROC)) continue;
 
+       /* Disallow lethal signals sent by user processes to sys processes. */
+       if (!ksig && SIGS_IS_LETHAL(signo) && (rmp->mp_flags & PRIV_PROC)) {
+           error_code = EPERM;
+           continue;
+       }
+
        /* Check for permission. */
        if (mp->mp_effuid != SUPER_USER
            && mp->mp_realuid != rmp->mp_realuid
@@ -627,7 +630,7 @@ struct mproc *rmp;          /* which process */
        r = sys_delay_stop(rmp->mp_endpoint);
 
        /* If the process is still busy sending a message, the kernel will give
-        * us EBUSY now and send a SIGNDELAY to the process as soon as sending
+        * us EBUSY now and send a SIGKNDELAY to the process as soon as sending
         * is done.
         */
        if (r == EBUSY) {
index 5fd8bf94c4baf7a0d6e44d91cd54a83ccf66b368..0e3e0eafd1a0edc9066b6f267d3c037730126117 100644 (file)
@@ -113,7 +113,7 @@ _PROTOTYPE (int (*call_vec[]), (void) ) = {
        do_cprofile,    /* 99 = cprofile */
        /* THE MINIX3 ABI ENDS HERE */
        do_exec_newmem, /* 100 = exec_newmem */
-       do_fork_nb,     /* 101 = forknb */
+       do_srv_fork,    /* 101 = srv_fork */
        do_execrestart, /* 102 = exec_restart */
        do_procstat,    /* 103 = procstat */
        do_getprocnr,   /* 104 = getprocnr */
@@ -123,6 +123,7 @@ _PROTOTYPE (int (*call_vec[]), (void) ) = {
        do_adddma,      /* 108 = adddma */
        do_deldma,      /* 109 = deldma */
        do_getdma,      /* 110 = getdma */
+       do_srv_kill,    /* 111 = srv_kill */
 };
 /* This should not fail with "array size is negative": */
 extern int dummy[sizeof(call_vec) == NCALLS * sizeof(call_vec[0]) ? 1 : -1];
index 1bd073636ed6cf8214fd7d5032b70bf66c85c552..20b8d6ddeceec30a5e1a30a3c0babbf7f9ea5e5c 100644 (file)
@@ -19,7 +19,7 @@ LDFLAGS = -i
 LIBS = -lsys 
 
 UTIL_OBJ = service.o
-OBJ = exec.o main.o manager.o table.o utility.o memory.o
+OBJ = exec.o main.o request.o manager.o table.o utility.o memory.o error.o
 
 # build local binary
 all build:     $(SERVER) $(UTIL)
@@ -27,7 +27,7 @@ $(UTIL):      $(UTIL_OBJ)
        $(CC) -o $@ $(LDFLAGS) $(UTIL_OBJ) $(UTIL_LIBS)
 $(SERVER):     $(OBJ)
        $(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
-       install -S 450k $@
+       install -S 850k $@
 
 # install with other servers
 install:       /bin/$(UTIL) /usr/sbin/$(SERVER)
index c060553b4a51620c37a42a17b13deccde36222e7..dc70af845c3dff36f317d1550a18e3fb6afc530e 100644 (file)
@@ -3,6 +3,12 @@
 #ifndef RS_CONST_H
 #define RS_CONST_H
 
+#define DEBUG_DEFAULT 0
+
+#ifndef DEBUG
+#define DEBUG DEBUG_DEFAULT
+#endif
+
 /* Space reserved for program and arguments. */
 #define MAX_COMMAND_LEN     512         /* maximum argument string length */
 #define MAX_SCRIPT_LEN      256         /* maximum restart script name length */
 
 /* Flag values. */
 #define RS_IN_USE       0x001    /* set when process slot is in use */
-#define RS_EXITING      0x004    /* set when exit is expected */
-#define RS_REFRESHING   0x008    /* set when refresh must be done */
-#define RS_NOPINGREPLY  0x010    /* service failed to reply to a ping request */
-#define RS_KILLED       0x020    /* service is killed */
-#define RS_CRASHED      0x040    /* service crashed */
-#define RS_LATEREPLY    0x080    /* no reply sent to RS_DOWN caller yet */
-#define RS_SIGNALED     0x100    /* service crashed */
-#define RS_INITIALIZING 0x200    /* set when init is in progress */
-#define RS_UPDATING     0x400    /* set when update is in progress */
+#define RS_EXITING      0x002    /* set when exit is expected */
+#define RS_REFRESHING   0x004    /* set when refresh must be done */
+#define RS_NOPINGREPLY  0x008    /* service failed to reply to a ping request */
+#define RS_TERMINATED   0x010    /* service has terminated */
+#define RS_LATEREPLY    0x020    /* no reply sent to RS_DOWN caller yet */
+#define RS_INITIALIZING 0x040    /* set when init is in progress */
+#define RS_UPDATING     0x080    /* set when update is in progress */
+#define RS_ACTIVE       0x100    /* set for the active instance of a service */
 
 /* Sys flag values. */
-#define SF_CORE_SRV     0x001    /* set for core system services
-                                  * XXX FIXME: This should trigger a system
-                                  * panic when a CORE_SRV service cannot
-                                  * be restarted. We need better error-handling
-                                  * in RS to change this.
-                                  */
+#define SF_CORE_SRV     0x001    /* set for core system services */
 #define SF_SYNCH_BOOT   0X002    /* set when process needs synch boot init */
 #define SF_NEED_COPY    0x004    /* set when process needs copy to restart */
 #define SF_USE_COPY     0x008    /* set when process has a copy in memory */
     ( spi_to(PM_PROC_NR) | spi_to(FS_PROC_NR) | spi_to(RS_PROC_NR) \
     | spi_to(VM_PROC_NR) )                         /* root user proc */
 
+/* Define the signal manager for the various process types. */
+#define SRV_SM  RS_PROC_NR                         /* system services */
+#define DSRV_SM RS_PROC_NR                         /* dynamic system services */
+#define RUSR_SM PM_PROC_NR                         /* root user proc */
+
 /* Define sys flags for the various process types. */
 #define SRV_SF   (SF_CORE_SRV | SF_NEED_COPY)  /* system services */
 #define SRVC_SF  (SRV_SF | SF_USE_COPY)        /* system services with a copy */
diff --git a/servers/rs/error.c b/servers/rs/error.c
new file mode 100644 (file)
index 0000000..088dea4
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Changes:
+ *   Mar 07, 2010:  Created  (Cristiano Giuffrida)
+ */
+
+#include "inc.h"
+
+/* A single error entry. */
+struct errentry {
+    int errnum;
+    char* errstr;
+};
+
+/* Initialization errors. */
+PRIVATE struct errentry init_errlist[] = {
+  { ENOSYS,     "service does not support the requested initialization type"  }
+};
+PRIVATE const int init_nerr = sizeof(init_errlist) / sizeof(init_errlist[0]);
+
+/* Live update errors. */
+PRIVATE struct errentry lu_errlist[] = {
+  { ENOSYS,     "service does not support live update"                        },
+  { EINVAL,     "service does not support the required state"                 },
+  { EBUSY,      "service is not able to prepare for the update now"           },
+  { EGENERIC,   "generic error occurred while preparing for the update"       }
+};
+PRIVATE const int lu_nerr = sizeof(lu_errlist) / sizeof(lu_errlist[0]);
+
+/*===========================================================================*
+ *                               rs_strerror                                *
+ *===========================================================================*/
+PRIVATE char * rs_strerror(int errnum, struct errentry *errlist, const int nerr)
+{
+  int i;
+
+  for(i=0; i < nerr; i++) {
+      if(errnum == errlist[i].errnum)
+          return errlist[i].errstr;
+  }
+
+  return strerror(-errnum);
+}
+
+/*===========================================================================*
+ *                               init_strerror                              *
+ *===========================================================================*/
+PUBLIC char * init_strerror(int errnum)
+{
+  return rs_strerror(errnum, init_errlist, init_nerr);
+}
+
+/*===========================================================================*
+ *                                lu_strerror                               *
+ *===========================================================================*/
+PUBLIC char * lu_strerror(int errnum)
+{
+  return rs_strerror(errnum, lu_errlist, lu_nerr);
+}
index 7755bb5dbf83ac962ad70abc2691144eb79c641b..741cf50bebd6a9eee61676154b3f3cdeb37344cf 100644 (file)
@@ -21,7 +21,7 @@ FORWARD _PROTOTYPE( void patch_ptr, (char stack[ARG_MAX],
 FORWARD _PROTOTYPE( int read_seg, (char *exec, size_t exec_len, off_t off,
        int proc_e, int seg, phys_bytes seg_bytes)                      );
 
-int dev_execve(int proc_e, char *exec, size_t exec_len, char **argv,
+int srv_execve(int proc_e, char *exec, size_t exec_len, char **argv,
        char **Xenvp)
 {
        char * const *ap;
@@ -56,16 +56,6 @@ int dev_execve(int proc_e, char *exec, size_t exec_len, char **argv,
                argc++;
        }
 
-#if 0
-printf("here: %s, %d\n", __FILE__, __LINE__);
-       for (ep= envp; *ep != NULL; ep++) {
-               n = sizeof(*ep) + strlen(*ep) + 1;
-               frame_size+= n;
-               if (frame_size < n) ov= 1;
-               string_off+= sizeof(*ap);
-       }
-#endif
-
        /* Add an argument count and two terminating nulls. */
        frame_size+= sizeof(argc) + sizeof(*ap) + sizeof(*ep);
        string_off+= sizeof(argc) + sizeof(*ap) + sizeof(*ep);
@@ -144,6 +134,7 @@ static int do_exec(int proc_e, char *exec, size_t exec_len, char *progname,
        if (r != OK)
        {
                printf("do_exec: read_header failed\n");
+               error= r;
                goto fail;
        }
        need_restart= 1;
index c2eb506f1e9e47b32a58b8ebdcc7c0f484f386ff..c907f5e8cd55933bbffee9485ba380acf15c94d7 100644 (file)
@@ -25,19 +25,13 @@ extern struct boot_image_dev boot_image_dev_table[];
 
 /* The system process table. This table only has entries for system
  * services (servers and drivers), and thus is not directly indexed by
- * slot number.
+ * slot number. The size of the table must match the size of the privilege
+ * table in the kernel.
  */
 EXTERN struct rprocpub rprocpub[NR_SYS_PROCS];  /* public entries */
 EXTERN struct rproc rproc[NR_SYS_PROCS];
 EXTERN struct rproc *rproc_ptr[NR_PROCS];       /* mapping for fast access */
 
-/* Pipe for detection of exec failures. The pipe is close-on-exec, and
- * no data will be written to the pipe if the exec succeeds. After an 
- * exec failure, the slot number is written to the pipe. After each exit,
- * a non-blocking read retrieves the slot number from the pipe.
- */
-EXTERN int exec_pipe[2];
-
 /* Global init descriptor. This descriptor holds data to initialize system
  * services.
  */
@@ -51,5 +45,8 @@ EXTERN struct rupdate rupdate;
 /* Enable/disable verbose output. */
 EXTERN long rs_verbose;
 
+/* Set when we are shutting down. */
+EXTERN int shutting_down;
+
 #endif /* RS_GLO_H */
 
index 70ff1b8c396696f435a4fc1abc9416f4cc3f9c3e..5c8e9d858a0979f706754e2403c24961ffbe20fd 100644 (file)
@@ -9,10 +9,16 @@
 
 #include <ansi.h>
 #include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/ptrace.h>
 #include <limits.h>
 #include <errno.h>
 #include <signal.h>
 #include <unistd.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <lib.h>
 
 #include <minix/callnr.h>
 #include <minix/config.h>
@@ -26,6 +32,9 @@
 #include <minix/rs.h>
 #include <minix/dmap.h>
 #include <minix/endpoint.h>
+#include <minix/vm.h>
+#include <minix/ds.h>
+#include <minix/minlib.h>
 
 #include <machine/archtypes.h>
 #include <timers.h>                            /* For priv.h */
index d300f49b2933750cd8e6c954d7213b01a01b5629..b1bb20390febe5c23321c32727a3d5413ed0fb41 100644 (file)
@@ -16,7 +16,6 @@
 #include "../../kernel/type.h"
 #include "../../kernel/proc.h"
 #include "../pm/mproc.h"
-#include "../pm/const.h"
 
 /* Declare some local functions. */
 FORWARD _PROTOTYPE(void exec_image_copy, ( int boot_proc_idx,
@@ -26,9 +25,7 @@ FORWARD _PROTOTYPE(void boot_image_info_lookup, ( endpoint_t endpoint,
     struct boot_image **ip, struct boot_image_priv **pp,
     struct boot_image_sys **sp, struct boot_image_dev **dp)             );
 FORWARD _PROTOTYPE(void catch_boot_init_ready, (endpoint_t endpoint)   );
-FORWARD _PROTOTYPE(void sig_handler, (void)                            );
 FORWARD _PROTOTYPE(void get_work, (message *m)                         );
-FORWARD _PROTOTYPE(void reply, (int whom, message *m_out)              );
 
 /* The buffer where the boot image is copied during initialization. */
 PRIVATE int boot_image_buffer_size;
@@ -40,6 +37,8 @@ EXTERN int unmap_ok;
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void)                      );
 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
+FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
+FORWARD _PROTOTYPE( int sef_cb_signal_manager, (endpoint_t target, int signo) );
 
 /*===========================================================================*
  *                             main                                         *
@@ -63,15 +62,15 @@ PUBLIC int main(void)
       /* Wait for request message. */
       get_work(&m);
       who_e = m.m_source;
-      who_p = _ENDPOINT_P(who_e);
-      if(who_p < -NR_TASKS || who_p >= NR_PROCS)
-       panic("message from bogus source: %d", who_e);
+      if(rs_isokendpt(who_e, &who_p) != OK) {
+          panic("message from bogus source: %d", who_e);
+      }
 
       call_nr = m.m_type;
 
       /* Now determine what to do.  Four types of requests are expected:
        * - Heartbeat messages (notifications from registered system services)
-       * - System notifications (POSIX signals or synchronous alarm)
+       * - System notifications (synchronous alarm)
        * - User requests (control messages to manage system services)
        * - Ready messages (reply messages from registered services)
        */
@@ -84,13 +83,11 @@ PUBLIC int main(void)
           case CLOCK:
              do_period(&m);                    /* check services status */
              continue;
-          case PM_PROC_NR:                      /* signal or PM heartbeat */
-             sig_handler();                            
          default:                              /* heartbeat notification */
              if (rproc_ptr[who_p] != NULL) {   /* mark heartbeat time */ 
                  rproc_ptr[who_p]->r_alive_tm = m.NOTIFY_TIMESTAMP;
              } else {
-                 printf("Warning, RS got unexpected notify message from %d\n",
+                 printf("RS: warning: got unexpected notify message from %d\n",
                      m.m_source);
              }
          }
@@ -104,7 +101,7 @@ PUBLIC int main(void)
                (call_nr < RS_RQ_BASE || call_nr >= RS_RQ_BASE+0x100))
          {
                /* Ignore invalid requests. Do not try to reply. */
-               printf("RS: got invalid request %d from endpoint %d\n",
+               printf("RS: warning: got invalid request %d from endpoint %d\n",
                        call_nr, m.m_source);
                continue;
          }
@@ -124,7 +121,7 @@ PUBLIC int main(void)
          case RS_INIT:         result = do_init_ready(&m);     break;
          case RS_LU_PREPARE:   result = do_upd_ready(&m);      break;
           default: 
-              printf("Warning, RS got unexpected request %d from %d\n",
+              printf("RS: warning: got unexpected request %d from %d\n",
                   m.m_type, m.m_source);
               result = EINVAL;
           }
@@ -146,6 +143,10 @@ PRIVATE void sef_local_startup()
   /* Register init callbacks. */
   sef_setcb_init_fresh(sef_cb_init_fresh);     /* RS can only start fresh. */
 
+  /* Register signal callbacks. */
+  sef_setcb_signal_handler(sef_cb_signal_handler);
+  sef_setcb_signal_manager(sef_cb_signal_manager);
+
   /* Let SEF perform startup. */
   sef_startup();
 }
@@ -156,7 +157,6 @@ PRIVATE void sef_local_startup()
 PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
 {
 /* Initialize the reincarnation server. */
-  struct sigaction sa;
   struct boot_image *ip;
   int s,i,j;
   int nr_image_srvs, nr_image_priv_srvs, nr_uncaught_init_srvs;
@@ -179,8 +179,9 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
       panic("unable to create rprocpub table grant: %d", rinit.rproctab_gid);
   }
 
-  /* Initialize the global update descriptor. */
+  /* Initialize some global variables. */
   rupdate.flags = 0;
+  shutting_down = FALSE;
 
   /* Get a copy of the boot image table. */
   if ((s = sys_getimage(image)) != OK) {
@@ -290,11 +291,12 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
           rp->r_priv.s_id = static_priv_id(
               _ENDPOINT_P(boot_image_priv->endpoint));
 
-          /* Initialize privilege bitmaps. */
+          /* Initialize privilege bitmaps and signal manager. */
           rp->r_priv.s_flags = boot_image_priv->flags;         /* priv flags */
           rp->r_priv.s_trap_mask = boot_image_priv->trap_mask; /* traps */
           memcpy(&rp->r_priv.s_ipc_to, &boot_image_priv->ipc_to,
                             sizeof(rp->r_priv.s_ipc_to));      /* targets */
+          rp->r_priv.s_sig_mgr = boot_image_priv->sig_mgr;     /* sig mgr */
 
           /* Initialize kernel call mask bitmap from unordered set. */
           fill_call_mask(boot_image_priv->k_calls, NR_SYS_CALLS,
@@ -329,10 +331,8 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
 
       /* Get command settings. */
       rp->r_cmd[0]= '\0';
-      rp->r_argv[0] = rp->r_cmd;
-      rp->r_argv[1] = NULL;
-      rp->r_argc = 1;
       rp->r_script[0]= '\0';
+      build_cmd_dep(rp);
 
       /* Initialize vm call mask bitmap from unordered set. */
       fill_call_mask(boot_image_priv->vm_calls, NR_VM_CALLS,
@@ -343,6 +343,10 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
       rpub->endpoint = ip->endpoint;
 
       /* Set some defaults. */
+      rp->r_old_rp = NULL;                     /* no old version yet */
+      rp->r_new_rp = NULL;                     /* no new version yet */
+      rp->r_prev_rp = NULL;                    /* no prev replica yet */
+      rp->r_next_rp = NULL;                    /* no next replica yet */
       rp->r_uid = 0;                           /* root */
       rp->r_check_tm = 0;                      /* not checked yet */
       getuptime(&rp->r_alive_tm);              /* currently alive */
@@ -350,8 +354,8 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
       rp->r_restarts = 0;                      /* no restarts so far */
       rp->r_set_resources = 0;                 /* don't set resources */
 
-      /* Mark as in use. */
-      rp->r_flags = RS_IN_USE;
+      /* Mark as in use and active. */
+      rp->r_flags = RS_IN_USE | RS_ACTIVE;
       rproc_ptr[_ENDPOINT_P(rpub->endpoint)]= rp;
       rpub->in_use = TRUE;
   }
@@ -409,7 +413,7 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
 
   /* - Step 4: all the system services in the boot image are now running.
    * Complete the initialization of the system process table in collaboration
-   * with other system processes.
+   * with other system services.
    */
   if ((s = getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc)) != OK) {
       panic("unable to get copy of PM process table: %d", s);
@@ -427,7 +431,7 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
       rpub = rp->r_pub;
 
       /* Get pid from PM process table. */
-      rp->r_pid = NO_PID;
+      rp->r_pid = -1;
       for (j = 0; j < NR_PROCS; j++) {
           if (mproc[j].mp_endpoint == rpub->endpoint) {
               rp->r_pid = mproc[j].mp_pid;
@@ -455,32 +459,6 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
   if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
       panic("couldn't set alarm: %d", s);
 
-  /* Install signal handlers. Ask PM to transform signal into message. */
-  sa.sa_handler = SIG_MESS;
-  sigemptyset(&sa.sa_mask);
-  sa.sa_flags = 0;
-  if (sigaction(SIGCHLD,&sa,NULL)<0) panic("sigaction failed: %d", errno);
-  if (sigaction(SIGTERM,&sa,NULL)<0) panic("sigaction failed: %d", errno);
-
-  /* Initialize the exec pipe. */
-  if (pipe(exec_pipe) == -1)
-       panic("pipe failed: %d", errno);
-  if (fcntl(exec_pipe[0], F_SETFD,
-       fcntl(exec_pipe[0], F_GETFD) | FD_CLOEXEC) == -1)
-  {
-       panic("fcntl set FD_CLOEXEC on pipe input failed: %d", errno);
-  }
-  if (fcntl(exec_pipe[1], F_SETFD,
-       fcntl(exec_pipe[1], F_GETFD) | FD_CLOEXEC) == -1)
-  {
-       panic("fcntl set FD_CLOEXEC on pipe output failed: %d", errno);
-  }
-  if (fcntl(exec_pipe[0], F_SETFL,
-       fcntl(exec_pipe[0], F_GETFL) | O_NONBLOCK) == -1)
-  {
-       panic("fcntl set O_NONBLOCK on pipe input failed: %d", errno);
-  }
-
  /* Map out our own text and data. This is normally done in crtso.o
   * but RS is an exception - we don't get to talk to VM so early on.
   * That's why we override munmap() and munmap_text() in utility.c.
@@ -495,6 +473,70 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
   return(OK);
 }
 
+/*===========================================================================*
+ *                         sef_cb_signal_handler                            *
+ *===========================================================================*/
+PRIVATE void sef_cb_signal_handler(int signo)
+{
+  int exit_status;
+
+  /* Check for known signals, ignore anything else. */
+  switch(signo) {
+      case SIGCHLD:
+          do_sigchld();
+      break;
+      case SIGTERM:
+          do_shutdown(NULL);
+      break;
+  }
+}
+
+/*===========================================================================*
+ *                         sef_cb_signal_manager                            *
+ *===========================================================================*/
+PRIVATE int sef_cb_signal_manager(endpoint_t target, int signo)
+{
+/* Process system signal on behalf of the kernel. */
+  int target_p;
+  struct rproc *rp;
+  struct rprocpub *rpub;
+  message m;
+
+  /* Lookup slot. */
+  if(rs_isokendpt(target, &target_p) != OK || rproc_ptr[target_p] == NULL) {
+      if(rs_verbose)
+          printf("RS: ignoring spurious signal %d for process %d\n",
+              signo, target);
+      return;
+  }
+  rp = rproc_ptr[target_p];
+  rpub = rp->r_pub;
+
+  /* Don't bother if a termination signal has already been processed. */
+  if( rp->r_flags & (RS_TERMINATED|RS_EXITING) == RS_TERMINATED ) {
+      return EDEADSRCDST; /* process is gone */
+  }
+
+  if(rs_verbose)
+      printf("RS: %s got %s signal %d\n", srv_to_string(rp),
+          SIGS_IS_TERMINATION(signo) ? "termination" : "non-termination",signo);
+
+  /* In case of termination signal handle the event. */
+  if(SIGS_IS_TERMINATION(signo)) {
+      rp->r_flags |= RS_TERMINATED;
+      terminate_service(rp);
+
+      return EDEADSRCDST; /* process is now gone */
+  }
+
+  /* Translate every non-termination signal into a message. */
+  m.m_type = SIGS_SIGNAL_RECEIVED;
+  m.SIGS_SIG_NUM = signo;
+  asynsend3(rpub->endpoint, &m, AMF_NOREPLY);
+
+  return OK; /* signal has been delivered */
+}
+
 /*===========================================================================*
  *                         exec_image_copy                                  *
  *===========================================================================*/
@@ -643,28 +685,16 @@ endpoint_t endpoint;
       panic("unable to complete init for service: %d", m.m_source);
   }
 
+  /* Send a reply to unblock the service. */
+  m.m_type = OK;
+  reply(m.m_source, &m);
+
   /* Mark the slot as no longer initializing. */
   rp->r_flags &= ~RS_INITIALIZING;
   rp->r_check_tm = 0;
   getuptime(&rp->r_alive_tm);
 }
 
-/*===========================================================================*
- *                             sig_handler                                  *
- *===========================================================================*/
-PRIVATE void sig_handler()
-{
-  sigset_t sigset;
-  int sig;
-
-  /* Try to obtain signal set from PM. */
-  if (getsigset(&sigset) != 0) return;
-
-  /* Check for known signals. */
-  if (sigismember(&sigset, SIGCHLD)) do_exit(NULL);
-  if (sigismember(&sigset, SIGTERM)) do_shutdown(NULL);
-}
-
 /*===========================================================================*
  *                             get_work                                     *
  *===========================================================================*/
@@ -676,17 +706,3 @@ message *m_in;                             /* pointer to message */
         panic("sef_receive failed: %d", s);
 }
 
-/*===========================================================================*
- *                             reply                                        *
- *===========================================================================*/
-PRIVATE void reply(who, m_out)
-int who;                               /* replyee */
-message *m_out;                         /* reply message */
-{
-    int s;                             /* send status */
-
-    s = sendnb(who, m_out);            /* send the message */
-    if (s != OK)
-        printf("RS: unable to send reply to %d: %d\n", who, s);
-}
-
index 01a4f256c5ce0cadff8e6dc1b120ea0c661f8ca7..39dc03fcda170539f730ccbf84cfa80d98651ada 100644 (file)
@@ -6,50 +6,11 @@
  */
 
 #include "inc.h"
-#include <ctype.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <sys/vm.h>
-#include <minix/vm.h>
-#include <lib.h>
-
-#include <minix/sysutil.h>
-
-/* Prototypes for internal functions that do the hard work. */
-FORWARD _PROTOTYPE( int caller_is_root, (endpoint_t endpoint) );
-FORWARD _PROTOTYPE( int caller_can_control, (endpoint_t endpoint,
-       char *label) );
-FORWARD _PROTOTYPE( int copy_label, (endpoint_t src_e,
-       struct rss_label *src_label, char *dst_label, size_t dst_len) );
-FORWARD _PROTOTYPE( int start_service, (struct rproc *rp, int flags,
-       endpoint_t *ep) );
-FORWARD _PROTOTYPE( void stop_service, (struct rproc *rp,int how) );
-FORWARD _PROTOTYPE( int fork_nb, (void) );
-FORWARD _PROTOTYPE( int read_exec, (struct rproc *rp) );
-FORWARD _PROTOTYPE( int share_exec, (struct rproc *rp_src,
-       struct rproc *rp_dst) );
-FORWARD _PROTOTYPE( void free_slot, (struct rproc *rp) );
-FORWARD _PROTOTYPE( void run_script, (struct rproc *rp) );
-FORWARD _PROTOTYPE( char *get_next_label, (char *ptr, char *label,
-       char *caller_label) );
-FORWARD _PROTOTYPE( void add_forward_ipc, (struct rproc *rp,
-       struct priv *privp) );
-FORWARD _PROTOTYPE( void add_backward_ipc, (struct rproc *rp,
-       struct priv *privp) );
-FORWARD _PROTOTYPE( void init_privs, (struct rproc *rp, struct priv *privp) );
-FORWARD _PROTOTYPE( void init_pci, (struct rproc *rp, int endpoint) );
-FORWARD _PROTOTYPE( void update_period, (message *m_ptr) );
-FORWARD _PROTOTYPE( void end_update, (clock_t now) );
-
-PRIVATE int shutting_down = FALSE;
 
 /*===========================================================================*
  *                             caller_is_root                               *
  *===========================================================================*/
-PRIVATE int caller_is_root(endpoint)
+PUBLIC int caller_is_root(endpoint)
 endpoint_t endpoint;                           /* caller endpoint */
 {
   uid_t euid;
@@ -67,7 +28,7 @@ endpoint_t endpoint;                          /* caller endpoint */
 /*===========================================================================*
  *                             caller_can_control                           *
  *===========================================================================*/
-PRIVATE int caller_can_control(endpoint, label)
+PUBLIC int caller_can_control(endpoint, label)
 endpoint_t endpoint;
 char *label;
 {
@@ -78,13 +39,8 @@ char *label;
   char *progname;
 
   /* Find name of binary for given label. */
-  for (rp = BEG_RPROC_ADDR; rp < END_RPROC_ADDR; rp++) {
-       rpub = rp->r_pub;
-       if (strcmp(rpub->label, label) == 0) {
-               break;
-       }
-  }
-  if (rp == END_RPROC_ADDR) return 0;
+  rp = lookup_slot_by_label(label);
+  if (!rp) return 0;
   progname = strrchr(rp->r_argv[0], '/');
   if (progname != NULL)
        progname++;
@@ -106,27 +62,92 @@ char *label;
        }
   }
 
-  if (rs_verbose) {
+  if (rs_verbose) 
        printf("RS: allowing %u control over %s via policy: %s\n",
                endpoint, label, control_allowed ? "yes" : "no");
-  }
+
   return control_allowed;
 }
 
+/*===========================================================================*
+ *                          check_call_permission                           *
+ *===========================================================================*/
+PUBLIC int check_call_permission(caller, call, rp)
+endpoint_t caller;
+int call;
+struct rproc *rp;
+{
+/* Check if the caller has permission to execute a particular call. */
+  struct rprocpub *rpub;
+  int call_allowed;
+
+  /* Caller should be either root or have control privileges. */
+  call_allowed = caller_is_root(caller);
+  if(rp) {
+      call_allowed |= caller_can_control(caller, rp->r_pub->label);
+  }
+  if(!call_allowed) {
+      return EPERM;
+  }
+
+  if(rp) {
+      rpub = rp->r_pub;
+
+      /* Disallow the call if the target is RS or a user process. */
+      if(!(rp->r_priv.s_flags & SYS_PROC) || rpub->endpoint == RS_PROC_NR) {
+          return EPERM;
+      }
+
+      /* Disallow the call if another call is in progress for the service. */
+      if(rp->r_flags & RS_LATEREPLY || rp->r_flags & RS_INITIALIZING) {
+          return EBUSY;
+      }
+
+      /* Only allow RS_DOWN and RS_RESTART if the service has terminated. */
+      if(rp->r_flags & RS_TERMINATED) {
+          if(call != RS_DOWN && call != RS_RESTART) return EPERM;
+      }
+
+      /* Disallow RS_DOWN for core system services. */
+      if (rpub->sys_flags & SF_CORE_SRV) {
+          if(call == RS_DOWN) return EPERM;
+      }
+  }
+
+  return OK;
+}
+
+/*===========================================================================*
+ *                             copy_rs_start                                *
+ *===========================================================================*/
+PUBLIC int copy_rs_start(src_e, src_rs_start, dst_rs_start)
+endpoint_t src_e;
+char *src_rs_start;
+struct rs_start *dst_rs_start;
+{
+  int r;
+
+  r = sys_datacopy(src_e, (vir_bytes) src_rs_start, 
+       SELF, (vir_bytes) dst_rs_start, sizeof(struct rs_start));
+
+  return r;
+}
+
 /*===========================================================================*
  *                             copy_label                                   *
  *===========================================================================*/
-PRIVATE int copy_label(src_e, src_label, dst_label, dst_len)
+PUBLIC int copy_label(src_e, src_label, src_len, dst_label, dst_len)
 endpoint_t src_e;
-struct rss_label *src_label;
+char *src_label;
+size_t src_len;
 char *dst_label;
 size_t dst_len;
 {
   int s, len;
 
-  len = MIN(dst_len-1, src_label->l_len);
+  len = MIN(dst_len-1, src_len);
 
-  s = sys_datacopy(src_e, (vir_bytes) src_label->l_addr,
+  s = sys_datacopy(src_e, (vir_bytes) src_label,
        SELF, (vir_bytes) dst_label, len);
   if (s != OK) return s;
 
@@ -136,66 +157,24 @@ size_t dst_len;
 }
 
 /*===========================================================================*
- *                                do_up                                     *
+ *                             build_cmd_dep                                *
  *===========================================================================*/
-PUBLIC int do_up(m_ptr)
-message *m_ptr;                                        /* request message pointer */
+PUBLIC void build_cmd_dep(struct rproc *rp)
 {
-/* A request was made to start a new system service. 
- */
-  register struct rproc *rp;                   /* system process table */
-  register struct rprocpub *rpub;              /* public entry */
-  int slot_nr;                                 /* local table entry */
-  int arg_count;                               /* number of arguments */
-  char *cmd_ptr;                               /* parse command string */
-  char *label;                                 /* unique name of command */
-  enum dev_style dev_style;                    /* device style */
-  int s;                                       /* status variable */
-  int len;                                     /* length of string */
-  int i;
-  int r;
-  endpoint_t ep;
-  struct rproc *tmp_rp;
-  struct rprocpub *tmp_rpub;
-  struct rs_start rs_start;
-
-  /* This call requires special privileges. */
-  if (!caller_is_root(m_ptr->m_source)) return(EPERM);
+  struct rprocpub *rpub;
+  int arg_count;
+  int len;
+  char *cmd_ptr;
 
-  /* See if there is a free entry in the table with system processes. */
-  for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
-      rp = &rproc[slot_nr];                    /* get pointer to slot */
-      if (!(rp->r_flags & RS_IN_USE))          /* check if available */
-         break;
-  }
-  if (slot_nr >= NR_SYS_PROCS)
-  {
-      printf("RS: do_up: system process table full\n");
-       return ENOMEM;
-  }
   rpub = rp->r_pub;
 
-  /* Ok, there is space. Get the request structure. */
-  s= sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR, 
-       SELF, (vir_bytes) &rs_start, sizeof(rs_start));
-  if (s != OK) return(s);
-
-  /* Obtain command name and parameters. This is a space-separated string
-   * that looks like "/sbin/service arg1 arg2 ...". Arguments are optional.
-   */
-  if (rs_start.rss_cmdlen > MAX_COMMAND_LEN-1) return(E2BIG);
-  s=sys_datacopy(m_ptr->m_source, (vir_bytes) rs_start.rss_cmd, 
-       SELF, (vir_bytes) rp->r_cmd, rs_start.rss_cmdlen);
-  if (s != OK) return(s);
-  rp->r_cmd[rs_start.rss_cmdlen] = '\0';       /* ensure it is terminated */
-  if (rp->r_cmd[0] != '/') return(EINVAL);     /* insist on absolute path */
-
   /* Build argument vector to be passed to execute call. The format of the
    * arguments vector is: path, arguments, NULL. 
    */
+  strcpy(rp->r_args, rp->r_cmd);               /* copy raw command */
   arg_count = 0;                               /* initialize arg count */
-  rp->r_argv[arg_count++] = rp->r_cmd;         /* start with path */
-  cmd_ptr = rp->r_cmd;                         /* do some parsing */ 
+  rp->r_argv[arg_count++] = rp->r_args;                /* start with path */
+  cmd_ptr = rp->r_args;                                /* do some parsing */ 
   while(*cmd_ptr != '\0') {                    /* stop at end of string */
       if (*cmd_ptr == ' ') {                   /* next argument */
           *cmd_ptr = '\0';                     /* terminate previous */
@@ -209,7 +188,7 @@ message *m_ptr;                                     /* request message pointer */
   rp->r_argv[arg_count] = NULL;                        /* end with NULL pointer */
   rp->r_argc = arg_count;
   
-  /* Process name for the service. */
+  /* Build process name. */
   cmd_ptr = strrchr(rp->r_argv[0], '/');
   if (cmd_ptr)
        cmd_ptr++;
@@ -220,1285 +199,1337 @@ message *m_ptr;                                       /* request message pointer */
        len= RS_MAX_LABEL_LEN-1;        /* truncate name */
   memcpy(rpub->proc_name, cmd_ptr, len);
   rpub->proc_name[len]= '\0';
-  if(rs_verbose)
-      printf("RS: do_up: using proc_name (from binary %s) '%s'\n",
-          rp->r_argv[0], rpub->proc_name);
-
-  if(rs_start.rss_label.l_len > 0) {
-       /* RS_UP caller has supplied a custom label for this service. */
-       int s = copy_label(m_ptr->m_source, &rs_start.rss_label,
-               rpub->label, sizeof(rpub->label));
-       if(s != OK)
-               return s;
-        if(rs_verbose)
-         printf("RS: do_up: using label (custom) '%s'\n", rpub->label);
-  } else {
-       /* Default label for the service. */
-       label = rpub->proc_name;
-       len= strlen(label);
-       memcpy(rpub->label, label, len);
-       rpub->label[len]= '\0';
-        if(rs_verbose)
-          printf("RS: do_up: using label (from proc_name) '%s'\n",
-               rpub->label);
-  }
-
-  if(rs_start.rss_nr_control > 0) {
-       int i, s;
-       if (rs_start.rss_nr_control > RS_NR_CONTROL)
-       {
-               printf("RS: do_up: too many control labels\n");
-               return EINVAL;
-       }
-       for (i=0; i<rs_start.rss_nr_control; i++) {
-               s = copy_label(m_ptr->m_source, &rs_start.rss_control[i],
-                       rp->r_control[i], sizeof(rp->r_control[i]));
-               if(s != OK)
-                       return s;
-       }
-       rp->r_nr_control = rs_start.rss_nr_control;
+}
 
-       if (rs_verbose) {
-               printf("RS: do_up: control labels:");
-               for (i=0; i<rp->r_nr_control; i++)
-                       printf(" %s", rp->r_control[i]);
-               printf("\n");
-       }
-  }
+/*===========================================================================*
+ *                              srv_fork                                    *
+ *===========================================================================*/
+PUBLIC pid_t srv_fork()
+{
+  message m;
 
-  /* Check for duplicates */
-  for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
-      tmp_rp = &rproc[slot_nr];                        /* get pointer to slot */
-      if (!(tmp_rp->r_flags & RS_IN_USE))      /* check if available */
-         continue;
-      if (tmp_rp == rp)
-         continue;                             /* Our slot */
-      tmp_rpub = tmp_rp->r_pub;
-      if (strcmp(tmp_rpub->label, rpub->label) == 0)
-      {
-         printf("RS: found duplicate label '%s': slot %d\n",
-               rpub->label, slot_nr);
-         return EBUSY;
-      }
-  }
+  return(_syscall(PM_PROC_NR, SRV_FORK, &m));
+}
 
-  rp->r_script[0]= '\0';
-  if (rs_start.rss_scriptlen > MAX_SCRIPT_LEN-1) return(E2BIG);
-  if (rs_start.rss_script != NULL)
-  {
-         s=sys_datacopy(m_ptr->m_source, (vir_bytes) rs_start.rss_script, 
-               SELF, (vir_bytes) rp->r_script, rs_start.rss_scriptlen);
-         if (s != OK) return(s);
-         rp->r_script[rs_start.rss_scriptlen] = '\0';
-  }
-  rp->r_uid= rs_start.rss_uid;
-  rp->r_nice= rs_start.rss_nice;
+/*===========================================================================*
+ *                              srv_kill                                    *
+ *===========================================================================*/
+PUBLIC int srv_kill(pid_t pid, int sig)
+{
+  message m;
 
-  if (rs_start.rss_flags & RSS_IPC_VALID)
-  {
-       if (rs_start.rss_ipclen+1 > sizeof(rp->r_ipc_list))
-       {
-               printf("rs: ipc list too long for '%s'\n", rpub->label);
-               return EINVAL;
-       }
-       s=sys_datacopy(m_ptr->m_source, (vir_bytes) rs_start.rss_ipc, 
-               SELF, (vir_bytes) rp->r_ipc_list, rs_start.rss_ipclen);
-       if (s != OK) return(s);
-       rp->r_ipc_list[rs_start.rss_ipclen]= '\0';
-  }
-  else
-       rp->r_ipc_list[0]= '\0';
+  m.m1_i1 = pid;
+  m.m1_i2 = sig;
+  return(_syscall(PM_PROC_NR, SRV_KILL, &m));
+}
 
-  rpub->sys_flags = DSRV_SF;
-  rp->r_exec= NULL;
-  if (rs_start.rss_flags & RSS_COPY) {
-       int exst_cpy;
-       struct rproc *rp2;
-       struct rprocpub *rpub2;
-       exst_cpy = 0;
-       
-       if(rs_start.rss_flags & RSS_REUSE) {
-                int i;
+/*===========================================================================*
+ *                             update_period                                *
+ *===========================================================================*/
+PUBLIC void update_period(message *m_ptr)
+{
+  clock_t now = m_ptr->NOTIFY_TIMESTAMP;
+  short has_update_timed_out;
+  message m;
+  struct rprocpub *rpub;
 
-                for(i = 0; i < NR_SYS_PROCS; i++) {
-                       rp2 = &rproc[i];
-                       rpub2 = rproc[i].r_pub;
-                        if(strcmp(rpub->proc_name, rpub2->proc_name) == 0 &&
-                           (rpub2->sys_flags & SF_USE_COPY)) {
-                                /* We have found the same binary that's
-                                 * already been copied */
-                                 exst_cpy = 1;
-                                 break;
-                        }
-                }
-         }                
+  rpub = rupdate.rp->r_pub;
 
-       if(!exst_cpy)
-               s = read_exec(rp);
-       else
-               s = share_exec(rp, rp2);
+  /* See if a timeout has occurred. */
+  has_update_timed_out = (now - rupdate.prepare_tm > rupdate.prepare_maxtime);
 
-       if (s != OK)
-               return s;
+  /* If an update timed out, end the update process and notify
+   * the old version that the update has been canceled. From now on, the old
+   * version will continue executing.
+   */
+  if(has_update_timed_out) {
+      printf("RS: update failed: maximum prepare time reached\n");
+      end_update(EINTR);
 
-       rpub->sys_flags |= SF_USE_COPY;
+      /* Prepare cancel request. */
+      m.m_type = RS_LU_PREPARE;
+      m.RS_LU_STATE = SEF_LU_STATE_NULL;
+      asynsend(rpub->endpoint, &m);
   }
+}
 
-  /* All dynamically created services get the same privilege flags, and
-   * allowed traps. Other privilege settings can be specified at runtime.
-   * The privilege id is dynamically allocated by the kernel.
-   */
-  rp->r_priv.s_flags = DSRV_F;           /* privilege flags */
-  rp->r_priv.s_trap_mask = DSRV_T;       /* allowed traps */
+/*===========================================================================*
+ *                             end_update                                   *
+ *===========================================================================*/
+PUBLIC void end_update(int result)
+{
+/* End the update process. There are two possibilities:
+ * 1) the update succeeded. In that case, cleanup the old version and mark the
+ *    new version as no longer under update.
+ * 2) the update failed. In that case, cleanup the new version and mark the old
+ *    version as no longer under update. Eventual late ready to update
+ *    messages (if any) will simply be ignored and the service can
+ *    continue executing. In addition, reset the check timestamp, so that if the
+ *    service has a period, a status request will be forced in the next period.
+ */
+  struct rproc *old_rp, *new_rp, *exiting_rp, *surviving_rp;
+  message m;
 
-  /* Copy granted resources */
-  if (rs_start.rss_nr_irq > NR_IRQ)
-  {
-       printf("RS: do_up: too many IRQs requested\n");
-       return EINVAL;
-  }
-  rp->r_priv.s_nr_irq= rs_start.rss_nr_irq;
-  for (i= 0; i<rp->r_priv.s_nr_irq; i++)
-  {
-       rp->r_priv.s_irq_tab[i]= rs_start.rss_irq[i];
-       if(rs_verbose)
-               printf("RS: do_up: IRQ %d\n", rp->r_priv.s_irq_tab[i]);
-  }
+  old_rp = rupdate.rp;
+  new_rp = old_rp->r_new_rp;
 
-  if (rs_start.rss_nr_io > NR_IO_RANGE)
-  {
-       printf("RS: do_up: too many I/O ranges requested\n");
-       return EINVAL;
-  }
-  rp->r_priv.s_nr_io_range= rs_start.rss_nr_io;
-  for (i= 0; i<rp->r_priv.s_nr_io_range; i++)
-  {
-       rp->r_priv.s_io_tab[i].ior_base= rs_start.rss_io[i].base;
-       rp->r_priv.s_io_tab[i].ior_limit=
-               rs_start.rss_io[i].base+rs_start.rss_io[i].len-1;
-       if(rs_verbose)
-          printf("RS: do_up: I/O [%x..%x]\n",
-               rp->r_priv.s_io_tab[i].ior_base,
-               rp->r_priv.s_io_tab[i].ior_limit);
-  }
+  if(rs_verbose)
+      printf("RS: ending update from %s to %s with result: %d\n",
+          srv_to_string(old_rp), srv_to_string(new_rp), result);
 
-  if (rs_start.rss_nr_pci_id > RS_NR_PCI_DEVICE)
-  {
-       printf("RS: do_up: too many PCI device IDs\n");
-       return EINVAL;
-  }
-  rpub->pci_acl.rsp_nr_device = rs_start.rss_nr_pci_id;
-  for (i= 0; i<rpub->pci_acl.rsp_nr_device; i++)
-  {
-       rpub->pci_acl.rsp_device[i].vid= rs_start.rss_pci_id[i].vid;
-       rpub->pci_acl.rsp_device[i].did= rs_start.rss_pci_id[i].did;
-       if(rs_verbose)
-          printf("RS: do_up: PCI %04x/%04x\n",
-               rpub->pci_acl.rsp_device[i].vid,
-               rpub->pci_acl.rsp_device[i].did);
-  }
-  if (rs_start.rss_nr_pci_class > RS_NR_PCI_CLASS)
-  {
-       printf("RS: do_up: too many PCI class IDs\n");
-       return EINVAL;
-  }
-  rpub->pci_acl.rsp_nr_class= rs_start.rss_nr_pci_class;
-  for (i= 0; i<rpub->pci_acl.rsp_nr_class; i++)
-  {
-       rpub->pci_acl.rsp_class[i].class= rs_start.rss_pci_class[i].class;
-       rpub->pci_acl.rsp_class[i].mask= rs_start.rss_pci_class[i].mask;
-       if(rs_verbose)
-           printf("RS: do_up: PCI class %06x mask %06x\n",
-               rpub->pci_acl.rsp_class[i].class,
-               rpub->pci_acl.rsp_class[i].mask);
-  }
+  /* Decide which version has to die out and which version has to survive. */
+  surviving_rp = (result == OK ? new_rp : old_rp);
+  exiting_rp =   (result == OK ? old_rp : new_rp);
 
-  /* Copy 'system' call number bits */
-  if (sizeof(rs_start.rss_system[0]) == sizeof(rp->r_call_mask[0]) &&
-       sizeof(rs_start.rss_system) == sizeof(rp->r_call_mask))
-  {
-       for (i= 0; i<RS_SYS_CALL_MASK_SIZE; i++)
-               rp->r_call_mask[i]= rs_start.rss_system[i];
-  }
-  else
-  {
-       printf(
-       "RS: do_up: internal inconsistency: bad size of r_call_mask\n");
-       memset(rp->r_call_mask, '\0', sizeof(rp->r_call_mask));
-  }
+  /* End update. */
+  rupdate.flags &= ~RS_UPDATING;
+  rupdate.rp = NULL;
+  old_rp->r_new_rp = NULL;
+  new_rp->r_old_rp = NULL;
+  old_rp->r_check_tm = 0;
 
-  /* Initialize some fields. */
-  rpub->period = rs_start.rss_period;
-  rpub->dev_nr = rs_start.rss_major;
-  rpub->dev_style = STYLE_DEV; 
-  rp->r_restarts = -1;                                 /* will be incremented */
-  rp->r_set_resources= 1;                      /* set resources */
+  /* Make the version that has to survive as active. */
+  activate_service(surviving_rp, exiting_rp);
 
-  if (sizeof(rpub->vm_call_mask) == sizeof(rs_start.rss_vm) &&
-      sizeof(rpub->vm_call_mask[0]) == sizeof(rs_start.rss_vm[0]))
-  {
-          int basic_vmc[] =  { VM_BASIC_CALLS, SYS_NULL_C };
-         memcpy(rpub->vm_call_mask, rs_start.rss_vm,
-               sizeof(rpub->vm_call_mask));
-         fill_call_mask(basic_vmc, NR_VM_CALLS,
-               rpub->vm_call_mask, VM_RQ_BASE, FALSE);
-  }
-  else
-  {
-         printf("RS: internal inconsistency: bad size of vm_call_mask\n");
-         memset(rpub->vm_call_mask, '\0', sizeof(rpub->vm_call_mask));
-  }
+  /* Send a late reply if necessary. */
+  late_reply(old_rp, result);
 
-  /* All information was gathered. Now try to start the system service. */
-  r = start_service(rp, 0, &ep);
-  m_ptr->RS_ENDPOINT = ep;
-  return r;
-}
+  /* Unpublish and cleanup the version that has to die out and mark the other
+   * version as no longer updating.
+   */
+  surviving_rp->r_flags &= ~RS_UPDATING;
+  unpublish_process(exiting_rp);
+  cleanup_service(exiting_rp);
 
+  if(rs_verbose)
+      printf("RS: service %s ended the update\n", srv_to_string(surviving_rp));
+}
 
 /*===========================================================================*
- *                             do_down                                      *
+ *                          kill_service_debug                              *
  *===========================================================================*/
-PUBLIC int do_down(message *m_ptr)
+PUBLIC int kill_service_debug(file, line, rp, errstr, err)
+char *file;
+int line;
+struct rproc *rp;
+char *errstr;
+int err;
 {
-  register struct rproc *rp;
-  register struct rprocpub *rpub;
-  size_t len;
-  int s, proc;
-  char label[RS_MAX_LABEL_LEN];
+/* Crash a system service and don't let it restart. */
+  struct rprocpub *rpub;
 
-  /* This call requires special privileges. */
-  if (!caller_is_root(m_ptr->m_source)) return(EPERM);
+  if(errstr && !shutting_down) {
+      printf("RS: %s (error %d)\n", errstr, err);
+  }
+  rp->r_flags |= RS_EXITING;                           /* expect exit */
+  crash_service_debug(file, line, rp);                 /* simulate crash */
 
-  len= m_ptr->RS_CMD_LEN;
-  if (len >= sizeof(label))
-       return EINVAL;          /* Too long */
+  return err;
+}
 
-  s= sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR, 
-       SELF, (vir_bytes) label, len);
-  if (s != OK) return(s);
-  label[len]= '\0';
+/*===========================================================================*
+ *                         crash_service_debug                              *
+ *===========================================================================*/
+PUBLIC int crash_service_debug(file, line, rp)
+char *file;
+int line;
+struct rproc *rp;
+{
+/* Simluate a crash in a system service. */
+  struct rprocpub *rpub;
 
-  for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
-      rpub = rp->r_pub;
-      if (rp->r_flags & RS_IN_USE && strcmp(rpub->label, label) == 0) {
-       /* Core system services should never go down. */
-       if (rpub->sys_flags & SF_CORE_SRV) return(EPERM);
+  rpub = rp->r_pub;
 
-       if(rs_verbose)
-         printf("RS: stopping '%s' (%d)\n", label, rp->r_pid);
-       stop_service(rp,RS_EXITING);
-       if (rp->r_pid == -1)
-       {
-               /* Process is already gone, release slot. */
-               free_slot(rp);
-               return(OK);
-       }
+  if(rs_verbose)
+      printf("RS: %s %skilled at %s:%d\n", srv_to_string(rp),
+          rp->r_flags & RS_EXITING ? "lethally " : "", file, line);
 
-       /* Late reply - send a reply when process dies. */
-       rp->r_flags |= RS_LATEREPLY;
-       rp->r_caller = m_ptr->m_source;
-       return EDONTREPLY;
-      }
-  }
-  if(rs_verbose) printf("RS: do_down: '%s' not found\n", label);
-  return(ESRCH);
+  return sys_kill(rpub->endpoint, SIGKILL);
 }
 
-
 /*===========================================================================*
- *                             do_restart                                   *
+ *                       cleanup_service_debug                              *
  *===========================================================================*/
-PUBLIC int do_restart(message *m_ptr)
+PUBLIC void cleanup_service_debug(file, line, rp)
+char *file;
+int line;
+struct rproc *rp;
 {
-  register struct rproc *rp;
-  register struct rprocpub *rpub;
-  size_t len;
-  int s, proc, r;
-  char label[RS_MAX_LABEL_LEN];
-  endpoint_t ep;
+/* Ask PM to exit the service and free slot. */
+  struct rprocpub *rpub;
 
-  len= m_ptr->RS_CMD_LEN;
-  if (len >= sizeof(label))
-       return EINVAL;          /* Too long */
+  rpub = rp->r_pub;
 
-  s= sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR, 
-       SELF, (vir_bytes) label, len);
-  if (s != OK) return(s);
-  label[len]= '\0';
+  if(rs_verbose)
+      printf("RS: %s cleaned up at %s:%d\n", srv_to_string(rp),
+          file, line);
 
-  /* This call requires special privileges. */
-  if (! (caller_can_control(m_ptr->m_source, label) ||
-               caller_is_root(m_ptr->m_source))) {
+  if(rp->r_pid == -1) {
+      printf("RS: warning: attempt to kill pid -1!\n");
+  }
+  else {
+      srv_kill(rp->r_pid, SIGKILL);
+  }
+
+  free_slot(rp);
+}
+
+/*===========================================================================*
+ *                             create_service                               *
+ *===========================================================================*/
+PUBLIC int create_service(rp)
+struct rproc *rp;
+{
+/* Create the given system service. */
+  int child_proc_nr_e, child_proc_nr_n;                /* child process slot */
+  pid_t child_pid;                             /* child's process id */
+  char *file_only;
+  int s, use_copy, slot_nr;
+  bitchunk_t *vm_mask;
+  message m;
+  extern char **environ;
+  char * null_env = NULL;
+  struct rprocpub *rpub;
+
+  rpub = rp->r_pub;
+  use_copy= (rpub->sys_flags & SF_USE_COPY);
+
+  /* See if we are not using a copy but we do need one to start the service. */
+  if(!use_copy && (rpub->sys_flags & SF_NEED_COPY)) {
+       printf("RS: unable to start service '%s' without an in-memory copy\n",
+           rpub->label);
+       free_slot(rp);
        return(EPERM);
   }
 
-  for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
-      rpub = rp->r_pub;
-      if ((rp->r_flags & RS_IN_USE) && strcmp(rpub->label, label) == 0) {
-         if(rs_verbose) printf("RS: restarting '%s' (%d)\n", label, rp->r_pid);
-         if (rp->r_pid >= 0)
-         {
-               if(rs_verbose)
-                 printf("RS: do_restart: '%s' is (still) running, pid = %d\n",
-                       rp->r_pid);
-               return EBUSY;
-         }
-         rp->r_flags &= ~(RS_REFRESHING|RS_NOPINGREPLY);
-         r = start_service(rp, 0, &ep);        
-         if (r != OK) printf("do_restart: start_service failed: %d\n", r);
-         m_ptr->RS_ENDPOINT = ep;
-         return(r);
+  /* Now fork and branch for parent and child process (and check for error). */
+  if(rs_verbose)
+      printf("RS: forking child with srv_fork()...\n");
+  child_pid= srv_fork();
+  if(child_pid == -1) {
+      printf("RS: srv_fork() failed (error %d)\n", errno);
+      free_slot(rp);
+      return(errno);
+  }
+
+  /* Get endpoint of the child. */
+  child_proc_nr_e = getnprocnr(child_pid);
+
+  /* There is now a child process. Update the system process table. */
+  child_proc_nr_n = _ENDPOINT_P(child_proc_nr_e);
+  rp->r_flags = RS_IN_USE;                     /* mark slot in use */
+  rp->r_restarts += 1;                         /* raise nr of restarts */
+  rp->r_old_rp = NULL;                         /* no old version yet */
+  rp->r_new_rp = NULL;                         /* no new version yet */
+  rp->r_prev_rp = NULL;                                /* no prev replica yet */
+  rp->r_next_rp = NULL;                                /* no next replica yet */
+  rpub->endpoint = child_proc_nr_e;            /* set child endpoint */
+  rp->r_pid = child_pid;                       /* set child pid */
+  rp->r_check_tm = 0;                          /* not checked yet */
+  getuptime(&rp->r_alive_tm);                  /* currently alive */
+  rp->r_stop_tm = 0;                           /* not exiting yet */
+  rp->r_backoff = 0;                           /* not to be restarted */
+  rproc_ptr[child_proc_nr_n] = rp;             /* mapping for fast access */
+  rpub->in_use = TRUE;                         /* public entry is now in use */
+
+
+  /* Set resources when asked to. */
+  if (rp->r_set_resources) {
+       /* Initialize privilege structure. */
+       init_privs(rp, &rp->r_priv);
+  }
+
+  /* Set and synch the privilege structure for the new service. */
+  if ((s = sys_privctl(child_proc_nr_e, SYS_PRIV_SET_SYS, &rp->r_priv)) != OK
+       || (s = sys_getpriv(&rp->r_priv, child_proc_nr_e)) != OK) {
+       panic("unable to set privilege structure: %d", s);
+  }
+
+  /* Copy the executable image into the child process. If this call
+   * fails, the child process may or may not be killed already. If it is
+   * not killed, it's blocked because of NO_PRIV. Kill it now either way.
+   * If no copy exists, allocate one and free it right after exec completes.
+   */
+  if(use_copy) {
+      if(rs_verbose)
+          printf("RS: %s uses an in-memory copy\n",
+              srv_to_string(rp));
+  }
+  else {
+      if ((s = read_exec(rp)) != OK) {
+       return kill_service(rp, "read_exec failed", s);
       }
   }
-  if(rs_verbose) {
-      printf("RS: do_restart: '%s' not found\n", label);
+  if(rs_verbose)
+      printf("RS: execing child with srv_execve()...\n");
+  s = srv_execve(child_proc_nr_e, rp->r_exec, rp->r_exec_len, rp->r_argv,
+       environ);
+
+  if (s != OK) {
+       return kill_service(rp, "srv_execve failed", s);
   }
-  
-  return(ESRCH);
-}
+  if(!use_copy) {
+       free_exec(rp);
+  }
+
+  /* The purpose of non-blocking forks is to avoid involving VFS in the forking
+   * process, because VFS may be blocked on a sendrec() to a MFS that is
+   * waiting for a endpoint update for a dead driver. We have just published
+   * that update, but VFS may still be blocked. As a result, VFS may not yet
+   * have received PM's fork message. Hence, if we call mapdriver()
+   * immediately, VFS may not know about the process and thus refuse to add the
+   * driver entry. The following temporary hack works around this by forcing
+   * blocking communication from PM to VFS. Once VFS has been made non-blocking
+   * towards MFS instances, this hack and the big part of srv_fork() can go.
+   */
+  setuid(0);
+
+  if(rs_verbose)
+      printf("RS: %s created\n", srv_to_string(rp));
 
+  return OK;
+}
 
 /*===========================================================================*
- *                             do_refresh                                   *
+ *                             publish_service                              *
  *===========================================================================*/
-PUBLIC int do_refresh(message *m_ptr)
+PUBLIC int publish_service(rp)
+struct rproc *rp;                              /* pointer to service slot */
 {
-  register struct rproc *rp;
-  register struct rprocpub *rpub;
-  size_t len;
-  int s;
-  char label[RS_MAX_LABEL_LEN];
-
-  len= m_ptr->RS_CMD_LEN;
-  if (len >= sizeof(label))
-       return EINVAL;          /* Too long */
+/* Publish service-wide properties of a service. */
+  int r;
+  struct rprocpub *rpub;
 
-  s= sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR, 
-       SELF, (vir_bytes) label, len);
-  if (s != OK) return(s);
-  label[len]= '\0';
+  rpub = rp->r_pub;
 
-  /* This call requires special privileges. */
-  if (! (caller_can_control(m_ptr->m_source, label) ||
-               caller_is_root(m_ptr->m_source))) {
-       return(EPERM);
+  /* Register label with DS. */
+  r = ds_publish_label(rpub->label, rpub->endpoint, DSF_OVERWRITE);
+  if (r != OK) {
+      return kill_service(rp, "ds_publish_label call failed", r);
   }
 
-  for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
-      rpub = rp->r_pub;
-      if (rp->r_flags & RS_IN_USE && strcmp(rpub->label, label) == 0) {
-          /* Only system processes not including RS can refresh. */
-          if(!(rp->r_priv.s_flags & SYS_PROC) || rpub->endpoint == RS_PROC_NR) {
-              return EPERM;
-          }
+  if(rs_verbose)
+      printf("RS: %s service-wide properties published\n",
+          srv_to_string(rp));
 
-          if(rs_verbose) {
-              printf("RS: refreshing %s (%d)\n", rpub->label, rp->r_pid);
-          }
-         stop_service(rp,RS_REFRESHING);
-         return(OK);
+  return OK;
+}
+
+/*===========================================================================*
+ *                             publish_process                              *
+ *===========================================================================*/
+PUBLIC int publish_process(rp)
+struct rproc *rp;                              /* pointer to service slot */
+{
+/* Publish process-wide properties of a service. */
+  int r;
+  struct rprocpub *rpub;
+  struct rs_pci pci_acl;
+
+  rpub = rp->r_pub;
+
+  /* If PCI properties are set, inform the PCI driver about the new service. */
+  if(rpub->pci_acl.rsp_nr_device || rpub->pci_acl.rsp_nr_class) {
+      pci_acl = rpub->pci_acl;
+      strcpy(pci_acl.rsp_label, rpub->label);
+      pci_acl.rsp_endpoint= rpub->endpoint;
+
+      r = pci_set_acl(&pci_acl);
+      if (r != OK) {
+          return kill_service(rp, "pci_set_acl call failed", r);
       }
   }
-  if(rs_verbose) {
-      printf("RS: do_refresh: '%s' not found\n", label);
+
+  /* Tell VM about allowed calls, if any. */
+  if(rpub->vm_call_mask[0]) {
+      r = vm_set_priv(rpub->endpoint, &rpub->vm_call_mask[0]);
+      if (r != OK) {
+          return kill_service(rp, "vm_set_priv call failed", r);
+      }
   }
-  
-  return(ESRCH);
+
+  if(rs_verbose)
+      printf("RS: %s process-wide properties published\n",
+          srv_to_string(rp));
+
+  return OK;
 }
 
 /*===========================================================================*
- *                             do_shutdown                                  *
+ *                           unpublish_service                              *
  *===========================================================================*/
-PUBLIC int do_shutdown(message *m_ptr)
+PUBLIC int unpublish_service(rp)
+struct rproc *rp;                              /* pointer to service slot */
 {
-  /* This call requires special privileges. */
-  if (m_ptr != NULL && !caller_is_root(m_ptr->m_source)) return(EPERM);
+/* Unpublish service-wide properties of a service. */
+  struct rprocpub *rpub;
+  int r, result;
 
-  /* Set flag so that RS server knows services shouldn't be restarted. */
-  shutting_down = TRUE;
-  return(OK);
-}
+  rpub = rp->r_pub;
+  result = OK;
 
+  /* Unregister label with DS. */
+  r = ds_delete_label(rpub->label);
+  if (r != OK && !shutting_down) {
+     printf("RS: ds_delete_label call failed (error %d)\n", r);
+     result = r;
+  }
+
+  /* No need to inform VFS, cleanup is performed on exit automatically. */
+
+  if(rs_verbose)
+      printf("RS: %s service-wide properties unpublished\n",
+          srv_to_string(rp));
+
+  return result;
+}
 
 /*===========================================================================*
- *                             do_init_ready                                *
+ *                         unpublish_process                                *
  *===========================================================================*/
-PUBLIC int do_init_ready(message *m_ptr)
+PUBLIC int unpublish_process(rp)
+struct rproc *rp;                              /* pointer to service slot */
 {
-  int who_p;
-  struct rproc *rp;
+/* Unpublish process-wide properties of a service. */
   struct rprocpub *rpub;
-  int result;
+  int r, result;
 
-  who_p = _ENDPOINT_P(m_ptr->m_source);
-  rp = rproc_ptr[who_p];
   rpub = rp->r_pub;
-  result = m_ptr->RS_INIT_RESULT;
+  result = OK;
 
-  /* Make sure the originating service was requested to initialize. */
-  if(! (rp->r_flags & RS_INITIALIZING) ) {
-      if(rs_verbose) {
-          printf("RS: do_init_ready: got unexpected init ready msg from %d\n",
-              m_ptr->m_source);
+  /* If PCI properties are set, inform the PCI driver. */
+  if(rpub->pci_acl.rsp_nr_device || rpub->pci_acl.rsp_nr_class) {
+      r = pci_del_acl(rpub->endpoint);
+      if (r != OK && !shutting_down) {
+          printf("RS: pci_del_acl call failed (error %d)\n", r);
+          result = r;
       }
-      return(EINVAL);
   }
 
-  /* Mark the slot as no longer initializing. */
-  rp->r_flags &= ~RS_INITIALIZING;
-  rp->r_check_tm = 0;
-  getuptime(&rp->r_alive_tm);
+  /* No need to inform VM, cleanup is performed on exit automatically. */
 
-  /* Check if something went wrong and the service failed to init.
-   * In that case, kill it and make sure it won't be restarted.
-   */
-  if(result != OK) {
-      if(rs_verbose)
-          printf("RS: initialization failed for service %d: %d\n",
-              rpub->endpoint, result);
-      rp->r_flags |= RS_EXITING;
-      kill(rp->r_pid, SIGKILL);
+  if(rs_verbose)
+      printf("RS: %s process-wide properties unpublished\n",
+          srv_to_string(rp));
+
+  return result;
+}
+
+/*===========================================================================*
+ *                             run_service                                  *
+ *===========================================================================*/
+PUBLIC int run_service(rp, init_type)
+struct rproc *rp;
+int init_type;
+{
+/* Let a newly created service run. */
+  int s, use_copy;
+  struct rprocpub *rpub;
+
+  rpub = rp->r_pub;
+  use_copy= (rpub->sys_flags & SF_USE_COPY);
+
+  /* Allow the service to run. */
+  if ((s = sys_privctl(rpub->endpoint, SYS_PRIV_ALLOW, NULL)) != OK) {
+      return kill_service(rp, "unable to allow the service to run",s);
   }
-  else {
-      if(rs_verbose)
-          printf("RS: initialization succeeded for service %d\n",
-              rpub->endpoint);
+
+  /* Initialize service. */
+  if((s = init_service(rp, init_type)) != OK) {
+      return kill_service(rp, "unable to initialize service", s);
   }
 
-  return(EDONTREPLY);
+  if(rs_verbose)
+      printf("RS: %s allowed to run\n", srv_to_string(rp));
+
+  return OK;
 }
 
 /*===========================================================================*
- *                             do_update                                    *
+ *                             start_service                                *
  *===========================================================================*/
-PUBLIC int do_update(message *m_ptr)
+PUBLIC int start_service(rp)
+struct rproc *rp;
 {
-  register struct rproc *rp;
-  register struct rprocpub *rpub;
-  size_t len;
-  int s;
-  char label[RS_MAX_LABEL_LEN];
-  int lu_state;
-  int prepare_maxtime;
-
-  /* Retrieve label. */
-  len= m_ptr->RS_CMD_LEN;
-  if (len >= sizeof(label))
-      return EINVAL;           /* Too long */
-  s= sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR, 
-      SELF, (vir_bytes) label, len);
-  if (s != OK) return(s);
-  label[len]= '\0';
+/* Start a system service. */
+  int r, init_type;
+  struct rprocpub *rpub;
 
-  /* This call requires special privileges. */
-  if (! (caller_can_control(m_ptr->m_source, label) ||
-      caller_is_root(m_ptr->m_source))) {
-      return(EPERM);
-  }
+  rpub = rp->r_pub;
 
-  /* Retrieve live update state. */
-  lu_state = m_ptr->RS_LU_STATE;
-  if(lu_state == SEF_LU_STATE_NULL) {
-      return(EINVAL);
+  /* Create. */
+  r = create_service(rp);
+  if(r != OK) {
+      return r;
   }
 
-  /* Retrieve prepare max time. */
-  prepare_maxtime = m_ptr->RS_LU_PREPARE_MAXTIME;
-  if(prepare_maxtime) {
-      if(prepare_maxtime < 0 || prepare_maxtime > RS_MAX_PREPARE_MAXTIME) {
-          return(EINVAL);
-      }
+  /* Publish service properties. */
+  r = publish_process(rp);
+  if (r != OK) {
+      return r;
   }
-  else {
-      prepare_maxtime = RS_DEFAULT_PREPARE_MAXTIME;
+  r = publish_service(rp);
+  if (r != OK) {
+      return r;
   }
 
-  /* Make sure we are not already updating. */
-  if(rupdate.flags & RS_UPDATING) {
-      if(rs_verbose) {
-         printf("RS: do_update: an update is already in progress");
-      }
-      return(EBUSY);
+  /* Run. */
+  init_type = rp->r_restarts > 0 ? SEF_INIT_RESTART : SEF_INIT_FRESH;
+  r = run_service(rp, init_type);
+  if(r != OK) {
+      return r;
   }
 
-  /* Try to start the update process. */
-  for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
-      rpub = rp->r_pub;
-      if (rp->r_flags & RS_IN_USE && strcmp(rpub->label, label) == 0) {
-          /* Only system processes not including RS can update. */
-          if(!(rp->r_priv.s_flags & SYS_PROC) || rpub->endpoint == RS_PROC_NR) {
-              return EPERM;
-          }
+  /* The system service now has been successfully started. The only thing
+   * that can go wrong now, is that execution fails at the child. If that's
+   * the case, the child will exit. 
+   */
+  if(rs_verbose)
+      printf("RS: %s started with major %d\n", srv_to_string(rp),
+          rpub->dev_nr);
 
-          if(rs_verbose) {
-             printf("RS: updating %s (%d)\n", rpub->label, rp->r_pid);
-         }
+  return OK;
+}
 
-         rp->r_flags |= RS_UPDATING;
-         rupdate.flags |= RS_UPDATING;
-         getuptime(&rupdate.prepare_tm);
-          rupdate.prepare_maxtime = prepare_maxtime;
-         rupdate.rp = rp;
+/*===========================================================================*
+ *                             stop_service                                 *
+ *===========================================================================*/
+PUBLIC void stop_service(struct rproc *rp,int how)
+{
+  struct rprocpub *rpub;
 
-         m_ptr->m_type = RS_LU_PREPARE;
-         asynsend(rpub->endpoint, m_ptr);  /* request to update */
+  rpub = rp->r_pub;
 
-         return(OK);
-      }
+  /* Try to stop the system service. First send a SIGTERM signal to ask the
+   * system service to terminate. If the service didn't install a signal 
+   * handler, it will be killed. If it did and ignores the signal, we'll
+   * find out because we record the time here and send a SIGKILL.
+   */
+  if(rs_verbose)
+      printf("RS: %s signaled with SIGTERM\n", srv_to_string(rp));
+
+  rp->r_flags |= how;                          /* what to on exit? */
+  sys_kill(rpub->endpoint, SIGTERM);           /* first try friendly */
+  getuptime(&rp->r_stop_tm);                   /* record current time */
+}
+
+/*===========================================================================*
+ *                             update_service                               *
+ *===========================================================================*/
+PUBLIC int update_service(src_rpp, dst_rpp)
+struct rproc **src_rpp;
+struct rproc **dst_rpp;
+{
+/* Update an existing service. */
+  int r;
+  struct rproc *src_rp;
+  struct rproc *dst_rp;
+  struct rprocpub *src_rpub;
+  struct rprocpub *dst_rpub;
+  int pid;
+  endpoint_t endpoint;
+
+  src_rp = *src_rpp;
+  dst_rp = *dst_rpp;
+  src_rpub = src_rp->r_pub;
+  dst_rpub = dst_rp->r_pub;
+
+  if(rs_verbose)
+      printf("RS: %s updating into %s\n",
+          srv_to_string(src_rp), srv_to_string(dst_rp));
+
+  /* Ask VM to swap the slots of the two processes and tell the kernel to
+   * do the same.
+   */
+  r = vm_update(src_rpub->endpoint, dst_rpub->endpoint);
+  if(r != OK) {
+      return r;
   }
-  if(rs_verbose) {
-      printf("RS: do_update: '%s' not found\n", label);
+
+  /* Swap slots here as well. */
+  pid = src_rp->r_pid;
+  endpoint = src_rpub->endpoint;
+  swap_slot(&src_rp, &dst_rp);
+
+  /* Reassign pids and endpoints. */
+  src_rp->r_pid = dst_rp->r_pid;
+  src_rp->r_pub->endpoint = dst_rp->r_pub->endpoint;
+  rproc_ptr[_ENDPOINT_P(src_rp->r_pub->endpoint)] = src_rp;
+  dst_rp->r_pid = pid;
+  dst_rp->r_pub->endpoint = endpoint;
+  rproc_ptr[_ENDPOINT_P(dst_rp->r_pub->endpoint)] = dst_rp;
+
+  /* Adjust input pointers. */
+  *src_rpp = src_rp;
+  *dst_rpp = dst_rp;
+
+  if(rs_verbose)
+      printf("RS: %s updated into %s\n",
+          srv_to_string(src_rp), srv_to_string(dst_rp));
+
+  return OK;
+}
+
+/*===========================================================================*
+ *                           activate_service                               *
+ *===========================================================================*/
+PUBLIC void activate_service(struct rproc *rp, struct rproc *ex_rp)
+{
+/* Activate a service instance and deactivate another one if requested. */
+
+  if(ex_rp && (ex_rp->r_flags & RS_ACTIVE) ) {
+      ex_rp->r_flags &= ~RS_ACTIVE;
+      if(rs_verbose)
+          printf("RS: %s becomes inactive\n", srv_to_string(ex_rp));
   }
 
-  return(ESRCH);
+  if(! (rp->r_flags & RS_ACTIVE) ) {
+      rp->r_flags |= RS_ACTIVE;
+      if(rs_verbose)
+          printf("RS: %s becomes active\n", srv_to_string(rp));
+  }
 }
 
 /*===========================================================================*
- *                             do_upd_ready                                 *
+ *                           terminate_service                              *
  *===========================================================================*/
-PUBLIC int do_upd_ready(message *m_ptr)
+PUBLIC void terminate_service(struct rproc *rp)
 {
-  register struct rproc *rp;
-  int who_p;
-  clock_t now = m_ptr->NOTIFY_TIMESTAMP;
-  int result;
+/* Handle a termination event for a system service. */
+  struct rproc **rps;
+  struct rprocpub *rpub;
+  int nr_rps;
+  int i, r;
 
-  who_p = _ENDPOINT_P(m_ptr->m_source);
-  rp = rproc_ptr[who_p];
-  result = m_ptr->RS_LU_RESULT;
+  rpub = rp->r_pub;
 
-  /* Make sure the originating service was requested to prepare for update. */
-  if(! (rp->r_flags & RS_UPDATING) ) {
-      if(rs_verbose) {
-          printf("RS: do_upd_ready: got unexpected update ready msg from %d\n",
-              m_ptr->m_source);
+  if(rs_verbose)
+     printf("RS: %s terminated\n", srv_to_string(rp));
+
+  /* Deal with failures during initialization. */
+  if(rp->r_flags & RS_INITIALIZING) {
+      printf("RS: service '%s' exited during initialization\n", rpub->label);
+      rp->r_flags |= RS_EXITING; /* don't restart. */
+
+      /* If updating, rollback. */
+      if(rp->r_flags & RS_UPDATING) {
+          message m;
+          struct rproc *old_rp, *new_rp;
+          printf("RS: update failed: state transfer failed. Rolling back...\n");
+          new_rp = rp;
+          old_rp = new_rp->r_old_rp;
+          new_rp->r_flags &= ~RS_INITIALIZING;
+          update_service(&new_rp, &old_rp); /* can't fail */
+          m.m_type = ERESTART;
+          reply(old_rp->r_pub->endpoint, &m);
+          end_update(ERESTART);
+          return;
       }
-      return(EINVAL);
   }
 
-  /* Check if something went wrong and the service failed to prepare
-   * for the update. In that case, end the update process.
-   */
-  if(result != OK) {
-      end_update(now);
-      switch(result) {
-          case EACCES:
-              printf("RS: update failed: %s\n",
-                  "service does not support live update");
-          break;
+  if (rp->r_flags & RS_EXITING) {
+      /* If a core system service is exiting, we are in trouble. */
+      if (rp->r_pub->sys_flags & SF_CORE_SRV && !shutting_down) {
+          panic("core system service died: %s", srv_to_string(rp));
+      }
 
-          case EINVAL:
-              printf("RS: update failed: %s\n",
-                  "service does not support the required state");
-          break;
+      /* See if a late reply has to be sent. */
+      r = (rp->r_caller_request == RS_DOWN ? OK : EDEADSRCDST);
+      late_reply(rp, r);
 
-          case EBUSY:
-              printf("RS: update failed: %s\n",
-                  "service is not able to prepare for the update now");
-          break;
+      /* Unpublish the service. */
+      unpublish_service(rp);
+      unpublish_process(rp);
 
-          case EGENERIC:
-              printf("RS: update failed: %s\n",
-                  "a generic error occurred while preparing for the update");
-          break;
+      /* Cleanup all the instances of the service. */
+      get_service_instances(rp, &rps, &nr_rps);
+      for(i=0;i<nr_rps;i++) {
+          cleanup_service(rps[i]);
+      }
+  }
+  else if(rp->r_flags & RS_REFRESHING) {
+      /* Restart service. */
+      restart_service(rp);
+  }
+  else {
+      /* If an update is in progress, end it. The old version
+       * that just exited will continue executing.
+       */
+      if(rp->r_flags & RS_UPDATING) {
+          if(! (rp->r_flags & RS_ACTIVE) ) {
+              return; /* ignore unexpected signals */
+          }
+          end_update(ERESTART);
+      }
 
-          default:
-              printf("RS: update failed: %s (%d)\n",
-                  "an unknown error occurred while preparing for the update\n",
-                  result);
-          break;
+      /* Determine what to do. If this is the first unexpected 
+       * exit, immediately restart this service. Otherwise use
+       * a binary exponential backoff.
+       */
+      if (rp->r_restarts > 0) {
+          rp->r_backoff = 1 << MIN(rp->r_restarts,(BACKOFF_BITS-2));
+          rp->r_backoff = MIN(rp->r_backoff,MAX_BACKOFF); 
+          if ((rpub->sys_flags & SF_USE_COPY) && rp->r_backoff > 1)
+              rp->r_backoff= 1;
+          return;
       }
 
-      return(OK);
+      /* Restart service. */
+      restart_service(rp);
   }
+}
 
-  /* Kill the process now and mark it for refresh, the new version will
-   * be automatically restarted.
-   */
-  rp->r_flags &= ~RS_EXITING;
-  rp->r_flags |= RS_REFRESHING;
-  kill(rp->r_pid, SIGKILL);
+/*===========================================================================*
+ *                           restart_service                                *
+ *===========================================================================*/
+PUBLIC void restart_service(rp)
+struct rproc *rp;
+{
+/* Restart service via a recovery script or directly. */
+  struct rproc *replica_rp;
+  int r;
+
+  /* See if a late reply has to be sent. */
+  late_reply(rp, OK);
 
-  return(EDONTREPLY);
+  if (rp->r_script[0] != '\0') {
+      /* Run a recovery script. */
+      run_script(rp);
+  }
+  else {
+      /* Unpublish the service. */
+      unpublish_service(rp);
+      unpublish_process(rp);
+
+      /* Clone slots. */
+      if((r = clone_slot(rp, &replica_rp)) != OK) {
+          kill_service(rp, "unable to clone service", r);
+          return;
+      }
+
+      if(rs_verbose)
+          printf("RS: %s restarting into %s\n",
+              srv_to_string(rp), srv_to_string(replica_rp));
+
+      /* Swap slots. */
+      swap_slot(&rp, &replica_rp);
+
+      /* Direct restart. */
+      if((r = start_service(replica_rp)) != OK) {
+          kill_service(rp, "unable to restart service", r);
+          return;
+      }
+
+      /* Link the two slots. */
+      rp->r_next_rp = replica_rp;
+      replica_rp->r_prev_rp = rp;
+
+      if(rs_verbose)
+          printf("RS: %s restarted into %s\n",
+              srv_to_string(rp), srv_to_string(replica_rp));
+  }
 }
 
 /*===========================================================================*
- *                             update_period                                *
+ *                      inherit_service_defaults                            *
  *===========================================================================*/
-PRIVATE void update_period(message *m_ptr)
+PUBLIC void inherit_service_defaults(def_rp, rp)
+struct rproc *def_rp;
+struct rproc *rp;
 {
-  clock_t now = m_ptr->NOTIFY_TIMESTAMP;
-  short has_update_timed_out;
-  message m;
+  struct rprocpub *def_rpub;
   struct rprocpub *rpub;
 
-  rpub = rupdate.rp->r_pub;
-
-  /* See if a timeout has occurred. */
-  has_update_timed_out = (now - rupdate.prepare_tm > rupdate.prepare_maxtime);
+  def_rpub = def_rp->r_pub;
+  rpub = rp->r_pub;
 
-  /* If an update timed out, end the update process and notify the service. */
-  if(has_update_timed_out) {
-      end_update(now);
-      printf("RS: update failed: maximum prepare time reached\n");
+  /* Device settings. These properties cannot change. */
+  rpub->dev_nr = def_rpub->dev_nr;
+  rpub->dev_style = def_rpub->dev_style;
 
-      /* Prepare cancel request. */
-      m.m_type = RS_LU_PREPARE;
-      m.RS_LU_STATE = SEF_LU_STATE_NULL;
-      asynsend(rpub->endpoint, &m);
+  /* Period. */
+  if(!rpub->period && def_rpub->period) {
+      rpub->period = def_rpub->period;
   }
 }
 
 /*===========================================================================*
- *                             end_update                                   *
+ *                        get_service_instances                             *
  *===========================================================================*/
-PRIVATE void end_update(clock_t now)
+PUBLIC void get_service_instances(rp, rps, length)
+struct rproc *rp;
+struct rproc ***rps;
+int *length;
 {
-  /* End the update process and mark the affected service as no longer under
-   * update. Eventual late ready to update message (if any) will simply be
-   * ignored and the service can continue executing.
-   * We reset the check timestamp, so that if the service has a period a status
-   * request will be forced in the next period.
-   */
-  rupdate.flags &= ~RS_UPDATING;
-  rupdate.rp->r_flags &= ~RS_UPDATING;
-  rupdate.rp->r_check_tm = 0;
+/* Retrieve all the service instances of a give service. */
+  static struct rproc *instances[5];
+  int nr_instances;
+
+  nr_instances = 0;
+  instances[nr_instances++] = rp;
+  if(rp->r_prev_rp) instances[nr_instances++] = rp->r_prev_rp;
+  if(rp->r_next_rp) instances[nr_instances++] = rp->r_next_rp;
+  if(rp->r_old_rp) instances[nr_instances++] = rp->r_old_rp;
+  if(rp->r_new_rp) instances[nr_instances++] = rp->r_new_rp;
+
+  *rps = instances;
+  *length = nr_instances;
 }
 
 /*===========================================================================*
- *                             do_exit                                      *
+ *                             share_exec                                   *
  *===========================================================================*/
-PUBLIC void do_exit(message *m_ptr)
+PUBLIC void share_exec(rp_dst, rp_src)
+struct rproc *rp_dst, *rp_src;
 {
-  register struct rproc *rp;
-  register struct rprocpub *rpub;
-  pid_t exit_pid;
-  int exit_status, r, slot_nr;
-  endpoint_t ep;
-  clock_t now = m_ptr->NOTIFY_TIMESTAMP;
-
-  if(rs_verbose)
-     printf("RS: got SIGCHLD signal, doing wait to get exited child.\n");
+  struct rprocpub *rpub_src;
+  struct rprocpub *rpub_dst;
 
-  /* See which child exited and what the exit status is. This is done in a
-   * loop because multiple children may have exited, all reported by one 
-   * SIGCHLD signal. The WNOHANG options is used to prevent blocking if, 
-   * somehow, no exited child can be found. 
-   */
-  while ( (exit_pid = waitpid(-1, &exit_status, WNOHANG)) != 0 ) {
-
-    if(rs_verbose) {
-#if 0
-      printf("RS: pid %d, ", exit_pid); 
-#endif
-      if (WIFSIGNALED(exit_status)) {
-#if 0
-          printf("killed, signal number %d\n", WTERMSIG(exit_status));
-#endif
-      } 
-      else if (WIFEXITED(exit_status)) {
-#if 0
-          printf("normal exit, status %d\n", WEXITSTATUS(exit_status));
-#endif
-      }
-    }
+  rpub_src = rp_src->r_pub;
+  rpub_dst = rp_dst->r_pub;
 
-       /* Read from the exec pipe */
-       for (;;)
-       {
-               r= read(exec_pipe[0], &slot_nr, sizeof(slot_nr));
-               if (r == -1)
-               {
-                       break;  /* No data */
-               }
-               if (r != sizeof(slot_nr))
-               {
-                       panic("do_exit: unaligned read from exec pipe: %d", r);
-               }
-               printf("do_exit: got slot %d\n", slot_nr);
-               if (slot_nr < 0 || slot_nr >= NR_SYS_PROCS)
-               {
-                       panic("do_exit: bad slot number from exec pipe: %d", slot_nr);
-               }
-               rp= &rproc[slot_nr];
-               rp->r_flags |= RS_EXITING;
-       }
+  if(rs_verbose)
+      printf("RS: %s shares exec image with %s\n",
+          srv_to_string(rp_dst), srv_to_string(rp_src));
 
-      /* Search the system process table to see who exited. 
-       * This should always succeed. 
-       */
-      for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
-          rpub = rp->r_pub;
-          if ((rp->r_flags & RS_IN_USE) && rp->r_pid == exit_pid) {
-             int proc;
-             proc = _ENDPOINT_P(rpub->endpoint);
-
-              rproc_ptr[proc] = NULL;          /* invalidate */
-             rp->r_pid= -1;
-
-             /* If PCI properties are set, inform the PCI driver. */
-              if(rpub->pci_acl.rsp_nr_device || rpub->pci_acl.rsp_nr_class) {
-                  pci_del_acl(rpub->endpoint);
-              }
-
-              if ((rp->r_flags & RS_EXITING) || shutting_down) {
-                 /* No reply sent to RS_DOWN yet. */
-                 if(rp->r_flags & RS_LATEREPLY) {
-                       message rsm;
-                       rsm.m_type = OK;
-                       send(rp->r_caller, &rsm);
-                 }
-
-                 /* Release slot. */
-                 free_slot(rp);
-             }
-             else if(rp->r_flags & RS_REFRESHING) {
-                     short is_updating = rp->r_flags & RS_UPDATING;
-
-                     /* Refresh */
-                     if (rp->r_script[0] != '\0')
-                       run_script(rp);
-                     else {
-                       start_service(rp, 0, &ep); /* direct restart */
-                       if(m_ptr)
-                               m_ptr->RS_ENDPOINT = ep;
-                     }
-
-                     /* If updating, end the update process. */
-                     if(is_updating) {
-                          end_update(now);
-                          printf("RS: update succeeded\n");
-                     }
-             }
-             else {
-                  /* Determine what to do. If this is the first unexpected 
-                  * exit, immediately restart this service. Otherwise use
-                  * a binary exponential backoff.
-                  */
-#if 0
-rp->r_restarts= 0;
-#endif
-                 if (WIFSIGNALED(exit_status)) {
-                       switch(WTERMSIG(exit_status))
-                       {
-                       case SIGKILL:   rp->r_flags |= RS_KILLED; break;
-                       default:        rp->r_flags |= RS_SIGNALED; break;
-                       }
-                 } 
-                 else
-                       rp->r_flags |= RS_CRASHED;
-
-                 if (rp->r_script[0] != '\0') {
-                       if(rs_verbose)
-                               printf("RS: running restart script for %s\n",
-                                       rp->r_cmd);
-                     run_script(rp);
-                 } else if (rp->r_restarts > 0) {
-                     printf("RS: restarting %s, restarts %d\n",
-                               rp->r_cmd, rp->r_backoff);
-                     rp->r_backoff = 1 << MIN(rp->r_restarts,(BACKOFF_BITS-2));
-                     rp->r_backoff = MIN(rp->r_backoff,MAX_BACKOFF); 
-                     if ((rpub->sys_flags & SF_USE_COPY) && rp->r_backoff > 1)
-                       rp->r_backoff= 1;
-                 }
-                 else {
-                     printf("RS: restarting %s\n", rp->r_cmd);
-                     start_service(rp, 0, &ep);        /* direct restart */
-                     if(m_ptr)
-                             m_ptr->RS_ENDPOINT = ep;
-                       /* Do this even if no I/O happens with the ioctl, in
-                        * order to disambiguate requests with DEV_IOCTL_S.
-                        */
-                 }
-              }
-             break;
-         }
-      }
-  } 
+  /* Share exec image from rp_src to rp_dst. */
+  rp_dst->r_exec_len = rp_src->r_exec_len;
+  rp_dst->r_exec = rp_src->r_exec;
 }
 
 /*===========================================================================*
- *                             do_period                                    *
+ *                             read_exec                                    *
  *===========================================================================*/
-PUBLIC void do_period(m_ptr)
-message *m_ptr;
+PUBLIC int read_exec(rp)
+struct rproc *rp;
 {
-  register struct rproc *rp;
-  register struct rprocpub *rpub;
-  clock_t now = m_ptr->NOTIFY_TIMESTAMP;
-  int s;
-  endpoint_t ep;
-  long period;
+  int e, r, fd;
+  char *e_name;
+  struct stat sb;
+
+  e_name= rp->r_argv[0];
+  if(rs_verbose)
+      printf("RS: service '%s' reads exec image from: %s\n", rp->r_pub->label,
+          e_name);
+
+  r= stat(e_name, &sb);
+  if (r != 0) 
+      return -errno;
+
+  fd= open(e_name, O_RDONLY);
+  if (fd == -1)
+      return -errno;
 
-  /* If an update is in progress, check its status. */
-  if(rupdate.flags & RS_UPDATING) {
-      update_period(m_ptr);
+  rp->r_exec_len= sb.st_size;
+  rp->r_exec= malloc(rp->r_exec_len);
+  if (rp->r_exec == NULL)
+  {
+      printf("RS: read_exec: unable to allocate %d bytes\n",
+          rp->r_exec_len);
+      close(fd);
+      return ENOMEM;
   }
 
-  /* Search system services table. Only check slots that are in use and not
-   * updating.
-   */
-  for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
-      rpub = rp->r_pub;
-      if ((rp->r_flags & RS_IN_USE) && !(rp->r_flags & RS_UPDATING)) {
+  r= read(fd, rp->r_exec, rp->r_exec_len);
+  e= errno;
+  close(fd);
+  if (r == rp->r_exec_len)
+      return OK;
 
-          /* Compute period. */
-          period = rpub->period;
-          if(rp->r_flags & RS_INITIALIZING) {
-              period = RS_INIT_T;
-          }
+  printf("RS: read_exec: read failed %d, errno %d\n", r, e);
 
-          /* If the service is to be revived (because it repeatedly exited, 
-          * and was not directly restarted), the binary backoff field is  
-          * greater than zero. 
-          */
-         if (rp->r_backoff > 0) {
-              rp->r_backoff -= 1;
-             if (rp->r_backoff == 0) {
-                 start_service(rp, 0, &ep);
-                 m_ptr->RS_ENDPOINT = ep;
-             }
-         }
-
-         /* If the service was signaled with a SIGTERM and fails to respond,
-          * kill the system service with a SIGKILL signal.
-          */
-         else if (rp->r_stop_tm > 0 && now - rp->r_stop_tm > 2*RS_DELTA_T
-          && rp->r_pid > 0) {
-              kill(rp->r_pid, SIGKILL);                /* terminate */
-         }
-       
-         /* There seems to be no special conditions. If the service has a 
-          * period assigned check its status. 
-          */
-         else if (period > 0) {
-
-             /* Check if an answer to a status request is still pending. If 
-              * the service didn't respond within time, kill it to simulate 
-              * a crash. The failure will be detected and the service will 
-              * be restarted automatically.
-              */
-              if (rp->r_alive_tm < rp->r_check_tm) { 
-                 if (now - rp->r_alive_tm > 2*period &&
-                     rp->r_pid > 0 && !(rp->r_flags & RS_NOPINGREPLY)) { 
-                     if(rs_verbose)
-                           printf("RS: service %d reported late\n",
-                               rpub->endpoint); 
-                     rp->r_flags |= RS_NOPINGREPLY;
-                     if(rp->r_flags & RS_INITIALIZING) {
-                           rp->r_flags |= RS_EXITING;   /* don't restart */
-                     }
-                      kill(rp->r_pid, SIGKILL);                /* simulate crash */
-                 }
-             }
-
-             /* No answer pending. Check if a period expired since the last
-              * check and, if so request the system service's status.
-              */
-             else if (now - rp->r_check_tm > rpub->period) {
-#if 0
-               if(rs_verbose)
-                  printf("RS: status request sent to %d\n", rpub->endpoint);
-#endif
-                 notify(rpub->endpoint);               /* request status */
-                 rp->r_check_tm = now;                 /* mark time */
-              }
-          }
+  free_exec(rp);
+
+  if (r >= 0)
+      return EIO;
+  else
+      return -e;
+}
+
+/*===========================================================================*
+ *                             free_exec                                    *
+ *===========================================================================*/
+PUBLIC void free_exec(rp)
+struct rproc *rp;
+{
+/* Free an exec image. */
+  int slot_nr, has_shared_exec;
+  struct rproc *other_rp;
+
+  /* Search for some other slot sharing the same exec image. */
+  has_shared_exec = FALSE;
+  for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
+      other_rp = &rproc[slot_nr];              /* get pointer to slot */
+      if (other_rp->r_flags & RS_IN_USE && other_rp != rp
+          && other_rp->r_exec == rp->r_exec) {  /* found! */
+          has_shared_exec = TRUE;
+          break;
       }
   }
 
-  /* Reschedule a synchronous alarm for the next period. */
-  if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
-      panic("couldn't set alarm: %d", s);
+  /* If nobody uses our copy of the exec image, we can get rid of it. */
+  if(!has_shared_exec) {
+      if(rs_verbose)
+          printf("RS: %s frees exec image\n", srv_to_string(rp));
+      free(rp->r_exec);
+  }
+  else {
+      if(rs_verbose)
+          printf("RS: %s no longer sharing exec image with %s\n",
+              srv_to_string(rp), srv_to_string(other_rp));
+  }
+  rp->r_exec = NULL;
+  rp->r_exec_len = 0;
 }
 
-
 /*===========================================================================*
- *                             start_service                                *
+ *                              init_slot                                   *
  *===========================================================================*/
-PRIVATE int start_service(rp, flags, endpoint)
+PUBLIC int init_slot(rp, rs_start, source)
 struct rproc *rp;
-int flags;
-endpoint_t *endpoint;
+struct rs_start *rs_start;
+endpoint_t source;
 {
-/* Try to execute the given system service. Fork a new process. The child
- * process will be inhibited from running by the NO_PRIV flag. Only let the
- * child run once its privileges have been set by the parent.
- */
-  int child_proc_nr_e, child_proc_nr_n;                /* child process slot */
-  pid_t child_pid;                             /* child's process id */
-  char *file_only;
-  int s, use_copy, slot_nr, init_type;
-  bitchunk_t *vm_mask;
-  message m;
-  char * null_env = NULL;
+/* Initialize a slot as requested by the client. */
   struct rprocpub *rpub;
+  int slot_nr;                                 /* local table entry */
+  int arg_count;                               /* number of arguments */
+  char *cmd_ptr;                               /* parse command string */
+  char *label;                                 /* unique name of command */
+  enum dev_style dev_style;                    /* device style */
+  struct rproc *tmp_rp;
+  struct rprocpub *tmp_rpub;
+  int len;                                     /* length of string */
+  int i;
+  int s;
+  int basic_kc[] =  { SYS_BASIC_CALLS, SYS_NULL_C };
+  int basic_vmc[] =  { VM_BASIC_CALLS, SYS_NULL_C };
+
+  rpub = rp->r_pub;
+
+/* Obtain command name and parameters. This is a space-separated string
+   * that looks like "/sbin/service arg1 arg2 ...". Arguments are optional.
+   */
+  if (rs_start->rss_cmdlen > MAX_COMMAND_LEN-1) return(E2BIG);
+  s=sys_datacopy(source, (vir_bytes) rs_start->rss_cmd, 
+       SELF, (vir_bytes) rp->r_cmd, rs_start->rss_cmdlen);
+  if (s != OK) return(s);
+  rp->r_cmd[rs_start->rss_cmdlen] = '\0';      /* ensure it is terminated */
+  if (rp->r_cmd[0] != '/') return(EINVAL);     /* insist on absolute path */
+
+  /* Build cmd dependencies: argv and program name. */
+  build_cmd_dep(rp);
+
+  if(rs_start->rss_label.l_len > 0) {
+       /* RS_UP caller has supplied a custom label for this service. */
+       int s = copy_label(source, rs_start->rss_label.l_addr,
+               rs_start->rss_label.l_len, rpub->label, sizeof(rpub->label));
+       if(s != OK)
+               return s;
+        if(rs_verbose)
+         printf("RS: init_slot: using label (custom) '%s'\n", rpub->label);
+  } else {
+       /* Default label for the service. */
+       label = rpub->proc_name;
+       len= strlen(label);
+       memcpy(rpub->label, label, len);
+       rpub->label[len]= '\0';
+        if(rs_verbose)
+          printf("RS: init_slot: using label (from proc_name) '%s'\n",
+               rpub->label);
+  }
+
+  if(rs_start->rss_nr_control > 0) {
+       int i, s;
+       if (rs_start->rss_nr_control > RS_NR_CONTROL)
+       {
+               printf("RS: init_slot: too many control labels\n");
+               return EINVAL;
+       }
+       for (i=0; i<rs_start->rss_nr_control; i++) {
+               s = copy_label(source, rs_start->rss_control[i].l_addr,
+                       rs_start->rss_control[i].l_len, rp->r_control[i],
+                       sizeof(rp->r_control[i]));
+               if(s != OK)
+                       return s;
+       }
+       rp->r_nr_control = rs_start->rss_nr_control;
+
+       if (rs_verbose) {
+               printf("RS: init_slot: control labels:");
+               for (i=0; i<rp->r_nr_control; i++)
+                       printf(" %s", rp->r_control[i]);
+               printf("\n");
+       }
+  }
+
+  rp->r_script[0]= '\0';
+  if (rs_start->rss_scriptlen > MAX_SCRIPT_LEN-1) return(E2BIG);
+  if (rs_start->rss_script != NULL)
+  {
+         s=sys_datacopy(source, (vir_bytes) rs_start->rss_script, 
+               SELF, (vir_bytes) rp->r_script, rs_start->rss_scriptlen);
+         if (s != OK) return(s);
+         rp->r_script[rs_start->rss_scriptlen] = '\0';
+  }
+  rp->r_uid= rs_start->rss_uid;
+  rp->r_nice= rs_start->rss_nice;
+
+  if (rs_start->rss_flags & RSS_IPC_VALID)
+  {
+       if (rs_start->rss_ipclen+1 > sizeof(rp->r_ipc_list))
+       {
+               printf("RS: ipc list too long for '%s'\n", rpub->label);
+               return EINVAL;
+       }
+       s=sys_datacopy(source, (vir_bytes) rs_start->rss_ipc, 
+               SELF, (vir_bytes) rp->r_ipc_list, rs_start->rss_ipclen);
+       if (s != OK) return(s);
+       rp->r_ipc_list[rs_start->rss_ipclen]= '\0';
+  }
+  else
+       rp->r_ipc_list[0]= '\0';
+
+  rpub->sys_flags = DSRV_SF;
+  rp->r_exec= NULL;
+  if (rs_start->rss_flags & RSS_COPY) {
+       int exst_cpy;
+       struct rproc *rp2;
+       struct rprocpub *rpub2;
+       exst_cpy = 0;
+       
+       if(rs_start->rss_flags & RSS_REUSE) {
+                int i;
+
+                for(i = 0; i < NR_SYS_PROCS; i++) {
+                       rp2 = &rproc[i];
+                       rpub2 = rproc[i].r_pub;
+                        if(strcmp(rpub->proc_name, rpub2->proc_name) == 0 &&
+                           (rpub2->sys_flags & SF_USE_COPY)) {
+                                /* We have found the same binary that's
+                                 * already been copied */
+                                 exst_cpy = 1;
+                                 break;
+                        }
+                }
+         }                
 
-  rpub = rp->r_pub;
-  use_copy= (rpub->sys_flags & SF_USE_COPY);
+       s = OK;
+       if(!exst_cpy)
+               s = read_exec(rp);
+       else
+               share_exec(rp, rp2);
 
-  /* See if we are not using a copy but we do need one to start the service. */
-  if(!use_copy && (rpub->sys_flags & SF_NEED_COPY)) {
-       printf("RS: unable to start service %s without an in-memory copy\n",
-           rpub->label);
-       free_slot(rp);
-       return(EPERM);
-  }
+       if (s != OK)
+               return s;
 
-  /* Now fork and branch for parent and child process (and check for error). */
-  if (use_copy) {
-  if(rs_verbose) printf("RS: fork_nb..\n");
-       child_pid= fork_nb();
-  } else {
-  if(rs_verbose) printf("RS: fork regular..\n");
-       child_pid = fork();
+       rpub->sys_flags |= SF_USE_COPY;
   }
 
-  switch(child_pid) {                                  /* see fork(2) */
-  case -1:                                             /* fork failed */
-      printf("RS: warning, fork() failed: %d\n", errno); /* shouldn't happen */
-      return(errno);                                   /* return error */
-
-  case 0:                                              /* child process */
-      /* Try to execute the binary that has an absolute path. If this fails, 
-       * e.g., because the root file system cannot be read, try to strip off
-       * the path, and see if the command is in RS' current working dir.
-       */
-      nice(rp->r_nice);                /* Nice before setuid, to allow negative
-                                * nice values.
-                                */
-      setuid(rp->r_uid);
-      cpf_reload();                    /* Tell kernel about grant table  */
-      if (!use_copy)
-      {
-       execve(rp->r_argv[0], rp->r_argv, &null_env);   /* POSIX execute */
-       file_only = strrchr(rp->r_argv[0], '/') + 1;
-       execve(file_only, rp->r_argv, &null_env);       /* POSIX execute */
-      }
-      printf("RS: exec failed for %s: %d\n", rp->r_argv[0], errno);
-      slot_nr= rp-rproc;
-      s= write(exec_pipe[1], &slot_nr, sizeof(slot_nr));
-      if (s != sizeof(slot_nr))
-       printf("RS: write to exec pipe failed: %d/%d\n", s, errno);
-      exit(1);                                         /* terminate child */
-
-  default:                                             /* parent process */
-#if 0
-      if(rs_verbose) printf("RS: parent forked, pid %d..\n", child_pid);
-#endif
-      child_proc_nr_e = getnprocnr(child_pid);         /* get child slot */ 
-#if 0
-      if(rs_verbose) printf("RS: forked into %d..\n", child_proc_nr_e);
-#endif
-      break;                                           /* continue below */
-  }
-
-  /* Regardless of any following failures, there is now a child process.
-   * Update the system process table that is maintained by the RS server.
-   */
-  child_proc_nr_n = _ENDPOINT_P(child_proc_nr_e);
-  rp->r_flags = RS_IN_USE | flags;             /* mark slot in use */
-  rp->r_restarts += 1;                         /* raise nr of restarts */
-  rpub->endpoint = child_proc_nr_e;            /* set child details */
-  rp->r_pid = child_pid;
-  rp->r_check_tm = 0;                          /* not checked yet */
-  getuptime(&rp->r_alive_tm);                  /* currently alive */
-  rp->r_stop_tm = 0;                           /* not exiting yet */
-  rp->r_backoff = 0;                           /* not to be restarted */
-  rproc_ptr[child_proc_nr_n] = rp;             /* mapping for fast access */
-  rpub->in_use = TRUE;                         /* public entry is now in use */
-
-  /* If any of the calls below fail, the RS_EXITING flag is set. This implies
-   * that the process will be removed from RS's process table once it has
-   * terminated. The assumption is that it is not useful to try to restart the
-   * process later in these failure cases.
+  /* All dynamically created services get the same privilege flags, and
+   * allowed traps, and signal manager. Other privilege settings can be
+   * specified at runtime. The privilege id is dynamically allocated by
+   * the kernel.
    */
+  rp->r_priv.s_flags = DSRV_F;           /* privilege flags */
+  rp->r_priv.s_trap_mask = DSRV_T;       /* allowed traps */
+  rp->r_priv.s_sig_mgr = DSRV_SM;        /* signal manager */
 
-  if (use_copy)
+  /* Copy granted resources */
+  if (rs_start->rss_nr_irq > NR_IRQ)
   {
-       extern char **environ;
-
-       /* Copy the executable image into the child process. If this call
-        * fails, the child process may or may not be killed already. If it is
-        * not killed, it's blocked because of NO_PRIV. Kill it now either way.
-        */
-       s = dev_execve(child_proc_nr_e, rp->r_exec, rp->r_exec_len, rp->r_argv,
-               environ);
-       if (s != OK) {
-               printf("RS: dev_execve call failed: %d\n", s);
-               kill(child_pid, SIGKILL);
-               rp->r_flags |= RS_EXITING;      /* don't try again */
-               return(s);
-       }
+       printf("RS: init_slot: too many IRQs requested\n");
+       return EINVAL;
   }
-
-  /* Set resources when asked to. */
-  if (rp->r_set_resources)
+  rp->r_priv.s_nr_irq= rs_start->rss_nr_irq;
+  for (i= 0; i<rp->r_priv.s_nr_irq; i++)
   {
-       /* Initialize privilege structure. */
-       init_privs(rp, &rp->r_priv);
-
-       /* Tell VM about allowed calls. */
-       vm_mask = &rpub->vm_call_mask[0];
-       if ((s = vm_set_priv(child_proc_nr_e, vm_mask)) < 0) {
-           printf("RS: vm_set_priv call failed: %d\n", s);
-           kill(child_pid, SIGKILL);
-           rp->r_flags |= RS_EXITING;
-           return (s);
-       }
+       rp->r_priv.s_irq_tab[i]= rs_start->rss_irq[i];
+       if(rs_verbose)
+               printf("RS: init_slot: IRQ %d\n", rp->r_priv.s_irq_tab[i]);
   }
 
-  /* Set and synch the privilege structure for the new service. */
-  if ((s = sys_privctl(child_proc_nr_e, SYS_PRIV_SET_SYS, &rp->r_priv)) != OK
-      || (s = sys_getpriv(&rp->r_priv, child_proc_nr_e)) != OK) {
-      printf("RS: unable to set privileges: %d\n", s);
-      kill(child_pid, SIGKILL);                                /* kill the service */
-      rp->r_flags |= RS_EXITING;                       /* expect exit */
-      return(s);                                       /* return error */
+  if (rs_start->rss_nr_io > NR_IO_RANGE)
+  {
+       printf("RS: init_slot: too many I/O ranges requested\n");
+       return EINVAL;
   }
-
-  /* If PCI properties are set, inform the PCI driver about the new service. */
-  if(rpub->pci_acl.rsp_nr_device || rpub->pci_acl.rsp_nr_class) {
-      init_pci(rp, child_proc_nr_e);
+  rp->r_priv.s_nr_io_range= rs_start->rss_nr_io;
+  for (i= 0; i<rp->r_priv.s_nr_io_range; i++)
+  {
+       rp->r_priv.s_io_tab[i].ior_base= rs_start->rss_io[i].base;
+       rp->r_priv.s_io_tab[i].ior_limit=
+               rs_start->rss_io[i].base+rs_start->rss_io[i].len-1;
+       if(rs_verbose)
+          printf("RS: init_slot: I/O [%x..%x]\n",
+               rp->r_priv.s_io_tab[i].ior_base,
+               rp->r_priv.s_io_tab[i].ior_limit);
   }
 
-  /* Publish the new system service. */
-  s = publish_service(rp);
-  if (s != OK) {
-       printf("RS: warning: publish_service failed: %d\n", s);
+  if (rs_start->rss_nr_pci_id > RS_NR_PCI_DEVICE)
+  {
+       printf("RS: init_slot: too many PCI device IDs\n");
+       return EINVAL;
   }
-
-  /* Allow the service to run.
-   * XXX: We should let the service run/init only after publishing information
-   * about the new system service, but this is not currently possible due to
-   * the blocking nature of mapdriver() that expects the service to be running.
-   * The current solution is not race-free. This hack can go once service
-   * publishing is made fully asynchronous in RS.
-   */
-  if ((s = sys_privctl(child_proc_nr_e, SYS_PRIV_ALLOW, NULL)) != OK) {
-      printf("RS: unable to allow the service to run: %d\n", s);
-      kill(child_pid, SIGKILL);                                /* kill the service */
-      rp->r_flags |= RS_EXITING;                       /* expect exit */
-      return(s);                                       /* return error */
+  rpub->pci_acl.rsp_nr_device = rs_start->rss_nr_pci_id;
+  for (i= 0; i<rpub->pci_acl.rsp_nr_device; i++)
+  {
+       rpub->pci_acl.rsp_device[i].vid= rs_start->rss_pci_id[i].vid;
+       rpub->pci_acl.rsp_device[i].did= rs_start->rss_pci_id[i].did;
+       if(rs_verbose)
+          printf("RS: init_slot: PCI %04x/%04x\n",
+               rpub->pci_acl.rsp_device[i].vid,
+               rpub->pci_acl.rsp_device[i].did);
   }
-
-  /* Initialize service. */
-  init_type = rp->r_restarts > 0 ? SEF_INIT_RESTART : SEF_INIT_FRESH;
-  if((s = init_service(rp, init_type)) != OK) {
-      panic("unable to initialize service: %d", s);
+  if (rs_start->rss_nr_pci_class > RS_NR_PCI_CLASS)
+  {
+       printf("RS: init_slot: too many PCI class IDs\n");
+       return EINVAL;
   }
-
-  /* The purpose of non-blocking forks is to avoid involving VFS in the forking
-   * process, because VFS may be blocked on a sendrec() to a MFS that is
-   * waiting for a endpoint update for a dead driver. We have just published
-   * that update, but VFS may still be blocked. As a result, VFS may not yet
-   * have received PM's fork message. Hence, if we call mapdriver()
-   * immediately, VFS may not know about the process and thus refuse to add the
-   * driver entry. The following temporary hack works around this by forcing
-   * blocking communication from PM to VFS. Once VFS has been made non-blocking
-   * towards MFS instances, this hack and the entire fork_nb() call can go.
-   */
-  if (use_copy)
-       setuid(0);
-
-  /* Map the new service. */
-  if (rpub->dev_nr > 0) {                              /* set driver map */
-      if ((s=mapdriver(rpub->label,
-             rpub->dev_nr, rpub->dev_style, !!use_copy /* force */)) < 0) {
-          printf("RS: couldn't map driver (continuing): %d\n", errno);
-      }
+  rpub->pci_acl.rsp_nr_class= rs_start->rss_nr_pci_class;
+  for (i= 0; i<rpub->pci_acl.rsp_nr_class; i++)
+  {
+       rpub->pci_acl.rsp_class[i].class= rs_start->rss_pci_class[i].class;
+       rpub->pci_acl.rsp_class[i].mask= rs_start->rss_pci_class[i].mask;
+       if(rs_verbose)
+           printf("RS: init_slot: PCI class %06x mask %06x\n",
+               rpub->pci_acl.rsp_class[i].class,
+               rpub->pci_acl.rsp_class[i].mask);
   }
 
-  if(rs_verbose)
-      printf("RS: started '%s', major %d, pid %d, endpoint %d, proc %d\n", 
-          rp->r_cmd, rpub->dev_nr, child_pid,
-         child_proc_nr_e, child_proc_nr_n);
+  /* Copy kernel call mask. Inherit basic kernel calls. */
+  memcpy(rp->r_priv.s_k_call_mask, rs_start->rss_system,
+       sizeof(rp->r_priv.s_k_call_mask));
+  fill_call_mask(basic_kc, NR_SYS_CALLS,
+       rp->r_priv.s_k_call_mask, KERNEL_CALL, FALSE);
 
-  /* The system service now has been successfully started. The only thing
-   * that can go wrong now, is that execution fails at the child. If that's
-   * the case, the child will exit. 
-   */
-  if(endpoint) *endpoint = child_proc_nr_e;    /* send back child endpoint */
+  /* Initialize some fields. */
+  rpub->period = rs_start->rss_period;
+  rpub->dev_nr = rs_start->rss_major;
+  rpub->dev_style = STYLE_DEV; 
+  rp->r_restarts = -1;                                 /* will be incremented */
+  rp->r_set_resources= 1;                      /* set resources */
+
+  /* Copy VM call mask. Inherit basic VM calls. */
+  memcpy(rpub->vm_call_mask, rs_start->rss_vm,
+       sizeof(rpub->vm_call_mask));
+  fill_call_mask(basic_vmc, NR_VM_CALLS,
+       rpub->vm_call_mask, VM_RQ_BASE, FALSE);
 
-  return(OK);
+  return OK;
 }
 
 /*===========================================================================*
- *                             stop_service                                 *
+ *                             clone_slot                                   *
  *===========================================================================*/
-PRIVATE void stop_service(struct rproc *rp,int how)
+PUBLIC int clone_slot(rp, clone_rpp)
+struct rproc *rp;
+struct rproc **clone_rpp;
 {
-  /* Try to stop the system service. First send a SIGTERM signal to ask the
-   * system service to terminate. If the service didn't install a signal 
-   * handler, it will be killed. If it did and ignores the signal, we'll
-   * find out because we record the time here and send a SIGKILL.
-   */
-  if(rs_verbose) printf("RS tries to stop %s (pid %d)\n", rp->r_cmd, rp->r_pid);
+  int r;
+  struct rproc *clone_rp;
+  struct rprocpub *rpub, *clone_rpub;
 
-  rp->r_flags |= how;                          /* what to on exit? */
-  if(rp->r_pid > 0) kill(rp->r_pid, SIGTERM);  /* first try friendly */
-  else if(rs_verbose) printf("RS: no process to kill\n");
-  getuptime(&rp->r_stop_tm);                   /* record current time */
-}
+  /* Allocate a system service slot for the clone. */
+  r = alloc_slot(&clone_rp);
+  if(r != OK) {
+      printf("RS: clone_slot: unable to allocate a new slot: %d\n", r);
+      return r;
+  }
+
+  rpub = rp->r_pub;
+  clone_rpub = clone_rp->r_pub;
+
+  /* Shallow copy. */
+  *clone_rp = *rp;
+  *clone_rpub = *rpub;
 
+  /* Deep copy. */
+  clone_rp->r_flags &= ~RS_ACTIVE; /* the clone is not active yet */
+  clone_rp->r_pid = -1;            /* no pid yet */
+  clone_rpub->endpoint = -1;        /* no endpoint yet */
+  clone_rp->r_pub = clone_rpub;    /* restore pointer to public entry */
+  build_cmd_dep(clone_rp);         /* rebuild cmd dependencies */
+  if(clone_rpub->sys_flags & SF_USE_COPY) {
+      share_exec(clone_rp, rp);        /* share exec image */
+  }
+
+  /* Force dynamic privilege id. */
+  clone_rp->r_priv.s_flags |= DYN_PRIV_ID;
+
+  *clone_rpp = clone_rp;
+  return OK;
+}
 
 /*===========================================================================*
- *                             do_getsysinfo                                *
+ *                         swap_slot_pointer                                *
  *===========================================================================*/
-PUBLIC int do_getsysinfo(m_ptr)
-message *m_ptr;
+PRIVATE void swap_slot_pointer(struct rproc **rpp, struct rproc *src_rp,
+    struct rproc *dst_rp)
 {
-  vir_bytes src_addr, dst_addr;
-  int dst_proc;
-  size_t len;
-  int s;
-
-  /* This call requires special privileges. */
-  if (!caller_is_root(m_ptr->m_source)) return(EPERM);
-
-  switch(m_ptr->m1_i1) {
-  case SI_PROC_TAB:
-       src_addr = (vir_bytes) rproc;
-       len = sizeof(struct rproc) * NR_SYS_PROCS;
-       break; 
-  case SI_PROCPUB_TAB:
-       src_addr = (vir_bytes) rprocpub;
-       len = sizeof(struct rprocpub) * NR_SYS_PROCS;
-       break; 
-  default:
-       return(EINVAL);
-  }
-
-  dst_proc = m_ptr->m_source;
-  dst_addr = (vir_bytes) m_ptr->m1_p1;
-  if (OK != (s=sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len)))
-       return(s);
-  return(OK);
+  if(*rpp == src_rp) {
+      *rpp = dst_rp;
+  }
+  else if(*rpp == dst_rp) {
+      *rpp = src_rp;
+  }
 }
 
 /*===========================================================================*
- *                              fork_nb                                     *
+ *                             swap_slot                                    *
  *===========================================================================*/
-PRIVATE pid_t fork_nb()
+PUBLIC void swap_slot(src_rpp, dst_rpp)
+struct rproc **src_rpp;
+struct rproc **dst_rpp;
 {
-  message m;
-
-  return(_syscall(PM_PROC_NR, FORK_NB, &m));
+/* Swap two service slots. */
+  struct rproc *src_rp;
+  struct rproc *dst_rp;
+  struct rprocpub *src_rpub;
+  struct rprocpub *dst_rpub;
+  struct rproc orig_src_rproc, orig_dst_rproc;
+  struct rprocpub orig_src_rprocpub, orig_dst_rprocpub;
+
+  src_rp = *src_rpp;
+  dst_rp = *dst_rpp;
+  src_rpub = src_rp->r_pub;
+  dst_rpub = dst_rp->r_pub;
+
+  /* Save existing data first. */
+  orig_src_rproc = *src_rp;
+  orig_src_rprocpub = *src_rpub;
+  orig_dst_rproc = *dst_rp;
+  orig_dst_rprocpub = *dst_rpub;
+
+  /* Swap slots. */
+  *src_rp = orig_dst_rproc;
+  *src_rpub = orig_dst_rprocpub;
+  *dst_rp = orig_src_rproc;
+  *dst_rpub = orig_src_rprocpub;
+
+  /* Restore public entries. */
+  src_rp->r_pub = orig_src_rproc.r_pub;
+  dst_rp->r_pub = orig_dst_rproc.r_pub;
+
+  /* Rebuild command dependencies. */
+  build_cmd_dep(src_rp);
+  build_cmd_dep(dst_rp);
+
+  /* Swap local slot pointers. */
+  swap_slot_pointer(&src_rp->r_prev_rp, src_rp, dst_rp);
+  swap_slot_pointer(&src_rp->r_next_rp, src_rp, dst_rp);
+  swap_slot_pointer(&src_rp->r_old_rp, src_rp, dst_rp);
+  swap_slot_pointer(&src_rp->r_new_rp, src_rp, dst_rp);
+  swap_slot_pointer(&dst_rp->r_prev_rp, src_rp, dst_rp);
+  swap_slot_pointer(&dst_rp->r_next_rp, src_rp, dst_rp);
+  swap_slot_pointer(&dst_rp->r_old_rp, src_rp, dst_rp);
+  swap_slot_pointer(&dst_rp->r_new_rp, src_rp, dst_rp);
+
+  /* Swap global slot pointers. */
+  swap_slot_pointer(&rupdate.rp, src_rp, dst_rp);
+  swap_slot_pointer(&rproc_ptr[_ENDPOINT_P(src_rp->r_pub->endpoint)],
+      src_rp, dst_rp);
+  swap_slot_pointer(&rproc_ptr[_ENDPOINT_P(dst_rp->r_pub->endpoint)],
+      src_rp, dst_rp);
+
+  /* Adjust input pointers. */
+  *src_rpp = dst_rp;
+  *dst_rpp = src_rp;
 }
 
 /*===========================================================================*
- *                             share_exec                                   *
+ *                        lookup_slot_by_label                              *
  *===========================================================================*/
-PRIVATE int share_exec(rp_dst, rp_src)
-struct rproc *rp_dst, *rp_src;
+PUBLIC struct rproc* lookup_slot_by_label(char *label)
 {
-  struct rprocpub *rpub_src;
-  struct rprocpub *rpub_dst;
-
-  rpub_src = rp_src->r_pub;
-  rpub_dst = rp_dst->r_pub;
+/* Lookup a service slot matching the given label. */
+  int slot_nr;
+  struct rproc *rp;
+  struct rprocpub *rpub;
 
-  if(rs_verbose) {
-      printf("RS: share_exec: sharing exec image from %s to %s\n",
-          rpub_src->label, rpub_dst->label);
+  for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
+      rp = &rproc[slot_nr];
+      if (!(rp->r_flags & RS_ACTIVE)) {
+          continue;
+      }
+      rpub = rp->r_pub;
+      if (strcmp(rpub->label, label) == 0) {
+          return rp;
+      }
   }
 
-  /* Share exec image from rp_src to rp_dst. */
-  rp_dst->r_exec_len = rp_src->r_exec_len;
-  rp_dst->r_exec = rp_src->r_exec;
-
-  return OK;
+  return NULL;
 }
 
 /*===========================================================================*
- *                             read_exec                                    *
+ *                        lookup_slot_by_pid                                *
  *===========================================================================*/
-PRIVATE int read_exec(rp)
-struct rproc *rp;
+PUBLIC struct rproc* lookup_slot_by_pid(pid_t pid)
 {
-  int e, r, fd;
-  char *e_name;
-  struct stat sb;
+/* Lookup a service slot matching the given pid. */
+  int slot_nr;
+  struct rproc *rp;
 
-  e_name= rp->r_argv[0];
-  if(rs_verbose) {
-      printf("RS: read_exec: copying exec image from: %s\n", e_name);
+  if(pid < 0) {
+      return NULL;
   }
 
-  r= stat(e_name, &sb);
-  if (r != 0) 
-      return -errno;
-
-  fd= open(e_name, O_RDONLY);
-  if (fd == -1)
-      return -errno;
-
-  rp->r_exec_len= sb.st_size;
-  rp->r_exec= malloc(rp->r_exec_len);
-  if (rp->r_exec == NULL)
-  {
-      printf("RS: read_exec: unable to allocate %d bytes\n",
-          rp->r_exec_len);
-      close(fd);
-      return ENOMEM;
+  for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
+      rp = &rproc[slot_nr];
+      if (!(rp->r_flags & RS_IN_USE)) {
+          continue;
+      }
+      if (rp->r_pid == pid) {
+          return rp;
+      }
   }
 
-  r= read(fd, rp->r_exec, rp->r_exec_len);
-  e= errno;
-  close(fd);
-  if (r == rp->r_exec_len)
-      return OK;
+  return NULL;
+}
 
-  printf("RS: read_exec: read failed %d, errno %d\n", r, e);
+/*===========================================================================*
+ *                             alloc_slot                                   *
+ *===========================================================================*/
+PUBLIC int alloc_slot(rpp)
+struct rproc **rpp;
+{
+/* Alloc a new system service slot. */
+  int slot_nr;
 
-  free(rp->r_exec);
-  rp->r_exec= NULL;
+  for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
+      *rpp = &rproc[slot_nr];                  /* get pointer to slot */
+      if (!((*rpp)->r_flags & RS_IN_USE))      /* check if available */
+         break;
+  }
+  if (slot_nr >= NR_SYS_PROCS) {
+       return ENOMEM;
+  }
 
-  if (r >= 0)
-      return EIO;
-  else
-      return -e;
+  return OK;
 }
 
 /*===========================================================================*
  *                             free_slot                                    *
  *===========================================================================*/
-PRIVATE void free_slot(rp)
+PUBLIC void free_slot(rp)
 struct rproc *rp;
 {
-  int slot_nr, has_shared_exec;
+/* Free a system service slot. */
   struct rprocpub *rpub;
-  struct rproc *other_rp;
 
   rpub = rp->r_pub;
 
+  /* Send a late reply if there is any pending. */
+  late_reply(rp, OK);
+
   /* Free memory if necessary. */
   if(rpub->sys_flags & SF_USE_COPY) {
-      /* Search for some other slot sharing the same exec image. */
-      has_shared_exec = FALSE;
-      for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
-          other_rp = &rproc[slot_nr];          /* get pointer to slot */
-          if (other_rp->r_flags & RS_IN_USE && other_rp != rp
-              && other_rp->r_exec == rp->r_exec) {  /* found! */
-              has_shared_exec = TRUE;
-          }
-      }
-
-      /* If nobody uses our copy of the exec image, we can get rid of it. */
-      if(!has_shared_exec) {
-          if(rs_verbose) {
-              printf("RS: free_slot: free exec image from %s\n",
-                  rpub->label);
-          }
-          free(rp->r_exec);
-          rp->r_exec = NULL;
-          rp->r_exec_len = 0;
-      }
+      free_exec(rp);
   }
 
   /* Mark slot as no longer in use.. */
   rp->r_flags = 0;
+  rp->r_pid = -1;
   rpub->in_use = FALSE;
   rproc_ptr[_ENDPOINT_P(rpub->endpoint)] = NULL;
 }
@@ -1506,7 +1537,7 @@ struct rproc *rp;
 /*===========================================================================*
  *                             run_script                                   *
  *===========================================================================*/
-PRIVATE void run_script(rp)
+PUBLIC int run_script(rp)
 struct rproc *rp;
 {
        int r, endpoint;
@@ -1521,34 +1552,21 @@ struct rproc *rp;
                reason= "restart";
        else if (rp->r_flags & RS_NOPINGREPLY)
                reason= "no-heartbeat";
-       else if (rp->r_flags & RS_KILLED)
-               reason= "killed";
-       else if (rp->r_flags & RS_CRASHED)
-               reason= "crashed";
-       else if (rp->r_flags & RS_SIGNALED)
-               reason= "signaled";
-       else
-       {
-               printf(
-               "RS: run_script: can't find reason for termination of '%s'\n",
-                       rpub->label);
-               return;
-       }
+       else reason= "crashed";
        sprintf(incarnation_str, "%d", rp->r_restarts);
 
        if(rs_verbose) {
-         printf("RS: calling script '%s'\n", rp->r_script);
-         printf("RS: sevice name: '%s'\n", rpub->label);
-         printf("RS: reason: '%s'\n", reason);
-         printf("RS: incarnation: '%s'\n", incarnation_str);
+               printf("RS: %s:\n", srv_to_string(rp));
+               printf("RS:     calling script '%s'\n", rp->r_script);
+               printf("RS:     reason: '%s'\n", reason);
+               printf("RS:     incarnation: '%s'\n", incarnation_str);
        }
 
        pid= fork();
        switch(pid)
        {
-       case -1:        
-               printf("RS: run_script: fork failed: %s\n", strerror(errno));
-               break;
+       case -1:
+               return kill_service(rp, "unable to fork script", errno);
        case 0:
                execle(rp->r_script, rp->r_script, rpub->label, reason,
                        incarnation_str, NULL, envp);
@@ -1560,14 +1578,12 @@ struct rproc *rp;
                endpoint = getnprocnr(pid);
                if ((r = sys_privctl(endpoint, SYS_PRIV_SET_USER, NULL))
                        != OK) {
-                       printf("RS: run_script: can't set privileges: %d\n",r);
+                       return kill_service(rp,"can't set script privileges",r);
                }
-               /* Allow the service to run. */
+               /* Allow the script to run. */
                if ((r = sys_privctl(endpoint, SYS_PRIV_ALLOW, NULL)) != OK) {
-                       printf("RS: run_script: process can't run: %d\n",r);
+                       return kill_service(rp,"can't let the script run",r);
                }
-               /* Do not wait for the child */
-               break;
        }
 }
 
@@ -1575,7 +1591,7 @@ struct rproc *rp;
 /*===========================================================================*
  *                             get_next_label                               *
  *===========================================================================*/
-PRIVATE char *get_next_label(ptr, label, caller_label)
+PUBLIC char *get_next_label(ptr, label, caller_label)
 char *ptr;
 char *label;
 char *caller_label;
@@ -1617,7 +1633,7 @@ char *caller_label;
 /*===========================================================================*
  *                             add_forward_ipc                              *
  *===========================================================================*/
-PRIVATE void add_forward_ipc(rp, privp)
+PUBLIC void add_forward_ipc(rp, privp)
 struct rproc *rp;
 struct priv *privp;
 {
@@ -1659,23 +1675,10 @@ struct priv *privp;
                else
                {
                        /* Try to find process */
-                       for (slot_nr = 0; slot_nr < NR_SYS_PROCS;
-                               slot_nr++)
-                       {
-                               tmp_rp = &rproc[slot_nr];
-                               if (!(tmp_rp->r_flags & RS_IN_USE))
-                                       continue;
-                               tmp_rpub = tmp_rp->r_pub;
-                               if (strcmp(tmp_rpub->label, label) == 0)
-                                       break;
-                       }
-                       if (slot_nr >= NR_SYS_PROCS)
-                       {
-                               if (rs_verbose)
-                                       printf(
-                       "add_forward_ipc: unable to find '%s'\n", label);
+                       tmp_rp = lookup_slot_by_label(label);
+                       if (!tmp_rp)
                                continue;
-                       }
+                       tmp_rpub = tmp_rp->r_pub;
                        endpoint= tmp_rpub->endpoint;
                }
 
@@ -1695,7 +1698,7 @@ struct priv *privp;
 /*===========================================================================*
  *                             add_backward_ipc                             *
  *===========================================================================*/
-PRIVATE void add_backward_ipc(rp, privp)
+PUBLIC void add_backward_ipc(rp, privp)
 struct rproc *rp;
 struct priv *privp;
 {
@@ -1746,42 +1749,11 @@ struct priv *privp;
 /*===========================================================================*
  *                             init_privs                                   *
  *===========================================================================*/
-PRIVATE void init_privs(rp, privp)
+PUBLIC void init_privs(rp, privp)
 struct rproc *rp;
 struct priv *privp;
 {
-       int i, src_bits_per_word, dst_bits_per_word, src_word, dst_word,
-               src_bit, call_nr;
-       unsigned long mask;
-
-       /* Clear s_k_call_mask */
-       memset(privp->s_k_call_mask, '\0', sizeof(privp->s_k_call_mask));
-
-       src_bits_per_word= 8*sizeof(rp->r_call_mask[0]);
-       dst_bits_per_word= 8*sizeof(privp->s_k_call_mask[0]);
-       for (src_word= 0; src_word < RS_SYS_CALL_MASK_SIZE; src_word++)
-       {
-               for (src_bit= 0; src_bit < src_bits_per_word; src_bit++)
-               {
-                       mask= (1UL << src_bit);
-                       if (!(rp->r_call_mask[src_word] & mask))
-                               continue;
-                       call_nr= src_word*src_bits_per_word+src_bit;
-#if 0
-                       if(rs_verbose)
-                         printf("RS: init_privs: system call %d\n", call_nr);
-#endif
-                       dst_word= call_nr / dst_bits_per_word;
-                       mask= (1UL << (call_nr % dst_bits_per_word));
-                       if (dst_word >= SYS_CALL_MASK_SIZE)
-                       {
-                               printf(
-                               "RS: init_privs: call number %d doesn't fit\n",
-                                       call_nr);
-                       }
-                       privp->s_k_call_mask[dst_word] |= mask;
-               }
-       }
+       int i;
 
        /* Clear s_ipc_to */
        memset(&privp->s_ipc_to, '\0', sizeof(privp->s_ipc_to));
@@ -1802,77 +1774,3 @@ struct priv *privp;
        }
 }
 
-/*===========================================================================*
- *                             init_pci                                     *
- *===========================================================================*/
-PRIVATE void init_pci(rp, endpoint)
-struct rproc *rp;
-int endpoint;
-{
-       /* Inform the PCI driver about the new service. */
-       size_t len;
-       int i, r;
-       struct rs_pci rs_pci;
-       struct rprocpub *rpub;
-
-       rpub = rp->r_pub;
-       rs_pci = rpub->pci_acl;
-       strcpy(rs_pci.rsp_label, rpub->label);
-       rs_pci.rsp_endpoint= endpoint;
-
-       if(rs_verbose)
-               printf("RS: init_pci: calling pci_set_acl\n");
-
-       r= pci_set_acl(&rs_pci);
-
-       if(rs_verbose)
-               printf("RS: init_pci: after pci_set_acl\n");
-
-       if (r != OK)
-       {
-               printf("RS: init_pci: pci_set_acl failed: %s\n",
-                       strerror(errno));
-               return;
-       }
-}
-
-/*===========================================================================*
- *                             do_lookup                                    *
- *===========================================================================*/
-PUBLIC int do_lookup(m_ptr)
-message *m_ptr;
-{
-       static char namebuf[100];
-       int len, r;
-       struct rproc *rrp;
-       struct rprocpub *rrpub;
-
-       len = m_ptr->RS_NAME_LEN;
-
-       if(len < 2 || len >= sizeof(namebuf)) {
-               printf("RS: len too weird (%d)\n", len);
-               return EINVAL;
-       }
-
-       if((r=sys_vircopy(m_ptr->m_source, D, (vir_bytes) m_ptr->RS_NAME,
-               SELF, D, (vir_bytes) namebuf, len)) != OK) {
-               printf("RS: name copy failed\n");
-               return r;
-
-       }
-
-       namebuf[len] = '\0';
-
-       for (rrp=BEG_RPROC_ADDR; rrp<END_RPROC_ADDR; rrp++) {
-               if (!(rrp->r_flags & RS_IN_USE))
-                       continue;
-               rrpub = rrp->r_pub;
-               if (!strcmp(rrpub->label, namebuf)) {
-                       m_ptr->RS_ENDPOINT = rrpub->endpoint;
-                       return OK;
-               }
-       }
-
-       return ESRCH;
-}
-
index 09b3a9f178ee46338af33349e8d3fd97a2cb9bca..d73314e8b6a7e0c6e653326ed9c647cfa7d0a54a 100644 (file)
 struct rproc;
 
 /* exec.c */
-_PROTOTYPE( int dev_execve, (int proc_e, 
+_PROTOTYPE( int srv_execve, (int proc_e, 
        char *exec, size_t exec_len,  char *argv[], char **env));
 
 /* main.c */
 _PROTOTYPE( int main, (void));
 
-/* manager.c */
+/* request.c */
 _PROTOTYPE( int do_up, (message *m));
 _PROTOTYPE( int do_down, (message *m));
 _PROTOTYPE( int do_refresh, (message *m));
 _PROTOTYPE( int do_restart, (message *m));
-_PROTOTYPE( int do_lookup, (message *m));
 _PROTOTYPE( int do_shutdown, (message *m));
 _PROTOTYPE( void do_period, (message *m));
 _PROTOTYPE( int do_init_ready, (message *m));
 _PROTOTYPE( int do_update, (message *m));
 _PROTOTYPE( int do_upd_ready, (message *m));
-_PROTOTYPE( void do_exit, (message *m));
+_PROTOTYPE( void do_sigchld, (void));
 _PROTOTYPE( int do_getsysinfo, (message *m));
+_PROTOTYPE( int do_lookup, (message *m));
+
+/* manager.c */
+_PROTOTYPE( int caller_is_root, (endpoint_t endpoint) );
+_PROTOTYPE( int caller_can_control, (endpoint_t endpoint, char *label) );
+_PROTOTYPE( int check_call_permission, (endpoint_t caller, int call,
+       struct rproc *rp) );
+_PROTOTYPE( int copy_rs_start, (endpoint_t src_e, char *src_rs_start,
+       struct rs_start *rs_start) );
+_PROTOTYPE( int copy_label, (endpoint_t src_e, char *src_label, size_t src_len,
+       char *dst_label, size_t dst_len) );
+_PROTOTYPE( void build_cmd_dep, (struct rproc *rp) );
+_PROTOTYPE( int srv_fork, (void) );
+_PROTOTYPE( int srv_kill, (pid_t pid, int sig) );
+#define kill_service(rp, errstr, err) \
+       kill_service_debug(__FILE__, __LINE__, rp, errstr, err)
+_PROTOTYPE( int kill_service_debug, (char *file, int line, struct rproc *rp,
+       char *errstr, int err) );
+#define crash_service(rp) \
+       crash_service_debug(__FILE__, __LINE__, rp)
+_PROTOTYPE( int crash_service_debug, (char *file, int line, struct rproc *rp) );
+#define cleanup_service(rp) \
+       cleanup_service_debug(__FILE__, __LINE__, rp)
+_PROTOTYPE( void cleanup_service_debug, (char *file, int line,
+       struct rproc *rp) );
+_PROTOTYPE( int create_service, (struct rproc *rp) );
+_PROTOTYPE( int publish_service, (struct rproc *rp) );
+_PROTOTYPE( int publish_process, (struct rproc *rp) );
+_PROTOTYPE( int unpublish_service, (struct rproc *rp) );
+_PROTOTYPE( int unpublish_process, (struct rproc *rp) );
+_PROTOTYPE( int run_service, (struct rproc *rp, int init_type) );
+_PROTOTYPE( int start_service, (struct rproc *rp) );
+_PROTOTYPE( void stop_service, (struct rproc *rp,int how) );
+_PROTOTYPE( int update_service, (struct rproc **src_rpp,
+       struct rproc **dst_rpp) );
+_PROTOTYPE( void activate_service, (struct rproc *rp, struct rproc *ex_rp) );
+_PROTOTYPE( void terminate_service, (struct rproc *rp));
+_PROTOTYPE( void restart_service, (struct rproc *rp) );
+_PROTOTYPE( void inherit_service_defaults, (struct rproc *def_rp,
+       struct rproc *rp) );
+_PROTOTYPE( void get_service_instances, (struct rproc *rp, struct rproc ***rps,
+       int *length) );
+_PROTOTYPE( int read_exec, (struct rproc *rp) );
+_PROTOTYPE( void share_exec, (struct rproc *rp_src, struct rproc *rp_dst) );
+_PROTOTYPE( void free_exec, (struct rproc *rp) );
+_PROTOTYPE( int init_slot, (struct rproc *rp, struct rs_start *rs_start,
+       endpoint_t source) );
+_PROTOTYPE( int clone_slot, (struct rproc *rp, struct rproc **clone_rpp) );
+_PROTOTYPE( void swap_slot, (struct rproc **src_rpp, struct rproc **dst_rpp) );
+_PROTOTYPE( struct rproc* lookup_slot_by_label, (char *label) );
+_PROTOTYPE( struct rproc* lookup_slot_by_pid, (pid_t pid) );
+_PROTOTYPE( int alloc_slot, (struct rproc **rpp) );
+_PROTOTYPE( void free_slot, (struct rproc *rp) );
+_PROTOTYPE( int run_script, (struct rproc *rp) );
+_PROTOTYPE( char *get_next_label, (char *ptr, char *label, char *caller_label));
+_PROTOTYPE( void add_forward_ipc, (struct rproc *rp, struct priv *privp) );
+_PROTOTYPE( void add_backward_ipc, (struct rproc *rp, struct priv *privp) );
+_PROTOTYPE( void init_privs, (struct rproc *rp, struct priv *privp) );
+_PROTOTYPE( void update_period, (message *m_ptr) );
+_PROTOTYPE( void end_update, (int result) );
 
 /* utility.c */
 _PROTOTYPE( int init_service, (struct rproc *rp, int type));
-_PROTOTYPE( int publish_service, (struct rproc *rp));
 _PROTOTYPE(void fill_call_mask, ( int *calls, int tot_nr_calls,
-    bitchunk_t *call_mask, int call_base, int is_init));
+       bitchunk_t *call_mask, int call_base, int is_init));
+_PROTOTYPE( char* srv_to_string, (struct rproc *rp));
+_PROTOTYPE( void reply, (endpoint_t who, message *m_ptr));
+_PROTOTYPE( void late_reply, (struct rproc *rp, int code));
+_PROTOTYPE( int rs_isokendpt, (endpoint_t endpoint, int *proc));
 
 /* memory.c */
 _PROTOTYPE( void* rs_startup_sbrk, (size_t size));
 _PROTOTYPE( void* rs_startup_sbrk_synch, (size_t size));
 _PROTOTYPE( int rs_startup_segcopy, (endpoint_t src_proc, int src_s,
-    int dst_s, vir_bytes dst_vir, phys_bytes bytes));
+       int dst_s, vir_bytes dst_vir, phys_bytes bytes));
+
+/* error.c */
+_PROTOTYPE( char * init_strerror, (int errnum) );
+_PROTOTYPE( char * lu_strerror, (int errnum) );
 
diff --git a/servers/rs/request.c b/servers/rs/request.c
new file mode 100755 (executable)
index 0000000..66ea117
--- /dev/null
@@ -0,0 +1,694 @@
+/*
+ * Changes:
+ *   Jan 22, 2010:  Created  (Cristiano Giuffrida)
+ */
+
+#include "inc.h"
+
+/*===========================================================================*
+ *                                do_up                                     *
+ *===========================================================================*/
+PUBLIC int do_up(m_ptr)
+message *m_ptr;                                        /* request message pointer */
+{
+/* A request was made to start a new system service. */
+  struct rproc *rp;
+  struct rprocpub *rpub;
+  int r;
+  struct rs_start rs_start;
+
+  /* Check if the call can be allowed. */
+  if((r = check_call_permission(m_ptr->m_source, RS_UP, NULL)) != OK)
+      return r;
+
+  /* Allocate a new system service slot. */
+  r = alloc_slot(&rp);
+  if(r != OK) {
+      printf("RS: do_up: unable to allocate a new slot: %d\n", r);
+      return r;
+  }
+  rpub = rp->r_pub;
+
+  /* Copy the request structure. */
+  r = copy_rs_start(m_ptr->m_source, m_ptr->RS_CMD_ADDR, &rs_start);
+  if (r != OK) {
+      return r;
+  }
+
+  /* Initialize the slot as requested. */
+  r = init_slot(rp, &rs_start, m_ptr->m_source);
+  if(r != OK) {
+      printf("RS: do_up: unable to init the new slot: %d\n", r);
+      return r;
+  }
+
+  /* Check for duplicates */
+  if(lookup_slot_by_label(rpub->label)) {
+      printf("RS: service '%s' (%d) has duplicate label\n", rpub->label,
+          rpub->endpoint);
+      return EBUSY;
+  }
+
+  /* All information was gathered. Now try to start the system service. */
+  r = start_service(rp);
+  activate_service(rp, NULL);
+  if(r != OK) {
+      return r;
+  }
+
+  /* Late reply - send a reply when service completes initialization. */
+  rp->r_flags |= RS_LATEREPLY;
+  rp->r_caller = m_ptr->m_source;
+  rp->r_caller_request = RS_UP;
+
+  return EDONTREPLY;
+}
+
+/*===========================================================================*
+ *                             do_down                                      *
+ *===========================================================================*/
+PUBLIC int do_down(message *m_ptr)
+{
+  register struct rproc *rp;
+  register struct rprocpub *rpub;
+  int s, proc;
+  char label[RS_MAX_LABEL_LEN];
+
+  /* Copy label. */
+  s = copy_label(m_ptr->m_source, m_ptr->RS_CMD_ADDR,
+      m_ptr->RS_CMD_LEN, label, sizeof(label));
+  if(s != OK) {
+      return s;
+  }
+
+  /* Lookup slot by label. */
+  rp = lookup_slot_by_label(label);
+  if(!rp) {
+      if(rs_verbose)
+          printf("RS: do_down: service '%s' not found\n", label);
+      return(ESRCH);
+  }
+  rpub = rp->r_pub;
+
+  /* Check if the call can be allowed. */
+  if((s = check_call_permission(m_ptr->m_source, RS_DOWN, rp)) != OK)
+      return s;
+
+  /* Stop service. */
+  if (rp->r_flags & RS_TERMINATED) {
+        /* A recovery script is requesting us to bring down the service.
+         * The service is already gone, simply perform cleanup.
+         */
+        if(rs_verbose)
+            printf("RS: recovery script performs service down...\n");
+       unpublish_service(rp);
+        unpublish_process(rp);
+       cleanup_service(rp);
+       return(OK);
+  }
+  stop_service(rp,RS_EXITING);
+
+  /* Late reply - send a reply when service dies. */
+  rp->r_flags |= RS_LATEREPLY;
+  rp->r_caller = m_ptr->m_source;
+  rp->r_caller_request = RS_DOWN;
+
+  return EDONTREPLY;
+}
+
+/*===========================================================================*
+ *                             do_restart                                   *
+ *===========================================================================*/
+PUBLIC int do_restart(message *m_ptr)
+{
+  struct rproc *rp;
+  int s, proc, r;
+  char label[RS_MAX_LABEL_LEN];
+  char script[MAX_SCRIPT_LEN];
+
+  /* Copy label. */
+  s = copy_label(m_ptr->m_source, m_ptr->RS_CMD_ADDR,
+      m_ptr->RS_CMD_LEN, label, sizeof(label));
+  if(s != OK) {
+      return s;
+  }
+
+  /* Lookup slot by label. */
+  rp = lookup_slot_by_label(label);
+  if(!rp) {
+      if(rs_verbose)
+          printf("RS: do_restart: service '%s' not found\n", label);
+      return(ESRCH);
+  }
+
+  /* Check if the call can be allowed. */
+  if((r = check_call_permission(m_ptr->m_source, RS_RESTART, rp)) != OK)
+      return r;
+
+  /* We can only be asked to restart a service from a recovery script. */
+  if (! (rp->r_flags & RS_TERMINATED) ) {
+      if(rs_verbose)
+          printf("RS: %s is still running\n", srv_to_string(rp));
+      return EBUSY;
+  }
+
+  if(rs_verbose)
+      printf("RS: recovery script performs service restart...\n");
+
+  /* Restart the service, but make sure we don't call the script again. */
+  strcpy(script, rp->r_script);
+  rp->r_script[0] = '\0';
+  restart_service(rp);
+  strcpy(rp->r_script, script);
+
+  return OK;
+}
+
+
+/*===========================================================================*
+ *                             do_refresh                                   *
+ *===========================================================================*/
+PUBLIC int do_refresh(message *m_ptr)
+{
+  register struct rproc *rp;
+  register struct rprocpub *rpub;
+  int s;
+  char label[RS_MAX_LABEL_LEN];
+
+  /* Copy label. */
+  s = copy_label(m_ptr->m_source, m_ptr->RS_CMD_ADDR,
+      m_ptr->RS_CMD_LEN, label, sizeof(label));
+  if(s != OK) {
+      return s;
+  }
+
+  /* Lookup slot by label. */
+  rp = lookup_slot_by_label(label);
+  if(!rp) {
+      if(rs_verbose)
+          printf("RS: do_refresh: service '%s' not found\n", label);
+      return(ESRCH);
+  }
+  rpub = rp->r_pub;
+
+  /* Check if the call can be allowed. */
+  if((s = check_call_permission(m_ptr->m_source, RS_REFRESH, rp)) != OK)
+      return s;
+
+  /* Refresh service. */
+  if(rs_verbose)
+      printf("RS: %s refreshing\n", srv_to_string(rp));
+  stop_service(rp,RS_REFRESHING);
+
+  return OK;
+}
+
+/*===========================================================================*
+ *                             do_shutdown                                  *
+ *===========================================================================*/
+PUBLIC int do_shutdown(message *m_ptr)
+{
+  int slot_nr;
+  struct rproc *rp;
+  int r;
+
+  /* Check if the call can be allowed. */
+  if (m_ptr != NULL) {
+      if((r = check_call_permission(m_ptr->m_source, RS_SHUTDOWN, NULL)) != OK)
+          return r;
+  }
+
+  if(rs_verbose)
+      printf("RS: shutting down...\n");
+
+  /* Set flag to tell RS we are shutting down. */
+  shutting_down = TRUE;
+
+  /* Don't restart dead services. */
+  for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
+      rp = &rproc[slot_nr];
+      if (rp->r_flags & RS_IN_USE) {
+          rp->r_flags |= RS_EXITING;
+      }
+  }
+  return(OK);
+}
+
+/*===========================================================================*
+ *                             do_init_ready                                *
+ *===========================================================================*/
+PUBLIC int do_init_ready(message *m_ptr)
+{
+  int who_p;
+  struct rproc *rp;
+  struct rprocpub *rpub;
+  message m;
+  int result;
+
+  who_p = _ENDPOINT_P(m_ptr->m_source);
+  rp = rproc_ptr[who_p];
+  rpub = rp->r_pub;
+  result = m_ptr->RS_INIT_RESULT;
+
+  /* Make sure the originating service was requested to initialize. */
+  if(! (rp->r_flags & RS_INITIALIZING) ) {
+      if(rs_verbose)
+          printf("RS: do_init_ready: got unexpected init ready msg from %d\n",
+              m_ptr->m_source);
+      return(EDONTREPLY);
+  }
+
+  /* Check if something went wrong and the service failed to init.
+   * In that case, kill the service.
+   */
+  if(result != OK) {
+      if(rs_verbose)
+          printf("RS: %s initialization error: %s\n", srv_to_string(rp),
+              init_strerror(result));
+      crash_service(rp); /* simulate crash */
+      return(EDONTREPLY);
+  }
+
+  /* XXX If the service is a driver, map it. This should be part
+   * of publish_service() but the synchronous nature of mapdriver would
+   * cause a deadlock. The temporary hack is to map the driver here
+   * after initialization is complete.
+   */
+  m.m_type = OK;
+  reply(rpub->endpoint, &m);
+  if (rpub->dev_nr > 0) {
+      if (mapdriver(rpub->label, rpub->dev_nr, rpub->dev_style, 1) != OK) {
+          return kill_service(rp, "couldn't map driver", errno);
+      }
+  }
+
+  /* Mark the slot as no longer initializing. */
+  rp->r_flags &= ~RS_INITIALIZING;
+  rp->r_check_tm = 0;
+  getuptime(&rp->r_alive_tm);
+
+  /* See if a late reply has to be sent. */
+  late_reply(rp, OK);
+
+  if(rs_verbose)
+      printf("RS: %s initialized\n", srv_to_string(rp));
+
+  /* If the service has completed initialization after a live
+   * update, end the update now.
+   */
+  if(rp->r_flags & RS_UPDATING) {
+      printf("RS: update succeeded\n");
+      end_update(OK);
+  }
+
+  /* If the service has completed initialization after a crash
+   * make the new instance active and cleanup the old replica.
+   */
+  if(rp->r_prev_rp) {
+      activate_service(rp, rp->r_prev_rp);
+      cleanup_service(rp->r_prev_rp);
+      rp->r_prev_rp = NULL;
+
+      if(rs_verbose)
+          printf("RS: %s completed restart\n", srv_to_string(rp));
+  }
+
+  return(EDONTREPLY);
+}
+
+/*===========================================================================*
+ *                             do_update                                    *
+ *===========================================================================*/
+PUBLIC int do_update(message *m_ptr)
+{
+  struct rproc *rp;
+  struct rproc *new_rp;
+  struct rprocpub *rpub;
+  struct rprocpub *new_rpub;
+  struct rs_start rs_start;
+  int s;
+  char label[RS_MAX_LABEL_LEN];
+  int lu_state;
+  int prepare_maxtime;
+
+  /* Copy the request structure. */
+  s = copy_rs_start(m_ptr->m_source, m_ptr->RS_CMD_ADDR, &rs_start);
+  if (s != OK) {
+      return s;
+  }
+
+  /* Copy label. */
+  s = copy_label(m_ptr->m_source, rs_start.rss_label.l_addr,
+      rs_start.rss_label.l_len, label, sizeof(label));
+  if(s != OK) {
+      return s;
+  }
+
+  /* Lookup slot by label. */
+  rp = lookup_slot_by_label(label);
+  if(!rp) {
+      if(rs_verbose)
+          printf("RS: do_update: service '%s' not found\n", label);
+      return ESRCH;
+  }
+  rpub = rp->r_pub;
+
+  /* Check if the call can be allowed. */
+  if((s = check_call_permission(m_ptr->m_source, RS_UPDATE, rp)) != OK)
+      return s;
+
+  /* Retrieve live update state. */
+  lu_state = m_ptr->RS_LU_STATE;
+  if(lu_state == SEF_LU_STATE_NULL) {
+      return(EINVAL);
+  }
+
+  /* Retrieve prepare max time. */
+  prepare_maxtime = m_ptr->RS_LU_PREPARE_MAXTIME;
+  if(prepare_maxtime) {
+      if(prepare_maxtime < 0 || prepare_maxtime > RS_MAX_PREPARE_MAXTIME) {
+          return(EINVAL);
+      }
+  }
+  else {
+      prepare_maxtime = RS_DEFAULT_PREPARE_MAXTIME;
+  }
+
+  /* Make sure we are not already updating. */
+  if(rupdate.flags & RS_UPDATING) {
+      if(rs_verbose)
+         printf("RS: do_update: an update is already in progress\n");
+      return EBUSY;
+  }
+
+  /* Allocate a system service slot for the new version. */
+  s = alloc_slot(&new_rp);
+  if(s != OK) {
+      printf("RS: do_update: unable to allocate a new slot: %d\n", s);
+      return s;
+  }
+
+  /* Initialize the slot as requested. */
+  s = init_slot(new_rp, &rs_start, m_ptr->m_source);
+  if(s != OK) {
+      printf("RS: do_update: unable to init the new slot: %d\n", s);
+      return s;
+  }
+
+  /* Let the new version inherit defaults from the old one. */
+  inherit_service_defaults(rp, new_rp);
+
+  /* Create new version of the service but don't let it run. */
+  s = create_service(new_rp);
+  if(s != OK) {
+      printf("RS: do_update: unable to create a new service: %d\n", s);
+      return s;
+  }
+
+  /* Publish process-wide properties. */
+  s = publish_process(new_rp);
+  if (s != OK) {
+      printf("RS: do_update: publish_process failed: %d\n", s);
+      return s;
+  }
+
+  /* Link old version to new version and mark both as updating. */
+  rp->r_new_rp = new_rp;
+  new_rp->r_old_rp = rp;
+  rp->r_flags |= RS_UPDATING;
+  rp->r_new_rp->r_flags |= RS_UPDATING;
+  rupdate.flags |= RS_UPDATING;
+  getuptime(&rupdate.prepare_tm);
+  rupdate.prepare_maxtime = prepare_maxtime;
+  rupdate.rp = rp;
+
+  if(rs_verbose)
+    printf("RS: %s updating\n", srv_to_string(rp));
+
+  /* Request to update. */
+  m_ptr->m_type = RS_LU_PREPARE;
+  asynsend3(rpub->endpoint, m_ptr, AMF_NOREPLY);
+
+  /* Late reply - send a reply when the new version completes initialization. */
+  rp->r_flags |= RS_LATEREPLY;
+  rp->r_caller = m_ptr->m_source;
+  rp->r_caller_request = RS_UPDATE;
+
+  return EDONTREPLY;
+}
+
+/*===========================================================================*
+ *                             do_upd_ready                                 *
+ *===========================================================================*/
+PUBLIC int do_upd_ready(message *m_ptr)
+{
+  struct rproc *rp, *old_rp, *new_rp;
+  int who_p;
+  int result;
+  int r;
+
+  who_p = _ENDPOINT_P(m_ptr->m_source);
+  rp = rproc_ptr[who_p];
+  result = m_ptr->RS_LU_RESULT;
+
+  /* Make sure the originating service was requested to prepare for update. */
+  if(rp != rupdate.rp) {
+      if(rs_verbose)
+          printf("RS: do_upd_ready: got unexpected update ready msg from %d\n",
+              m_ptr->m_source);
+      return(EINVAL);
+  }
+
+  /* Check if something went wrong and the service failed to prepare
+   * for the update. In that case, end the update process. The old version will
+   * be replied to and continue executing.
+   */
+  if(result != OK) {
+      end_update(result);
+
+      printf("RS: update failed: %s\n", lu_strerror(result));
+      return OK;
+  }
+
+  /* Perform the update. */
+  old_rp = rp;
+  new_rp = rp->r_new_rp;
+  r = update_service(&old_rp, &new_rp);
+  if(r != OK) {
+      end_update(r);
+      printf("RS: update failed: error %d\n", r);
+      return r;
+  }
+
+  /* Let the new version run. */
+  r = run_service(new_rp, SEF_INIT_LU);
+  if(r != OK) {
+      update_service(&new_rp, &old_rp); /* rollback, can't fail. */
+      end_update(r);
+      printf("RS: update failed: error %d\n", r);
+      return r;
+  }
+
+  return(EDONTREPLY);
+}
+
+/*===========================================================================*
+ *                             do_period                                    *
+ *===========================================================================*/
+PUBLIC void do_period(m_ptr)
+message *m_ptr;
+{
+  register struct rproc *rp;
+  register struct rprocpub *rpub;
+  clock_t now = m_ptr->NOTIFY_TIMESTAMP;
+  int s;
+  long period;
+
+  /* If an update is in progress, check its status. */
+  if(rupdate.flags & RS_UPDATING) {
+      update_period(m_ptr);
+  }
+
+  /* Search system services table. Only check slots that are in use and not
+   * updating.
+   */
+  for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
+      rpub = rp->r_pub;
+      if ((rp->r_flags & RS_IN_USE) && !(rp->r_flags & RS_UPDATING)) {
+
+          /* Compute period. */
+          period = rpub->period;
+          if(rp->r_flags & RS_INITIALIZING) {
+              period = RS_INIT_T;
+          }
+
+          /* If the service is to be revived (because it repeatedly exited, 
+          * and was not directly restarted), the binary backoff field is  
+          * greater than zero. 
+          */
+         if (rp->r_backoff > 0) {
+              rp->r_backoff -= 1;
+             if (rp->r_backoff == 0) {
+                 restart_service(rp);
+             }
+         }
+
+         /* If the service was signaled with a SIGTERM and fails to respond,
+          * kill the system service with a SIGKILL signal.
+          */
+         else if (rp->r_stop_tm > 0 && now - rp->r_stop_tm > 2*RS_DELTA_T
+          && rp->r_pid > 0) {
+              crash_service(rp); /* simulate crash */
+              rp->r_stop_tm = 0;
+         }
+
+         /* There seems to be no special conditions. If the service has a 
+          * period assigned check its status. 
+          */
+         else if (period > 0) {
+
+             /* Check if an answer to a status request is still pending. If 
+              * the service didn't respond within time, kill it to simulate 
+              * a crash. The failure will be detected and the service will 
+              * be restarted automatically.
+              */
+              if (rp->r_alive_tm < rp->r_check_tm) { 
+                 if (now - rp->r_alive_tm > 2*period &&
+                     rp->r_pid > 0 && !(rp->r_flags & RS_NOPINGREPLY)) { 
+                     if(rs_verbose)
+                           printf("RS: %s reported late\n",
+                               srv_to_string(rp)); 
+                     rp->r_flags |= RS_NOPINGREPLY;
+                      crash_service(rp); /* simulate crash */
+                 }
+             }
+
+             /* No answer pending. Check if a period expired since the last
+              * check and, if so request the system service's status.
+              */
+             else if (now - rp->r_check_tm > rpub->period) {
+                 notify(rpub->endpoint);               /* request status */
+                 rp->r_check_tm = now;                 /* mark time */
+              }
+          }
+      }
+  }
+
+  /* Reschedule a synchronous alarm for the next period. */
+  if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
+      panic("couldn't set alarm: %d", s);
+}
+
+/*===========================================================================*
+ *                               do_sigchld                                 *
+ *===========================================================================*/
+PUBLIC void do_sigchld()
+{
+/* PM informed us that there are dead children to cleanup. Go get them. */
+  pid_t pid;
+  int status;
+  struct rproc *rp;
+  struct rproc **rps;
+  struct rprocpub *rpub;
+  int i, nr_rps;
+
+  if(rs_verbose)
+     printf("RS: got SIGCHLD signal, cleaning up dead children\n");
+
+  while ( (pid = waitpid(-1, &status, WNOHANG)) != 0 ) {
+      rp = lookup_slot_by_pid(pid);
+      if(rp != NULL) {
+          rpub = rp->r_pub;
+
+          if(rs_verbose)
+              printf("RS: %s exited via another signal manager\n",
+                  srv_to_string(rp));
+
+          /* The slot is still there. This means RS is not the signal
+           * manager assigned to the process. Ignore the event but
+           * free slots for all the service instances and send a late
+           * reply if necessary.
+           */
+             get_service_instances(rp, &rps, &nr_rps);
+             for(i=0;i<nr_rps;i++) {
+                 if(rupdate.flags & RS_UPDATING) {
+                     rupdate.flags &= ~RS_UPDATING;
+                 }
+                 free_slot(rps[i]);
+             }
+      }
+  }
+}
+
+/*===========================================================================*
+ *                             do_getsysinfo                                *
+ *===========================================================================*/
+PUBLIC int do_getsysinfo(m_ptr)
+message *m_ptr;
+{
+  vir_bytes src_addr, dst_addr;
+  int dst_proc;
+  size_t len;
+  int s;
+
+  /* Check if the call can be allowed. */
+  if((s = check_call_permission(m_ptr->m_source, 0, NULL)) != OK)
+      return s;
+
+  switch(m_ptr->m1_i1) {
+  case SI_PROC_TAB:
+       src_addr = (vir_bytes) rproc;
+       len = sizeof(struct rproc) * NR_SYS_PROCS;
+       break; 
+  case SI_PROCPUB_TAB:
+       src_addr = (vir_bytes) rprocpub;
+       len = sizeof(struct rprocpub) * NR_SYS_PROCS;
+       break; 
+  default:
+       return(EINVAL);
+  }
+
+  dst_proc = m_ptr->m_source;
+  dst_addr = (vir_bytes) m_ptr->m1_p1;
+  if (OK != (s=sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len)))
+       return(s);
+  return(OK);
+}
+
+/*===========================================================================*
+ *                             do_lookup                                    *
+ *===========================================================================*/
+PUBLIC int do_lookup(m_ptr)
+message *m_ptr;
+{
+       static char namebuf[100];
+       int len, r;
+       struct rproc *rrp;
+       struct rprocpub *rrpub;
+
+       len = m_ptr->RS_NAME_LEN;
+
+       if(len < 2 || len >= sizeof(namebuf)) {
+               printf("RS: len too weird (%d)\n", len);
+               return EINVAL;
+       }
+
+       if((r=sys_vircopy(m_ptr->m_source, D, (vir_bytes) m_ptr->RS_NAME,
+               SELF, D, (vir_bytes) namebuf, len)) != OK) {
+               printf("RS: name copy failed\n");
+               return r;
+
+       }
+
+       namebuf[len] = '\0';
+
+       rrp = lookup_slot_by_label(namebuf);
+       if(!rrp) {
+               return ESRCH;
+       }
+       rrpub = rrp->r_pub;
+       m_ptr->RS_ENDPOINT = rrpub->endpoint;
+
+       return OK;
+}
+
index d34aa8a04732be506ad9a7c7dec585621b54ffb5..1664f69be62d28a4da9b92c8d44a7967d6ac0022 100644 (file)
@@ -49,6 +49,8 @@ PRIVATE char *known_requests[] = {
 #define RUN_CMD                "run"
 #define RUN_SCRIPT     "/etc/rs.single"        /* Default script for 'run' */
 #define PATH_CONFIG    _PATH_SYSTEM_CONF       /* Default config file */
+#define DEFAULT_LU_STATE   3                    /* Default live update state */
+#define DEFAULT_LU_MAXTIME 0                    /* Default lu max time */
 
 /* Define names for arguments provided to this utility. The first few 
  * arguments are required and have a known index. Thereafter, some optional
@@ -60,8 +62,6 @@ PRIVATE char *known_requests[] = {
 #define ARG_REQUEST    0               /* request to perform */
 #define ARG_PATH       1               /* system service */
 #define ARG_LABEL      1               /* name of system service */
-#define ARG_LU_STATE           2       /* the state required to update */
-#define ARG_PREPARE_MAXTIME    3       /* max time to prepare for the update */
 
 #define MIN_ARG_COUNT  1               /* require an action */
 
@@ -75,7 +75,9 @@ PRIVATE char *known_requests[] = {
 #define ARG_CONFIG     "-config"       /* name of the file with the resource
                                         * configuration 
                                         */
-#define ARG_PRINTEP    "-printep"      /* print endpoint number after start */
+
+#define ARG_LU_STATE   "-state"        /* the live update state required */
+#define ARG_LU_MAXTIME "-maxtime"      /* max time to prepare for the update */
 
 #define SERVICE_LOGIN  "service"       /* passwd file entry for services */
 
@@ -95,10 +97,9 @@ PRIVATE long req_period;
 PRIVATE char *req_script;
 PRIVATE char *req_ipc;
 PRIVATE char *req_config = PATH_CONFIG;
-PRIVATE int req_printep;
 PRIVATE int class_recurs;      /* Nesting level of class statements */
-PRIVATE int req_lu_state;
-PRIVATE int req_prepare_maxtime;
+PRIVATE int req_lu_state = DEFAULT_LU_STATE;
+PRIVATE int req_lu_maxtime = DEFAULT_LU_MAXTIME;
 
 /* Buffer to build "/command arg1 arg2 ..." string to pass to RS server. */
 PRIVATE char command[4096];    
@@ -113,12 +114,12 @@ PRIVATE void print_usage(char *app_name, char *problem)
   fprintf(stderr, "Warning, %s\n", problem);
   fprintf(stderr, "Usage:\n");
   fprintf(stderr,
-  "    %s [-c -r] (up|run) <binary> [%s <args>] [%s <special>] [%s <ticks>]\n", 
-       app_name, ARG_ARGS, ARG_DEV, ARG_PERIOD);
+  "    %s [-c -r] (up|run|update) <binary> [%s <args>] [%s <special>] [%s <ticks>] [%s <path>] [%s <name>] [%s <path>] [%s <state>] [%s <time>]\n", 
+       app_name, ARG_ARGS, ARG_DEV, ARG_PERIOD, ARG_SCRIPT, ARG_LABELNAME,
+       ARG_CONFIG, ARG_LU_STATE, ARG_LU_MAXTIME);
   fprintf(stderr, "    %s down label\n", app_name);
   fprintf(stderr, "    %s refresh label\n", app_name);
   fprintf(stderr, "    %s restart label\n", app_name);
-  fprintf(stderr, "    %s update label state maxtime\n", app_name);
   fprintf(stderr, "    %s shutdown\n", app_name);
   fprintf(stderr, "\n");
 }
@@ -196,7 +197,9 @@ PRIVATE int parse_arguments(int argc, char **argv)
        req_nr = RS_RQ_BASE + req_type;
   }
 
-  if (req_nr == RS_UP) {
+  if (req_nr == RS_UP || req_nr == RS_UPDATE) {
+      u32_t system_hz;
+
       rs_start.rss_flags= RSS_IPC_VALID;
       if (c_flag)
        rs_start.rss_flags |= RSS_COPY;
@@ -233,6 +236,14 @@ PRIVATE int parse_arguments(int argc, char **argv)
           exit(EINVAL);
       }
 
+      /* Get HZ. */
+      if(getsysinfo_up(PM_PROC_NR,
+          SIU_SYSTEMHZ, sizeof(system_hz), &system_hz) < 0) {
+          system_hz = DEFAULT_HZ;
+          fprintf(stderr, "WARNING: reverting to default HZ %d\n",
+              system_hz);
+      }
+
       /* Check optional arguments that come in pairs like "-args arglist". */
       for (i=optind+MIN_ARG_COUNT+1; i<argc; i=i+2) {
           if (! (i+1 < argc)) {
@@ -243,14 +254,6 @@ PRIVATE int parse_arguments(int argc, char **argv)
               req_args = argv[i+1];
           }
           else if (strcmp(argv[i], ARG_PERIOD)==0) {
-               u32_t system_hz;
-               if(getsysinfo_up(PM_PROC_NR,
-                       SIU_SYSTEMHZ, sizeof(system_hz), &system_hz) < 0) {
-                       system_hz = DEFAULT_HZ;
-                       fprintf(stderr, "WARNING: reverting to default HZ %d\n",
-                               system_hz);
-               } 
-
              req_period = strtol(argv[i+1], &hz, 10);
              if (strcmp(hz,"HZ")==0) req_period *= system_hz;
              if (req_period < 1) {
@@ -280,8 +283,30 @@ PRIVATE int parse_arguments(int argc, char **argv)
           else if (strcmp(argv[i], ARG_CONFIG)==0) {
               req_config = argv[i+1];
           }
-          else if (strcmp(argv[i], ARG_PRINTEP)==0) {
-              req_printep = 1;
+          else if (strcmp(argv[i], ARG_LU_STATE)==0) {
+              errno=0;
+              req_lu_state = strtol(argv[i+1], &buff, 10);
+              if(errno || strcmp(buff, "")) {
+                  print_usage(argv[ARG_NAME],
+                    "bad live update state");
+                  exit(EINVAL);
+              }
+              if(req_lu_state == SEF_LU_STATE_NULL) {
+                  print_usage(argv[ARG_NAME],
+                      "null live update state.");
+                  exit(EINVAL);
+              }
+          }
+          else if (strcmp(argv[i], ARG_LU_MAXTIME)==0) {
+              errno=0;
+              req_lu_maxtime = strtol(argv[i+1], &hz, 10);
+              if(errno || (strcmp(hz, "") && strcmp(hz, "HZ"))
+                  || req_lu_maxtime<0) {
+                  print_usage(argv[ARG_NAME],
+                      "bad live update max time");
+                  exit(EINVAL);
+              }
+              if (strcmp(hz,"HZ")==0) req_lu_maxtime *= system_hz;
           }
           else {
               print_usage(argv[ARG_NAME], "unknown optional argument given");
@@ -301,43 +326,6 @@ PRIVATE int parse_arguments(int argc, char **argv)
   else if (req_nr == RS_SHUTDOWN) {
         /* no extra arguments required */
   }
-  else if (req_nr == RS_UPDATE) {
-      /* Check for mandatory arguments */ 
-      if (argc - 1 < optind+ARG_LU_STATE) {
-          print_usage(argv[ARG_NAME],
-              "action requires at least a label and a live update state");
-          exit(EINVAL);
-      }
-      
-      /* Label. */
-      req_label= argv[optind+ARG_LABEL];
-      
-      /* Live update state. */
-      errno=0;
-      req_lu_state=strtol(argv[optind+ARG_LU_STATE], &buff, 10);
-      if(errno || strcmp(buff, "")) {
-          print_usage(argv[ARG_NAME],
-              "action requires a correct live update state");
-          exit(EINVAL);
-      }
-      if(req_lu_state == SEF_LU_STATE_NULL) {
-          print_usage(argv[ARG_NAME],
-              "action requires a non-null live update state.");
-          exit(EINVAL);
-      }
-      
-      /* Prepare max time. */
-      req_prepare_maxtime=0;
-      if (argc - 1 >= optind+ARG_PREPARE_MAXTIME) {
-          req_prepare_maxtime=strtol(argv[optind+ARG_PREPARE_MAXTIME],
-              &buff, 10);
-          if(errno || strcmp(buff, "") || req_prepare_maxtime<0) {
-              print_usage(argv[ARG_NAME],
-                "action requires a correct max time to prepare for the update");
-              exit(EINVAL);
-          }
-      }
-  }
 
   /* Return the request number if no error were found. */
   return(req_nr);
@@ -714,7 +702,6 @@ struct
        int call_nr;
 } system_tab[]=
 {
-       { "EXIT",               SYS_EXIT },
        { "PRIVCTL",            SYS_PRIVCTL },
        { "TRACE",              SYS_TRACE },
        { "KILL",               SYS_KILL },
@@ -725,21 +712,9 @@ struct
        { "DEVIO",              SYS_DEVIO },
        { "SDEVIO",             SYS_SDEVIO },
        { "VDEVIO",             SYS_VDEVIO },
-       { "SETALARM",           SYS_SETALARM },
-       { "TIMES",              SYS_TIMES },
-       { "GETINFO",            SYS_GETINFO },
-       { "SAFECOPYFROM",       SYS_SAFECOPYFROM },
-       { "SAFECOPYTO",         SYS_SAFECOPYTO },
-       { "SAFEMAP",            SYS_SAFEMAP },
-       { "SAFEREVMAP",         SYS_SAFEREVMAP },
-       { "SAFEUNMAP",          SYS_SAFEUNMAP },
-       { "VSAFECOPY",          SYS_VSAFECOPY },
-       { "SETGRANT",           SYS_SETGRANT },
        { "READBIOS",           SYS_READBIOS },
-       { "PROFBUF",            SYS_PROFBUF },
        { "STIME",              SYS_STIME },
        { "VMCTL",              SYS_VMCTL },
-       { "SYSCTL",             SYS_SYSCTL },
        { NULL,         0 }
 };
 
@@ -836,10 +811,7 @@ PRIVATE void do_vm(config_t *cpe)
 
 PRIVATE void do_system(config_t *cpe)
 {
-       int i, call_nr, word, bits_per_word;
-       unsigned long mask;
-
-       bits_per_word= sizeof(rs_start.rss_system[0])*8;
+       int i, call_nr;
 
        /* Process a list of 'system' calls that are allowed */
        for (; cpe; cpe= cpe->next)
@@ -855,38 +827,13 @@ PRIVATE void do_system(config_t *cpe)
                                cpe->file, cpe->line);
                }
 
-               /* Get call number */
-               for (i= 0; system_tab[i].label != NULL; i++)
-               {
-                       if (strcmp(cpe->word, system_tab[i].label) == 0)
+               for (i = 0; system_tab[i].label != NULL; i++)
+                       if (!strcmp(cpe->word, system_tab[i].label))
                                break;
-               }
                if (system_tab[i].label == NULL)
-               {
                        fatal("do_system: unknown call '%s' at %s:%d",
                                cpe->word, cpe->file, cpe->line);
-               }
-               call_nr= system_tab[i].call_nr;
-
-               /* Subtract KERNEL_CALL */
-               if (call_nr < KERNEL_CALL)
-               {
-                       fatal(
-               "do_system: bad call number %d in system tab for '%s'",
-                               call_nr, system_tab[i].label);
-               }
-               call_nr -= KERNEL_CALL;
-
-               word= call_nr / bits_per_word;
-               mask= (1UL << (call_nr % bits_per_word));
-
-               if (word >= RS_SYS_CALL_MASK_SIZE)
-               {
-                       fatal(
-                       "RS_SYS_CALL_MASK_SIZE is too small (%d needed)",
-                               word+1);
-               }
-               rs_start.rss_system[word] |= mask;
+               SET_BIT(rs_start.rss_system, system_tab[i].call_nr - KERNEL_CALL);
        }
 }
 
@@ -1081,19 +1028,20 @@ PUBLIC int main(int argc, char **argv)
    */
   request = parse_arguments(argc, argv);
 
-  if(req_path) {
-       /* Obtain binary name. */
-       progname = strrchr(req_path, '/');
-       assert(progname);       /* an absolute path was required */
-       progname++;     /* skip last slash */
-  }
-
   /* Arguments seem fine. Try to perform the request. Only valid requests 
    * should end up here. The default is used for not yet supported requests. 
    */
+  result = OK;
   switch(request) {
+  case RS_UPDATE:
+      m.RS_LU_STATE = req_lu_state;
+      m.RS_LU_PREPARE_MAXTIME = req_lu_maxtime;
+      /* fall through */
   case RS_UP:
       /* Build space-separated command string to be passed to RS server. */
+      progname = strrchr(req_path, '/');
+      assert(progname);        /* an absolute path was required */
+      progname++;      /* skip last slash */
       strcpy(command, req_path);
       command[strlen(req_path)] = ' ';
       strcpy(command+strlen(req_path)+1, req_args);
@@ -1137,39 +1085,27 @@ PUBLIC int main(int argc, char **argv)
       }
 
       m.RS_CMD_ADDR = (char *) &rs_start;
-
-      /* Build request message and send the request. */
-      if (_syscall(RS_PROC_NR, request, &m) == -1) 
-          failure();
-      else if(req_printep)
-       printf("%d\n", m.RS_ENDPOINT);  
-      result = m.m_type;
       break;
-
   case RS_DOWN:
   case RS_REFRESH:
   case RS_RESTART:
       m.RS_CMD_ADDR = req_label;
       m.RS_CMD_LEN = strlen(req_label);
-      if (_syscall(RS_PROC_NR, request, &m) == -1) 
-          failure();
       break;
   case RS_SHUTDOWN:
-      if (_syscall(RS_PROC_NR, request, &m) == -1) 
-          failure();
-      break;
-  case RS_UPDATE:
-      m.RS_CMD_ADDR = req_label;
-      m.RS_CMD_LEN = strlen(req_label);
-      m.RS_LU_STATE = req_lu_state;
-      m.RS_LU_PREPARE_MAXTIME = req_prepare_maxtime;
-      if (_syscall(RS_PROC_NR, request, &m) == -1) 
-          failure();
       break;
   default:
       print_usage(argv[ARG_NAME], "request is not yet supported");
       result = EGENERIC;
   }
+
+  /* Build request message and send the request. */
+  if(result == OK) {
+    if (_syscall(RS_PROC_NR, request, &m) == -1) 
+        failure();
+    result = m.m_type;
+  }
+
   return(result);
 }
 
index 19994afa91c6d17554ba9ddf785a2d01650a90de..bddf9d13c7eb246a6f257d27a02338263e5f3704 100644 (file)
  * Calls are unordered lists, converted by RS to bitmasks
  * once at runtime.
  */
-#define FS_KC   SYS_KILL, SYS_VIRCOPY, SYS_SAFECOPYFROM, SYS_SAFECOPYTO, \
-    SYS_UMAP, SYS_GETINFO, SYS_EXIT, SYS_TIMES, SYS_SETALARM, \
-    SYS_PRIVCTL, SYS_TRACE , SYS_SETGRANT, SYS_PROFBUF, SYS_SYSCTL, \
-    SYS_SAFEMAP, SYS_SAFEREVMAP, SYS_SAFEUNMAP
-#define DRV_KC FS_KC, SYS_SEGCTL, SYS_IRQCTL, SYS_INT86, SYS_DEVIO, \
-    SYS_SDEVIO, SYS_VDEVIO, SYS_SETGRANT, SYS_PROFBUF, SYS_SYSCTL
+#define FS_KC   SYS_BASIC_CALLS, SYS_TRACE, SYS_UMAP, SYS_VIRCOPY, SYS_KILL
+#define DRV_KC SYS_BASIC_CALLS, SYS_TRACE, SYS_UMAP, SYS_VIRCOPY, SYS_SEGCTL, \
+    SYS_IRQCTL, SYS_INT86, SYS_DEVIO, SYS_SDEVIO, SYS_VDEVIO
 
 PRIVATE int
   pm_kc[] =   { SYS_ALL_C, SYS_NULL_C },
@@ -26,7 +23,7 @@ PRIVATE int
   rs_kc[] =   { SYS_ALL_C, SYS_NULL_C },
   ds_kc[] =   { SYS_ALL_C, SYS_NULL_C },
   vm_kc[] =   { SYS_ALL_C, SYS_NULL_C },
-  tty_kc[] =  { DRV_KC, SYS_PHYSCOPY, SYS_ABORT, SYS_IOPENABLE,
+  tty_kc[] =  { DRV_KC, SYS_KILL, SYS_PHYSCOPY, SYS_ABORT, SYS_IOPENABLE,
       SYS_READBIOS, SYS_NULL_C },
   mem_kc[] =  { DRV_KC, SYS_PHYSCOPY, SYS_IOPENABLE, SYS_NULL_C},
   log_kc[] =  { DRV_KC, SYS_NULL_C },
@@ -45,7 +42,7 @@ PRIVATE int
       VM_PUSH_SIG, VM_WILLEXIT, VM_ADDDMA, VM_DELDMA, VM_GETDMA,
       VM_NOTIFY_SIG, SYS_NULL_C },
   vfs_vmc[] =  { VM_BASIC_CALLS, SYS_NULL_C },
-  rs_vmc[] =   { VM_BASIC_CALLS, VM_RS_SET_PRIV, SYS_NULL_C },
+  rs_vmc[] =   { VM_BASIC_CALLS, VM_RS_SET_PRIV, VM_RS_UPDATE, SYS_NULL_C },
   ds_vmc[] =   { VM_BASIC_CALLS, SYS_NULL_C },
   vm_vmc[] =   { SYS_NULL_C },
   tty_vmc[] =  { VM_BASIC_CALLS, SYS_NULL_C },
@@ -61,19 +58,19 @@ PRIVATE int
  * at boot time.
  */
 PUBLIC struct boot_image_priv boot_image_priv_table[] = {
-  /*endpoint,     label,      flags,  traps,  ipcto,  kcalls,  vmcalls  */
-  { RS_PROC_NR,   "rs",       RSYS_F, RSYS_T, RSYS_M, rs_kc,   rs_vmc   },
-  { VM_PROC_NR,   "vm",       VM_F,   SRV_T,  SRV_M,  vm_kc,   vm_vmc   },
-  { PM_PROC_NR,   "pm",       SRV_F,  SRV_T,  SRV_M,  pm_kc,   pm_vmc   },
-  { VFS_PROC_NR,  "vfs",      SRV_F,  SRV_T,  SRV_M,  vfs_kc,  vfs_vmc  },
-  { DS_PROC_NR,   "ds",       SRV_F,  SRV_T,  SRV_M,  ds_kc,   ds_vmc   },
-  { TTY_PROC_NR,  "tty",      SRV_F,  SRV_T,  SRV_M,  tty_kc,  tty_vmc  },
-  { MEM_PROC_NR,  "memory",   SRV_F,  SRV_T,  SRV_M,  mem_kc,  mem_vmc  },
-  { LOG_PROC_NR,  "log",      SRV_F,  SRV_T,  SRV_M,  log_kc,  log_vmc  },
-  { MFS_PROC_NR,  "fs_imgrd", SRV_F,  SRV_T,  SRV_M,  mfs_kc,  mfs_vmc  },
-  { PFS_PROC_NR,  "pfs",      SRV_F,  SRV_T,  SRV_M,  pfs_kc,  pfs_vmc  },
-  { INIT_PROC_NR, "init",     RUSR_F, RUSR_T, RUSR_M, rusr_kc, rusr_vmc },
-  { NULL_BOOT_NR, "",         0,      0,      0,      no_kc,   no_vmc   }
+/*endpoint,     label,     flags,  traps,  ipcto,  sigmgr,  kcalls,  vmcalls */
+{RS_PROC_NR,   "rs",       RSYS_F, RSYS_T, RSYS_M, RSYS_SM, rs_kc,   rs_vmc   },
+{VM_PROC_NR,   "vm",       VM_F,   SRV_T,  SRV_M,  SRV_SM,  vm_kc,   vm_vmc   },
+{PM_PROC_NR,   "pm",       SRV_F,  SRV_T,  SRV_M,  SRV_SM,  pm_kc,   pm_vmc   },
+{VFS_PROC_NR,  "vfs",      SRV_F,  SRV_T,  SRV_M,  SRV_SM,  vfs_kc,  vfs_vmc  },
+{DS_PROC_NR,   "ds",       SRV_F,  SRV_T,  SRV_M,  SRV_SM,  ds_kc,   ds_vmc   },
+{TTY_PROC_NR,  "tty",      SRV_F,  SRV_T,  SRV_M,  SRV_SM,  tty_kc,  tty_vmc  },
+{MEM_PROC_NR,  "memory",   SRV_F,  SRV_T,  SRV_M,  SRV_SM,  mem_kc,  mem_vmc  },
+{LOG_PROC_NR,  "log",      SRV_F,  SRV_T,  SRV_M,  SRV_SM,  log_kc,  log_vmc  },
+{MFS_PROC_NR,  "fs_imgrd", SRV_F,  SRV_T,  SRV_M,  SRV_SM,  mfs_kc,  mfs_vmc  },
+{PFS_PROC_NR,  "pfs",      SRV_F,  SRV_T,  SRV_M,  SRV_SM,  pfs_kc,  pfs_vmc  },
+{INIT_PROC_NR, "init",     RUSR_F, RUSR_T, RUSR_M, RUSR_SM, rusr_kc, rusr_vmc },
+{NULL_BOOT_NR, "",         0,      0,      0,      0,       no_kc,   no_vmc   }
 };
 
 /* Definition of the boot image sys table. */
index 3fce4533f67e2756c369bcd4e94d71a13420d96a..9b57dd877af5a5d7014f8bbbe411252437bcbf1c 100644 (file)
@@ -11,6 +11,7 @@ struct boot_image_priv {
   int flags;                   /* privilege flags */
   short trap_mask;             /* allowed system call traps */
   int ipc_to;                  /* send mask protection */
+  endpoint_t sig_mgr;          /* signal manager */
   int *k_calls;                /* allowed kernel calls */
   int *vm_calls;               /* allowed vm calls */
 };
@@ -34,6 +35,10 @@ struct boot_image_dev {
 /* Definition of an entry of the system process table. */
 struct rproc {
   struct rprocpub *r_pub;       /* pointer to the corresponding public entry */
+  struct rproc *r_old_rp;       /* pointer to the slot with the old version */
+  struct rproc *r_new_rp;       /* pointer to the slot with the new version */
+  struct rproc *r_prev_rp;      /* pointer to the slot with the prev replica */
+  struct rproc *r_next_rp;      /* pointer to the slot with the next replica */
   pid_t r_pid;                 /* process id, -1 if the process is not there */
 
   int r_restarts;              /* number of restarts (initially zero) */
@@ -44,11 +49,13 @@ struct rproc {
   clock_t r_alive_tm;          /* timestamp of last heartbeat */
   clock_t r_stop_tm;           /* timestamp of SIGTERM signal */
   endpoint_t r_caller;         /* RS_LATEREPLY caller */
+  int r_caller_request;                /* RS_LATEREPLY caller request */
 
   char r_cmd[MAX_COMMAND_LEN]; /* raw command plus arguments */
-  char r_script[MAX_SCRIPT_LEN]; /* name of the restart script executable */
+  char r_args[MAX_COMMAND_LEN];        /* null-separated raw command plus arguments */
   char *r_argv[MAX_NR_ARGS+2];  /* parsed arguments vector */
   int r_argc;                          /* number of arguments */
+  char r_script[MAX_SCRIPT_LEN]; /* name of the restart script executable */
 
   char *r_exec;                        /* Executable image */ 
   size_t r_exec_len;           /* Length of image */
@@ -60,7 +67,6 @@ struct rproc {
   uid_t r_uid;
   int r_nice;
 
-  u32_t r_call_mask[RS_SYS_CALL_MASK_SIZE];
   char r_ipc_list[MAX_IPC_LIST];
   int r_nr_control;
   char r_control[RS_NR_CONTROL][RS_MAX_LABEL_LEN];
index 0845206d66e991dd11ca6dee3221218075459b2c..30dfb78e1c62ab75f0406b2bf3eb623ce604ac73 100644 (file)
@@ -6,8 +6,6 @@
 
 #include "inc.h"
 
-#include <minix/ds.h>
-
 /*===========================================================================*
  *                              init_service                                *
  *===========================================================================*/
@@ -32,31 +30,6 @@ int type;                                    /* type of initialization */
   return r;
 }
 
-/*===========================================================================*
- *                             publish_service                              *
- *===========================================================================*/
-PUBLIC int publish_service(rp)
-struct rproc *rp;                              /* pointer to process slot */
-{
-/* A new system service has been started. Publish the necessary information. */
-  int s;
-  struct rprocpub *rpub;
-
-  rpub = rp->r_pub;
-
-  /* Register its label with DS. */
-  s= ds_publish_label(rpub->label, rpub->endpoint, DSF_OVERWRITE);
-  if (s != OK) {
-      return s;
-  }
-  if (rs_verbose) {
-      printf("RS: publish_service: DS label registration done: %s -> %d\n", 
-          rpub->label, rpub->endpoint);
-  }
-
-  return(OK);
-}
-
 /*===========================================================================*
  *                           fill_call_mask                                 *
  *===========================================================================*/
@@ -99,3 +72,91 @@ int is_init;                    /* set when initializing a call mask */
   }
 }
 
+/*===========================================================================*
+ *                          srv_to_string                                   *
+ *===========================================================================*/
+PUBLIC char* srv_to_string(rp)
+struct rproc *rp;                      /* pointer to process slot */
+{
+  struct rprocpub *rpub;
+  int slot_nr;
+  char *srv_string;
+  static char srv_string_pool[3][RS_MAX_LABEL_LEN + (DEBUG ? 256 : 64)];
+  static int srv_string_pool_index = 0;
+
+  rpub = rp->r_pub;
+  slot_nr = rp - rproc;
+  srv_string = srv_string_pool[srv_string_pool_index];
+  srv_string_pool_index = (srv_string_pool_index + 1) % 3;
+
+#define srv_str(cmd) ((cmd) == NULL || (cmd)[0] == '\0' ? "_" : (cmd))
+#define srv_ep_str(rp) (itoa((rp)->r_pub->endpoint))
+#define srv_active_str(rp) ((rp)->r_flags & RS_ACTIVE ? "*" : " ")
+#define srv_version_str(rp) ((rp)->r_new_rp || (rp)->r_next_rp ? "-" : \
+    ((rp)->r_old_rp || (rp)->r_prev_rp ? "+" : " "))
+
+#if DEBUG
+  sprintf(srv_string, "service '%s'%s%s(slot %d, ep %d, pid %d, cmd %s, script %s, proc %s, major %d, style %d, flags 0x%03x, sys_flags 0x%02x)",
+      rpub->label, srv_active_str(rp), srv_version_str(rp),
+      slot_nr, rpub->endpoint, rp->r_pid, srv_str(rp->r_cmd),
+      srv_str(rp->r_script), srv_str(rpub->proc_name), rpub->dev_nr,
+      rpub->dev_style, rp->r_flags, rpub->sys_flags);
+#else
+  sprintf(srv_string, "service '%s'%s%s(slot %d, ep %d, pid %d)",
+      rpub->label, srv_active_str(rp), srv_version_str(rp),
+      slot_nr, rpub->endpoint, rp->r_pid);
+#endif
+
+  return srv_string;
+}
+
+/*===========================================================================*
+ *                             reply                                        *
+ *===========================================================================*/
+PUBLIC void reply(who, m_ptr)
+endpoint_t who;                                /* replyee */
+message *m_ptr;                         /* reply message */
+{
+  int r;                               /* send status */
+
+  r = sendnb(who, m_ptr);              /* send the message */
+  if (r != OK)
+      printf("RS: unable to send reply to %d: %d\n", who, r);
+}
+
+/*===========================================================================*
+ *                           late_reply                                     *
+ *===========================================================================*/
+PUBLIC void late_reply(rp, code)
+struct rproc *rp;                              /* pointer to process slot */
+int code;                                      /* status code */
+{
+/* If a caller is waiting for a reply, unblock it. */
+  struct rprocpub *rpub;
+
+  rpub = rp->r_pub;
+
+  if(rp->r_flags & RS_LATEREPLY) {
+      message m;
+      m.m_type = code;
+      if(rs_verbose)
+          printf("RS: %s late reply %d to %d for request %d\n",
+              srv_to_string(rp), code, rp->r_caller, rp->r_caller_request);
+
+      reply(rp->r_caller, &m);
+      rp->r_flags &= ~RS_LATEREPLY;
+  }
+}
+
+/*===========================================================================*
+ *                             rs_isokendpt                                 *
+ *===========================================================================*/
+PUBLIC int rs_isokendpt(int endpoint, int *proc)
+{
+       *proc = _ENDPOINT_P(endpoint);
+       if(*proc < -NR_TASKS || *proc >= NR_PROCS)
+               return EINVAL;
+
+       return OK;
+}
+
index 120e624c30705365face23f28e6b12d8cb36498a..39eca07ca83e02b7b330c491cf408898d5e791ab 100644 (file)
@@ -52,7 +52,8 @@ PRIVATE struct dmap init_dmap[] = {
   DT(0, 0,       0,       0,           DMAP_MUTABLE, "")   /*14 = not used   */
   DT(1, gen_opcl, gen_io,  LOG_PROC_NR, 0, "")             /*15 = /dev/klog  */
   DT(0, no_dev,   0,       NONE,       DMAP_MUTABLE, "")   /*16 = /dev/random*/
-  DT(0, 0,       0,       0,           DMAP_MUTABLE, "")   /*17 = not used   */
+  DT(0, no_dev,          0,       0,           DMAP_MUTABLE, "")   /*17 = /dev/hello */
+  DT(0, 0,       0,       0,           DMAP_MUTABLE, "")   /*18 = not used   */
 #endif /* IBM_PC */
 };
 
index 0a47eb88a03ee4c9c57b982f3f2bebe8ff9cd611..aab220f81240c5fceafdb2fc9c237f0a5afed716 100644 (file)
@@ -106,11 +106,7 @@ PUBLIC int main(void)
 
        /* Check for special control messages first. */
         if (is_notify(call_nr)) {
-               if (who_p == PM_PROC_NR)
-               {
-                       /* Signaled by PM, ignore. */
-               }
-               else if (who_p == CLOCK)
+               if (who_p == CLOCK)
                {
                        /* Alarm timer expired. Used only for select().
                         * Check it.
@@ -198,7 +194,7 @@ PRIVATE void sef_local_startup()
 {
   /* Register init callbacks. */
   sef_setcb_init_fresh(sef_cb_init_fresh);
-  sef_setcb_init_restart(sef_cb_init_restart_fail);
+  sef_setcb_init_restart(sef_cb_init_fail);
 
   /* No live update support for now. */
 
@@ -560,10 +556,10 @@ PRIVATE void service_pm()
        break;
 
   case PM_FORK:
-  case PM_FORK_NB:
+  case PM_SRV_FORK:
        pm_fork(m_in.PM_PPROC, m_in.PM_PROC, m_in.PM_CPID);
 
-       m_out.m_type = (call_nr == PM_FORK) ? PM_FORK_REPLY : PM_FORK_NB_REPLY;
+       m_out.m_type = (call_nr == PM_FORK) ? PM_FORK_REPLY : PM_SRV_FORK_REPLY;
        m_out.PM_PROC = m_in.PM_PROC;
 
        break;
index 3e5e78f65207dd5451c7c154d17aa3f834c4e153..064990f8bb32edcf5502d5177fc2f70c67167741 100644 (file)
@@ -117,7 +117,7 @@ PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = {
        no_sys,         /* 99 = (cprofile) */
        /* THE MINIX3 ABI ENDS HERE */
        no_sys,         /* 100 = (exec_newmem) */
-       no_sys,         /* 101 = (fork_nb) */
+       no_sys,         /* 101 = (srv_fork) */
        no_sys,         /* 102 = (exec_restart) */
        no_sys,         /* 103 = (procstat) */
        no_sys,         /* 104 = (getprocnr) */
@@ -127,6 +127,7 @@ PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = {
        no_sys,         /* 108 = (adddma) */
        no_sys,         /* 109 = (deldma) */
        no_sys,         /* 110 = (getdma) */
+       no_sys,         /* 111 = (srv_kill) */
 };
 /* This should not fail with "array size is negative": */
 extern int dummy[sizeof(call_vec) == NCALLS * sizeof(call_vec[0]) ? 1 : -1];
index 7990684a038f9ae8e642d6070325029779fadfc5..3af26c56fe54e739ceea05c567ceecd80d5395d4 100644 (file)
@@ -119,13 +119,3 @@ PUBLIC int do_willexit(message *msg)
        return OK;
 }
 
-PUBLIC void _exit(int code)
-{
-        sys_exit(SELF);
-}
-
-PUBLIC void __exit(int code)
-{
-        sys_exit(SELF);
-}
-
index 34184e27c7bec105467ec76703907fc9b4f4bd44..55311bdc605ede55f39a602c749ff971bb136fba 100644 (file)
@@ -1,5 +1,7 @@
 
-#define _SYSTEM 1
+#define _POSIX_SOURCE      1
+#define _MINIX             1
+#define _SYSTEM            1
 
 #include <minix/callnr.h>
 #include <minix/com.h>
@@ -39,6 +41,8 @@ extern int missing_spares;
 #include "../../kernel/config.h" 
 #include "../../kernel/proc.h"
 
+#include <signal.h>
+
 /* Table of calls and a macro to test for being in range. */
 struct {
        int (*vmc_func)(message *);     /* Call handles message. */
@@ -61,6 +65,7 @@ extern int unmap_ok;
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
+FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
 
 /*===========================================================================*
  *                             main                                         *
@@ -69,6 +74,7 @@ PUBLIC int main(void)
 {
   message msg;
   int result, who_e;
+  sigset_t sigset;
 
   /* SEF local startup. */
   sef_local_startup();
@@ -89,27 +95,8 @@ PUBLIC int main(void)
        SANITYCHECK(SCL_DETAIL);
 
        if(msg.m_type & NOTIFY_MESSAGE) {
-               switch(msg.m_source) {
-                       case SYSTEM:
-                               /* Kernel wants to have memory ranges
-                                * verified, and/or pagefaults handled.
-                                */
-                               do_memory();
-                               break;
-                       case HARDWARE:
-                               do_pagefaults();
-                               break;
-                       case PM_PROC_NR:
-                               /* PM sends a notify() on shutdown, which
-                                * is OK and we ignore.
-                                */
-                               break;
-                       default:
-                               /* No-one else should send us notifies. */
-                               printf("VM: ignoring notify() from %d\n",
-                                       msg.m_source);
-                               break;
-               }
+               /* Unexpected notify(). */
+               printf("VM: ignoring notify() from %d\n", msg.m_source);
                continue;
        }
        who_e = msg.m_source;
@@ -152,10 +139,13 @@ PRIVATE void sef_local_startup()
 {
   /* Register init callbacks. */
   sef_setcb_init_fresh(sef_cb_init_fresh);
-  sef_setcb_init_restart(sef_cb_init_restart_fail);
+  sef_setcb_init_restart(sef_cb_init_fail);
 
   /* No live update support for now. */
 
+  /* Register signal callbacks. */
+  sef_setcb_signal_handler(sef_cb_signal_handler);
+
   /* Let SEF perform startup. */
   sef_startup();
 }
@@ -341,6 +331,7 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
 
        /* Calls from RS */
        CALLMAP(VM_RS_SET_PRIV, do_rs_set_priv);
+       CALLMAP(VM_RS_UPDATE, do_rs_update);
 
        /* Generic calls. */
        CALLMAP(VM_REMAP, do_remap);
@@ -377,6 +368,24 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
        return(OK);
 }
 
+/*===========================================================================*
+ *                         sef_cb_signal_handler                            *
+ *===========================================================================*/
+PRIVATE void sef_cb_signal_handler(int signo)
+{
+       /* Check for known kernel signals, ignore anything else. */
+       switch(signo) {
+               /* There is a pending memory request from the kernel. */
+               case SIGKMEM:
+                       do_memory();
+               break;
+               /* There is a pending page fault request from the kernel. */
+               case SIGKPF:
+                       do_pagefaults();
+               break;
+       }
+}
+
 /*===========================================================================*
  *                            map_service                                   *
  *===========================================================================*/
index 0cbb2dc349c37d195ee627a80eba25cf6f46421e..5364585db6e7422f58217f3201469e51a8f06eae 100644 (file)
@@ -145,7 +145,7 @@ PRIVATE int do_map_memory(struct vmproc *vms, struct vmproc *vmd,
        physr_start_iter(vrs->phys, &iter, offset_s, AVL_EQUAL);
        prs = physr_get_iter(&iter);
        if(!prs)
-               panic("map_memory: no aligned phys region: %d", 0);
+               panic("do_map_memory: no aligned phys region: %d", 0);
 
        /* flag: 0 -> read-only
         *       1 -> writable
@@ -230,10 +230,10 @@ PUBLIC int map_memory(endpoint_t sour, endpoint_t dest,
        int r;
 
        if(vm_isokendpt(sour, &p) != OK)
-               panic("handle_memory: endpoint wrong: %d", sour);
+               panic("map_memory: bad endpoint: %d", sour);
        vms = &vmproc[p];
        if(vm_isokendpt(dest, &p) != OK)
-               panic("handle_memory: endpoint wrong: %d", dest);
+               panic("map_memory: bad endpoint: %d", dest);
        vmd = &vmproc[p];
 
        vrs = map_lookup(vms, virt_s);
@@ -251,30 +251,12 @@ PUBLIC int map_memory(endpoint_t sour, endpoint_t dest,
        map_handle_memory(vms, vrs, offset_s, length, 0);
 
        /* Prepare work. */
-       #define map_printregion(x, y) (x = x)
-       #define printf(x, y, z) (z = z)
-       printf("before clean with offset, length: %d, %d\n", offset_s, length);
-       map_printregion(vms, vrs);
        clean_phys_regions(vrs, offset_s, length);
-       printf("after clean with offset, length: %d, %d\n", offset_s, length);
-       map_printregion(vms, vrs);
-
-       printf("before clean with offset, length: %d, %d\n", offset_d, length);
-       map_printregion(vmd, vrd);
        clean_phys_regions(vrd, offset_d, length);
-       printf("after clean with offset, length: %d, %d\n", offset_d, length);
-       map_printregion(vmd, vrd);
-
        rm_phys_regions(vrd, offset_d, length);
-       printf("after rm with offset, length: %d, %d\n", offset_d, length);
-       map_printregion(vmd, vrd);
 
        /* Map memory. */
        r = do_map_memory(vms, vmd, vrs, vrd, offset_s, offset_d, length, flag);
-       printf("after map (dst) with offset, length: %d, %d\n", offset_d, length);
-       map_printregion(vmd, vrd);
-       #undef map_printregion
-       #undef printf
 
        return r;
 }
@@ -295,7 +277,7 @@ PUBLIC int unmap_memory(endpoint_t sour, endpoint_t dest,
 
        /* Use information on the destination process to unmap. */
        if(vm_isokendpt(dest, &p) != OK)
-               panic("handle_memory: endpoint wrong: %d", dest);
+               panic("unmap_memory: bad endpoint: %d", dest);
        vmd = &vmproc[p];
 
        vrd = map_lookup(vmd, virt_d);
@@ -306,7 +288,7 @@ PUBLIC int unmap_memory(endpoint_t sour, endpoint_t dest,
        physr_start_iter(vrd->phys, &iter, off, AVL_EQUAL);
        pr = physr_get_iter(&iter);
        if(!pr)
-               panic("map_memory: no aligned phys region: %d", 0);
+               panic("unmap_memory: no aligned phys region: %d", 0);
 
        /* Copy the phys block now rather than doing COW. */
        end = off + length;
index cccbed4f74c3e0f6e447f63f5d916b08682784c9..e2d8a7d76ec04060dff54936e05b14b0b304e4ae 100644 (file)
@@ -224,3 +224,4 @@ int handle_memory(struct vmproc *vmp, vir_bytes mem, vir_bytes len, int wrflag)
 
        return OK;
 }
+
index 56a0a67b8850b83ed18c2c9abcea0f3097ceac4c..dbf9bbc0159896e93d8f50cd7b74eb54fa442981 100644 (file)
@@ -181,6 +181,7 @@ _PROTOTYPE( vir_bytes arch_addrok, (struct vmproc *vmp, vir_bytes addr));
 
 /* rs.c */
 _PROTOTYPE(int do_rs_set_priv, (message *m));
+_PROTOTYPE(int do_rs_update, (message *m));
 
 /* queryexit.c */
 _PROTOTYPE(int do_query_exit, (message *m));
index 6611a1e2b8b6a6460c6d45831c504de5c4006aec..35337ec5dc99844a4d3f9ac9d408e8b42317e976 100644 (file)
@@ -24,6 +24,9 @@
 #include "glo.h"
 #include "proto.h"
 #include "util.h"
+#include "region.h"
+
+#define LU_DEBUG 0
 
 /*===========================================================================*
  *                             do_rs_set_priv                               *
@@ -53,3 +56,91 @@ PUBLIC int do_rs_set_priv(message *m)
        return OK;
 }
 
+/*===========================================================================*
+ *                             do_rs_update                                 *
+ *===========================================================================*/
+PUBLIC int do_rs_update(message *m_ptr)
+{
+       endpoint_t src_e, dst_e;
+       struct vmproc *src_vmp, *dst_vmp;
+       struct vmproc orig_src_vmproc, orig_dst_vmproc;
+       int src_p, dst_p, r;
+       struct vir_region *vr;
+
+       src_e = m_ptr->VM_RS_SRC_ENDPT;
+       dst_e = m_ptr->VM_RS_DST_ENDPT;
+
+       /* Let the kernel do the update first. */
+       r = sys_update(src_e, dst_e);
+       if(r != OK) {
+               return r;
+       }
+
+       /* Lookup slots for source and destination process. */
+       if(vm_isokendpt(src_e, &src_p) != OK) {
+               printf("do_rs_update: bad src endpoint %d\n", src_e);
+               return EINVAL;
+       }
+       src_vmp = &vmproc[src_p];
+       if(vm_isokendpt(dst_e, &dst_p) != OK) {
+               printf("do_rs_update: bad dst endpoint %d\n", dst_e);
+               return EINVAL;
+       }
+       dst_vmp = &vmproc[dst_p];
+
+#if LU_DEBUG
+       printf("do_rs_update: updating %d (%d, %d) into %d (%d, %d)\n",
+           src_vmp->vm_endpoint, src_p, src_vmp->vm_slot,
+           dst_vmp->vm_endpoint, dst_p, dst_vmp->vm_slot);
+
+       printf("do_rs_update: map_printmap for source before updating:\n");
+       map_printmap(src_vmp);
+       printf("do_rs_update: map_printmap for destination before updating:\n");
+       map_printmap(dst_vmp);
+#endif
+
+       /* Save existing data. */
+       orig_src_vmproc = *src_vmp;
+       orig_dst_vmproc = *dst_vmp;
+
+       /* Swap slots. */
+       *src_vmp = orig_dst_vmproc;
+       *dst_vmp = orig_src_vmproc;
+
+       /* Preserve endpoints and slot numbers. */
+       src_vmp->vm_endpoint = orig_src_vmproc.vm_endpoint;
+       src_vmp->vm_slot = orig_src_vmproc.vm_slot;
+       dst_vmp->vm_endpoint = orig_dst_vmproc.vm_endpoint;
+       dst_vmp->vm_slot = orig_dst_vmproc.vm_slot;
+
+       /* Preserve vir_region's parents. */
+       for(vr = src_vmp->vm_regions; vr; vr = vr->next) {
+               vr->parent = src_vmp;
+       }
+       for(vr = dst_vmp->vm_regions; vr; vr = vr->next) {
+               vr->parent = dst_vmp;
+       }
+
+       /* Adjust page tables. */
+       vm_assert(src_vmp->vm_flags & VMF_HASPT);
+       vm_assert(dst_vmp->vm_flags & VMF_HASPT);
+       pt_bind(&src_vmp->vm_pt, src_vmp);
+       pt_bind(&dst_vmp->vm_pt, dst_vmp);
+       if((r=sys_vmctl(SELF, VMCTL_FLUSHTLB, 0)) != OK) {
+               panic("do_rs_update: VMCTL_FLUSHTLB failed: %d", r);
+       }
+
+#if LU_DEBUG
+       printf("do_rs_update: updated %d (%d, %d) into %d (%d, %d)\n",
+           src_vmp->vm_endpoint, src_p, src_vmp->vm_slot,
+           dst_vmp->vm_endpoint, dst_p, dst_vmp->vm_slot);
+
+       printf("do_rs_update: map_printmap for source after updating:\n");
+       map_printmap(src_vmp);
+       printf("do_rs_update: map_printmap for destination after updating:\n");
+       map_printmap(dst_vmp);
+#endif
+
+       return OK;
+}
+
index d6d13fef6d58d73302b9882572bd15b7ad04da4b..5634e4593b779b1094fbc8a2026203d2d83380eb 100644 (file)
@@ -57,7 +57,7 @@ void test_str(void)
        r = ds_publish_str(key_str, string, 0);
        assert(r == OK);
 
-       r = ds_retrieve_str(key_str, buf, 0);
+       r = ds_retrieve_str(key_str, buf, sizeof(buf)-1);
        assert(r == OK && strcmp(string, buf) == 0);
 
        r = ds_delete_str(key_str);
@@ -65,7 +65,14 @@ void test_str(void)
 
        /* Publish a long string. */
        r = ds_publish_str(key_str, longstring, 0);
-       assert(r == EINVAL);
+       assert(r == OK);
+
+       r = ds_retrieve_str(key_str, buf, sizeof(buf)-1);
+       assert(r == OK && strcmp(string, buf) != 0
+               && strncmp(longstring, buf, sizeof(buf)-1) == 0);
+
+       r = ds_delete_str(key_str);
+       assert(r == OK);
 
        printf("DSTEST: STRING test successful!\n");
 }
index ad73776462792d6c8c6f1b82dfc440fd09389ccc..f186b9f7a0a2808e8ecc4bd86e38ec12da7717bd 100644 (file)
@@ -62,7 +62,7 @@ int main(void)
                        printf("U32: %d\n", num);
                        break;
                case DSF_TYPE_STR:
-                       r = ds_retrieve_str(key, string, 0);
+                       r = ds_retrieve_str(key, string, sizeof(string)-1);
                        if(r != OK)
                                printf("error in ds_retrieve_str.\n");
                        printf("STR: %s\n", string);
index 17fba33b2bbe00335e72d6a062c5aaddad5a7b0d..9b939518ec782d0d7a8d9f8dd1b313b74e77fb43 100644 (file)
@@ -2,12 +2,8 @@
 service dstest
 {
        system
-               UMAP
-               PRIVCTL
-               SAFEMAP
-               SETGRANT
-               GETINFO
-               SYSCTL
+               PRIVCTL         #  4
+               UMAP            # 14
        ;
        uid     0;
 };
@@ -15,11 +11,8 @@ service dstest
 service subs
 {
        system
-               UMAP
-               PRIVCTL
-               SETGRANT
-               GETINFO
-               SYSCTL
+               PRIVCTL         #  4
+               UMAP            # 14
        ;
        uid     0;
 };
index 57f778f32061418e53b0fd23a8ecc2f44aeb53ea..7ad8b67b23fbab66f45e9df894abfa63be06f4fe 100644 (file)
@@ -2,16 +2,8 @@
 service requestor
 {
        system
-               SAFECOPYFROM
-               SAFECOPYTO
-               SAFEMAP
-               SAFEREVMAP
-               SAFEUNMAP
-               UMAP
-               PRIVCTL
-               SETGRANT
-               GETINFO
-               SYSCTL
+               PRIVCTL         #  4
+               UMAP            # 14
        ;
        uid     0;
 };
@@ -19,16 +11,8 @@ service requestor
 service grantor
 {
        system
-               SAFECOPYFROM
-               SAFECOPYTO
-               SAFEMAP
-               SAFEREVMAP
-               SAFEUNMAP
-               UMAP
-               PRIVCTL
-               SETGRANT
-               GETINFO
-               SYSCTL
+               PRIVCTL         #  4
+               UMAP            # 14
        ;
        uid     0;
 };
index 57f778f32061418e53b0fd23a8ecc2f44aeb53ea..7ad8b67b23fbab66f45e9df894abfa63be06f4fe 100644 (file)
@@ -2,16 +2,8 @@
 service requestor
 {
        system
-               SAFECOPYFROM
-               SAFECOPYTO
-               SAFEMAP
-               SAFEREVMAP
-               SAFEUNMAP
-               UMAP
-               PRIVCTL
-               SETGRANT
-               GETINFO
-               SYSCTL
+               PRIVCTL         #  4
+               UMAP            # 14
        ;
        uid     0;
 };
@@ -19,16 +11,8 @@ service requestor
 service grantor
 {
        system
-               SAFECOPYFROM
-               SAFECOPYTO
-               SAFEMAP
-               SAFEREVMAP
-               SAFEUNMAP
-               UMAP
-               PRIVCTL
-               SETGRANT
-               GETINFO
-               SYSCTL
+               PRIVCTL         #  4
+               UMAP            # 14
        ;
        uid     0;
 };
index 57f778f32061418e53b0fd23a8ecc2f44aeb53ea..7ad8b67b23fbab66f45e9df894abfa63be06f4fe 100644 (file)
@@ -2,16 +2,8 @@
 service requestor
 {
        system
-               SAFECOPYFROM
-               SAFECOPYTO
-               SAFEMAP
-               SAFEREVMAP
-               SAFEUNMAP
-               UMAP
-               PRIVCTL
-               SETGRANT
-               GETINFO
-               SYSCTL
+               PRIVCTL         #  4
+               UMAP            # 14
        ;
        uid     0;
 };
@@ -19,16 +11,8 @@ service requestor
 service grantor
 {
        system
-               SAFECOPYFROM
-               SAFECOPYTO
-               SAFEMAP
-               SAFEREVMAP
-               SAFEUNMAP
-               UMAP
-               PRIVCTL
-               SETGRANT
-               GETINFO
-               SYSCTL
+               PRIVCTL         #  4
+               UMAP            # 14
        ;
        uid     0;
 };