MIB: slim process tables to reduce memory usage
- 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
This commit is contained in:
parent
305e366fe4
commit
6ad322a932
@ -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_CALL_STATS 9 /* system call statistics */
|
||||||
#define SI_PROCPUB_TAB 11 /* copy of public entries of process table */
|
#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_PROCALL_TAB 12 /* copy of both private and public entries */
|
||||||
|
#define SI_PROCLIGHT_TAB 13 /* copy of light version of process table */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -14,11 +14,10 @@
|
|||||||
|
|
||||||
typedef struct proc ixfer_proc_t;
|
typedef struct proc ixfer_proc_t;
|
||||||
typedef struct mproc ixfer_mproc_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_proc_t proc_tab[NR_TASKS + NR_PROCS];
|
||||||
static ixfer_mproc_t mproc_tab[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
|
* 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. */
|
/* Retrieve an extract of the VFS process table. */
|
||||||
r = getsysinfo(VFS_PROC_NR, SI_PROC_TAB, fproc_tab, sizeof(fproc_tab));
|
r = getsysinfo(VFS_PROC_NR, SI_PROCLIGHT_TAB, fproc_tab,
|
||||||
|
sizeof(fproc_tab));
|
||||||
if (r != OK) {
|
if (r != OK) {
|
||||||
printf("MIB: unable to obtain VFS process table (%d)\n", r);
|
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)
|
int32_t * flag)
|
||||||
{
|
{
|
||||||
struct mproc *mp;
|
struct mproc *mp;
|
||||||
struct fproc *fp;
|
struct fproc_light *fp;
|
||||||
struct proc *kp;
|
struct proc *kp;
|
||||||
const char *wmesg;
|
const char *wmesg;
|
||||||
uint64_t wchan;
|
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) {
|
} else if (mp->mp_flags & SIGSUSPENDED) {
|
||||||
wchan = 0x202;
|
wchan = 0x202;
|
||||||
wmesg = "pause";
|
wmesg = "pause";
|
||||||
} else if (fp->fp_blocked_on != FP_BLOCKED_ON_NONE) {
|
} else if (fp->fpl_blocked_on != FP_BLOCKED_ON_NONE) {
|
||||||
wchan = (fp->fp_blocked_on << 8) | 0x03;
|
wchan = (fp->fpl_blocked_on << 8) | 0x03;
|
||||||
switch (fp->fp_blocked_on) {
|
switch (fp->fpl_blocked_on) {
|
||||||
case FP_BLOCKED_ON_PIPE:
|
case FP_BLOCKED_ON_PIPE:
|
||||||
wmesg = "pipe";
|
wmesg = "pipe";
|
||||||
break;
|
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,
|
* wchan value, and use the driver's process name,
|
||||||
* without parentheses, as wmesg text.
|
* without parentheses, as wmesg text.
|
||||||
*/
|
*/
|
||||||
wchan |= (uint64_t)fp->fp_task << 16;
|
wchan |= (uint64_t)fp->fpl_task << 16;
|
||||||
fill_wmesg(wmptr, wmsz, fp->fp_task, FALSE /*ipc*/);
|
fill_wmesg(wmptr, wmsz, fp->fpl_task, FALSE /*ipc*/);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* A newly added flag we don't yet know about? */
|
/* 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)
|
fill_proc2_user(struct kinfo_proc2 * p, int mslot)
|
||||||
{
|
{
|
||||||
struct mproc *mp;
|
struct mproc *mp;
|
||||||
struct fproc *fp;
|
struct fproc_light *fp;
|
||||||
time_t boottime;
|
time_t boottime;
|
||||||
dev_t tty;
|
dev_t tty;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
@ -703,7 +703,7 @@ fill_proc2_user(struct kinfo_proc2 * p, int mslot)
|
|||||||
fp = &fproc_tab[mslot];
|
fp = &fproc_tab[mslot];
|
||||||
|
|
||||||
zombie = (mp->mp_flags & (TRACE_ZOMBIE | ZOMBIE));
|
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;
|
p->p_eflag = 0;
|
||||||
if (tty != NO_DEV)
|
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 */
|
continue; /* TODO: revoke(2) support */
|
||||||
/* Do not access the fproc_tab slot of zombies. */
|
/* Do not access the fproc_tab slot of zombies. */
|
||||||
zombie = (mp->mp_flags & (TRACE_ZOMBIE | ZOMBIE));
|
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 ((dev_t)arg == KERN_PROC_TTY_NODEV) {
|
||||||
if (tty != NO_DEV)
|
if (tty != NO_DEV)
|
||||||
continue;
|
continue;
|
||||||
|
@ -84,6 +84,8 @@ int do_fork()
|
|||||||
/* Set up the child and its memory map; copy its 'mproc' slot from parent. */
|
/* Set up the child and its memory map; copy its 'mproc' slot from parent. */
|
||||||
procs_in_use++;
|
procs_in_use++;
|
||||||
*rmc = *rmp; /* copy parent's process slot to child's */
|
*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 */
|
rmc->mp_parent = who_p; /* record child's parent */
|
||||||
if (!(rmc->mp_trace_flags & TO_TRACEFORK)) {
|
if (!(rmc->mp_trace_flags & TO_TRACEFORK)) {
|
||||||
rmc->mp_tracer = NO_TRACER; /* no tracer attached */
|
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. */
|
/* Set up the child and its memory map; copy its 'mproc' slot from parent. */
|
||||||
procs_in_use++;
|
procs_in_use++;
|
||||||
*rmc = *rmp; /* copy parent's process slot to child's */
|
*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 */
|
rmc->mp_parent = who_p; /* record child's parent */
|
||||||
if (!(rmc->mp_trace_flags & TO_TRACEFORK)) {
|
if (!(rmc->mp_trace_flags & TO_TRACEFORK)) {
|
||||||
rmc->mp_tracer = NO_TRACER; /* no tracer attached */
|
rmc->mp_tracer = NO_TRACER; /* no tracer attached */
|
||||||
|
@ -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++) {
|
for (rmp=&mproc[0]; rmp<&mproc[NR_PROCS]; rmp++) {
|
||||||
init_timer(&rmp->mp_timer);
|
init_timer(&rmp->mp_timer);
|
||||||
rmp->mp_magic = MP_MAGIC;
|
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
|
/* Build the set of signals which cause core dumps, and the set of signals
|
||||||
|
@ -13,7 +13,13 @@
|
|||||||
/* Needs to be included here, for 'ps' etc */
|
/* Needs to be included here, for 'ps' etc */
|
||||||
#include "const.h"
|
#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;
|
typedef struct sigaction ixfer_sigaction;
|
||||||
|
EXTERN ixfer_sigaction mpsigact[NR_PROCS][_NSIG];
|
||||||
|
|
||||||
EXTERN struct mproc {
|
EXTERN struct mproc {
|
||||||
char mp_exitstatus; /* storage for status when process exits */
|
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_sigpending; /* pending signals to be handled */
|
||||||
sigset_t mp_ksigpending; /* bitmap for pending signals from the kernel */
|
sigset_t mp_ksigpending; /* bitmap for pending signals from the kernel */
|
||||||
sigset_t mp_sigtrace; /* signals to hand to tracer first */
|
sigset_t mp_sigtrace; /* signals to hand to tracer first */
|
||||||
ixfer_sigaction mp_sigact[_NSIG]; /* as in sigaction(2) */
|
ixfer_sigaction *mp_sigact; /* as in sigaction(2), pointer into mpsigact */
|
||||||
#ifdef __ACK__
|
|
||||||
char mp_padding[60]; /* align structure with new libc */
|
|
||||||
#endif
|
|
||||||
vir_bytes mp_sigreturn; /* address of C library __sigreturn function */
|
vir_bytes mp_sigreturn; /* address of C library __sigreturn function */
|
||||||
minix_timer_t mp_timer; /* watchdog timer for alarm(2), setitimer(2) */
|
minix_timer_t mp_timer; /* watchdog timer for alarm(2), setitimer(2) */
|
||||||
clock_t mp_interval[NR_ITIMERS]; /* setitimer(2) repetition intervals */
|
clock_t mp_interval[NR_ITIMERS]; /* setitimer(2) repetition intervals */
|
||||||
|
@ -71,4 +71,16 @@ EXTERN struct fproc {
|
|||||||
#define REVIVING 0xDEEAD /* process is being revived from suspension */
|
#define REVIVING 0xDEEAD /* process is being revived from suspension */
|
||||||
#define PID_FREE 0 /* process slot free */
|
#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__ */
|
#endif /* __VFS_FPROC_H__ */
|
||||||
|
@ -51,6 +51,8 @@ static void free_proc(int flags);
|
|||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int do_getsysinfo(void)
|
int do_getsysinfo(void)
|
||||||
{
|
{
|
||||||
|
struct fproc *rfp;
|
||||||
|
struct fproc_light *rfpl;
|
||||||
vir_bytes src_addr, dst_addr;
|
vir_bytes src_addr, dst_addr;
|
||||||
size_t len, buf_size;
|
size_t len, buf_size;
|
||||||
int what;
|
int what;
|
||||||
@ -75,6 +77,17 @@ int do_getsysinfo(void)
|
|||||||
src_addr = (vir_bytes) dmap;
|
src_addr = (vir_bytes) dmap;
|
||||||
len = sizeof(struct dmap) * NR_DEVICES;
|
len = sizeof(struct dmap) * NR_DEVICES;
|
||||||
break;
|
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
|
#if ENABLE_SYSCALL_STATS
|
||||||
case SI_CALL_STATS:
|
case SI_CALL_STATS:
|
||||||
src_addr = (vir_bytes) calls_stats;
|
src_addr = (vir_bytes) calls_stats;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user