2006-10-01 10:28:55 +04:00
/*
* tsacct . c - System accounting over taskstats interface
*
* Copyright ( C ) Jay Lan , < jlan @ sgi . com >
*
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
*/
# include <linux/kernel.h>
# include <linux/sched.h>
# include <linux/tsacct_kern.h>
# include <linux/acct.h>
2006-10-01 10:29:00 +04:00
# include <linux/jiffies.h>
2006-10-01 10:28:55 +04:00
/*
* fill in basic accounting fields
*/
void bacct_add_tsk ( struct taskstats * stats , struct task_struct * tsk )
{
struct timespec uptime , ts ;
s64 ac_etime ;
BUILD_BUG_ON ( TS_COMM_LEN < TASK_COMM_LEN ) ;
/* calculate task elapsed time in timespec */
do_posix_clock_monotonic_gettime ( & uptime ) ;
2006-10-28 21:38:50 +04:00
ts = timespec_sub ( uptime , tsk - > start_time ) ;
2006-10-01 10:28:55 +04:00
/* rebase elapsed time to usec */
ac_etime = timespec_to_ns ( & ts ) ;
do_div ( ac_etime , NSEC_PER_USEC ) ;
stats - > ac_etime = ac_etime ;
2007-07-25 04:47:43 +04:00
stats - > ac_btime = get_seconds ( ) - ts . tv_sec ;
2006-10-01 10:28:55 +04:00
if ( thread_group_leader ( tsk ) ) {
stats - > ac_exitcode = tsk - > exit_code ;
if ( tsk - > flags & PF_FORKNOEXEC )
stats - > ac_flag | = AFORK ;
}
if ( tsk - > flags & PF_SUPERPRIV )
stats - > ac_flag | = ASU ;
if ( tsk - > flags & PF_DUMPCORE )
stats - > ac_flag | = ACORE ;
if ( tsk - > flags & PF_SIGNALED )
stats - > ac_flag | = AXSIG ;
stats - > ac_nice = task_nice ( tsk ) ;
stats - > ac_sched = tsk - > policy ;
stats - > ac_uid = tsk - > uid ;
stats - > ac_gid = tsk - > gid ;
stats - > ac_pid = tsk - > pid ;
2006-10-28 21:38:50 +04:00
rcu_read_lock ( ) ;
stats - > ac_ppid = pid_alive ( tsk ) ?
rcu_dereference ( tsk - > real_parent ) - > tgid : 0 ;
rcu_read_unlock ( ) ;
2006-10-01 10:28:55 +04:00
stats - > ac_utime = cputime_to_msecs ( tsk - > utime ) * USEC_PER_MSEC ;
stats - > ac_stime = cputime_to_msecs ( tsk - > stime ) * USEC_PER_MSEC ;
stats - > ac_minflt = tsk - > min_flt ;
stats - > ac_majflt = tsk - > maj_flt ;
strncpy ( stats - > ac_comm , tsk - > comm , sizeof ( stats - > ac_comm ) ) ;
}
2006-10-01 10:28:58 +04:00
# ifdef CONFIG_TASK_XACCT
2006-10-01 10:29:00 +04:00
# define KB 1024
# define MB (1024*KB)
2006-10-01 10:28:58 +04:00
/*
* fill in extended accounting fields
*/
void xacct_add_tsk ( struct taskstats * stats , struct task_struct * p )
{
2006-10-30 09:46:43 +03:00
struct mm_struct * mm ;
2006-10-01 10:29:00 +04:00
/* convert pages-jiffies to Mbyte-usec */
stats - > coremem = jiffies_to_usecs ( p - > acct_rss_mem1 ) * PAGE_SIZE / MB ;
stats - > virtmem = jiffies_to_usecs ( p - > acct_vm_mem1 ) * PAGE_SIZE / MB ;
2006-10-30 09:46:43 +03:00
mm = get_task_mm ( p ) ;
if ( mm ) {
2006-10-01 10:29:00 +04:00
/* adjust to KB unit */
2006-10-30 09:46:43 +03:00
stats - > hiwater_rss = mm - > hiwater_rss * PAGE_SIZE / KB ;
stats - > hiwater_vm = mm - > hiwater_vm * PAGE_SIZE / KB ;
mmput ( mm ) ;
2006-10-01 10:28:58 +04:00
}
stats - > read_char = p - > rchar ;
stats - > write_char = p - > wchar ;
stats - > read_syscalls = p - > syscr ;
stats - > write_syscalls = p - > syscw ;
2006-12-10 13:19:53 +03:00
# ifdef CONFIG_TASK_IO_ACCOUNTING
stats - > read_bytes = p - > ioac . read_bytes ;
stats - > write_bytes = p - > ioac . write_bytes ;
stats - > cancelled_write_bytes = p - > ioac . cancelled_write_bytes ;
# else
stats - > read_bytes = 0 ;
stats - > write_bytes = 0 ;
stats - > cancelled_write_bytes = 0 ;
# endif
2006-10-01 10:28:58 +04:00
}
2006-10-01 10:29:00 +04:00
# undef KB
# undef MB
2006-10-01 10:28:59 +04:00
/**
* acct_update_integrals - update mm integral fields in task_struct
* @ tsk : task_struct for accounting
*/
void acct_update_integrals ( struct task_struct * tsk )
{
if ( likely ( tsk - > mm ) ) {
2006-10-01 10:29:00 +04:00
long delta = cputime_to_jiffies (
cputime_sub ( tsk - > stime , tsk - > acct_stimexpd ) ) ;
2006-10-01 10:28:59 +04:00
if ( delta = = 0 )
return ;
tsk - > acct_stimexpd = tsk - > stime ;
tsk - > acct_rss_mem1 + = delta * get_mm_rss ( tsk - > mm ) ;
tsk - > acct_vm_mem1 + = delta * tsk - > mm - > total_vm ;
}
}
/**
* acct_clear_integrals - clear the mm integral fields in task_struct
* @ tsk : task_struct whose accounting fields are cleared
*/
void acct_clear_integrals ( struct task_struct * tsk )
{
tsk - > acct_stimexpd = 0 ;
tsk - > acct_rss_mem1 = 0 ;
tsk - > acct_vm_mem1 = 0 ;
}
2006-10-01 10:28:58 +04:00
# endif