2005-04-17 02:20:36 +04: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 11:46:31 +04:00
# include <linux/uaccess.h>
# include <linux/io.h>
2005-04-17 02:20:36 +04: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>
# include <linux/times.h>
# include <linux/cpuset.h>
2005-09-17 06:28:13 +04:00
# include <linux/rcupdate.h>
2006-07-14 11:24:43 +04:00
# include <linux/delayacct.h>
2007-10-19 10:40:14 +04:00
# include <linux/pid_namespace.h>
2005-04-17 02:20:36 +04: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 )
2007-07-16 11:46:31 +04:00
static inline char * task_name ( struct task_struct * p , char * buf )
2005-04-17 02:20:36 +04:00
{
int i ;
2007-07-16 11:46:31 +04:00
char * name ;
2005-04-17 02:20:36 +04:00
char tcomm [ sizeof ( p - > comm ) ] ;
get_task_comm ( tcomm , p ) ;
ADDBUF ( buf , " Name: \t " ) ;
name = tcomm ;
i = sizeof ( tcomm ) ;
do {
unsigned char c = * name ;
name + + ;
i - - ;
* buf = c ;
if ( ! c )
break ;
if ( c = = ' \\ ' ) {
buf [ 1 ] = c ;
buf + = 2 ;
continue ;
}
if ( c = = ' \n ' ) {
buf [ 0 ] = ' \\ ' ;
buf [ 1 ] = ' n ' ;
buf + = 2 ;
continue ;
}
buf + + ;
} while ( i ) ;
* buf = ' \n ' ;
return buf + 1 ;
}
/*
* 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 11:46:31 +04:00
static inline const char * get_task_state ( struct task_struct * tsk )
2005-04-17 02:20:36 +04:00
{
2007-12-06 19:03:36 +03:00
unsigned int state = ( tsk - > state & TASK_REPORT ) | tsk - > exit_state ;
2005-04-17 02:20:36 +04:00
const char * * p = & task_state_array [ 0 ] ;
while ( state ) {
p + + ;
state > > = 1 ;
}
return * p ;
}
2007-07-16 11:46:31 +04:00
static inline char * task_state ( struct task_struct * p , char * buffer )
2005-04-17 02:20:36 +04:00
{
struct group_info * group_info ;
int g ;
2005-09-10 00:04:10 +04:00
struct fdtable * fdt = NULL ;
2007-10-19 10:40:14 +04:00
struct pid_namespace * ns ;
pid_t ppid , tpid ;
2005-04-17 02:20:36 +04:00
2007-10-19 10:40:14 +04:00
ns = current - > nsproxy - > pid_ns ;
2006-10-02 13:18:54 +04:00
rcu_read_lock ( ) ;
2007-10-19 10:40:14 +04: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 23:52:04 +03:00
task_pid_nr_ns ( rcu_dereference ( p - > parent ) , ns ) : 0 ;
2005-04-17 02:20:36 +04:00
buffer + = sprintf ( buffer ,
" 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-19 10:40:14 +04:00
task_tgid_nr_ns ( p , ns ) ,
task_pid_nr_ns ( p , ns ) ,
ppid , tpid ,
2005-04-17 02:20:36 +04:00
p - > uid , p - > euid , p - > suid , p - > fsuid ,
p - > gid , p - > egid , p - > sgid , p - > fsgid ) ;
2006-10-02 13:18:54 +04:00
2005-04-17 02:20:36 +04:00
task_lock ( p ) ;
2005-09-10 00:04:10 +04:00
if ( p - > files )
fdt = files_fdtable ( p - > files ) ;
2005-04-17 02:20:36 +04:00
buffer + = sprintf ( buffer ,
" FDSize: \t %d \n "
" Groups: \t " ,
2005-09-10 00:04:10 +04:00
fdt ? fdt - > max_fds : 0 ) ;
2005-09-17 06:28:13 +04:00
rcu_read_unlock ( ) ;
2005-04-17 02:20:36 +04:00
group_info = p - > group_info ;
get_group_info ( group_info ) ;
task_unlock ( p ) ;
2007-07-16 11:46:31 +04:00
for ( g = 0 ; g < min ( group_info - > ngroups , NGROUPS_SMALL ) ; g + + )
buffer + = sprintf ( buffer , " %d " , GROUP_AT ( group_info , g ) ) ;
2005-04-17 02:20:36 +04:00
put_group_info ( group_info ) ;
buffer + = sprintf ( buffer , " \n " ) ;
return buffer ;
}
2007-07-16 11:46:31 +04:00
static char * render_sigset_t ( const char * header , sigset_t * set , char * buffer )
2005-04-17 02:20:36 +04:00
{
int i , len ;
len = strlen ( header ) ;
memcpy ( buffer , header , len ) ;
buffer + = len ;
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 ;
* buffer + + = ( x < 10 ? ' 0 ' : ' a ' - 10 ) + x ;
} while ( i > = 4 ) ;
* buffer + + = ' \n ' ;
* buffer = 0 ;
return buffer ;
}
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 ) ;
}
}
2007-07-16 11:46:31 +04:00
static inline char * task_sig ( struct task_struct * p , char * buffer )
2005-04-17 02:20:36 +04:00
{
2006-10-02 13:18:52 +04:00
unsigned long flags ;
2005-04-17 02:20:36 +04: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 13:18:52 +04:00
rcu_read_lock ( ) ;
if ( lock_task_sighand ( p , & flags ) ) {
2005-04-17 02:20:36 +04: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 13:18:52 +04:00
unlock_task_sighand ( p , & flags ) ;
2005-04-17 02:20:36 +04:00
}
2006-10-02 13:18:52 +04:00
rcu_read_unlock ( ) ;
2005-04-17 02:20:36 +04:00
buffer + = sprintf ( buffer , " Threads: \t %d \n " , num_threads ) ;
buffer + = sprintf ( buffer , " SigQ: \t %lu/%lu \n " , qsize , qlim ) ;
/* render them all */
buffer = render_sigset_t ( " SigPnd: \t " , & pending , buffer ) ;
buffer = render_sigset_t ( " ShdPnd: \t " , & shpending , buffer ) ;
buffer = render_sigset_t ( " SigBlk: \t " , & blocked , buffer ) ;
buffer = render_sigset_t ( " SigIgn: \t " , & ignored , buffer ) ;
buffer = render_sigset_t ( " SigCgt: \t " , & caught , buffer ) ;
return buffer ;
}
static inline char * task_cap ( struct task_struct * p , char * buffer )
{
return buffer + sprintf ( buffer , " CapInh: \t %016x \n "
" CapPrm: \t %016x \n "
" CapEff: \t %016x \n " ,
cap_t ( p - > cap_inheritable ) ,
cap_t ( p - > cap_permitted ) ,
cap_t ( p - > cap_effective ) ) ;
}
2007-07-16 10:40:48 +04:00
static inline char * task_context_switch_counts ( struct task_struct * p ,
char * buffer )
{
return buffer + sprintf ( buffer , " voluntary_ctxt_switches: \t %lu \n "
" nonvoluntary_ctxt_switches: \t %lu \n " ,
p - > nvcsw ,
p - > nivcsw ) ;
}
2007-07-16 11:46:31 +04:00
int proc_pid_status ( struct task_struct * task , char * buffer )
2005-04-17 02:20:36 +04:00
{
2007-07-16 11:46:31 +04:00
char * orig = buffer ;
2005-04-17 02:20:36 +04:00
struct mm_struct * mm = get_task_mm ( task ) ;
buffer = task_name ( task , buffer ) ;
buffer = task_state ( task , buffer ) ;
2007-07-16 11:46:31 +04:00
2005-04-17 02:20:36 +04:00
if ( mm ) {
buffer = task_mem ( mm , buffer ) ;
mmput ( mm ) ;
}
buffer = task_sig ( task , buffer ) ;
buffer = task_cap ( task , buffer ) ;
buffer = cpuset_task_status_allowed ( task , buffer ) ;
2006-01-06 11:19:28 +03:00
# if defined(CONFIG_S390)
2005-04-17 02:20:36 +04:00
buffer = task_show_regs ( task , buffer ) ;
# endif
2007-07-16 10:40:48 +04:00
buffer = task_context_switch_counts ( task , buffer ) ;
2005-04-17 02:20:36 +04:00
return buffer - orig ;
}
2007-08-23 17:18:02 +04: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 20:51:59 +04: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 23:18:11 +03:00
p - > prev_utime = max ( p - > prev_utime , clock_t_to_cputime ( utime ) ) ;
return p - > prev_utime ;
2007-07-09 20:51:59 +04:00
}
2007-08-23 17:18:02 +04:00
static cputime_t task_stime ( struct task_struct * p )
2007-07-09 20:51:59 +04:00
{
2007-07-16 11:46:30 +04:00
clock_t stime ;
2007-07-09 20:51:59 +04: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 17:18:02 +04:00
stime = nsec_to_clock_t ( p - > se . sum_exec_runtime ) -
cputime_to_clock_t ( task_utime ( p ) ) ;
2007-07-09 20:51:59 +04:00
2007-11-26 23:21:49 +03:00
if ( stime > = 0 )
p - > prev_stime = max ( p - > prev_stime , clock_t_to_cputime ( stime ) ) ;
2007-10-30 02:26:32 +03:00
return p - > prev_stime ;
2007-07-09 20:51:59 +04:00
}
2007-08-23 17:18:02 +04:00
# endif
2007-07-09 20:51:59 +04:00
2007-10-15 19:00:19 +04:00
static cputime_t task_gtime ( struct task_struct * p )
{
return p - > gtime ;
}
2007-07-16 11:46:31 +04:00
static int do_task_stat ( struct task_struct * task , char * buffer , int whole )
2005-04-17 02:20:36 +04:00
{
unsigned long vsize , eip , esp , wchan = ~ 0UL ;
long priority , nice ;
int tty_pgrp = - 1 , tty_nr = 0 ;
sigset_t sigign , sigcatch ;
char state ;
int res ;
2007-07-16 11:46:31 +04:00
pid_t ppid = 0 , pgid = - 1 , sid = - 1 ;
2005-04-17 02:20:36 +04: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 17:18:02 +04:00
cputime_t cutime , cstime , utime , stime ;
2007-10-15 19:00:19 +04:00
cputime_t cgtime , gtime ;
2005-04-17 02:20:36 +04:00
unsigned long rsslim = 0 ;
char tcomm [ sizeof ( task - > comm ) ] ;
2006-10-02 13:18:53 +04:00
unsigned long flags ;
2007-10-19 10:40:14 +04:00
struct pid_namespace * ns ;
ns = current - > nsproxy - > pid_ns ;
2005-04-17 02:20:36 +04: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 17:18:02 +04:00
cutime = cstime = utime = stime = cputime_zero ;
2007-10-15 19:00:19 +04:00
cgtime = gtime = cputime_zero ;
2006-09-29 13:00:41 +04:00
2006-10-02 13:18:53 +04:00
rcu_read_lock ( ) ;
if ( lock_task_sighand ( task , & flags ) ) {
struct signal_struct * sig = task - > signal ;
2006-12-08 13:36:07 +03:00
if ( sig - > tty ) {
2007-10-19 10:40:14 +04:00
tty_pgrp = pid_nr_ns ( sig - > tty - > pgrp , ns ) ;
2006-12-08 13:36:07 +03:00
tty_nr = new_encode_dev ( tty_devnum ( sig - > tty ) ) ;
2006-10-02 13:18:53 +04:00
}
num_threads = atomic_read ( & sig - > count ) ;
2005-04-17 02:20:36 +04:00
collect_sigign_sigcatch ( task , & sigign , & sigcatch ) ;
2006-10-02 13:18:53 +04:00
cmin_flt = sig - > cmin_flt ;
cmaj_flt = sig - > cmaj_flt ;
cutime = sig - > cutime ;
cstime = sig - > cstime ;
2007-10-15 19:00:19 +04:00
cgtime = sig - > cgtime ;
2006-10-02 13:18:53 +04:00
rsslim = sig - > rlim [ RLIMIT_RSS ] . rlim_cur ;
2005-04-17 02:20:36 +04:00
/* add up live thread stats at the group level */
if ( whole ) {
2006-10-02 13:18:53 +04:00
struct task_struct * t = task ;
2005-04-17 02:20:36 +04:00
do {
min_flt + = t - > min_flt ;
maj_flt + = t - > maj_flt ;
2007-08-23 17:18:02 +04:00
utime = cputime_add ( utime , task_utime ( t ) ) ;
stime = cputime_add ( stime , task_stime ( t ) ) ;
2007-10-15 19:00:19 +04:00
gtime = cputime_add ( gtime , task_gtime ( t ) ) ;
2005-04-17 02:20:36 +04:00
t = next_thread ( t ) ;
} while ( t ! = task ) ;
2006-10-02 13:18:53 +04:00
min_flt + = sig - > min_flt ;
maj_flt + = sig - > maj_flt ;
2007-08-23 17:18:02 +04:00
utime = cputime_add ( utime , sig - > utime ) ;
stime = cputime_add ( stime , sig - > stime ) ;
2007-10-19 22:52:40 +04:00
gtime = cputime_add ( gtime , sig - > gtime ) ;
2005-04-17 02:20:36 +04:00
}
2006-10-02 13:18:53 +04:00
2007-10-19 10:40:14 +04: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-19 10:40:14 +04:00
pgid = task_pgrp_nr_ns ( task , ns ) ;
2006-10-02 13:18:53 +04:00
unlock_task_sighand ( task , & flags ) ;
2005-04-17 02:20:36 +04:00
}
2006-10-02 13:18:53 +04:00
rcu_read_unlock ( ) ;
2005-04-17 02:20:36 +04:00
2007-07-16 11:46:31 +04:00
if ( ! whole | | num_threads < 2 )
2005-04-17 02:20:36 +04:00
wchan = get_wchan ( task ) ;
if ( ! whole ) {
min_flt = task - > min_flt ;
maj_flt = task - > maj_flt ;
2007-07-09 20:51:59 +04:00
utime = task_utime ( task ) ;
stime = task_stime ( task ) ;
2007-10-15 19:00:19 +04:00
gtime = task_gtime ( task ) ;
2005-04-17 02:20:36 +04: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-16 10:39:42 +04:00
start_time =
( unsigned long long ) task - > real_start_time . tv_sec * NSEC_PER_SEC
+ task - > real_start_time . tv_nsec ;
2005-04-17 02:20:36 +04:00
/* convert nsec -> ticks */
start_time = nsec_to_clock_t ( start_time ) ;
2007-07-16 11:46:31 +04:00
res = sprintf ( buffer , " %d (%s) %c %d %d %d %d %d %u %lu \
2006-03-26 13:38:10 +04:00
% lu % lu % lu % lu % lu % ld % ld % ld % ld % d 0 % llu % lu % ld % lu % lu % lu % lu % lu \
2007-10-15 19:00:19 +04:00
% lu % lu % lu % lu % lu % lu % lu % lu % d % d % u % u % llu % lu % ld \ n " ,
2007-10-19 10:40:14 +04:00
task_pid_nr_ns ( task , ns ) ,
2005-04-17 02:20:36 +04:00
tcomm ,
state ,
ppid ,
pgid ,
sid ,
tty_nr ,
tty_pgrp ,
task - > flags ,
min_flt ,
cmin_flt ,
maj_flt ,
cmaj_flt ,
2007-08-23 17:18:02 +04:00
cputime_to_clock_t ( utime ) ,
cputime_to_clock_t ( stime ) ,
2005-04-17 02:20:36 +04:00
cputime_to_clock_t ( cutime ) ,
cputime_to_clock_t ( cstime ) ,
priority ,
nice ,
num_threads ,
start_time ,
vsize ,
2005-10-30 04:16:05 +03:00
mm ? get_mm_rss ( mm ) : 0 ,
2007-07-16 11:46:31 +04:00
rsslim ,
2005-04-17 02:20:36 +04: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 11:24:43 +04:00
task - > policy ,
2007-10-15 19:00:19 +04:00
( unsigned long long ) delayacct_blkio_ticks ( task ) ,
cputime_to_clock_t ( gtime ) ,
cputime_to_clock_t ( cgtime ) ) ;
2007-07-16 11:46:31 +04:00
if ( mm )
2005-04-17 02:20:36 +04:00
mmput ( mm ) ;
return res ;
}
2007-07-16 11:46:31 +04:00
int proc_tid_stat ( struct task_struct * task , char * buffer )
2005-04-17 02:20:36 +04:00
{
return do_task_stat ( task , buffer , 0 ) ;
}
2007-07-16 11:46:31 +04:00
int proc_tgid_stat ( struct task_struct * task , char * buffer )
2005-04-17 02:20:36 +04:00
{
return do_task_stat ( task , buffer , 1 ) ;
}
int proc_pid_statm ( struct task_struct * task , char * buffer )
{
int size = 0 , resident = 0 , shared = 0 , text = 0 , lib = 0 , data = 0 ;
struct mm_struct * mm = get_task_mm ( task ) ;
2007-07-16 11:46:31 +04:00
2005-04-17 02:20:36 +04:00
if ( mm ) {
size = task_statm ( mm , & shared , & text , & data , & resident ) ;
mmput ( mm ) ;
}
2007-07-16 11:46:31 +04:00
return sprintf ( buffer , " %d %d %d %d %d %d %d \n " ,
2005-04-17 02:20:36 +04:00
size , resident , shared , text , lib , data , 0 ) ;
}