support times
This commit is contained in:
@ -347,7 +347,7 @@ typedef void pgio_func_t(void *arg);
|
||||
* special "init" process */
|
||||
struct process {
|
||||
struct list_head hash_list;
|
||||
mcs_rwlock_lock_t update_lock; // lock for parent, status, ...?
|
||||
mcs_rwlock_lock_t update_lock; // lock for parent, status, cpu time...
|
||||
|
||||
// process vm
|
||||
struct process_vm *vm;
|
||||
@ -431,6 +431,10 @@ struct process {
|
||||
|
||||
ihk_spinlock_t mckfd_lock;
|
||||
struct mckfd *mckfd;
|
||||
|
||||
// cpu time (summary)
|
||||
struct timespec stime;
|
||||
struct timespec utime;
|
||||
};
|
||||
|
||||
void hold_thread(struct thread *ftn);
|
||||
@ -518,6 +522,11 @@ struct thread {
|
||||
unsigned long *ptrace_debugreg; /* debug registers for ptrace */
|
||||
struct sig_pending *ptrace_recvsig;
|
||||
struct sig_pending *ptrace_sendsig;
|
||||
|
||||
// cpu time
|
||||
struct timespec stime;
|
||||
struct timespec utime;
|
||||
struct timespec btime;
|
||||
};
|
||||
|
||||
struct process_vm {
|
||||
|
||||
@ -337,4 +337,7 @@ struct tod_data_s {
|
||||
};
|
||||
extern struct tod_data_s tod_data; /* residing in arch-dependent file */
|
||||
|
||||
void reset_cputime();
|
||||
void set_cputime(int mode);
|
||||
|
||||
#endif
|
||||
|
||||
@ -53,5 +53,27 @@ struct timezone
|
||||
int tz_dsttime; /* Nonzero if DST is ever in effect. */
|
||||
};
|
||||
|
||||
static inline void
|
||||
ts_add(struct timespec *ats, const struct timespec *bts)
|
||||
{
|
||||
ats->tv_sec += bts->tv_sec;
|
||||
ats->tv_nsec += bts->tv_nsec;
|
||||
while(ats->tv_nsec >= 1000000000){
|
||||
ats->tv_sec++;
|
||||
ats->tv_nsec -= 1000000000;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
ts_sub(struct timespec *ats, const struct timespec *bts)
|
||||
{
|
||||
ats->tv_sec -= bts->tv_sec;
|
||||
ats->tv_nsec -= bts->tv_nsec;
|
||||
while(ats->tv_nsec < 0){
|
||||
ats->tv_sec--;
|
||||
ats->tv_nsec += 1000000000;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __TIME_H
|
||||
|
||||
|
||||
@ -53,6 +53,7 @@ static unsigned long pa_start, pa_end;
|
||||
static struct page *pa_pages;
|
||||
|
||||
extern int ihk_mc_pt_print_pte(struct page_table *pt, void *virt);
|
||||
extern int interrupt_from_user(void *);
|
||||
|
||||
struct tlb_flush_entry tlb_flush_vector[IHK_TLB_FLUSH_IRQ_VECTOR_SIZE];
|
||||
|
||||
@ -369,6 +370,7 @@ static void page_fault_handler(void *fault_addr, uint64_t reason, void *regs)
|
||||
struct thread *thread = cpu_local_var(current);
|
||||
int error;
|
||||
|
||||
set_cputime(interrupt_from_user(regs)? 1: 2);
|
||||
dkprintf("[%d]page_fault_handler(%p,%lx,%p)\n",
|
||||
ihk_mc_get_processor_id(), fault_addr, reason, regs);
|
||||
|
||||
@ -427,6 +429,7 @@ out:
|
||||
ihk_mc_get_processor_id(), fault_addr, reason,
|
||||
regs, error);
|
||||
check_need_resched();
|
||||
set_cputime(0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -2161,11 +2161,17 @@ void destroy_thread(struct thread *thread)
|
||||
void release_thread(struct thread *thread)
|
||||
{
|
||||
struct process_vm *vm;
|
||||
struct mcs_rwlock_node lock;
|
||||
|
||||
if (!ihk_atomic_dec_and_test(&thread->refcount)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mcs_rwlock_writer_lock_noirq(&thread->proc->update_lock, &lock);
|
||||
ts_add(&thread->proc->stime, &thread->stime);
|
||||
ts_add(&thread->proc->utime, &thread->utime);
|
||||
mcs_rwlock_writer_unlock_noirq(&thread->proc->update_lock, &lock);
|
||||
|
||||
vm = thread->vm;
|
||||
|
||||
procfs_delete_thread(thread);
|
||||
@ -2547,6 +2553,7 @@ redo:
|
||||
if (prev != next) {
|
||||
switch_ctx = 1;
|
||||
v->current = next;
|
||||
reset_cputime();
|
||||
}
|
||||
|
||||
if (switch_ctx) {
|
||||
|
||||
@ -113,6 +113,7 @@ extern unsigned long ihk_mc_get_ns_per_tsc(void);
|
||||
extern int ptrace_detach(int pid, int data);
|
||||
extern void debug_log(unsigned long);
|
||||
extern void free_all_process_memory_range(struct process_vm *vm);
|
||||
extern struct cpu_local_var *clv;
|
||||
|
||||
int prepare_process_ranges_args_envs(struct thread *thread,
|
||||
struct program_load_desc *pn,
|
||||
@ -401,6 +402,10 @@ do_wait(int pid, int *status, int options, void *rusage)
|
||||
ret = wait_zombie(thread, child, status, options);
|
||||
mcs_rwlock_writer_unlock_noirq(&thread->proc->children_lock, &lock);
|
||||
if(!(options & WNOWAIT)){
|
||||
mcs_rwlock_writer_lock_noirq(&proc->update_lock, &lock);
|
||||
ts_add(&proc->stime, &child->stime);
|
||||
ts_add(&proc->utime, &child->utime);
|
||||
mcs_rwlock_writer_unlock_noirq(&proc->update_lock, &lock);
|
||||
release_process(child);
|
||||
}
|
||||
goto out_found;
|
||||
@ -2034,6 +2039,37 @@ SYSCALL_DECLARE(set_tid_address)
|
||||
return cpu_local_var(current)->proc->pid;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
timespec_to_jiffy(const struct timespec *ats)
|
||||
{
|
||||
return ats->tv_sec * 100 + ats->tv_nsec / 10000000;
|
||||
}
|
||||
|
||||
SYSCALL_DECLARE(times)
|
||||
{
|
||||
struct tms {
|
||||
unsigned long tms_utime;
|
||||
unsigned long tms_stime;
|
||||
unsigned long tms_cutime;
|
||||
unsigned long tms_cstime;
|
||||
};
|
||||
struct tms mytms;
|
||||
struct tms *buf = (struct tms *)ihk_mc_syscall_arg0(ctx);
|
||||
struct thread *thread = cpu_local_var(current);
|
||||
struct process *proc = thread->proc;
|
||||
struct timespec ats = {0, 0};
|
||||
|
||||
mytms.tms_utime = timespec_to_jiffy(&thread->utime);
|
||||
mytms.tms_stime = timespec_to_jiffy(&thread->stime);
|
||||
mytms.tms_cutime = timespec_to_jiffy(&proc->utime);
|
||||
mytms.tms_cstime = timespec_to_jiffy(&proc->stime);
|
||||
if(copy_to_user(buf, &mytms, sizeof mytms))
|
||||
return -EFAULT;
|
||||
if(gettime_local_support)
|
||||
calculate_time_from_tsc(&ats);
|
||||
return timespec_to_jiffy(&ats);
|
||||
}
|
||||
|
||||
SYSCALL_DECLARE(kill)
|
||||
{
|
||||
int pid = ihk_mc_syscall_arg0(ctx);
|
||||
@ -6604,13 +6640,67 @@ SYSCALL_DECLARE(pmc_reset)
|
||||
return ihk_mc_perfctr_reset(counter);
|
||||
}
|
||||
|
||||
void
|
||||
reset_cputime()
|
||||
{
|
||||
struct thread *thread;
|
||||
|
||||
if(clv == NULL)
|
||||
return;
|
||||
|
||||
if(!(thread = cpu_local_var(current)))
|
||||
return;
|
||||
|
||||
thread->btime.tv_sec = 0;
|
||||
thread->btime.tv_nsec = 0;
|
||||
}
|
||||
|
||||
void
|
||||
set_cputime(int mode)
|
||||
{
|
||||
struct thread *thread;
|
||||
struct timespec ats;
|
||||
|
||||
if(!gettime_local_support)
|
||||
return;
|
||||
|
||||
if(clv == NULL)
|
||||
return;
|
||||
|
||||
if(!(thread = cpu_local_var(current)))
|
||||
return;
|
||||
|
||||
calculate_time_from_tsc(&ats);
|
||||
if(thread->btime.tv_sec != 0 && thread->btime.tv_nsec != 0){
|
||||
struct timespec dts;
|
||||
|
||||
dts.tv_sec = ats.tv_sec;
|
||||
dts.tv_nsec = ats.tv_nsec;
|
||||
ts_sub(&dts, &thread->btime);
|
||||
if(mode == 1)
|
||||
ts_add(&thread->utime, &dts);
|
||||
else
|
||||
ts_add(&thread->stime, &dts);
|
||||
}
|
||||
if(mode == 2){
|
||||
thread->btime.tv_sec = 0;
|
||||
thread->btime.tv_nsec = 0;
|
||||
}
|
||||
else{
|
||||
thread->btime.tv_sec = ats.tv_sec;
|
||||
thread->btime.tv_nsec = ats.tv_nsec;
|
||||
}
|
||||
}
|
||||
|
||||
long syscall(int num, ihk_mc_user_context_t *ctx)
|
||||
{
|
||||
long l;
|
||||
|
||||
set_cputime(1);
|
||||
if(cpu_local_var(current)->proc->status == PS_EXITED &&
|
||||
(num != __NR_exit && num != __NR_exit_group)){
|
||||
check_signal(-EINVAL, NULL, 0);
|
||||
set_cputime(0);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -6669,5 +6759,6 @@ long syscall(int num, ihk_mc_user_context_t *ctx)
|
||||
ptrace_syscall_exit(cpu_local_var(current));
|
||||
}
|
||||
|
||||
set_cputime(0);
|
||||
return l;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user