]> Zhao Yanbai Git Server - minix.git/commitdiff
MIB: slim process tables to reduce memory usage 56/3256/2
authorDavid van Moolenbroek <david@minix3.org>
Sun, 8 Nov 2015 12:39:45 +0000 (12:39 +0000)
committerLionel Sambuc <lionel.sambuc@gmail.com>
Wed, 13 Jan 2016 19:32:55 +0000 (20:32 +0100)
- About 80% of PM's process table consisted of per-signal sigaction
  structures.  This is information not used by the MIB service, and
  can safely be stored outside the main process table.

- The MIB service does not need most of the VFS process table, so VFS
  now generates a "light" version of its table upon request, with just
  the fields used by the MIB service.

The result is a size reduction of the MIB service of about 700KB.

Change-Id: I79fe7239361fbfb45286af8e86a10aed4c2d2be7

minix/include/minix/sysinfo.h
minix/servers/mib/proc.c
minix/servers/pm/forkexit.c
minix/servers/pm/main.c
minix/servers/pm/mproc.h
minix/servers/vfs/fproc.h
minix/servers/vfs/misc.c

index 1e4e2bbf9536928c3b0cc5da2f5a54bee5327d39..edb5643c5db7c35b071762e932eaea27e45bcaf2 100644 (file)
@@ -14,6 +14,7 @@ int getsysinfo(endpoint_t who, int what, void *where, size_t size);
 #define SI_CALL_STATS     9    /* system call statistics */
 #define SI_PROCPUB_TAB    11   /* copy of public entries of process table */
 #define SI_PROCALL_TAB    12   /* copy of both private and public entries */
+#define SI_PROCLIGHT_TAB   13  /* copy of light version of process table */
 
 #endif
 
index 277497ff08fc6583e776eb15aca91e8ab8ecde8b..f103b483a22acc82c227d8b3085ca93e099c4bf2 100644 (file)
 
 typedef struct proc ixfer_proc_t;
 typedef struct mproc ixfer_mproc_t;
-typedef struct fproc ixfer_fproc_t;
 
 static ixfer_proc_t proc_tab[NR_TASKS + NR_PROCS];
 static ixfer_mproc_t mproc_tab[NR_PROCS];
