From d7efdde5a68c58661b2002701d4538e567ba14a0 Mon Sep 17 00:00:00 2001 From: Xiaoguang Sun Date: Tue, 11 Jun 2013 16:33:34 +0000 Subject: [PATCH] Implement getrusage in kernel pm vfs vm and libc --- include/minix/callnr.h | 4 ++- include/minix/com.h | 12 ++++++-- include/minix/syslib.h | 4 +++ kernel/system.c | 2 ++ kernel/system.h | 2 ++ kernel/system/Makefile.inc | 3 +- kernel/system/do_getrusage.c | 51 +++++++++++++++++++++++++++++++++ lib/libc/sys-minix/Makefile.inc | 3 +- lib/libc/sys-minix/getrusage.c | 23 +++++++++++++++ lib/libc/sys/Makefile.inc | 4 +-- lib/libsys/Makefile | 3 +- lib/libsys/sys_getrusage.c | 14 +++++++++ servers/pm/Makefile | 2 +- servers/pm/getrusage.c | 37 ++++++++++++++++++++++++ servers/pm/proto.h | 3 ++ servers/pm/table.c | 6 ++++ servers/vfs/Makefile | 2 +- servers/vfs/getrusage.c | 31 ++++++++++++++++++++ servers/vfs/proto.h | 3 ++ servers/vfs/table.c | 6 ++++ servers/vm/Makefile | 2 +- servers/vm/getrusage.c | 29 +++++++++++++++++++ servers/vm/main.c | 3 ++ servers/vm/proto.h | 3 ++ sys/sys/resource.h | 29 +++++++++++++++++++ 25 files changed, 270 insertions(+), 11 deletions(-) create mode 100644 kernel/system/do_getrusage.c create mode 100644 lib/libc/sys-minix/getrusage.c create mode 100644 lib/libsys/sys_getrusage.c create mode 100644 servers/pm/getrusage.c create mode 100644 servers/vfs/getrusage.c create mode 100644 servers/vm/getrusage.c diff --git a/include/minix/callnr.h b/include/minix/callnr.h index 0ec74931b..f799a4ba9 100644 --- a/include/minix/callnr.h +++ b/include/minix/callnr.h @@ -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,5 @@ * really a standalone call. */ #define MAPDRIVER 122 /* to VFS, map a device */ + +#define GETRUSAGE 123 /* to PM, VFS */ diff --git a/include/minix/com.h b/include/minix/com.h index 08496d220..2d5d94d08 100644 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -352,9 +352,10 @@ # define SYS_STATECTL (KERNEL_CALL + 55) /* sys_statectl() */ # define SYS_SAFEMEMSET (KERNEL_CALL + 56) /* sys_safememset() */ +# define SYS_GETRUSAGE (KERNEL_CALL + 57) /* sys_getrusage() */ /* Total */ -#define NR_SYS_CALLS 57 /* number of kernel calls */ +#define NR_SYS_CALLS 58 /* number of kernel calls */ #define SYS_CALL_MASK_SIZE BITMAP_CHUNKS(NR_SYS_CALLS) @@ -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 */ diff --git a/include/minix/syslib.h b/include/minix/syslib.h index a5fcefc6f..52cb2fd69 100644 --- a/include/minix/syslib.h +++ b/include/minix/syslib.h @@ -17,6 +17,7 @@ /* Forward declaration */ struct reg86u; struct rs_pci; +struct rusage; #define SYSTASK SYSTEM @@ -249,5 +250,8 @@ int sys_setmcontext(endpoint_t proc, mcontext_t *mcp); /* input */ int tty_input_inject(int type, int code, int val); +/* resource */ +int sys_getrusage(endpoint_t proc, struct rusage *r_usage); + #endif /* _SYSLIB_H */ diff --git a/kernel/system.c b/kernel/system.c index 423b353b1..cab4432aa 100644 --- a/kernel/system.c +++ b/kernel/system.c @@ -263,6 +263,8 @@ void system_init(void) map(SYS_SCHEDULE, do_schedule); /* reschedule a process */ map(SYS_SCHEDCTL, do_schedctl); /* change process scheduler */ + /* getrusage */ + map(SYS_GETRUSAGE, do_getrusage); /* getrusage */ } /*===========================================================================* * get_priv * diff --git a/kernel/system.h b/kernel/system.h index 9f493ab6f..d27b7fbe1 100644 --- a/kernel/system.h +++ b/kernel/system.h @@ -208,5 +208,7 @@ int do_statectl(struct proc * caller, message *m_ptr); #define do_statectl NULL #endif +int do_getrusage(struct proc * caller, message *m_ptr); + #endif /* SYSTEM_H */ diff --git a/kernel/system/Makefile.inc b/kernel/system/Makefile.inc index e90b47640..7c6321e0f 100644 --- a/kernel/system/Makefile.inc +++ b/kernel/system/Makefile.inc @@ -38,7 +38,8 @@ SRCS+= \ do_vmctl.c \ do_schedule.c \ do_schedctl.c \ - do_statectl.c + do_statectl.c \ + do_getrusage.c .if ${MACHINE_ARCH} == "i386" SRCS+= \ diff --git a/kernel/system/do_getrusage.c b/kernel/system/do_getrusage.c new file mode 100644 index 000000000..c6b3fcadc --- /dev/null +++ b/kernel/system/do_getrusage.c @@ -0,0 +1,51 @@ +/* The kernel call implemented in this file: + * m_type: SYS_GETRUSAGE + * + * The parameters for this kernel call are: + * m1_i1: RU_ENDPT (process to get rusage) + * m1_p1: RU_RUSAGE_PTR (pointer to struct rusage) + */ + +#include "kernel/system.h" +#include "kernel/proc.h" + +#include +#include +/*===========================================================================* + * do_getrusage * + *===========================================================================*/ +int do_getrusage(struct proc * caller, message * msg) +{ + struct proc *target = NULL; + int target_slot = 0; + struct rusage r_usage; + u64_t usec; + + if (!isokendpt(msg->RU_ENDPT, &target_slot)) + return EINVAL; + + target = proc_addr(target_slot); + if (isemptyp(target)) + return EINVAL; + + if (data_copy(msg->m_source, (vir_bytes) msg->RU_RUSAGE_ADDR, KERNEL, + (vir_bytes) &r_usage, (vir_bytes) sizeof(struct rusage)) != OK) + return EFAULT; + + 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_msgsnd = target->p_message_sent; + r_usage.ru_msgrcv = target->p_message_received; + r_usage.ru_nsignals = target->p_signal_received; + r_usage.ru_nvcsw = target->p_voluntary_context_switch; + r_usage.ru_nivcsw = target->p_involuntary_context_switch; + + /* Get the mcontext structure into our address space. */ + return data_copy(KERNEL, (vir_bytes) &r_usage, msg->m_source, + (vir_bytes) msg->RU_RUSAGE_ADDR, + (vir_bytes) sizeof(struct rusage)); +} diff --git a/lib/libc/sys-minix/Makefile.inc b/lib/libc/sys-minix/Makefile.inc index 98a208fab..890b66d87 100644 --- a/lib/libc/sys-minix/Makefile.inc +++ b/lib/libc/sys-minix/Makefile.inc @@ -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 diff --git a/lib/libc/sys-minix/getrusage.c b/lib/libc/sys-minix/getrusage.c new file mode 100644 index 000000000..fa12a7322 --- /dev/null +++ b/lib/libc/sys-minix/getrusage.c @@ -0,0 +1,23 @@ +#include +#include "namespace.h" +#include + +#include +#include + +int getrusage(int who, struct rusage *r_usage) +{ + int rc; + message m; + m.RU_WHO = who; + m.RU_RUSAGE_ADDR = r_usage; + + memset(r_usage, 0, sizeof(struct rusage)); + if ((rc = _syscall(PM_PROC_NR, GETRUSAGE, &m)) < 0) + return rc; + m.m1_p1 = r_usage; + if ((rc = _syscall(VFS_PROC_NR, GETRUSAGE, &m)) < 0) + return rc; + m.m1_p1 = r_usage; + return _syscall(VM_PROC_NR, VM_GETRUSAGE, &m); +} diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc index b20b7ea66..2fa88dfd5 100644 --- a/lib/libc/sys/Makefile.inc +++ b/lib/libc/sys/Makefile.inc @@ -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 \ diff --git a/lib/libsys/Makefile b/lib/libsys/Makefile index ba949cbda..46976deeb 100644 --- a/lib/libsys/Makefile +++ b/lib/libsys/Makefile @@ -88,7 +88,8 @@ SRCS+= \ vm_notify_sig.c \ vm_umap.c \ vm_procctl.c \ - vprintf.c + vprintf.c \ + sys_getrusage.c .if ${MKPCI} != "no" SRCS+= pci_attr_r16.c \ diff --git a/lib/libsys/sys_getrusage.c b/lib/libsys/sys_getrusage.c new file mode 100644 index 000000000..3a4a0640a --- /dev/null +++ b/lib/libsys/sys_getrusage.c @@ -0,0 +1,14 @@ +#include "syslib.h" +#include + +int sys_getrusage(endpoint_t proc, struct rusage *r_usage) +{ + /* Fetch the resource usage for a process. */ + message m; + int r; + + m.RU_ENDPT = proc; + m.RU_RUSAGE_ADDR = r_usage; + r = _kernel_call(SYS_GETRUSAGE, &m); + return(r); +} diff --git a/servers/pm/Makefile b/servers/pm/Makefile index 5a64169c0..d126adbd1 100644 --- a/servers/pm/Makefile +++ b/servers/pm/Makefile @@ -4,7 +4,7 @@ PROG= pm SRCS= main.c forkexit.c break.c exec.c time.c alarm.c \ signal.c utility.c table.c getset.c misc.c \ - profile.c schedule.c + profile.c schedule.c getrusage.c .if ${USE_MCONTEXT} != "no" SRCS+= mcontext.c diff --git a/servers/pm/getrusage.c b/servers/pm/getrusage.c new file mode 100644 index 000000000..cd2ffe49d --- /dev/null +++ b/servers/pm/getrusage.c @@ -0,0 +1,37 @@ +#include "pm.h" +#include +#include +#include +#include +#include "mproc.h" +#include "param.h" + +/*===========================================================================* + * 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 ((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; + + if ((res = sys_getrusage(who_e, &r_usage)) < 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)); +} diff --git a/servers/pm/proto.h b/servers/pm/proto.h index 73e8a4a69..08d45ba19 100644 --- a/servers/pm/proto.h +++ b/servers/pm/proto.h @@ -106,3 +106,6 @@ struct mproc *find_proc(pid_t lpid); int nice_to_priority(int nice, unsigned *new_q); int pm_isokendpt(int ep, int *proc); void tell_vfs(struct mproc *rmp, message *m_ptr); + +/* getrusage.c */ +int do_getrusage(void); diff --git a/servers/pm/table.c b/servers/pm/table.c index d1c2075a1..b9007553b 100644 --- a/servers/pm/table.c +++ b/servers/pm/table.c @@ -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]; diff --git a/servers/vfs/Makefile b/servers/vfs/Makefile index 083a5675c..6bf205f42 100644 --- a/servers/vfs/Makefile +++ b/servers/vfs/Makefile @@ -7,7 +7,7 @@ SRCS= main.c open.c read.c write.c pipe.c dmap.c \ filedes.c stadir.c protect.c time.c \ lock.c misc.c utility.c select.c table.c \ vnode.c vmnt.c request.c \ - tll.c comm.c worker.c coredump.c + tll.c comm.c worker.c coredump.c getrusage.c .if ${MKCOVERAGE} != "no" SRCS+= gcov.c diff --git a/servers/vfs/getrusage.c b/servers/vfs/getrusage.c new file mode 100644 index 000000000..7c05ce877 --- /dev/null +++ b/servers/vfs/getrusage.c @@ -0,0 +1,31 @@ +/* This file takes care of GETRUSAGE system call + */ + +#include "fs.h" +#include "fproc.h" +#include "glo.h" +#include +#include +#include + +/*===========================================================================* + * 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 = fp->in_blocks; + r_usage.ru_oublock = fp->out_blocks; + 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)); +} diff --git a/servers/vfs/proto.h b/servers/vfs/proto.h index 339949042..e6861edfd 100644 --- a/servers/vfs/proto.h +++ b/servers/vfs/proto.h @@ -376,4 +376,7 @@ void worker_stop_by_endpt(endpoint_t proc_e); void worker_wait(void); void sys_worker_start(void *(*func)(void *arg)); void dl_worker_start(void *(*func)(void *arg)); + +/* getrusage.c */ +int do_getrusage(message *m_out); #endif diff --git a/servers/vfs/table.c b/servers/vfs/table.c index 6aa4f734b..586c055d5 100644 --- a/servers/vfs/table.c +++ b/servers/vfs/table.c @@ -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]; diff --git a/servers/vm/Makefile b/servers/vm/Makefile index f24cf428f..babdf9903 100644 --- a/servers/vm/Makefile +++ b/servers/vm/Makefile @@ -6,7 +6,7 @@ SRCS= main.c alloc.c utility.c exit.c fork.c break.c \ mmap.c slaballoc.c region.c pagefaults.c \ rs.c queryexit.c pb.c regionavl.c \ mem_anon.c mem_directphys.c mem_anon_contig.c mem_shared.c \ - mem_cache.c cache.c vfs.c mem_file.c fdref.c + mem_cache.c cache.c vfs.c mem_file.c fdref.c getrusage.c .if ${MACHINE_ARCH} == "earm" LDFLAGS+= -T ${.CURDIR}/arch/${MACHINE_ARCH}/vm.lds diff --git a/servers/vm/getrusage.c b/servers/vm/getrusage.c new file mode 100644 index 000000000..f35271fce --- /dev/null +++ b/servers/vm/getrusage.c @@ -0,0 +1,29 @@ +#include +#include "proto.h" +#include "vmproc.h" +#include "glo.h" + +/*===========================================================================* + * 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)); +} diff --git a/servers/vm/main.c b/servers/vm/main.c index 3f494033a..95e64486d 100644 --- a/servers/vm/main.c +++ b/servers/vm/main.c @@ -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(); diff --git a/servers/vm/proto.h b/servers/vm/proto.h index 03badb81c..beab41776 100644 --- a/servers/vm/proto.h +++ b/servers/vm/proto.h @@ -240,3 +240,6 @@ struct fdref *fdref_dedup_or_new(struct vmproc *owner, ino_t ino, dev_t dev, void fdref_ref(struct fdref *ref, struct vir_region *region); void fdref_deref(struct vir_region *region); void fdref_sanitycheck(void); + +/* getrusage.c */ +int do_getrusage(message *m); diff --git a/sys/sys/resource.h b/sys/sys/resource.h index e6fb8aebd..97b31185f 100644 --- a/sys/sys/resource.h +++ b/sys/sys/resource.h @@ -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