2005-04-16 15:20:36 -07:00
/*
* linux / fs / proc / array . c
*
* Copyright ( C ) 1992 by Linus Torvalds
* based on ideas by Darren Senn
*
* Fixes :
* Michael . K . Johnson : stat , statm extensions .
* < johnsonm @ stolaf . edu >
*
* Pauline Middelink : Made cmdline , envline only break at ' \0 ' s , to
* make sure SET_PROCTITLE works . Also removed
* bad ' ! ' which forced address recalculation for
* EVERY character on the current page .
* < middelin @ polyware . iaf . nl >
*
* Danny ter Haar : added cpuinfo
* < dth @ cistron . nl >
*
* Alessandro Rubini : profile extension .
* < rubini @ ipvvis . unipv . it >
*
* Jeff Tranter : added BogoMips field to cpuinfo
* < Jeff_Tranter @ Mitel . COM >
*
* Bruno Haible : remove 4 K limit for the maps file
* < haible @ ma2s2 . mathematik . uni - karlsruhe . de >
*
* Yves Arrouye : remove removal of trailing spaces in get_array .
* < Yves . Arrouye @ marin . fdn . fr >
*
* Jerome Forissier : added per - CPU time information to / proc / stat
* and / proc / < pid > / cpu extension
* < forissier @ isia . cma . fr >
* - Incorporation and non - SMP safe operation
* of forissier patch in 2.1 .78 by
* Hans Marcus < crowbar @ concepts . nl >
*
* aeb @ cwi . nl : / proc / partitions
*
*
* Alan Cox : security fixes .
* < Alan . Cox @ linux . org >
*
* Al Viro : safe handling of mm_struct
*
* Gerhard Wichert : added BIGMEM support
* Siemens AG < Gerhard . Wichert @ pdb . siemens . de >
*
* Al Viro & Jeff Garzik : moved most of the thing into base . c and
* : proc_misc . c . The rest may eventually go into
* : base . c too .
*/
# include <linux/types.h>
# include <linux/errno.h>
# include <linux/time.h>
# include <linux/kernel.h>
# include <linux/kernel_stat.h>
# include <linux/tty.h>
# include <linux/string.h>
# include <linux/mman.h>
# include <linux/proc_fs.h>
# include <linux/ioport.h>
2007-07-16 09:46:31 +02:00
# include <linux/uaccess.h>
# include <linux/io.h>
2005-04-16 15:20:36 -07:00
# include <linux/mm.h>
# include <linux/hugetlb.h>
# include <linux/pagemap.h>
# include <linux/swap.h>
# include <linux/slab.h>
# include <linux/smp.h>
# include <linux/signal.h>
# include <linux/highmem.h>
# include <linux/file.h>
2008-04-24 07:44:08 -04:00
# include <linux/fdtable.h>
2005-04-16 15:20:36 -07:00
# include <linux/times.h>
# include <linux/cpuset.h>
2005-09-16 19:28:13 -07:00
# include <linux/rcupdate.h>
2006-07-14 00:24:43 -07:00
# include <linux/delayacct.h>
2008-02-08 04:18:31 -08:00
# include <linux/seq_file.h>
2007-10-18 23:40:14 -07:00
# include <linux/pid_namespace.h>
2005-04-16 15:20:36 -07:00
# include <asm/pgtable.h>
# include <asm/processor.h>
# include "internal.h"
/* Gcc optimizes away "strlen(x)" for constant x */
# define ADDBUF(buffer, string) \
do { memcpy ( buffer , string , strlen ( string ) ) ; \
buffer + = strlen ( string ) ; } while ( 0 )
2008-02-08 04:18:33 -08:00
static inline void task_name ( struct seq_file * m , struct task_struct * p )
2005-04-16 15:20:36 -07:00
{
int i ;
2008-02-08 04:18:33 -08:00
char * buf , * end ;
2007-07-16 09:46:31 +02:00
char * name ;
2005-04-16 15:20:36 -07:00
char tcomm [ sizeof ( p - > comm ) ] ;
get_task_comm ( tcomm , p ) ;
2008-02-08 04:18:33 -08:00
seq_printf ( m , " Name: \t " ) ;
end = m - > buf + m - > size ;
buf = m - > buf + m - > count ;
2005-04-16 15:20:36 -07:00
name = tcomm ;
i = sizeof ( tcomm ) ;
2008-02-08 04:18:33 -08:00
while ( i & & ( buf < end ) ) {
2005-04-16 15:20:36 -07:00
unsigned char c = * name ;
name + + ;
i - - ;
* buf = c ;
if ( ! c )
break ;
if ( c = = ' \\ ' ) {
2008-02-08 04:18:33 -08:00
buf + + ;
if ( buf < end )
* buf + + = c ;
2005-04-16 15:20:36 -07:00
continue ;
}
if ( c = = ' \n ' ) {
2008-02-08 04:18:33 -08:00
* buf + + = ' \\ ' ;
if ( buf < end )
* buf + + = ' n ' ;
2005-04-16 15:20:36 -07:00
continue ;
}
buf + + ;
2008-02-08 04:18:33 -08:00
}
m - > count = buf - m - > buf ;
seq_printf ( m , " \n " ) ;
2005-04-16 15:20:36 -07:00
}
/*
* The task state array is a strange " bitmap " of
* reasons to sleep . Thus " running " is zero , and
* you can test for combinations of others with
* simple bit tests .
*/
static const char * task_state_array [ ] = {
" R (running) " , /* 0 */
" S (sleeping) " , /* 1 */
" D (disk sleep) " , /* 2 */
" T (stopped) " , /* 4 */
" T (tracing stop) " , /* 8 */
" Z (zombie) " , /* 16 */
" X (dead) " /* 32 */
} ;
2007-07-16 09:46:31 +02:00
static inline const char * get_task_state ( struct task_struct * tsk )
2005-04-16 15:20:36 -07:00
{
2007-12-06 11:03:36 -05:00
unsigned int state = ( tsk - > state & TASK_REPORT ) | tsk - > exit_state ;
2005-04-16 15:20:36 -07:00
const char * * p = & task_state_array [ 0 ] ;
while ( state ) {
p + + ;
state > > = 1 ;
}
return * p ;
}
2008-02-08 04:18:33 -08:00
static inline void task_state ( struct seq_file * m , struct pid_namespace * ns ,
struct pid * pid , struct task_struct * p )
2005-04-16 15:20:36 -07:00
{
struct group_info * group_info ;
int g ;
2005-09-09 13:04:10 -07:00
struct fdtable * fdt = NULL ;
2007-10-18 23:40:14 -07:00
pid_t ppid , tpid ;
2005-04-16 15:20:36 -07:00
2006-10-02 02:18:54 -07:00
rcu_read_lock ( ) ;
2007-10-18 23:40:14 -07:00
ppid = pid_alive ( p ) ?
task_tgid_nr_ns ( rcu_dereference ( p - > real_parent ) , ns ) : 0 ;
tpid = pid_alive ( p ) & & p - > ptrace ?
2008-01-10 12:52:04 -08:00
task_pid_nr_ns ( rcu_dereference ( p - > parent ) , ns ) : 0 ;
2008-02-08 04:18:33 -08:00
seq_printf ( m ,
2005-04-16 15:20:36 -07:00
" State: \t %s \n "
" Tgid: \t %d \n "
" Pid: \t %d \n "
" PPid: \t %d \n "
" TracerPid: \t %d \n "
" Uid: \t %d \t %d \t %d \t %d \n "
" Gid: \t %d \t %d \t %d \t %d \n " ,
get_task_state ( p ) ,
2007-10-18 23:40:14 -07:00
task_tgid_nr_ns ( p , ns ) ,
2008-02-08 04:18:33 -08:00
pid_nr_ns ( pid , ns ) ,
2007-10-18 23:40:14 -07:00
ppid , tpid ,
2005-04-16 15:20:36 -07:00
p - > uid , p - > euid , p - > suid , p - > fsuid ,
p - > gid , p - > egid , p - > sgid , p - > fsgid ) ;
2006-10-02 02:18:54 -07:00
2005-04-16 15:20:36 -07:00
task_lock ( p ) ;
2005-09-09 13:04:10 -07:00
if ( p - > files )
fdt = files_fdtable ( p - > files ) ;
2008-02-08 04:18:33 -08:00
seq_printf ( m ,
2005-04-16 15:20:36 -07:00
" FDSize: \t %d \n "
" Groups: \t " ,
2005-09-09 13:04:10 -07:00
fdt ? fdt - > max_fds : 0 ) ;
2005-09-16 19:28:13 -07:00
rcu_read_unlock ( ) ;
2005-04-16 15:20:36 -07:00
group_info = p - > group_info ;
get_group_info ( group_info ) ;
task_unlock ( p ) ;
2007-07-16 09:46:31 +02:00
for ( g = 0 ; g < min ( group_info - > ngroups , NGROUPS_SMALL ) ; g + + )
2008-02-08 04:18:33 -08:00
seq_printf ( m , " %d " , GROUP_AT ( group_info , g ) ) ;
2005-04-16 15:20:36 -07:00
put_group_info ( group_info ) ;
2008-02-08 04:18:33 -08:00
seq_printf ( m , " \n " ) ;
2005-04-16 15:20:36 -07:00
}
2008-02-08 04:18:33 -08:00
static void render_sigset_t ( struct seq_file * m , const char * header ,
sigset_t * set )
2005-04-16 15:20:36 -07:00
{
2008-02-08 04:18:33 -08:00
int i ;
2005-04-16 15:20:36 -07:00
2008-02-08 04:18:33 -08:00
seq_printf ( m , " %s " , header ) ;
2005-04-16 15:20:36 -07:00
i = _NSIG ;
do {
int x = 0 ;
i - = 4 ;
if ( sigismember ( set , i + 1 ) ) x | = 1 ;
if ( sigismember ( set , i + 2 ) ) x | = 2 ;
if ( sigismember ( set , i + 3 ) ) x | = 4 ;
if ( sigismember ( set , i + 4 ) ) x | = 8 ;
2008-02-08 04:18:33 -08:00
seq_printf ( m , " %x " , x ) ;
2005-04-16 15:20:36 -07:00
} while ( i > = 4 ) ;
2008-02-08 04:18:33 -08:00
seq_printf ( m , " \n " ) ;
2005-04-16 15:20:36 -07:00
}
static void collect_sigign_sigcatch ( struct task_struct * p , sigset_t * ign ,
sigset_t * catch )
{
struct k_sigaction * k ;
int i ;
k = p - > sighand - > action ;
for ( i = 1 ; i < = _NSIG ; + + i , + + k ) {
if ( k - > sa . sa_handler = = SIG_IGN )
sigaddset ( ign , i ) ;
else if ( k - > sa . sa_handler ! = SIG_DFL )
sigaddset ( catch , i ) ;
}
}
2008-02-08 04:18:33 -08:00
static inline void task_sig ( struct seq_file * m , struct task_struct * p )
2005-04-16 15:20:36 -07:00
{
2006-10-02 02:18:52 -07:00
unsigned long flags ;
2005-04-16 15:20:36 -07:00
sigset_t pending , shpending , blocked , ignored , caught ;
int num_threads = 0 ;
unsigned long qsize = 0 ;
unsigned long qlim = 0 ;
sigemptyset ( & pending ) ;
sigemptyset ( & shpending ) ;
sigemptyset ( & blocked ) ;
sigemptyset ( & ignored ) ;
sigemptyset ( & caught ) ;
2006-10-02 02:18:52 -07:00
rcu_read_lock ( ) ;
if ( lock_task_sighand ( p , & flags ) ) {
2005-04-16 15:20:36 -07:00
pending = p - > pending . signal ;
shpending = p - > signal - > shared_pending . signal ;
blocked = p - > blocked ;
collect_sigign_sigcatch ( p , & ignored , & caught ) ;
num_threads = atomic_read ( & p - > signal - > count ) ;
qsize = atomic_read ( & p - > user - > sigpending ) ;
qlim = p - > signal - > rlim [ RLIMIT_SIGPENDING ] . rlim_cur ;
2006-10-02 02:18:52 -07:00
unlock_task_sighand ( p , & flags ) ;
2005-04-16 15:20:36 -07:00
}
2006-10-02 02:18:52 -07:00
rcu_read_unlock ( ) ;
2005-04-16 15:20:36 -07:00
2008-02-08 04:18:33 -08:00
seq_printf ( m , " Threads: \t %d \n " , num_threads ) ;
seq_printf ( m , " SigQ: \t %lu/%lu \n " , qsize , qlim ) ;
2005-04-16 15:20:36 -07:00
/* render them all */
2008-02-08 04:18:33 -08:00
render_sigset_t ( m , " SigPnd: \t " , & pending ) ;
render_sigset_t ( m , " ShdPnd: \t " , & shpending ) ;
render_sigset_t ( m , " SigBlk: \t " , & blocked ) ;
render_sigset_t ( m , " SigIgn: \t " , & ignored ) ;
render_sigset_t ( m , " SigCgt: \t " , & caught ) ;
2005-04-16 15:20:36 -07:00
}
2008-02-08 04:18:33 -08:00
static void render_cap_t ( struct seq_file * m , const char * header ,
kernel_cap_t * a )
2008-02-04 22:29:42 -08:00
{
unsigned __capi ;
2008-02-08 04:18:33 -08:00
seq_printf ( m , " %s " , header ) ;
2008-02-04 22:29:42 -08:00
CAP_FOR_EACH_U32 ( __capi ) {
2008-02-08 04:18:33 -08:00
seq_printf ( m , " %08x " ,
2008-05-27 22:05:17 -07:00
a - > cap [ ( _KERNEL_CAPABILITY_U32S - 1 ) - __capi ] ) ;
2008-02-04 22:29:42 -08:00
}
2008-02-08 04:18:33 -08:00
seq_printf ( m , " \n " ) ;
2008-02-04 22:29:42 -08:00
}
2008-02-08 04:18:33 -08:00
static inline void task_cap ( struct seq_file * m , struct task_struct * p )
2005-04-16 15:20:36 -07:00
{
2008-02-08 04:18:33 -08:00
render_cap_t ( m , " CapInh: \t " , & p - > cap_inheritable ) ;
render_cap_t ( m , " CapPrm: \t " , & p - > cap_permitted ) ;
render_cap_t ( m , " CapEff: \t " , & p - > cap_effective ) ;
2008-05-12 14:02:13 -07:00
render_cap_t ( m , " CapBnd: \t " , & p - > cap_bset ) ;
2005-04-16 15:20:36 -07:00
}
2008-02-08 04:18:33 -08:00
static inline void task_context_switch_counts ( struct seq_file * m ,
struct task_struct * p )
2007-07-15 23:40:48 -07:00
{
2008-02-08 04:18:33 -08:00
seq_printf ( m , " voluntary_ctxt_switches: \t %lu \n "
" nonvoluntary_ctxt_switches: \t %lu \n " ,
p - > nvcsw ,
p - > nivcsw ) ;
2007-07-15 23:40:48 -07:00
}
2008-02-08 04:18:33 -08:00
int proc_pid_status ( struct seq_file * m , struct pid_namespace * ns ,
struct pid * pid , struct task_struct * task )
2005-04-16 15:20:36 -07:00
{
struct mm_struct * mm = get_task_mm ( task ) ;
2008-02-08 04:18:33 -08:00
task_name ( m , task ) ;
task_state ( m , ns , pid , task ) ;
2007-07-16 09:46:31 +02:00
2005-04-16 15:20:36 -07:00
if ( mm ) {
2008-02-08 04:18:33 -08:00
task_mem ( m , mm ) ;
2005-04-16 15:20:36 -07:00
mmput ( mm ) ;
}
2008-02-08 04:18:33 -08:00
task_sig ( m , task ) ;
task_cap ( m , task ) ;
cpuset_task_status_allowed ( m , task ) ;
2006-01-06 00:19:28 -08:00
# if defined(CONFIG_S390)
2008-02-08 04:18:33 -08:00
task_show_regs ( m , task ) ;
2005-04-16 15:20:36 -07:00
# endif
2008-02-08 04:18:33 -08:00
task_context_switch_counts ( m , task ) ;
return 0 ;
2005-04-16 15:20:36 -07:00
}
2007-08-23 15:18:02 +02:00
/*
* Use precise platform statistics if available :
*/
# ifdef CONFIG_VIRT_CPU_ACCOUNTING
static cputime_t task_utime ( struct task_struct * p )
{
return p - > utime ;
}
static cputime_t task_stime ( struct task_struct * p )
{
return p - > stime ;
}
# else
static cputime_t task_utime ( struct task_struct * p )
2007-07-09 18:51:59 +02:00
{
clock_t utime = cputime_to_clock_t ( p - > utime ) ,
total = utime + cputime_to_clock_t ( p - > stime ) ;
u64 temp ;
/*
* Use CFS ' s precise accounting :
*/
temp = ( u64 ) nsec_to_clock_t ( p - > se . sum_exec_runtime ) ;
if ( total ) {
temp * = utime ;
do_div ( temp , total ) ;
}
utime = ( clock_t ) temp ;
2007-10-29 21:18:11 +01:00
p - > prev_utime = max ( p - > prev_utime , clock_t_to_cputime ( utime ) ) ;
return p - > prev_utime ;
2007-07-09 18:51:59 +02:00
}
2007-08-23 15:18:02 +02:00
static cputime_t task_stime ( struct task_struct * p )
2007-07-09 18:51:59 +02:00
{
2007-07-16 09:46:30 +02:00
clock_t stime ;
2007-07-09 18:51:59 +02:00
/*
* Use CFS ' s precise accounting . ( we subtract utime from
* the total , to make sure the total observed by userspace
* grows monotonically - apps rely on that ) :
*/
2007-08-23 15:18:02 +02:00
stime = nsec_to_clock_t ( p - > se . sum_exec_runtime ) -
cputime_to_clock_t ( task_utime ( p ) ) ;
2007-07-09 18:51:59 +02:00
2007-11-26 21:21:49 +01:00
if ( stime > = 0 )
p - > prev_stime = max ( p - > prev_stime , clock_t_to_cputime ( stime ) ) ;
2007-10-30 00:26:32 +01:00
return p - > prev_stime ;
2007-07-09 18:51:59 +02:00
}
2007-08-23 15:18:02 +02:00
# endif
2007-07-09 18:51:59 +02:00
2007-10-15 17:00:19 +02:00
static cputime_t task_gtime ( struct task_struct * p )
{
return p - > gtime ;
}
2008-02-08 04:18:31 -08:00
static int do_task_stat ( struct seq_file * m , struct pid_namespace * ns ,
struct pid * pid , struct task_struct * task , int whole )
2005-04-16 15:20:36 -07:00
{
unsigned long vsize , eip , esp , wchan = ~ 0UL ;
long priority , nice ;
int tty_pgrp = - 1 , tty_nr = 0 ;
sigset_t sigign , sigcatch ;
char state ;
2007-07-16 09:46:31 +02:00
pid_t ppid = 0 , pgid = - 1 , sid = - 1 ;
2005-04-16 15:20:36 -07:00
int num_threads = 0 ;
struct mm_struct * mm ;
unsigned long long start_time ;
unsigned long cmin_flt = 0 , cmaj_flt = 0 ;
unsigned long min_flt = 0 , maj_flt = 0 ;
2007-08-23 15:18:02 +02:00
cputime_t cutime , cstime , utime , stime ;
2007-10-15 17:00:19 +02:00
cputime_t cgtime , gtime ;
2005-04-16 15:20:36 -07:00
unsigned long rsslim = 0 ;
char tcomm [ sizeof ( task - > comm ) ] ;
2006-10-02 02:18:53 -07:00
unsigned long flags ;
2005-04-16 15:20:36 -07:00
state = * get_task_state ( task ) ;
vsize = eip = esp = 0 ;
mm = get_task_mm ( task ) ;
if ( mm ) {
vsize = task_vsize ( mm ) ;
eip = KSTK_EIP ( task ) ;
esp = KSTK_ESP ( task ) ;
}
get_task_comm ( tcomm , task ) ;
sigemptyset ( & sigign ) ;
sigemptyset ( & sigcatch ) ;
2007-08-23 15:18:02 +02:00
cutime = cstime = utime = stime = cputime_zero ;
2007-10-15 17:00:19 +02:00
cgtime = gtime = cputime_zero ;
2006-09-29 02:00:41 -07:00
2006-10-02 02:18:53 -07:00
if ( lock_task_sighand ( task , & flags ) ) {
struct signal_struct * sig = task - > signal ;
2006-12-08 02:36:07 -08:00
if ( sig - > tty ) {
2008-04-30 00:53:31 -07:00
struct pid * pgrp = tty_get_pgrp ( sig - > tty ) ;
tty_pgrp = pid_nr_ns ( pgrp , ns ) ;
put_pid ( pgrp ) ;
2006-12-08 02:36:07 -08:00
tty_nr = new_encode_dev ( tty_devnum ( sig - > tty ) ) ;
2006-10-02 02:18:53 -07:00
}
num_threads = atomic_read ( & sig - > count ) ;
2005-04-16 15:20:36 -07:00
collect_sigign_sigcatch ( task , & sigign , & sigcatch ) ;
2006-10-02 02:18:53 -07:00
cmin_flt = sig - > cmin_flt ;
cmaj_flt = sig - > cmaj_flt ;
cutime = sig - > cutime ;
cstime = sig - > cstime ;
2007-10-15 17:00:19 +02:00
cgtime = sig - > cgtime ;
2006-10-02 02:18:53 -07:00
rsslim = sig - > rlim [ RLIMIT_RSS ] . rlim_cur ;
2005-04-16 15:20:36 -07:00
/* add up live thread stats at the group level */
if ( whole ) {
2006-10-02 02:18:53 -07:00
struct task_struct * t = task ;
2005-04-16 15:20:36 -07:00
do {
min_flt + = t - > min_flt ;
maj_flt + = t - > maj_flt ;
2007-08-23 15:18:02 +02:00
utime = cputime_add ( utime , task_utime ( t ) ) ;
stime = cputime_add ( stime , task_stime ( t ) ) ;
2007-10-15 17:00:19 +02:00
gtime = cputime_add ( gtime , task_gtime ( t ) ) ;
2005-04-16 15:20:36 -07:00
t = next_thread ( t ) ;
} while ( t ! = task ) ;
2006-10-02 02:18:53 -07:00
min_flt + = sig - > min_flt ;
maj_flt + = sig - > maj_flt ;
2007-08-23 15:18:02 +02:00
utime = cputime_add ( utime , sig - > utime ) ;
stime = cputime_add ( stime , sig - > stime ) ;
2007-10-19 20:52:40 +02:00
gtime = cputime_add ( gtime , sig - > gtime ) ;
2005-04-16 15:20:36 -07:00
}
2006-10-02 02:18:53 -07:00
2007-10-18 23:40:14 -07:00
sid = task_session_nr_ns ( task , ns ) ;
2008-01-15 00:02:37 +03:00
ppid = task_tgid_nr_ns ( task - > real_parent , ns ) ;
2007-10-18 23:40:14 -07:00
pgid = task_pgrp_nr_ns ( task , ns ) ;
2006-10-02 02:18:53 -07:00
unlock_task_sighand ( task , & flags ) ;
2005-04-16 15:20:36 -07:00
}
2007-07-16 09:46:31 +02:00
if ( ! whole | | num_threads < 2 )
2005-04-16 15:20:36 -07:00
wchan = get_wchan ( task ) ;
if ( ! whole ) {
min_flt = task - > min_flt ;
maj_flt = task - > maj_flt ;
2007-07-09 18:51:59 +02:00
utime = task_utime ( task ) ;
stime = task_stime ( task ) ;
2007-10-15 17:00:19 +02:00
gtime = task_gtime ( task ) ;
2005-04-16 15:20:36 -07:00
}
/* scale priority and nice values from timeslices to -20..20 */
/* to make it look like a "normal" Unix priority/nice value */
priority = task_prio ( task ) ;
nice = task_nice ( task ) ;
/* Temporary variable needed for gcc-2.96 */
/* convert timespec -> nsec*/
2007-07-15 23:39:42 -07:00
start_time =
( unsigned long long ) task - > real_start_time . tv_sec * NSEC_PER_SEC
+ task - > real_start_time . tv_nsec ;
2005-04-16 15:20:36 -07:00
/* convert nsec -> ticks */
start_time = nsec_to_clock_t ( start_time ) ;
2008-02-08 04:18:31 -08:00
seq_printf ( m , " %d (%s) %c %d %d %d %d %d %u %lu \
2006-03-26 01:38:10 -08:00
% lu % lu % lu % lu % lu % ld % ld % ld % ld % d 0 % llu % lu % ld % lu % lu % lu % lu % lu \
2007-10-15 17:00:19 +02:00
% lu % lu % lu % lu % lu % lu % lu % lu % d % d % u % u % llu % lu % ld \ n " ,
2008-02-08 04:18:31 -08:00
pid_nr_ns ( pid , ns ) ,
2005-04-16 15:20:36 -07:00
tcomm ,
state ,
ppid ,
pgid ,
sid ,
tty_nr ,
tty_pgrp ,
task - > flags ,
min_flt ,
cmin_flt ,
maj_flt ,
cmaj_flt ,
2007-08-23 15:18:02 +02:00
cputime_to_clock_t ( utime ) ,
cputime_to_clock_t ( stime ) ,
2005-04-16 15:20:36 -07:00
cputime_to_clock_t ( cutime ) ,
cputime_to_clock_t ( cstime ) ,
priority ,
nice ,
num_threads ,
start_time ,
vsize ,
2005-10-29 18:16:05 -07:00
mm ? get_mm_rss ( mm ) : 0 ,
2007-07-16 09:46:31 +02:00
rsslim ,
2005-04-16 15:20:36 -07:00
mm ? mm - > start_code : 0 ,
mm ? mm - > end_code : 0 ,
mm ? mm - > start_stack : 0 ,
esp ,
eip ,
/* The signal information here is obsolete.
* It must be decimal for Linux 2.0 compatibility .
* Use / proc / # / status for real - time signals .
*/
task - > pending . signal . sig [ 0 ] & 0x7fffffffUL ,
task - > blocked . sig [ 0 ] & 0x7fffffffUL ,
sigign . sig [ 0 ] & 0x7fffffffUL ,
sigcatch . sig [ 0 ] & 0x7fffffffUL ,
wchan ,
0UL ,
0UL ,
task - > exit_signal ,
task_cpu ( task ) ,
task - > rt_priority ,
2006-07-14 00:24:43 -07:00
task - > policy ,
2007-10-15 17:00:19 +02:00
( unsigned long long ) delayacct_blkio_ticks ( task ) ,
cputime_to_clock_t ( gtime ) ,
cputime_to_clock_t ( cgtime ) ) ;
2007-07-16 09:46:31 +02:00
if ( mm )
2005-04-16 15:20:36 -07:00
mmput ( mm ) ;
2008-02-08 04:18:31 -08:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
2008-02-08 04:18:31 -08:00
int proc_tid_stat ( struct seq_file * m , struct pid_namespace * ns ,
struct pid * pid , struct task_struct * task )
2005-04-16 15:20:36 -07:00
{
2008-02-08 04:18:31 -08:00
return do_task_stat ( m , ns , pid , task , 0 ) ;
2005-04-16 15:20:36 -07:00
}
2008-02-08 04:18:31 -08:00
int proc_tgid_stat ( struct seq_file * m , struct pid_namespace * ns ,
struct pid * pid , struct task_struct * task )
2005-04-16 15:20:36 -07:00
{
2008-02-08 04:18:31 -08:00
return do_task_stat ( m , ns , pid , task , 1 ) ;
2005-04-16 15:20:36 -07:00
}
2008-02-08 04:18:32 -08:00
int proc_pid_statm ( struct seq_file * m , struct pid_namespace * ns ,
struct pid * pid , struct task_struct * task )
2005-04-16 15:20:36 -07:00
{
int size = 0 , resident = 0 , shared = 0 , text = 0 , lib = 0 , data = 0 ;
struct mm_struct * mm = get_task_mm ( task ) ;
2007-07-16 09:46:31 +02:00
2005-04-16 15:20:36 -07:00
if ( mm ) {
size = task_statm ( mm , & shared , & text , & data , & resident ) ;
mmput ( mm ) ;
}
2008-02-08 04:18:32 -08:00
seq_printf ( m , " %d %d %d %d %d %d %d \n " ,
size , resident , shared , text , lib , data , 0 ) ;
2005-04-16 15:20:36 -07:00
2008-02-08 04:18:32 -08:00
return 0 ;
2005-04-16 15:20:36 -07:00
}