-static ixfer_fproc_t fproc_tab[NR_PROCS];
+static struct fproc_light fproc_tab[NR_PROCS];
 
 /*
  * The number of processes added to the current number of processes when doing
@@ -103,8 +102,9 @@ update_tables(void)
                }
        }
 
-       /* Retrieve the VFS process table, which has no magic number. */
-       r = getsysinfo(VFS_PROC_NR, SI_PROC_TAB, fproc_tab, sizeof(fproc_tab));
+       /* Retrieve an extract of the VFS process table. */
+       r = getsysinfo(VFS_PROC_NR, SI_PROCLIGHT_TAB, fproc_tab,
+           sizeof(fproc_tab));
        if (r != OK) {
                printf("MIB: unable to obtain VFS process table (%d)\n", r);
 
@@ -226,7 +226,7 @@ get_lwp_stat(int mslot, uint64_t * wcptr, char * wmptr, size_t wmsz,
        int32_t * flag)
 {
        struct mproc *mp;
-       struct fproc *fp;
+       struct fproc_light *fp;
        struct proc *kp;
        const char *wmesg;
        uint64_t wchan;
@@ -290,9 +290,9 @@ get_lwp_stat(int mslot, uint64_t * wcptr, char * wmptr, size_t wmsz,
        } else if (mp->mp_flags & SIGSUSPENDED) {
                wchan = 0x202;
                wmesg = "pause";
-       } else if (fp->fp_blocked_on != FP_BLOCKED_ON_NONE) {
-               wchan = (fp->fp_blocked_on << 8) | 0x03;
-               switch (fp->fp_blocked_on) {
+       } else if (fp->fpl_blocked_on != FP_BLOCKED_ON_NONE) {
+               wchan = (fp->fpl_blocked_on << 8) | 0x03;
+               switch (fp->fpl_blocked_on) {
                case FP_BLOCKED_ON_PIPE:
                        wmesg = "pipe";
                        break;
@@ -311,8 +311,8 @@ get_lwp_stat(int mslot, uint64_t * wcptr, char * wmptr, size_t wmsz,
                         * wchan value, and use the driver's process name,
                         * without parentheses, as wmesg text.
                         */
-                       wchan |= (uint64_t)fp->fp_task << 16;
-                       fill_wmesg(wmptr, wmsz, fp->fp_task, FALSE /*ipc*/);
+                       wchan |= (uint64_t)fp->fpl_task << 16;
+                       fill_wmesg(wmptr, wmsz, fp->fpl_task, FALSE /*ipc*/);
                        break;
                default:
                        /* A newly added flag we don't yet know about? */
@@ -687,7 +687,7 @@ static void
 fill_proc2_user(struct kinfo_proc2 * p, int mslot)
 {
        struct mproc *mp;
-       struct fproc *fp;
+       struct fproc_light *fp;
        time_t boottime;
        dev_t tty;
        struct timeval tv;
@@ -703,7 +703,7 @@ fill_proc2_user(struct kinfo_proc2 * p, int mslot)
        fp = &fproc_tab[mslot];
 
        zombie = (mp->mp_flags & (TRACE_ZOMBIE | ZOMBIE));
-       tty = (!zombie) ? fp->fp_tty : NO_DEV;
+       tty = (!zombie) ? fp->fpl_tty : NO_DEV;
 
        p->p_eflag = 0;
        if (tty != NO_DEV)
@@ -869,7 +869,7 @@ mib_kern_proc2(struct mib_call * call, struct mib_node * node __unused,
                                continue; /* TODO: revoke(2) support */
                        /* Do not access the fproc_tab slot of zombies. */
                        zombie = (mp->mp_flags & (TRACE_ZOMBIE | ZOMBIE));
-                       tty = (zombie) ? fproc_tab[mslot].fp_tty : NO_DEV;
+                       tty = (zombie) ? fproc_tab[mslot].fpl_tty : NO_DEV;
                        if ((dev_t)arg == KERN_PROC_TTY_NODEV) {
                                if (tty != NO_DEV)
                                        continue;
index bacff3510bb18432c59cb6981b904e250fdb6292..30dfb5a3de36b2aafdf1cb7fd00de29176d3ff0c 100644 (file)
@@ -84,6 +84,8 @@ int do_fork()
   /* Set up the child and its memory map; copy its 'mproc' slot from parent. */
   procs_in_use++;
   *rmc = *rmp;                 /* copy parent's process slot to child's */
+  rmc->mp_sigact = mpsigact[next_child];       /* restore mp_sigact ptr */
+  memcpy(rmc->mp_sigact, rmp->mp_sigact, sizeof(mpsigact[next_child]));
   rmc->mp_parent = who_p;                      /* record child's parent */
   if (!(rmc->mp_trace_flags & TO_TRACEFORK)) {
        rmc->mp_tracer = NO_TRACER;             /* no tracer attached */
@@ -182,6 +184,8 @@ int do_srv_fork()
   /* Set up the child and its memory map; copy its 'mproc' slot from parent. */
   procs_in_use++;
   *rmc = *rmp;                 /* copy parent's process slot to child's */
+  rmc->mp_sigact = mpsigact[next_child];       /* restore mp_sigact ptr */
+  memcpy(rmc->mp_sigact, rmp->mp_sigact, sizeof(mpsigact[next_child]));
   rmc->mp_parent = who_p;                      /* record child's parent */
   if (!(rmc->mp_trace_flags & TO_TRACEFORK)) {
        rmc->mp_tracer = NO_TRACER;             /* no tracer attached */
index af86de54a0e6c1dc67f87a7f8e3ae43af6720967..86dee877ab3c8fb65dcb513f0bbaa8ae0dd9664c 100644 (file)
@@ -145,6 +145,7 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
   for (rmp=&mproc[0]; rmp<&mproc[NR_PROCS]; rmp++) {
        init_timer(&rmp->mp_timer);
        rmp->mp_magic = MP_MAGIC;
+       rmp->mp_sigact = mpsigact[rmp - mproc];
   }
 
   /* Build the set of signals which cause core dumps, and the set of signals
index f8894447005c531a9e15ae01302fd7a146b3925e..02069fab91545d7986fd2ed622a6f030e6e65d68 100644 (file)
 /* Needs to be included here, for 'ps' etc */
 #include "const.h"
 
+/*
+ * The per-process sigaction structures are stored outside of the mproc table,
+ * so that the MIB service can avoid pulling them in, as they account for
+ * roughly 80% of the per-process state.
+ */
 typedef struct sigaction ixfer_sigaction;
+EXTERN ixfer_sigaction mpsigact[NR_PROCS][_NSIG];
 
 EXTERN struct mproc {
   char mp_exitstatus;          /* storage for status when process exits */
@@ -48,10 +54,7 @@ EXTERN struct mproc {
   sigset_t mp_sigpending;      /* pending signals to be handled */
   sigset_t mp_ksigpending;     /* bitmap for pending signals from the kernel */
   sigset_t mp_sigtrace;                /* signals to hand to tracer first */
-  ixfer_sigaction mp_sigact[_NSIG]; /* as in sigaction(2) */
-#ifdef __ACK__
-  char mp_padding[60];         /* align structure with new libc */
-#endif
+  ixfer_sigaction *mp_sigact;  /* as in sigaction(2), pointer into mpsigact */
   vir_bytes mp_sigreturn;      /* address of C library __sigreturn function */
   minix_timer_t mp_timer;      /* watchdog timer for alarm(2), setitimer(2) */
   clock_t mp_interval[NR_ITIMERS];     /* setitimer(2) repetition intervals */
index 8d74292e939f4260517ff6ee21170761845542c1..28bc56d3c4e12b9593083018479c195fa5bccef4 100644 (file)
@@ -71,4 +71,16 @@ EXTERN struct fproc {
 #define REVIVING           0xDEEAD     /* process is being revived from suspension */
 #define PID_FREE          0    /* process slot free */
 
+/*
+ * Upon request from the MIB service, this table is filled with a relatively
+ * small subset of per-process fields, so that the MIB service can avoid
+ * pulling in the entire fproc table.  Other fields may be added to this
+ * structure as required by the MIB service.
+ */
+EXTERN struct fproc_light {
+  dev_t fpl_tty;               /* copy of fproc.fp_tty */
+  int fpl_blocked_on;          /* copy of fproc.fp_blocked_on */
+  endpoint_t fpl_task;         /* copy of fproc.fp_task */
+} fproc_light[NR_PROCS];
+
 #endif /* __VFS_FPROC_H__ */
index dcaa53588734a1f722d04b99862ca12705ffbfc8..29a97fb49045bccd90a01f7e7fe4ffdffdc009f6 100644 (file)
@@ -51,6 +51,8 @@ static void free_proc(int flags);
  *===========================================================================*/
 int do_getsysinfo(void)
 {
+  struct fproc *rfp;
+  struct fproc_light *rfpl;
   vir_bytes src_addr, dst_addr;
   size_t len, buf_size;
   int what;
@@ -75,6 +77,17 @@ int do_getsysinfo(void)
        src_addr = (vir_bytes) dmap;
        len = sizeof(struct dmap) * NR_DEVICES;
        break;
+    case SI_PROCLIGHT_TAB:
+       /* Fill the light process table for the MIB service upon request. */
+       rfpl = &fproc_light[0];
+       for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++, rfpl++) {
+               rfpl->fpl_tty = rfp->fp_tty;
+               rfpl->fpl_blocked_on = rfp->fp_blocked_on;
+               rfpl->fpl_task = rfp->fp_task;
+       }
+       src_addr = (vir_bytes) fproc_light;
+       len = sizeof(fproc_light);
+       break;
 #if ENABLE_SYSCALL_STATS
     case SI_CALL_STATS:
        src_addr = (vir_bytes) calls_stats;