From dbc778e4fa90d82835b074eb1f0d932fdba67d2d Mon Sep 17 00:00:00 2001 From: Tomoki Shirasawa Date: Mon, 7 Mar 2016 17:06:44 +0900 Subject: [PATCH] support getrusage (work in progress) --- arch/x86/kernel/include/syscall_list.h | 1 + arch/x86/kernel/memory.c | 2 + kernel/include/process.h | 5 ++ kernel/include/syscall.h | 23 ++++++++ kernel/process.c | 6 ++ kernel/syscall.c | 78 +++++++++++++++++++++++++- 6 files changed, 112 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/include/syscall_list.h b/arch/x86/kernel/include/syscall_list.h index 33212922..2a2b88a5 100644 --- a/arch/x86/kernel/include/syscall_list.h +++ b/arch/x86/kernel/include/syscall_list.h @@ -71,6 +71,7 @@ SYSCALL_DELEGATED(79, getcwd) SYSCALL_DELEGATED(89, readlink) SYSCALL_HANDLED(96, gettimeofday) SYSCALL_HANDLED(97, getrlimit) +SYSCALL_HANDLED(98, getrusage) SYSCALL_HANDLED(100, times) SYSCALL_HANDLED(101, ptrace) SYSCALL_HANDLED(102, getuid) diff --git a/arch/x86/kernel/memory.c b/arch/x86/kernel/memory.c index 6c75ade9..3cdf8d73 100644 --- a/arch/x86/kernel/memory.c +++ b/arch/x86/kernel/memory.c @@ -1102,6 +1102,7 @@ static int clear_range_l1(void *args0, pte_t *ptep, uint64_t base, if (page && page_unmap(page)) { ihk_mc_free_pages(phys_to_virt(phys), 1); } + args->vm->currss -= PAGE_SIZE; } remote_flush_tlb_cpumask(args->vm, base, ihk_mc_get_processor_id()); @@ -1150,6 +1151,7 @@ static int clear_range_l2(void *args0, pte_t *ptep, uint64_t base, if (page && page_unmap(page)) { ihk_mc_free_pages(phys_to_virt(phys), PTL2_SIZE/PTL1_SIZE); } + args->vm->currss -= LARGE_PAGE_SIZE; } remote_flush_tlb_cpumask(args->vm, base, ihk_mc_get_processor_id()); diff --git a/kernel/include/process.h b/kernel/include/process.h index e7e88e4d..7ed6ec0a 100644 --- a/kernel/include/process.h +++ b/kernel/include/process.h @@ -439,6 +439,9 @@ struct process { // cpu time (children) struct timespec stime_children; struct timespec utime_children; + + long maxrss; + long maxrss_children; }; void hold_thread(struct thread *ftn); @@ -560,6 +563,8 @@ struct process_vm { ihk_atomic_t refcount; int exiting; + + long currss; }; diff --git a/kernel/include/syscall.h b/kernel/include/syscall.h index 0b96fcb9..33a012bf 100644 --- a/kernel/include/syscall.h +++ b/kernel/include/syscall.h @@ -326,6 +326,29 @@ struct procfs_file { char fname[PROCFS_NAME_MAX]; /* procfs filename (request) */ }; +#define RUSAGE_SELF 0 +#define RUSAGE_CHILDREN -1 +#define RUSAGE_THREAD 1 + +struct rusage { + struct timeval ru_utime; + struct timeval ru_stime; + long ru_maxrss; + long ru_ixrss; + long ru_idrss; + long ru_isrss; + long ru_minflt; + long ru_majflt; + long ru_nswap; + long ru_inblock; + long ru_oublock; + long ru_msgsnd; + long ru_msgrcv; + long ru_nsignals; + long ru_nvcsw; + long ru_nivcsw; +}; + extern void terminate(int, int); struct tod_data_s { diff --git a/kernel/process.c b/kernel/process.c index 18e4131a..62d4ef57 100644 --- a/kernel/process.c +++ b/kernel/process.c @@ -381,6 +381,9 @@ clone_thread(struct thread *org, unsigned long pc, unsigned long sp, goto err_free_proc; } + thread->proc->maxrss = org->proc->maxrss; + thread->vm->currss = org->vm->currss; + dkprintf("fork(): copy_user_ranges() OK\n"); } @@ -1570,6 +1573,9 @@ static int page_fault_process_memory_range(struct process_vm *vm, struct vm_rang flush_tlb_single(fault_addr); error = 0; page = NULL; + vm->currss += PAGE_SIZE; + if(vm->currss > vm->proc->maxrss) + vm->proc->maxrss = vm->currss; out: ihk_mc_spinlock_unlock_noirq(&vm->page_table_lock); if (page) { diff --git a/kernel/syscall.c b/kernel/syscall.c index 9209ac75..e17c7059 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -407,6 +407,10 @@ do_wait(int pid, int *status, int options, void *rusage) ts_add(&proc->utime_children, &child->utime); ts_add(&proc->stime_children, &child->stime_children); ts_add(&proc->utime_children, &child->utime_children); + if(child->maxrss > proc->maxrss_children) + proc->maxrss_children = child->maxrss; + if(child->maxrss_children > proc->maxrss_children) + proc->maxrss_children = child->maxrss_children; mcs_rwlock_writer_unlock_noirq(&proc->update_lock, &lock); release_process(child); } @@ -3954,6 +3958,75 @@ SYSCALL_DECLARE(getrlimit) return 0; } +SYSCALL_DECLARE(getrusage) +{ + int who = ihk_mc_syscall_arg0(ctx); + struct rusage *usage = (struct rusage *)ihk_mc_syscall_arg1(ctx); + struct rusage kusage; + struct thread *thread = cpu_local_var(current); + struct process *proc = thread->proc; + struct timespec utime; + struct timespec stime; + struct mcs_rwlock_node lock; + + if(who != RUSAGE_SELF && + who != RUSAGE_CHILDREN && + who != RUSAGE_THREAD) + return -EINVAL; + + memset(&kusage, '\0', sizeof kusage); + + if(who == RUSAGE_SELF){ + struct thread *child; + + memset(&utime, '\0', sizeof utime); + memset(&stime, '\0', sizeof stime); + mcs_rwlock_reader_lock_noirq(&proc->threads_lock, &lock); + list_for_each_entry(child, &proc->threads_list, siblings_list){ + if(child != thread && + child->status == PS_RUNNING && + !child->in_kernel){ + child->times_update = 0; + ihk_mc_interrupt_cpu(get_x86_cpu_local_variable(child->cpu_id)->apic_id, 0xd1); + } + else + child->times_update = 1; + } + utime.tv_sec = proc->utime.tv_sec; + utime.tv_nsec = proc->utime.tv_nsec; + stime.tv_sec = proc->stime.tv_sec; + stime.tv_nsec = proc->stime.tv_nsec; + list_for_each_entry(child, &proc->threads_list, siblings_list){ + while(!child->times_update) + cpu_pause(); + ts_add(&utime, &child->utime); + ts_add(&stime, &child->stime); + } + mcs_rwlock_reader_unlock_noirq(&proc->threads_lock, &lock); + ts_to_tv(&kusage.ru_utime, &utime); + ts_to_tv(&kusage.ru_stime, &stime); + + kusage.ru_maxrss = proc->maxrss / 1024; + } + else if(who == RUSAGE_CHILDREN){ + ts_to_tv(&kusage.ru_utime, &proc->utime_children); + ts_to_tv(&kusage.ru_stime, &proc->stime_children); + + kusage.ru_maxrss = proc->maxrss_children / 1024; + } + else if(who == RUSAGE_THREAD){ + ts_to_tv(&kusage.ru_utime, &thread->utime); + ts_to_tv(&kusage.ru_stime, &thread->stime); + + kusage.ru_maxrss = proc->maxrss / 1024; + } + + if(copy_to_user(usage, &kusage, sizeof kusage)) + return -EFAULT; + + return 0; +} + extern int ptrace_traceme(void); extern void clear_single_step(struct thread *thread); extern void set_single_step(struct thread *thread); @@ -4997,7 +5070,6 @@ SYSCALL_DECLARE(sched_setaffinity) int empty_set = 1; extern int num_processors; -kprintf("sched_setaffinity tid=%d len=%d set=%p\n", tid, len, u_cpu_set); if (sizeof(k_cpu_set) > len) { memset(&k_cpu_set, 0, sizeof(k_cpu_set)); } @@ -5295,7 +5367,7 @@ SYSCALL_DECLARE(clock_gettime) struct thread *child; struct mcs_rwlock_node lock; - mcs_rwlock_reader_lock_noirq(&proc->children_lock, &lock); + mcs_rwlock_reader_lock_noirq(&proc->threads_lock, &lock); list_for_each_entry(child, &proc->threads_list, siblings_list){ if(child != thread && child->status == PS_RUNNING && @@ -5313,7 +5385,7 @@ SYSCALL_DECLARE(clock_gettime) ts_add(&ats, &child->utime); ts_add(&ats, &child->stime); } - mcs_rwlock_reader_unlock_noirq(&proc->children_lock, &lock); + mcs_rwlock_reader_unlock_noirq(&proc->threads_lock, &lock); return copy_to_user(ts, &ats, sizeof ats); } else if(clock_id == CLOCK_THREAD_CPUTIME_ID){