Implement getrusage
Implement getrusage. These fields of struct rusage are not supported and always set to zero at this time long ru_nswap; /* swaps */ long ru_inblock; /* block input operations */ long ru_oublock; /* block output operations */ long ru_msgsnd; /* messages sent */ long ru_msgrcv; /* messages received */ long ru_nvcsw; /* voluntary context switches */ long ru_nivcsw; /* involuntary context switches */ test75.c is the unit test for this new function Change-Id: I3f1eb69de1fce90d087d76773b09021fc6106539
This commit is contained in:
parent
4241cc5d98
commit
64f10ee644
41 changed files with 403 additions and 29 deletions
|
@ -1508,6 +1508,7 @@
|
|||
./usr/man/man2/getpeername.2 minix-sys
|
||||
./usr/man/man2/getpid.2 minix-sys
|
||||
./usr/man/man2/getpriority.2 minix-sys
|
||||
./usr/man/man2/getrusage.2 minix-sys
|
||||
./usr/man/man2/getsockname.2 minix-sys
|
||||
./usr/man/man2/getsockopt.2 minix-sys
|
||||
./usr/man/man2/gettimeofday.2 minix-sys
|
||||
|
@ -4653,6 +4654,7 @@
|
|||
./usr/tests/minix-posix/test72 minix-sys
|
||||
./usr/tests/minix-posix/test73 minix-sys
|
||||
./usr/tests/minix-posix/test74 minix-sys
|
||||
./usr/tests/minix-posix/test75 minix-sys
|
||||
./usr/tests/minix-posix/test7 minix-sys
|
||||
./usr/tests/minix-posix/test8 minix-sys
|
||||
./usr/tests/minix-posix/test9 minix-sys
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#define NCALLS 118 /* number of system calls allowed */
|
||||
#define NCALLS 124 /* number of system calls allowed */
|
||||
|
||||
/* In case it isn't obvious enough: this list is sorted numerically. */
|
||||
#define EXIT 1
|
||||
|
@ -113,3 +113,4 @@
|
|||
* really a standalone call.
|
||||
*/
|
||||
#define MAPDRIVER 122 /* to VFS, map a device */
|
||||
#define GETRUSAGE 123 /* to PM, VFS */
|
||||
|
|
|
@ -473,6 +473,7 @@
|
|||
# define GET_IDLETSC 21 /* get cumulative idle time stamp counter */
|
||||
# define GET_CPUINFO 23 /* get information about cpus */
|
||||
# define GET_REGS 24 /* get general process registers */
|
||||
# define GET_RUSAGE 25 /* get resource usage */
|
||||
#define I_ENDPT m7_i4 /* calling process (may only be SELF) */
|
||||
#define I_VAL_PTR m7_p1 /* virtual address at caller */
|
||||
#define I_VAL_LEN m7_i1 /* max length of value */
|
||||
|
@ -1078,8 +1079,10 @@
|
|||
|
||||
#define VM_VFS_MMAP (VM_RQ_BASE+46)
|
||||
|
||||
#define VM_GETRUSAGE (VM_RQ_BASE+47)
|
||||
|
||||
/* Total. */
|
||||
#define NR_VM_CALLS 47
|
||||
#define NR_VM_CALLS 48
|
||||
#define VM_CALL_MASK_SIZE BITMAP_CHUNKS(NR_VM_CALLS)
|
||||
|
||||
/* not handled as a normal VM call, thus at the end of the reserved rage */
|
||||
|
@ -1294,4 +1297,9 @@
|
|||
# define BDEV_NOFLAGS 0x00 /* no flags are set */
|
||||
# define BDEV_FORCEWRITE 0x01 /* force write to disk immediately */
|
||||
|
||||
/* Field names for GETRUSAGE related calls */
|
||||
#define RU_ENDPT m1_i1 /* indicates a process for sys_getrusage */
|
||||
#define RU_WHO m1_i1 /* who argument in getrusage call */
|
||||
#define RU_RUSAGE_ADDR m1_p1 /* pointer to struct rusage */
|
||||
|
||||
/* _MINIX_COM_H */
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
/* Forward declaration */
|
||||
struct reg86u;
|
||||
struct rs_pci;
|
||||
struct rusage;
|
||||
|
||||
#define SYSTASK SYSTEM
|
||||
|
||||
|
@ -178,6 +179,7 @@ int send_taskreply(endpoint_t who, endpoint_t endpoint, int status);
|
|||
#define sys_getpriv(dst, nr) sys_getinfo(GET_PRIV, dst, 0,0, nr)
|
||||
#define sys_getidletsc(dst) sys_getinfo(GET_IDLETSC, dst, 0,0,0)
|
||||
#define sys_getregs(dst,nr) sys_getinfo(GET_REGS, dst, 0,0, nr)
|
||||
#define sys_getrusage(dst, nr) sys_getinfo(GET_RUSAGE, dst, 0,0, nr)
|
||||
int sys_getinfo(int request, void *val_ptr, int val_len, void *val_ptr2,
|
||||
int val_len2);
|
||||
int sys_whoami(endpoint_t *ep, char *name, int namelen, int
|
||||
|
|
|
@ -1906,3 +1906,8 @@ void ser_dump_proc()
|
|||
print_proc_recursive(pp);
|
||||
}
|
||||
}
|
||||
|
||||
void increase_proc_signals(struct proc *p)
|
||||
{
|
||||
p->p_signal_received++;
|
||||
}
|
||||
|
|
|
@ -126,6 +126,8 @@ struct proc {
|
|||
*/
|
||||
struct { reg_t r1, r2, r3; } p_defer;
|
||||
|
||||
u64_t p_signal_received;
|
||||
|
||||
#if DEBUG_TRACE
|
||||
int p_schedules;
|
||||
#endif
|
||||
|
|
|
@ -76,6 +76,7 @@ int isokendpt_f(endpoint_t e, int *p, int f);
|
|||
#endif
|
||||
void proc_no_time(struct proc *p);
|
||||
void reset_proc_accounting(struct proc *p);
|
||||
void increase_proc_signals(struct proc *p);
|
||||
void flag_account(struct proc *p, int flag);
|
||||
int try_deliver_senda(struct proc *caller_ptr, asynmsg_t *table, size_t
|
||||
size);
|
||||
|
|
|
@ -373,6 +373,7 @@ int send_sig(endpoint_t ep, int sig_nr)
|
|||
priv = priv(rp);
|
||||
if(!priv) return ENOENT;
|
||||
sigaddset(&priv->s_sig_pending, sig_nr);
|
||||
increase_proc_signals(rp);
|
||||
mini_notify(proc_addr(SYSTEM), rp->p_endpoint);
|
||||
|
||||
return OK;
|
||||
|
@ -434,6 +435,7 @@ int sig_nr; /* signal to be sent */
|
|||
/* Check if the signal is already pending. Process it otherwise. */
|
||||
if (! sigismember(&rp->p_pending, sig_nr)) {
|
||||
sigaddset(&rp->p_pending, sig_nr);
|
||||
increase_proc_signals(rp);
|
||||
if (! (RTS_ISSET(rp, RTS_SIGNALED))) { /* other pending */
|
||||
RTS_SET(rp, RTS_SIGNALED | RTS_SIG_PENDING);
|
||||
if(OK != send_sig(sig_mgr, SIGKSIG))
|
||||
|
|
|
@ -90,6 +90,7 @@ int do_fork(struct proc * caller, message * m_ptr)
|
|||
make_zero64(rpc->p_cycles);
|
||||
make_zero64(rpc->p_kcall_cycles);
|
||||
make_zero64(rpc->p_kipc_cycles);
|
||||
rpc->p_signal_received = 0;
|
||||
|
||||
/* If the parent is a privileged process, take away the privileges from the
|
||||
* child process and inhibit it from running by setting the NO_PRIV flag.
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#if USE_GETINFO
|
||||
|
||||
#include <minix/u64.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
/*===========================================================================*
|
||||
* update_idle_time *
|
||||
|
@ -47,6 +48,7 @@ int do_getinfo(struct proc * caller, message * m_ptr)
|
|||
int nr_e, nr, r;
|
||||
int wipe_rnd_bin = -1;
|
||||
struct proc *p;
|
||||
struct rusage r_usage;
|
||||
|
||||
/* Set source address and length based on request type. */
|
||||
switch (m_ptr->I_REQUEST) {
|
||||
|
@ -180,6 +182,32 @@ int do_getinfo(struct proc * caller, message * m_ptr)
|
|||
src_vir = (vir_bytes) &idl->p_cycles;
|
||||
break;
|
||||
}
|
||||
case GET_RUSAGE: {
|
||||
struct proc *target = NULL;
|
||||
int target_slot = 0;
|
||||
u64_t usec;
|
||||
nr_e = (m_ptr->I_VAL_LEN2_E == SELF) ?
|
||||
caller->p_endpoint : m_ptr->I_VAL_LEN2_E;
|
||||
|
||||
if (!isokendpt(nr_e, &target_slot))
|
||||
return EINVAL;
|
||||
|
||||
target = proc_addr(target_slot);
|
||||
if (isemptyp(target))
|
||||
return EINVAL;
|
||||
|
||||
length = sizeof(r_usage);
|
||||
memset(&r_usage, 0, sizeof(r_usage));
|
||||
usec = target->p_user_time * 1000000 / system_hz;
|
||||
r_usage.ru_utime.tv_sec = usec / 1000000;
|
||||
r_usage.ru_utime.tv_usec = usec % 100000;
|
||||
usec = target->p_sys_time * 1000000 / system_hz;
|
||||
r_usage.ru_stime.tv_sec = usec / 1000000;
|
||||
r_usage.ru_stime.tv_usec = usec % 100000;
|
||||
r_usage.ru_nsignals = target->p_signal_received;
|
||||
src_vir = (vir_bytes) &r_usage;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printf("do_getinfo: invalid request %d\n", m_ptr->I_REQUEST);
|
||||
return(EINVAL);
|
||||
|
|
|
@ -18,7 +18,8 @@ SRCS+= accept.c access.c adjtime.c bind.c brk.c sbrk.c m_closefrom.c getsid.c \
|
|||
sigprocmask.c socket.c socketpair.c stat.c statvfs.c symlink.c \
|
||||
sync.c syscall.c sysuname.c truncate.c umask.c unlink.c write.c \
|
||||
utimensat.c utimes.c futimes.c lutimes.c futimens.c \
|
||||
_exit.c _ucontext.c environ.c __getcwd.c vfork.c sizeup.c init.c
|
||||
_exit.c _ucontext.c environ.c __getcwd.c vfork.c sizeup.c init.c \
|
||||
getrusage.c
|
||||
|
||||
# Minix specific syscalls.
|
||||
SRCS+= cprofile.c lseek64.c sprofile.c _mcontext.c
|
||||
|
|
32
lib/libc/sys-minix/getrusage.c
Normal file
32
lib/libc/sys-minix/getrusage.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
#include <sys/cdefs.h>
|
||||
#include "namespace.h"
|
||||
#include <lib.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
int getrusage(int who, struct rusage *r_usage)
|
||||
{
|
||||
int rc;
|
||||
message m;
|
||||
m.RU_WHO = who;
|
||||
m.RU_RUSAGE_ADDR = r_usage;
|
||||
|
||||
if (r_usage == NULL) {
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(r_usage, 0, sizeof(struct rusage));
|
||||
if ((rc = _syscall(PM_PROC_NR, GETRUSAGE, &m)) < 0)
|
||||
return rc;
|
||||
m.RU_RUSAGE_ADDR = r_usage;
|
||||
if ((rc = _syscall(VFS_PROC_NR, GETRUSAGE, &m)) < 0)
|
||||
return rc;
|
||||
m.RU_RUSAGE_ADDR = r_usage;
|
||||
return _syscall(VM_PROC_NR, VM_GETRUSAGE, &m);
|
||||
}
|
|
@ -228,7 +228,7 @@ MAN+= accept.2 access.2 acct.2 bind.2 brk.2 chdir.2 \
|
|||
flock.2 fork.2 fsync.2 getcontext.2 getdents.2 \
|
||||
getfh.2 getvfsstat.2 getgid.2 getgroups.2 \
|
||||
getitimer.2 getlogin.2 getpeername.2 getpgrp.2 getpid.2 \
|
||||
getpriority.2 getrlimit.2 getrusage.2 getsid.2 getsockname.2 \
|
||||
getpriority.2 getrlimit.2 getsid.2 getsockname.2 \
|
||||
getsockopt.2 gettimeofday.2 getuid.2 intro.2 ioctl.2 issetugid.2 \
|
||||
kill.2 kqueue.2 ktrace.2 \
|
||||
lfs_bmapv.2 lfs_markv.2 lfs_segclean.2 lfs_segwait.2 \
|
||||
|
@ -244,7 +244,7 @@ MAN+= accept.2 access.2 acct.2 bind.2 brk.2 chdir.2 \
|
|||
mprotect.2 mremap.2 msgctl.2 msgget.2 msgrcv.2 msgsnd.2 msync.2 \
|
||||
munmap.2 nanosleep.2 nfssvc.2 ntp_adjtime.2 open.2 pathconf.2 pipe.2
|
||||
.else
|
||||
MAN+= adjtime.2 clock_settime.2 pipe.2
|
||||
MAN+= adjtime.2 clock_settime.2 pipe.2 getrusage.2
|
||||
.endif # !defined(__MINIX)
|
||||
.if !defined(__MINIX)
|
||||
MAN+= pmc_control.2 poll.2 posix_fadvise.2 profil.2 ptrace.2 __quotactl.2 \
|
||||
|
|
|
@ -228,6 +228,11 @@ int libexec_load_elf(struct exec_info *execi)
|
|||
if(first || startv > vaddr) startv = vaddr;
|
||||
first = 0;
|
||||
|
||||
if ((ph->p_flags & PF_X) != 0 && execi->text_size < seg_membytes)
|
||||
execi->text_size = seg_membytes;
|
||||
else
|
||||
execi->data_size = seg_membytes;
|
||||
|
||||
if(try_mmap && execi->memmap(execi, vaddr, fbytes, foffset, clearend, mmap_prot) == OK) {
|
||||
#if ELF_DEBUG
|
||||
printf("libexec: mmap 0x%lx-0x%lx done, clearend 0x%x\n",
|
||||
|
|
|
@ -32,6 +32,8 @@ struct exec_info {
|
|||
int allow_setuid; /* Allow set{u,g}id execution? */
|
||||
vir_bytes stack_size; /* Desired stack size */
|
||||
vir_bytes load_offset; /* Desired load offset */
|
||||
vir_bytes text_size; /* Text segment size */
|
||||
vir_bytes data_size; /* Data segment size */
|
||||
off_t filesize; /* How big is the file */
|
||||
|
||||
/* Callback pointers for use by libexec */
|
||||
|
|
|
@ -492,3 +492,31 @@ void *brk_addr;
|
|||
_brksize = brk_addr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_getrusage *
|
||||
*===========================================================================*/
|
||||
int do_getrusage()
|
||||
{
|
||||
int res = 0;
|
||||
clock_t user_time = 0;
|
||||
clock_t sys_time = 0;
|
||||
struct rusage r_usage;
|
||||
u64_t usec;
|
||||
if (m_in.RU_WHO != RUSAGE_SELF && m_in.RU_WHO != RUSAGE_CHILDREN)
|
||||
return EINVAL;
|
||||
if ((res = sys_getrusage(&r_usage, who_e)) < 0)
|
||||
return res;
|
||||
|
||||
if (m_in.RU_WHO == RUSAGE_CHILDREN) {
|
||||
usec = mp->mp_child_utime * 1000000 / sys_hz();
|
||||
r_usage.ru_utime.tv_sec = usec / 1000000;
|
||||
r_usage.ru_utime.tv_usec = usec % 1000000;
|
||||
usec = mp->mp_child_stime * 1000000 / sys_hz();
|
||||
r_usage.ru_stime.tv_sec = usec / 1000000;
|
||||
r_usage.ru_stime.tv_usec = usec % 1000000;
|
||||
}
|
||||
|
||||
return sys_datacopy(SELF, &r_usage, who_e,
|
||||
(vir_bytes) m_in.RU_RUSAGE_ADDR, (vir_bytes) sizeof(r_usage));
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ int do_getepinfo(void);
|
|||
int do_getepinfo_o(void);
|
||||
int do_svrctl(void);
|
||||
int do_getsetpriority(void);
|
||||
int do_getrusage(void);
|
||||
|
||||
/* schedule.c */
|
||||
void sched_init(void);
|
||||
|
|
|
@ -129,6 +129,12 @@ int (*call_vec[])(void) = {
|
|||
do_gettime, /* 115 = clock_gettime */
|
||||
do_settime, /* 116 = clock_settime */
|
||||
no_sys, /* 117 = (vmcall) */
|
||||
no_sys, /* 118 = unsused */
|
||||
no_sys, /* 119 = unsused */
|
||||
no_sys, /* 120 = unsused */
|
||||
no_sys, /* 121 = (task reply) */
|
||||
no_sys, /* 122 = (map driver ) */
|
||||
do_getrusage, /* 123 = getrusage */
|
||||
};
|
||||
/* This should not fail with "array size is negative": */
|
||||
extern int dummy[sizeof(call_vec) == NCALLS * sizeof(call_vec[0]) ? 1 : -1];
|
||||
|
|
|
@ -253,6 +253,8 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
|
|||
|
||||
okendpt(proc_e, &slot);
|
||||
rfp = fp = &fproc[slot];
|
||||
rfp->text_size = 0;
|
||||
rfp->data_size = 0;
|
||||
|
||||
lookup_init(&resolve, fullpath, PATH_NOFLAGS, &execi.vmp, &execi.vp);
|
||||
|
||||
|
@ -409,6 +411,8 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
|
|||
|
||||
/* Remember the new name of the process */
|
||||
strlcpy(rfp->fp_name, execi.args.progname, PROC_NAME_LEN);
|
||||
rfp->text_size = execi.args.text_size;
|
||||
rfp->data_size = execi.args.data_size;
|
||||
|
||||
pm_execfinal:
|
||||
if(newfilp) unlock_filp(newfilp);
|
||||
|
|
|
@ -50,6 +50,9 @@ EXTERN struct fproc {
|
|||
int fp_vp_rdlocks; /* number of read-only locks on vnodes */
|
||||
int fp_vmnt_rdlocks; /* number of read-only locks on vmnts */
|
||||
#endif
|
||||
|
||||
vir_bytes text_size; /* text segment size of current process */
|
||||
vir_bytes data_size; /* data segment size of current process */
|
||||
} fproc[NR_PROCS];
|
||||
|
||||
/* fp_flags */
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <minix/u64.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/svrctl.h>
|
||||
#include <sys/resource.h>
|
||||
#include "file.h"
|
||||
#include "fproc.h"
|
||||
#include "scratchpad.h"
|
||||
|
@ -939,3 +940,24 @@ void panic_hook(void)
|
|||
mthread_stacktraces();
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_getrusage *
|
||||
*===========================================================================*/
|
||||
int do_getrusage(message *UNUSED(m_out))
|
||||
{
|
||||
int res;
|
||||
struct rusage r_usage;
|
||||
|
||||
if ((res = sys_datacopy(who_e, (vir_bytes) m_in.RU_RUSAGE_ADDR, SELF,
|
||||
(vir_bytes) &r_usage, (vir_bytes) sizeof(r_usage))) < 0)
|
||||
return res;
|
||||
|
||||
r_usage.ru_inblock = 0;
|
||||
r_usage.ru_oublock = 0;
|
||||
r_usage.ru_ixrss = fp->text_size;
|
||||
r_usage.ru_idrss = fp->data_size;
|
||||
r_usage.ru_isrss = DEFAULT_STACK_LIMIT;
|
||||
|
||||
return sys_datacopy(SELF, (vir_bytes) &r_usage, who_e,
|
||||
(vir_bytes) m_in.RU_RUSAGE_ADDR, (phys_bytes) sizeof(r_usage));
|
||||
}
|
||||
|
|
|
@ -147,6 +147,7 @@ int do_vm_call(message *m_out);
|
|||
int pm_dumpcore(endpoint_t proc_e, int sig, vir_bytes exe_name);
|
||||
void * ds_event(void *arg);
|
||||
int dupvm(struct fproc *fp, int pfd, int *vmfd, struct filp **f);
|
||||
int do_getrusage(message *m_out);
|
||||
|
||||
/* mount.c */
|
||||
int do_fsready(message *m_out);
|
||||
|
|
|
@ -133,6 +133,12 @@ int (*call_vec[])(message *m_out) = {
|
|||
no_sys, /* 115 = (clock_gettime) */
|
||||
no_sys, /* 116 = (clock_settime) */
|
||||
do_vm_call, /* 117 = call from vm */
|
||||
no_sys, /* 118 = unsused */
|
||||
no_sys, /* 119 = unsused */
|
||||
no_sys, /* 120 = unsused */
|
||||
no_sys, /* 121 = (task reply) */
|
||||
no_sys, /* 122 = (map driver ) */
|
||||
do_getrusage, /* 123 = getrusage */
|
||||
};
|
||||
/* This should not fail with "array size is negative": */
|
||||
extern int dummy[sizeof(call_vec) == NCALLS * sizeof(call_vec[0]) ? 1 : -1];
|
||||
|
|
|
@ -24,6 +24,14 @@
|
|||
#include "util.h"
|
||||
#include "sanitycheck.h"
|
||||
|
||||
static void reset_vm_rusage(struct vmproc *vmp)
|
||||
{
|
||||
vmp->vm_total = 0;
|
||||
vmp->vm_total_max = 0;
|
||||
vmp->vm_minor_page_fault = 0;
|
||||
vmp->vm_major_page_fault = 0;
|
||||
}
|
||||
|
||||
void free_proc(struct vmproc *vmp)
|
||||
{
|
||||
map_free_proc(vmp);
|
||||
|
@ -33,6 +41,7 @@ void free_proc(struct vmproc *vmp)
|
|||
vmp->vm_bytecopies = 0;
|
||||
#endif
|
||||
vmp->vm_region_top = 0;
|
||||
reset_vm_rusage(vmp);
|
||||
}
|
||||
|
||||
void clear_proc(struct vmproc *vmp)
|
||||
|
@ -43,6 +52,7 @@ void clear_proc(struct vmproc *vmp)
|
|||
vmp->vm_bytecopies = 0;
|
||||
#endif
|
||||
vmp->vm_region_top = 0;
|
||||
reset_vm_rusage(vmp);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
|
|
@ -443,6 +443,9 @@ void init_vm(void)
|
|||
CALLMAP(VM_MAPCACHEPAGE, do_mapcache);
|
||||
CALLMAP(VM_SETCACHEPAGE, do_setcache);
|
||||
|
||||
/* getrusage */
|
||||
CALLMAP(VM_GETRUSAGE, do_getrusage);
|
||||
|
||||
/* Initialize the structures for queryexit */
|
||||
init_query_exit();
|
||||
|
||||
|
|
|
@ -22,7 +22,8 @@ static void anon_split(struct vmproc *vmp, struct vir_region *vr,
|
|||
static int anon_lowshrink(struct vir_region *vr, vir_bytes len);
|
||||
static int anon_unreference(struct phys_region *pr);
|
||||
static int anon_pagefault(struct vmproc *vmp, struct vir_region *region,
|
||||
struct phys_region *ph, int write, vfs_callback_t cb, void *, int);
|
||||
struct phys_region *ph, int write, vfs_callback_t cb, void *state,
|
||||
int len, int *io);
|
||||
static int anon_sanitycheck(struct phys_region *pr, char *file, int line);
|
||||
static int anon_writable(struct phys_region *pr);
|
||||
static int anon_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l);
|
||||
|
@ -51,7 +52,8 @@ static int anon_unreference(struct phys_region *pr)
|
|||
}
|
||||
|
||||
static int anon_pagefault(struct vmproc *vmp, struct vir_region *region,
|
||||
struct phys_region *ph, int write, vfs_callback_t cb, void *st, int l)
|
||||
struct phys_region *ph, int write, vfs_callback_t cb, void *state,
|
||||
int len, int *io)
|
||||
{
|
||||
phys_bytes new_page, new_page_cl;
|
||||
u32_t allocflags;
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
static int anon_contig_reference(struct phys_region *, struct phys_region *);
|
||||
static int anon_contig_unreference(struct phys_region *pr);
|
||||
static int anon_contig_pagefault(struct vmproc *vmp, struct vir_region *region,
|
||||
struct phys_region *ph, int write, vfs_callback_t cb, void *st, int);
|
||||
struct phys_region *ph, int write, vfs_callback_t cb, void *state,
|
||||
int len, int *io);
|
||||
static int anon_contig_sanitycheck(struct phys_region *pr, char *file, int line);
|
||||
static int anon_contig_writable(struct phys_region *pr);
|
||||
static int anon_contig_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l);
|
||||
|
@ -29,7 +30,8 @@ struct mem_type mem_type_anon_contig = {
|
|||
};
|
||||
|
||||
static int anon_contig_pagefault(struct vmproc *vmp, struct vir_region *region,
|
||||
struct phys_region *ph, int write, vfs_callback_t cb, void *s, int l)
|
||||
struct phys_region *ph, int write, vfs_callback_t cb, void *state,
|
||||
int len, int *io)
|
||||
{
|
||||
panic("anon_contig_pagefault: pagefault cannot happen");
|
||||
}
|
||||
|
|
|
@ -29,7 +29,8 @@ static int cache_sanitycheck(struct phys_region *pr, char *file, int line);
|
|||
static int cache_writable(struct phys_region *pr);
|
||||
static int cache_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l);
|
||||
static int cache_pagefault(struct vmproc *vmp, struct vir_region *region,
|
||||
struct phys_region *ph, int write, vfs_callback_t cb, void *, int);
|
||||
struct phys_region *ph, int write, vfs_callback_t cb, void *state,
|
||||
int len, int *io);
|
||||
|
||||
struct mem_type mem_type_cache = {
|
||||
.name = "cache memory",
|
||||
|
@ -81,6 +82,7 @@ do_mapcache(message *msg)
|
|||
struct vir_region *vr;
|
||||
struct vmproc *caller;
|
||||
vir_bytes offset;
|
||||
int io = 0;
|
||||
|
||||
if(vm_isokendpt(msg->m_source, &n) != OK) panic("bogus source");
|
||||
caller = &vmproc[n];
|
||||
|
@ -113,7 +115,7 @@ do_mapcache(message *msg)
|
|||
assert(vr->length == bytes);
|
||||
assert(offset < vr->length);
|
||||
|
||||
if(map_pf(caller, vr, offset, 1, NULL, NULL, 0) != OK) {
|
||||
if(map_pf(caller, vr, offset, 1, NULL, NULL, 0, &io) != OK) {
|
||||
map_unmap_region(caller, vr, 0, bytes);
|
||||
printf("VM: map_pf failed\n");
|
||||
return ENOMEM;
|
||||
|
@ -136,7 +138,7 @@ do_mapcache(message *msg)
|
|||
|
||||
static int cache_pagefault(struct vmproc *vmp, struct vir_region *region,
|
||||
struct phys_region *ph, int write, vfs_callback_t cb,
|
||||
void *state, int len)
|
||||
void *state, int len, int *io)
|
||||
{
|
||||
vir_bytes offset = ph->offset;
|
||||
assert(ph->ph->phys == MAP_NONE);
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
static int phys_unreference(struct phys_region *pr);
|
||||
static int phys_writable(struct phys_region *pr);
|
||||
static int phys_pagefault(struct vmproc *vmp, struct vir_region *region,
|
||||
struct phys_region *ph, int write, vfs_callback_t cb, void *, int);
|
||||
struct phys_region *ph, int write, vfs_callback_t cb, void *state,
|
||||
int len, int *io);
|
||||
static int phys_copy(struct vir_region *vr, struct vir_region *newvr);
|
||||
|
||||
struct mem_type mem_type_directphys = {
|
||||
|
@ -34,7 +35,8 @@ static int phys_unreference(struct phys_region *pr)
|
|||
}
|
||||
|
||||
static int phys_pagefault(struct vmproc *vmp, struct vir_region *region,
|
||||
struct phys_region *ph, int write, vfs_callback_t cb, void *st, int len)
|
||||
struct phys_region *ph, int write, vfs_callback_t cb, void *state,
|
||||
int len, int *io)
|
||||
{
|
||||
phys_bytes arg = region->param.phys, phmem;
|
||||
assert(arg != MAP_NONE);
|
||||
|
|
|
@ -18,7 +18,8 @@ static void mappedfile_split(struct vmproc *vmp, struct vir_region *vr,
|
|||
struct vir_region *r1, struct vir_region *r2);
|
||||
static int mappedfile_unreference(struct phys_region *pr);
|
||||
static int mappedfile_pagefault(struct vmproc *vmp, struct vir_region *region,
|
||||
struct phys_region *ph, int write, vfs_callback_t callback, void *, int);
|
||||
struct phys_region *ph, int write, vfs_callback_t callback, void *state,
|
||||
int len, int *io);
|
||||
static int mappedfile_sanitycheck(struct phys_region *pr, char *file, int line);
|
||||
static int mappedfile_writable(struct phys_region *pr);
|
||||
static int mappedfile_copy(struct vir_region *vr, struct vir_region *newvr);
|
||||
|
@ -72,7 +73,7 @@ static int cow_block(struct vmproc *vmp, struct vir_region *region,
|
|||
|
||||
static int mappedfile_pagefault(struct vmproc *vmp, struct vir_region *region,
|
||||
struct phys_region *ph, int write, vfs_callback_t cb,
|
||||
void *state, int statelen)
|
||||
void *state, int statelen, int *io)
|
||||
{
|
||||
u32_t allocflags;
|
||||
int procfd = region->param.file.fdref->fd;
|
||||
|
@ -123,7 +124,7 @@ static int mappedfile_pagefault(struct vmproc *vmp, struct vir_region *region,
|
|||
printf("VM: mappedfile_pagefault: vfs_request failed\n");
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
*io = 1;
|
||||
return SUSPEND;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
|
||||
static int shared_unreference(struct phys_region *pr);
|
||||
static int shared_pagefault(struct vmproc *vmp, struct vir_region *region,
|
||||
struct phys_region *ph, int write, vfs_callback_t cb, void *, int);
|
||||
struct phys_region *ph, int write, vfs_callback_t cb, void *state,
|
||||
int len, int *io);
|
||||
static int shared_sanitycheck(struct phys_region *pr, char *file, int line);
|
||||
static int shared_writable(struct phys_region *pr);
|
||||
static void shared_delete(struct vir_region *region);
|
||||
|
@ -110,7 +111,7 @@ static void shared_delete(struct vir_region *region)
|
|||
|
||||
static int shared_pagefault(struct vmproc *vmp, struct vir_region *region,
|
||||
struct phys_region *ph, int write, vfs_callback_t cb,
|
||||
void *state, int statelen)
|
||||
void *state, int statelen, int *io)
|
||||
{
|
||||
struct vir_region *src_region;
|
||||
struct vmproc *src_vmp;
|
||||
|
@ -126,7 +127,7 @@ static int shared_pagefault(struct vmproc *vmp, struct vir_region *region,
|
|||
if(!(pr = physblock_get(src_region, ph->offset))) {
|
||||
int r;
|
||||
if((r=map_pf(src_vmp, src_region, ph->offset, write,
|
||||
NULL, NULL, 0)) != OK)
|
||||
NULL, NULL, 0, io)) != OK)
|
||||
return r;
|
||||
if(!(pr = physblock_get(src_region, ph->offset))) {
|
||||
panic("missing region after pagefault handling");
|
||||
|
|
|
@ -16,7 +16,8 @@ typedef struct mem_type {
|
|||
int (*ev_reference)(struct phys_region *pr, struct phys_region *newpr);
|
||||
int (*ev_unreference)(struct phys_region *pr);
|
||||
int (*ev_pagefault)(struct vmproc *vmp, struct vir_region *region,
|
||||
struct phys_region *ph, int write, vfs_callback_t cb, void *, int);
|
||||
struct phys_region *ph, int write, vfs_callback_t cb, void *state,
|
||||
int len, int *io);
|
||||
int (*ev_resize)(struct vmproc *vmp, struct vir_region *vr, vir_bytes len);
|
||||
void (*ev_split)(struct vmproc *vmp, struct vir_region *vr,
|
||||
struct vir_region *r1, struct vir_region *r2);
|
||||
|
|
|
@ -70,6 +70,7 @@ static void handle_pagefault(endpoint_t ep, vir_bytes addr, u32_t err, int retry
|
|||
struct vir_region *region;
|
||||
vir_bytes offset;
|
||||
int p, wr = PFERR_WRITE(err);
|
||||
int io = 0;
|
||||
|
||||
if(vm_isokendpt(ep, &p) != OK)
|
||||
panic("handle_pagefault: endpoint wrong: %d", ep);
|
||||
|
@ -111,7 +112,7 @@ static void handle_pagefault(endpoint_t ep, vir_bytes addr, u32_t err, int retry
|
|||
|
||||
/* Access is allowed; handle it. */
|
||||
if(retry) {
|
||||
result = map_pf(vmp, region, offset, wr, NULL, NULL, 0);
|
||||
result = map_pf(vmp, region, offset, wr, NULL, NULL, 0, &io);
|
||||
assert(result != SUSPEND);
|
||||
} else {
|
||||
struct pf_state state;
|
||||
|
@ -119,8 +120,12 @@ static void handle_pagefault(endpoint_t ep, vir_bytes addr, u32_t err, int retry
|
|||
state.vaddr = addr;
|
||||
state.err = err;
|
||||
result = map_pf(vmp, region, offset, wr, pf_cont,
|
||||
&state, sizeof(state));
|
||||
&state, sizeof(state), &io);
|
||||
}
|
||||
if (io)
|
||||
vmp->vm_major_page_fault++;
|
||||
else
|
||||
vmp->vm_minor_page_fault++;
|
||||
|
||||
if(result == SUSPEND) {
|
||||
return;
|
||||
|
|
|
@ -41,6 +41,7 @@ int get_stack_ptr(int proc_nr, vir_bytes *sp);
|
|||
int do_info(message *);
|
||||
int swap_proc_slot(struct vmproc *src_vmp, struct vmproc *dst_vmp);
|
||||
int swap_proc_dyn_data(struct vmproc *src_vmp, struct vmproc *dst_vmp);
|
||||
int do_getrusage(message *m);
|
||||
|
||||
/* exit.c */
|
||||
void clear_proc(struct vmproc *vmp);
|
||||
|
@ -143,7 +144,8 @@ int map_proc_copy_from(struct vmproc *dst, struct vmproc *src, struct
|
|||
struct vir_region *map_lookup(struct vmproc *vmp, vir_bytes addr,
|
||||
struct phys_region **pr);
|
||||
int map_pf(struct vmproc *vmp, struct vir_region *region, vir_bytes
|
||||
offset, int write, vfs_callback_t pf_callback, void *state, int);
|
||||
offset, int write, vfs_callback_t pf_callback, void *state, int len,
|
||||
int *io);
|
||||
int map_pin_memory(struct vmproc *vmp);
|
||||
int map_handle_memory(struct vmproc *vmp, struct vir_region *region,
|
||||
vir_bytes offset, vir_bytes len, int write, vfs_callback_t cb,
|
||||
|
|
|
@ -73,14 +73,21 @@ void physblock_set(struct vir_region *region, vir_bytes offset,
|
|||
struct phys_region *newphysr)
|
||||
{
|
||||
int i;
|
||||
struct vmproc *proc;
|
||||
assert(!(offset % VM_PAGE_SIZE));
|
||||
assert(offset >= 0 && offset < region->length);
|
||||
i = offset/VM_PAGE_SIZE;
|
||||
proc = region->parent;
|
||||
assert(proc);
|
||||
if(newphysr) {
|
||||
assert(!region->physblocks[i]);
|
||||
assert(newphysr->offset == offset);
|
||||
proc->vm_total += VM_PAGE_SIZE;
|
||||
if (proc->vm_total > proc->vm_total_max)
|
||||
proc->vm_total_max = proc->vm_total;
|
||||
} else {
|
||||
assert(region->physblocks[i]);
|
||||
proc->vm_total -= VM_PAGE_SIZE;
|
||||
}
|
||||
region->physblocks[i] = newphysr;
|
||||
}
|
||||
|
@ -671,7 +678,7 @@ u32_t vrallocflags(u32_t flags)
|
|||
/*===========================================================================*
|
||||
* map_pf *
|
||||
*===========================================================================*/
|
||||
int map_pf(vmp, region, offset, write, pf_callback, state, len)
|
||||
int map_pf(vmp, region, offset, write, pf_callback, state, len, io)
|
||||
struct vmproc *vmp;
|
||||
struct vir_region *region;
|
||||
vir_bytes offset;
|
||||
|
@ -679,6 +686,7 @@ int write;
|
|||
vfs_callback_t pf_callback;
|
||||
void *state;
|
||||
int len;
|
||||
int *io;
|
||||
{
|
||||
struct phys_region *ph;
|
||||
int r = OK;
|
||||
|
@ -725,7 +733,7 @@ int len;
|
|||
assert(ph->ph);
|
||||
|
||||
if((r = ph->memtype->ev_pagefault(vmp,
|
||||
region, ph, write, pf_callback, state, len)) == SUSPEND) {
|
||||
region, ph, write, pf_callback, state, len, io)) == SUSPEND) {
|
||||
return SUSPEND;
|
||||
}
|
||||
|
||||
|
@ -774,6 +782,7 @@ int statelen;
|
|||
{
|
||||
vir_bytes offset, lim;
|
||||
int r;
|
||||
int io = 0;
|
||||
|
||||
assert(length > 0);
|
||||
lim = start_offset + length;
|
||||
|
@ -781,7 +790,7 @@ int statelen;
|
|||
|
||||
for(offset = start_offset; offset < lim; offset += VM_PAGE_SIZE)
|
||||
if((r = map_pf(vmp, region, offset, write,
|
||||
cb, state, statelen)) != OK)
|
||||
cb, state, statelen, &io)) != OK)
|
||||
return r;
|
||||
|
||||
return OK;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <assert.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#include "proto.h"
|
||||
#include "glo.h"
|
||||
|
@ -320,4 +321,27 @@ int _brk(void *addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_getrusage *
|
||||
*===========================================================================*/
|
||||
int do_getrusage(message *m)
|
||||
{
|
||||
int res, slot;
|
||||
struct vmproc *vmp;
|
||||
struct rusage r_usage;
|
||||
if ((res = vm_isokendpt(m->m_source, &slot)) != OK)
|
||||
return ESRCH;
|
||||
|
||||
vmp = &vmproc[slot];
|
||||
|
||||
if ((res = sys_datacopy(m->m_source, (vir_bytes) m->RU_RUSAGE_ADDR,
|
||||
SELF, (vir_bytes) &r_usage, (vir_bytes) sizeof(r_usage))) < 0)
|
||||
return res;
|
||||
|
||||
r_usage.ru_maxrss = vmp->vm_total_max;
|
||||
r_usage.ru_minflt = vmp->vm_minor_page_fault;
|
||||
r_usage.ru_majflt = vmp->vm_major_page_fault;
|
||||
|
||||
return sys_datacopy(SELF, &r_usage, m->m_source,
|
||||
(vir_bytes) m->RU_RUSAGE_ADDR, (vir_bytes) sizeof(r_usage));
|
||||
}
|
||||
|
|
|
@ -25,6 +25,10 @@ struct vmproc {
|
|||
#if VMSTATS
|
||||
int vm_bytecopies;
|
||||
#endif
|
||||
vir_bytes vm_total;
|
||||
vir_bytes vm_total_max;
|
||||
u64_t vm_minor_page_fault;
|
||||
u64_t vm_major_page_fault;
|
||||
};
|
||||
|
||||
/* Bits for vm_flags */
|
||||
|
|
|
@ -47,6 +47,34 @@
|
|||
#define PRIO_PGRP 1
|
||||
#define PRIO_USER 2
|
||||
|
||||
/*
|
||||
* Resource utilization information.
|
||||
*/
|
||||
|
||||
#define RUSAGE_SELF 0
|
||||
#define RUSAGE_CHILDREN -1
|
||||
|
||||
struct rusage {
|
||||
struct timeval ru_utime; /* user time used */
|
||||
struct timeval ru_stime; /* system time used */
|
||||
long ru_maxrss; /* max resident set size */
|
||||
#define ru_first ru_ixrss
|
||||
long ru_ixrss; /* integral shared memory size */
|
||||
long ru_idrss; /* integral unshared data " */
|
||||
long ru_isrss; /* integral unshared stack " */
|
||||
long ru_minflt; /* page reclaims */
|
||||
long ru_majflt; /* page faults */
|
||||
long ru_nswap; /* swaps */
|
||||
long ru_inblock; /* block input operations */
|
||||
long ru_oublock; /* block output operations */
|
||||
long ru_msgsnd; /* messages sent */
|
||||
long ru_msgrcv; /* messages received */
|
||||
long ru_nsignals; /* signals received */
|
||||
long ru_nvcsw; /* voluntary context switches */
|
||||
long ru_nivcsw; /* involuntary " */
|
||||
#define ru_last ru_nivcsw
|
||||
};
|
||||
|
||||
/*
|
||||
* Resource limits
|
||||
*/
|
||||
|
@ -78,6 +106,7 @@ struct rlimit
|
|||
__BEGIN_DECLS
|
||||
int getpriority(int, int);
|
||||
int getrlimit(int, struct rlimit *);
|
||||
int getrusage(int, struct rusage *);
|
||||
int setpriority(int, int, int);
|
||||
__END_DECLS
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ MINIX_TESTS= \
|
|||
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
|
||||
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
|
||||
41 42 43 44 45 46 48 49 50 52 53 54 55 56 58 59 60 \
|
||||
61 64 65 66 67 68 69 70 71 72 73 74
|
||||
61 64 65 66 67 68 69 70 71 72 73 74 75
|
||||
|
||||
.if ${MACHINE_ARCH} == "i386"
|
||||
MINIX_TESTS+= \
|
||||
|
|
2
test/run
2
test/run
|
@ -24,7 +24,7 @@ setuids="test11 test33 test43 test44 test46 test56 test60 test61 test65 \
|
|||
alltests=" 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
|
||||
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
|
||||
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
|
||||
61 62 63 64 65 66 67 68 69 70 71 72 \
|
||||
61 62 63 64 65 66 67 68 69 70 71 72 75 \
|
||||
sh1.sh sh2.sh interp.sh"
|
||||
tests_no=`expr 0`
|
||||
|
||||
|
|
114
test/test75.c
Normal file
114
test/test75.c
Normal file
|
@ -0,0 +1,114 @@
|
|||
/* Test 75 - getrusage functionality test.
|
||||
*/
|
||||
|
||||
#include <sys/resource.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define CHECK_ZERO_FIELD(rusage, field) \
|
||||
if (rusage.field != 0) \
|
||||
em(1, #field " must be zero");
|
||||
|
||||
#define CHECK_NOT_ZERO_FIELD(rusage, field) \
|
||||
if (rusage.field == 0) \
|
||||
em(1, #field " can't be zero");
|
||||
|
||||
#define CHECK_EQUAL_FIELD(rusage1, rusage2, field) \
|
||||
if (rusage1.field != rusage2.field) \
|
||||
em(1, #field " of " #rusage1 " doesn't equal to " \
|
||||
#field " of " #rusage2);
|
||||
|
||||
static void spin()
|
||||
{
|
||||
struct timeval start_time;
|
||||
struct timeval end_time;
|
||||
int loop = 0;
|
||||
if (gettimeofday(&start_time, NULL) == -1) {
|
||||
e(1);
|
||||
exit(1);
|
||||
}
|
||||
memset(&end_time, 0, sizeof(end_time));
|
||||
while (start_time.tv_sec + 10 > end_time.tv_sec) {
|
||||
if ((++loop % 10000) == 0) {
|
||||
if (gettimeofday(&end_time, NULL) == -1) {
|
||||
e(1);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct rusage r_usage1;
|
||||
struct rusage r_usage2;
|
||||
struct rusage r_usage3;
|
||||
pid_t child;
|
||||
int status = 0;
|
||||
start(75);
|
||||
if ((getrusage(RUSAGE_SELF + 1, &r_usage1) != -1 || errno != EINVAL) ||
|
||||
(getrusage(RUSAGE_CHILDREN - 1, &r_usage1) != -1 ||
|
||||
errno != EINVAL) || (getrusage(RUSAGE_SELF, NULL) != -1 ||
|
||||
errno != EFAULT)) {
|
||||
e(1);
|
||||
exit(1);
|
||||
}
|
||||
spin();
|
||||
if (getrusage(RUSAGE_SELF, &r_usage1) != 0) {
|
||||
e(1);
|
||||
exit(1);
|
||||
}
|
||||
CHECK_NOT_ZERO_FIELD(r_usage1, ru_utime.tv_sec);
|
||||
CHECK_NOT_ZERO_FIELD(r_usage1, ru_maxrss);
|
||||
CHECK_NOT_ZERO_FIELD(r_usage1, ru_ixrss);
|
||||
CHECK_NOT_ZERO_FIELD(r_usage1, ru_idrss);
|
||||
CHECK_NOT_ZERO_FIELD(r_usage1, ru_isrss);
|
||||
if (getrusage(RUSAGE_CHILDREN, &r_usage2) != 0) {
|
||||
e(1);
|
||||
exit(1);
|
||||
}
|
||||
CHECK_ZERO_FIELD(r_usage2, ru_utime.tv_sec);
|
||||
CHECK_ZERO_FIELD(r_usage2, ru_utime.tv_usec);
|
||||
CHECK_NOT_ZERO_FIELD(r_usage2, ru_maxrss);
|
||||
CHECK_NOT_ZERO_FIELD(r_usage2, ru_ixrss);
|
||||
CHECK_NOT_ZERO_FIELD(r_usage2, ru_idrss);
|
||||
CHECK_NOT_ZERO_FIELD(r_usage2, ru_isrss);
|
||||
CHECK_EQUAL_FIELD(r_usage1, r_usage2, ru_ixrss);
|
||||
CHECK_EQUAL_FIELD(r_usage1, r_usage2, ru_idrss);
|
||||
CHECK_EQUAL_FIELD(r_usage1, r_usage2, ru_isrss);
|
||||
if ((child = fork()) != 0) {
|
||||
if (child != waitpid(child, &status, 0)) {
|
||||
e(1);
|
||||
exit(1);
|
||||
}
|
||||
if (WEXITSTATUS(status) != 0) {
|
||||
e(1);
|
||||
exit(1);
|
||||
}
|
||||
if (getrusage(RUSAGE_CHILDREN, &r_usage3) != 0) {
|
||||
e(1);
|
||||
exit(1);
|
||||
}
|
||||
CHECK_NOT_ZERO_FIELD(r_usage3, ru_utime.tv_sec);
|
||||
CHECK_NOT_ZERO_FIELD(r_usage3, ru_maxrss);
|
||||
CHECK_NOT_ZERO_FIELD(r_usage3, ru_ixrss);
|
||||
CHECK_NOT_ZERO_FIELD(r_usage3, ru_idrss);
|
||||
CHECK_NOT_ZERO_FIELD(r_usage3, ru_isrss);
|
||||
CHECK_EQUAL_FIELD(r_usage1, r_usage3, ru_ixrss);
|
||||
CHECK_EQUAL_FIELD(r_usage1, r_usage3, ru_idrss);
|
||||
CHECK_EQUAL_FIELD(r_usage1, r_usage3, ru_isrss);
|
||||
} else {
|
||||
spin();
|
||||
exit(0);
|
||||
}
|
||||
quit();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue