/**linux/fs/proc/array.c**Copyright(C)1992byLinusTorvalds*basedonideasbyDarrenSenn**Fixes:*Michael.K.Johnson:stat,statmextensions.*<johnsonm@stolaf.ed
u>**PaulineMiddelink:Madecmdline,envlineonlybreakat'\0's,to*makesureSETPROCTITLEworks.Alsoremoved*bad'!'whichforcedaddressrecalculationfor*EVERYcharac
teronthecurrentpage.*<middelin@polyware.iaf.nl>**DannyterHaar:addedcpuinfo*<dth@cistron.nl>**AlessandroRubini:profileextension.*<rubini@ipvvis.unipv.i
t>**JeffTranter:addedBogoMipsfieldtocpuinfo*<JeffTranter@Mitel.COM>**BrunoHaible:remove4Klimitforthemapsfile*<haible@ma2s2.mathematik.uni-karlsruhe.de
>**YvesArrouye:removeremovaloftrailingspacesingetarray.*<Yves.Arrouye@marin.fdn.fr>**JeromeForissier:addedper-CPUtimeinformationto/proc/stat*and/proc/
<pid>/cpuextension*<forissier@isia.cma.fr>*-Incorporationandnon-SMPsafeoperation*offorissierpatchin2.1.78by*HansMarcus<crowbar@concepts.nl>**aeb@cwi.n
l:/proc/partitions***AlanCox:securityfixes.*<Alan.Cox@linux.org>**GerhardWichert:addedBIGMEMsupport*SiemensAG<Gerhard.Wichert@pdb.siemens.de>*/#includ
e<linux/types.h>#include<linux/errno.h>#include<linux/sched.h>#include<linux/kernel.h>#include<linux/kernelstat.h>#include<linux/tty.h>#include<linux/
user.h>#include<linux/a.out.h>#include<linux/string.h>#include<linux/mman.h>#include<linux/procfs.h>#include<linux/ioport.h>#include<linux/config.h>#i
nclude<linux/mm.h>#include<linux/pagemap.h>#include<linux/swap.h>#include<linux/slab.h>#include<linux/smp.h>#include<linux/signal.h>#include<asm/uacce
ss.h>#include<asm/pgtable.h>#include<asm/io.h>#defineLOADINT(x)((x)>>FSHIFT)#defineLOADFRAC(x)LOADINT(((x)&(FIXED1-1))*100)#ifdefCONFIGDEBUGMALLOCintg
etmalloc(char*buffer);#endifstaticintopenkcore(structinode*inode,structfile*filp){returncapable(CAPSYSRAWIO)?0:-EPERM;}staticssizetreadcore(structfile
*file,char*buf,sizetcount,lofft*ppos){unsignedlongp=*ppos,memsize;ssizetread;ssizetcount1;char*pnt;structuserdump;#ifdefined(i386)||defined(mc68000)#d
efineFIRSTMAPPEDPAGESIZE/*wedon'thavepage0mappedonx86..*/#else#defineFIRSTMAPPED0#endifmemset(&dump,0,sizeof(structuser));dump.magic=CMAGIC;dump.udsiz
e=maxmapnr;#ifdefined(i386)dump.startcode=PAGEOFFSET;#endif#ifdefalphadump.startdata=PAGEOFFSET;#endifmemsize=(maxmapnr+1)<<PAGESHIFT;if(p>=memsize)re
turn0;if(count>memsize-p)count=memsize-p;read=0;if(p<sizeof(structuser)&&count>0){count1=count;if(p+count1>sizeof(structuser))count1=sizeof(structuser
)-p;pnt=(char*)&dump+p;copytouser(buf,(void*)pnt,count1);buf+=count1;p+=count1;count-=count1;read+=count1;}if(count>0&&p<PAGESIZE+FIRSTMAPPED){count1=
PAGESIZE+FIRSTMAPPED-p;if(count1>count)count1=count;clearuser(buf,count1);buf+=count1;p+=count1;count-=count1;read+=count1;}if(count>0){copytouser(buf
,(void*)(PAGEOFFSET+p-PAGESIZE),count);read+=count;}*ppos+=read;returnread;}staticstructfileoperationsprockcoreoperations={NULL,/*lseek*/readcore,NULL
,/*write*/NULL,/*readdir*/NULL,/*poll*/NULL,/*ioctl*/NULL,/*mmap*/openkcore};structinodeoperationsprockcoreinodeoperations={&prockcoreoperations,};/**
Thisfunctionaccessesprofilinginformation.Thereturneddatais*binary:thesamplingstepandtheactualcontentsoftheprofile*buffer.Useoftheprogramreadprofileisr
ecommendedinorderto*getmeaningfulinfooutofthesedata.*/staticssizetreadprofile(structfile*file,char*buf,sizetcount,lofft*ppos){unsignedlongp=*ppos;ssiz
etread;char*pnt;unsignedintsamplestep=1<<profshift;if(p>=(proflen+1)*sizeof(unsignedint))return0;if(count>(proflen+1)*sizeof(unsignedint)-p)count=(pro
flen+1)*sizeof(unsignedint)-p;read=0;while(p<sizeof(unsignedint)&&count>0){putuser(*((char*)(&samplestep)+p),buf);buf++;p++;count--;read++;}pnt=(char*
)profbuffer+p-sizeof(unsignedint);copytouser(buf,(void*)pnt,count);read+=count;*ppos+=read;returnread;}/**Writingto/proc/profileresetsthecounters**Wri
tinga'profilingmultiplier'valueintoitalsore-setstheprofiling*interruptfrequency,onarchitecturesthatsupportthis.*/staticssizetwriteprofile(structfile*f
ile,constchar*buf,sizetcount,lofft*ppos){#ifdefSMPexternintsetupprofilingtimer(unsignedintmultiplier);if(count==sizeof(int)){unsignedintmultiplier;if(
copyfromuser(&multiplier,buf,sizeof(int)))return-EFAULT;if(setupprofilingtimer(multiplier))return-EINVAL;}#endifmemset(profbuffer,0,proflen*sizeof(*pr
ofbuffer));returncount;}staticstructfileoperationsprocprofileoperations={NULL,/*lseek*/readprofile,writeprofile,};structinodeoperationsprocprofileinod
eoperations={&procprofileoperations,};staticintgetloadavg(char*buffer){inta,b,c;a=avenrun[0]+(FIXED1/200);b=avenrun[1]+(FIXED1/200);c=avenrun[2]+(FIXE
D1/200);returnsprintf(buffer,"%d.%02d%d.%02d%d.%02d%d/%d%d\n",LOADINT(a),LOADFRAC(a),LOADINT(b),LOADFRAC(b),LOADINT(c),LOADFRAC(c),nrrunning,nrtasks,l
astpid);}staticintgetkstat(char*buffer){inti,len;unsignedsum=0;externunsignedlongtotalforks;unsignedlongticks;ticks=jiffies*smpnumcpus;#ifndefCONFIGAR
CHS390for(i=0;i<NRIRQS;i++)sum+=kstatirqs(i);#endif#ifdefSMPlen=sprintf(buffer,"cpu%u%u%u%lu\n",kstat.cpuuser,kstat.cpunice,kstat.cpusystem,jiffies*sm
pnumcpus-(kstat.cpuuser+kstat.cpunice+kstat.cpusystem));for(i=0;i<smpnumcpus;i++)len+=sprintf(buffer+len,"cpu%d%u%u%u%lu\n",i,kstat.percpuuser[cpulogi
calmap(i)],kstat.percpunice[cpulogicalmap(i)],kstat.percpusystem[cpulogicalmap(i)],jiffies-(kstat.percpuuser[cpulogicalmap(i)]\+kstat.percpunice[cpulo
gicalmap(i)]\+kstat.percpusystem[cpulogicalmap(i)]));len+=sprintf(buffer+len,"disk%u%u%u%u\n""diskrio%u%u%u%u\n""diskwio%u%u%u%u\n""diskrblk%u%u%u%u\n
""diskwblk%u%u%u%u\n""page%u%u\n"#ifdefCONFIGARCHS390"swap%u%u\n""intr10",#else"swap%u%u\n""intr%u",#endif#elselen=sprintf(buffer,"cpu%u%u%u%lu\n""dis
k%u%u%u%u\n""diskrio%u%u%u%u\n""diskwio%u%u%u%u\n""diskrblk%u%u%u%u\n""diskwblk%u%u%u%u\n""page%u%u\n"#ifdefCONFIGARCHS390"swap%u%u\n""intr10",#else"s
wap%u%u\n""intr%u",#endifkstat.cpuuser,kstat.cpunice,kstat.cpusystem,ticks-(kstat.cpuuser+kstat.cpunice+kstat.cpusystem),#endifkstat.dkdrive[0],kstat.
dkdrive[1],kstat.dkdrive[2],kstat.dkdrive[3],kstat.dkdriverio[0],kstat.dkdriverio[1],kstat.dkdriverio[2],kstat.dkdriverio[3],kstat.dkdrivewio[0],kstat
.dkdrivewio[1],kstat.dkdrivewio[2],kstat.dkdrivewio[3],kstat.dkdriverblk[0],kstat.dkdriverblk[1],kstat.dkdriverblk[2],kstat.dkdriverblk[3],kstat.dkdri
vewblk[0],kstat.dkdrivewblk[1],kstat.dkdrivewblk[2],kstat.dkdrivewblk[3],kstat.pgpgin,kstat.pgpgout,kstat.pswpin,#ifdefCONFIGARCHS390kstat.pswpout);#e
lsekstat.pswpout,sum);for(i=0;i<NRIRQS;i++)len+=sprintf(buffer+len,"%u",kstatirqs(i));#endiflen+=sprintf(buffer+len,"\nctxt%u\n""btime%lu\n""processes
%lu\n",kstat.contextswtch,xtime.tvsec-jiffies/HZ,totalforks);returnlen;}staticintgetuptime(char*buffer){unsignedlonguptime;unsignedlongidle;uptime=jif
fies;idle=task[0]->times.tmsutime+task[0]->times.tmsstime;/*Theformulaforthefractionpartsreallyis((t*100)/HZ)%100,butthatwouldoverflowabouteveryfiveda
ysatHZ==100.Thereforetheidentitya=(a/b)*b+a%bisusedsothatitiscalculatedas(((t/HZ)*100)+((t%HZ)*100)/HZ)%100.Thepartinfrontofthe'+'alwaysevaluatesas0(m
od100).Alldivisionsintheaboveformulasaretruncating.ForHZbeingapowerof10,thecalculationssimplifytotheversioninthe#elsepart(iftheprintfformatisadaptedto
thesamenumberofdigitsaszeroesinHZ.*/#ifHZ!=100returnsprintf(buffer,"%lu.%02lu%lu.%02lu\n",uptime/HZ,(((uptime%HZ)*100)/HZ)%100,idle/HZ,(((idle%HZ)*100
)/HZ)%100);#elsereturnsprintf(buffer,"%lu.%02lu%lu.%02lu\n",uptime/HZ,uptime%HZ,idle/HZ,idle%HZ);#endif}staticintgetmeminfo(char*buffer){structsysinfo
i;intlen;simeminfo(&i);siswapinfo(&i);len=sprintf(buffer,"total:used:free:shared:buffers:cached:\n""Mem:%8lu%8lu%8lu%8lu%8lu%8lu\n""Swap:%8lu%8lu%8lu\
n",i.totalram,i.totalram-i.freeram,i.freeram,i.sharedram,i.bufferram,pagecachesize*PAGESIZE,i.totalswap,i.totalswap-i.freeswap,i.freeswap);/**Taggedfo
rmat,foreasygreppingandexpansion.Theabovewillgoaway*eventually,oncethetoolshavebeenupdated.*/returnlen+sprintf(buffer+len,"MemTotal:%8lukB\n""MemFree:
%8lukB\n""MemShared:%8lukB\n""Buffers:%8lukB\n""Cached:%8lukB\n""BigTotal:%8lukB\n""BigFree:%8lukB\n""SwapTotal:%8lukB\n""SwapFree:%8lukB\n",i.totalra
m>>10,i.freeram>>10,i.sharedram>>10,i.bufferram>>10,pagecachesize<<(PAGESHIFT-10),i.totalbig>>10,i.freebig>>10,i.totalswap>>10,i.freeswap>>10);}static
intgetversion(char*buffer){externchar*linuxbanner;strcpy(buffer,linuxbanner);returnstrlen(buffer);}staticintgetcmdline(char*buffer){externcharsavedcom
mandline[];returnsprintf(buffer,"%s\n",savedcommandline);}staticunsignedlonggetphysaddr(structtaskstruct*p,unsignedlongptr){pgdt*pagedir;pmdt*pagemidd
le;ptetpte;if(!p||!p->mm||ptr>=TASKSIZE)return0;/*CheckforNULLpgd..shouldn'thappen!*/if(!p->mm->pgd){printk("getphysaddr:pid%dhasNULLpgd!\n",p->pid);r
eturn0;}pagedir=pgdoffset(p->mm,ptr);if(pgdnone(*pagedir))return0;if(pgdbad(*pagedir)){printk("badpagedirectoryentry%08lx\n",pgdval(*pagedir));pgdclea
r(pagedir);return0;}pagemiddle=pmdoffset(pagedir,ptr);if(pmdnone(*pagemiddle))return0;if(pmdbad(*pagemiddle)){printk("badpagemiddleentry%08lx\n",pmdva
l(*pagemiddle));pmdclear(pagemiddle);return0;}pte=*pteoffset(pagemiddle,ptr);if(!ptepresent(pte))return0;returnptepage(pte)+(ptr&~PAGEMASK);}#include<
linux/bigmem.h>staticintgetarray(structtaskstruct*p,unsignedlongstart,unsignedlongend,char*buffer){unsignedlongaddr;intsize=0,result=0;charc;if(start>
=end)returnresult;for(;;){addr=getphysaddr(p,start);if(!addr)returnresult;addr=kmap(addr,KMREAD);do{c=*(char*)addr;if(!c)result=size;if(size<PAGESIZE)
buffer[size++]=c;else{kunmap(addr,KMREAD);returnresult;}addr++;start++;if(!c&&start>=end){kunmap(addr,KMREAD);returnresult;}}while(addr&~PAGEMASK);kun
map(addr-1,KMREAD);}returnresult;}staticintgetenv(intpid,char*buffer){structtaskstruct*p;readlock(&tasklistlock);p=findtaskbypid(pid);readunlock(&task
listlock);/*FIXME!!Thisshouldbedoneafterthelastuse*/if(!p||!p->mm)return0;returngetarray(p,p->mm->envstart,p->mm->envend,buffer);}staticintgetarg(intp
id,char*buffer){structtaskstruct*p;readlock(&tasklistlock);p=findtaskbypid(pid);readunlock(&tasklistlock);/*FIXME!!Thisshouldbedoneafterthelastuse*/if
(!p||!p->mm)return0;returngetarray(p,p->mm->argstart,p->mm->argend,buffer);}/**Thesebracketthesleepingfunctions..*/externvoidschedulingfunctionsstarth
ere(void);externvoidschedulingfunctionsendhere(void);#definefirstsched((unsignedlong)schedulingfunctionsstarthere)#definelastsched((unsignedlong)sched
ulingfunctionsendhere)staticunsignedlonggetwchan(structtaskstruct*p){if(!p||p==current||p->state==TASKRUNNING)return0;#ifdefined(i386){unsignedlongebp
,esp,eip;unsignedlongstackpage;intcount=0;stackpage=(unsignedlong)p;esp=p->tss.esp;if(!stackpage||esp<stackpage||esp>=8188+stackpage)return0;/*include
/asm-i386/system.h:switchto()pushesebplast.*/ebp=*(unsignedlong*)esp;do{if(ebp<stackpage||ebp>=8188+stackpage)return0;eip=*(unsignedlong*)(ebp+4);if(e
ip<firstsched||eip>=lastsched)returneip;ebp=*(unsignedlong*)ebp;}while(count++<16);}#elifdefined(alpha)/**Thisonedependsontheframesizeofschedule().Doa
*"disassschedule"ingdbtofindtheframesize.Also,the*codeassumesthatsleepon()followsimmediatelyafter*interruptiblesleepon()andthataddtimer()follows*immed
iatelyafterinterruptiblesleep().Ugly,isn'tit?*Maybeaddingawchanfieldtotaskstructwouldbebetter,*afterall...*/{unsignedlongscheduleframe;unsignedlongpc;
pc=threadsavedpc(&p->tss);if(pc>=firstsched&&pc<lastsched){scheduleframe=((unsignedlong*)p->tss.ksp)[6];return((unsignedlong*)scheduleframe)[12];}retu
rnpc;}#elifdefined(mips)/**ThesamecommentasontheAlphaapplieshere,too...*/{unsignedlongscheduleframe;unsignedlongpc;pc=threadsavedpc(&p->tss);if(pc>=(u
nsignedlong)interruptiblesleepon&&pc<(unsignedlong)addtimer){scheduleframe=((unsignedlong*)(long)p->tss.reg30)[16];return(unsignedlong)((unsignedlong*
)scheduleframe)[11];}returnpc;}#elifdefined(mc68000){unsignedlongfp,pc;unsignedlongstackpage;intcount=0;stackpage=(unsignedlong)p;fp=((structswitchsta
ck*)p->tss.ksp)->a6;do{if(fp<stackpage+sizeof(structtaskstruct)||fp>=8184+stackpage)return0;pc=((unsignedlong*)fp)[1];/*FIXME:Thisdependsontheorderoft
hesefunctions.*/if(pc<firstsched||pc>=lastsched)returnpc;fp=*(unsignedlong*)fp;}while(count++<16);}#elifdefined(powerpc){unsignedlongip,sp;unsignedlon
gstackpage=(unsignedlong)p;intcount=0;sp=p->tss.ksp;do{sp=*(unsignedlong*)sp;if(sp<stackpage||sp>=stackpage+8188)return0;if(count>0){ip=*(unsignedlong
*)(sp+4);if(ip<firstsched||ip>=lastsched)returnip;}}while(count++<16);}#elifdefined(arm){unsignedlongfp,lr;unsignedlongstackpage;intcount=0;stackpage=
4096+(unsignedlong)p;fp=getcssfp(&p->tss);do{if(fp<stackpage||fp>4092+stackpage)return0;lr=pcpointer(((unsignedlong*)fp)[-1]);if(lr<firstsched||lr>las
tsched)returnlr;fp=*(unsignedlong*)(fp-12);}while(count++<16);}#elifdefined(sparc){unsignedlongpc,fp,bias=0;unsignedlongtaskbase=(unsignedlong)p;struc
tregwindow*rw;intcount=0;#ifdefsparcv9bias=STACKBIAS;#endiffp=p->tss.ksp+bias;do{/*Bogusframepointer?*/if(fp<(taskbase+sizeof(structtaskstruct))||fp>=
(taskbase+(2*PAGESIZE)))break;rw=(structregwindow*)fp;pc=rw->ins[7];if(pc<firstsched||pc>=lastsched)returnpc;fp=rw->ins[6]+bias;}while(++count<16);}#e
lifdefined(s390){unsignedlongksp,backchain,ip;unsignedlongstackpage;intcount=0;stackpage=(unsignedlong)p;ksp=p->tss.ksp;if(!stackpage||ksp<stackpage||
ksp>=8188+stackpage)return0;backchain=(*(unsignedlong*)ksp)&0x7fffffff;do{if(backchain<stackpage||backchain>=8188+stackpage)return0;ip=(*(unsignedlong
*)(backchain+56))&0x7fffffff;if(ip<firstsched||ip>=lastsched)returnip;backchain=(*(unsignedlong*)backchain)&0x7fffffff;}while(count++<16);}#endifretur
n0;}#ifdefined(i386)#defineKSTKEIP(tsk)(((unsignedlong*)(4096+(unsignedlong)(tsk)))[1019])#defineKSTKESP(tsk)(((unsignedlong*)(4096+(unsignedlong)(tsk
)))[1022])#elifdefined(alpha)/**Seearch/alpha/kernel/ptrace.cfordetails.*/#definePTREG(reg)(PAGESIZE-sizeof(structptregs)\+(long)&((structptregs*)0)->
reg)#defineKSTKEIP(tsk)\(*(unsignedlong*)(PTREG(pc)+PAGESIZE+(unsignedlong)(tsk)))#defineKSTKESP(tsk)((tsk)==current?rdusp():(tsk)->tss.usp)#elifdefin
ed(arm)#defineKSTKEIP(tsk)(((unsignedlong*)(4096+(unsignedlong)(tsk)))[1022])#defineKSTKESP(tsk)(((unsignedlong*)(4096+(unsignedlong)(tsk)))[1020])#el
ifdefined(mc68000)#defineKSTKEIP(tsk)\({\unsignedlongeip=0;\if((tsk)->tss.esp0>PAGESIZE&&\MAPNR((tsk)->tss.esp0)<maxmapnr)\eip=((structptregs*)(tsk)->
tss.esp0)->pc;\eip;})#defineKSTKESP(tsk)((tsk)==current?rdusp():(tsk)->tss.usp)#elifdefined(powerpc)#defineKSTKEIP(tsk)((tsk)->tss.regs->nip)#defineKS
TKESP(tsk)((tsk)->tss.regs->gpr[1])#elifdefined(sparcv9)#defineKSTKEIP(tsk)((tsk)->tss.kregs->tpc)#defineKSTKESP(tsk)((tsk)->tss.kregs->uregs[UREGFP])
#elifdefined(sparc)#defineKSTKEIP(tsk)((tsk)->tss.kregs->pc)#defineKSTKESP(tsk)((tsk)->tss.kregs->uregs[UREGFP])#elifdefined(mips)#definePTREG(reg)((l
ong)&((structptregs*)0)->reg\-sizeof(structptregs))#defineKSTKTOS(tsk)((unsignedlong)(tsk)+KERNELSTACKSIZE-32)#defineKSTKEIP(tsk)(*(unsignedlong*)(KST
KTOS(tsk)+PTREG(cp0epc)))#defineKSTKESP(tsk)(*(unsignedlong*)(KSTKTOS(tsk)+PTREG(regs[29])))#elifdefined(s390)#defineKSTKEIP(tsk)((tsk)->tss.regs->psw
.addr)#defineKSTKESP(tsk)((tsk)->tss.ksp)#endif/*Gccoptimizesaway"strlen(x)"forconstantx*/#defineADDBUF(buffer,string)\do{memcpy(buffer,string,strlen(
string));\buffer+=strlen(string);}while(0)staticinlinechar*taskname(structtaskstruct*p,char*buf){inti;char*name;ADDBUF(buf,"Name:\t");name=p->comm;i=s
izeof(p->comm);do{unsignedcharc=*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;co
ntinue;}buf++;}while(i);*buf='\n';returnbuf+1;}/**Thetaskstatearrayisastrange"bitmap"of*reasonstosleep.Thus"running"iszero,and*youcantestforcombinatio
nsofotherswith*simplebittests.*/staticconstchar*taskstatearray[]={"R(running)",/*0*/"S(sleeping)",/*1*/"D(disksleep)",/*2*/"Z(zombie)",/*4*/"T(stopped
)",/*8*/"W(paging)"/*16*/};staticinlineconstchar*gettaskstate(structtaskstruct*tsk){unsignedintstate=tsk->state&(TASKRUNNING|TASKINTERRUPTIBLE|TASKUNI
NTERRUPTIBLE|TASKZOMBIE|TASKSTOPPED|TASKSWAPPING);constchar**p=&taskstatearray[0];while(state){p++;state>>=1;}return*p;}staticinlinechar*taskstate(str
ucttaskstruct*p,char*buffer){intg;buffer+=sprintf(buffer,"State:\t%s\n""Pid:\t%d\n""PPid:\t%d\n""Uid:\t%d\t%d\t%d\t%d\n""Gid:\t%d\t%d\t%d\t%d\n""Group
s:\t",gettaskstate(p),p->pid,p->ppptr->pid,p->uid,p->euid,p->suid,p->fsuid,p->gid,p->egid,p->sgid,p->fsgid);for(g=0;g<p->ngroups;g++)buffer+=sprintf(b
uffer,"%d",p->groups[g]);buffer+=sprintf(buffer,"\n");returnbuffer;}staticinlinechar*taskmem(structtaskstruct*p,char*buffer){structmmstruct*mm=p->mm;i
f(mm&&mm!=&initmm){structvmareastruct*vma=mm->mmap;unsignedlongdata=0,stack=0;unsignedlongexec=0,lib=0;for(vma=mm->mmap;vma;vma=vma->vmnext){unsignedl
onglen=(vma->vmend-vma->vmstart)>>10;if(!vma->vmfile){data+=len;if(vma->vmflags&VMGROWSDOWN)stack+=len;continue;}if(vma->vmflags&VMWRITE)continue;if(v
ma->vmflags&VMEXEC){exec+=len;if(vma->vmflags&VMEXECUTABLE)continue;lib+=len;}}buffer+=sprintf(buffer,"VmSize:\t%8lukB\n""VmLck:\t%8lukB\n""VmRSS:\t%8
lukB\n""VmData:\t%8lukB\n""VmStk:\t%8lukB\n""VmExe:\t%8lukB\n""VmLib:\t%8lukB\n",mm->totalvm<<(PAGESHIFT-10),mm->lockedvm<<(PAGESHIFT-10),mm->rss<<(PA
GESHIFT-10),data-stack,stack,exec-lib,lib);}returnbuffer;}staticvoidcollectsigignsigcatch(structtaskstruct*p,sigsett*ign,sigsett*catch){structksigacti
on*k;inti;sigemptyset(ign);sigemptyset(catch);if(p->sig){k=p->sig->action;for(i=1;i<=NSIG;++i,++k){if(k->sa.sahandler==SIGIGN)sigaddset(ign,i);elseif(
k->sa.sahandler!=SIGDFL)sigaddset(catch,i);}}}staticinlinechar*tasksig(structtaskstruct*p,char*buffer){sigsettign,catch;buffer+=sprintf(buffer,"SigPnd
:\t");buffer=rendersigsett(&p->signal,buffer);*buffer++='\n';buffer+=sprintf(buffer,"SigBlk:\t");buffer=rendersigsett(&p->blocked,buffer);*buffer++='\
n';collectsigignsigcatch(p,&ign,&catch);buffer+=sprintf(buffer,"SigIgn:\t");buffer=rendersigsett(&ign,buffer);*buffer++='\n';buffer+=sprintf(buffer,"S
igCgt:\t");/*Linux2.0uses"SigCgt"*/buffer=rendersigsett(&catch,buffer);*buffer++='\n';returnbuffer;}externinlinechar*taskcap(structtaskstruct*p,char*b
uffer){returnbuffer+sprintf(buffer,"CapInh:\t%016x\n""CapPrm:\t%016x\n""CapEff:\t%016x\n",capt(p->capinheritable),capt(p->cappermitted),capt(p->capeff
ective));}staticintgetstatus(intpid,char*buffer){char*orig=buffer;structtaskstruct*tsk;readlock(&tasklistlock);tsk=findtaskbypid(pid);readunlock(&task
listlock);/*FIXME!!Thisshouldbedoneafterthelastuse*/if(!tsk)return0;buffer=taskname(tsk,buffer);buffer=taskstate(tsk,buffer);buffer=taskmem(tsk,buffer
);buffer=tasksig(tsk,buffer);buffer=taskcap(tsk,buffer);#ifs390buffer=taskshowregs(tsk,buffer);#endifreturnbuffer-orig;}staticintgetstat(intpid,char*b
uffer){structtaskstruct*tsk;unsignedlongvsize,eip,esp,wchan;longpriority,nice;intttypgrp;sigsettsigign,sigcatch;charstate;readlock(&tasklistlock);tsk=
findtaskbypid(pid);if(!tsk){readunlock(&tasklistlock);return0;}state=*gettaskstate(tsk);vsize=eip=esp=0;if(tsk->mm&&tsk->mm!=&initmm){structvmareastru
ct*vma=tsk->mm->mmap;while(vma){vsize+=vma->vmend-vma->vmstart;vma=vma->vmnext;}if((current->fsuid==tsk->euid&&tsk->dumpable&&capissubset(tsk->capperm
itted,current->cappermitted))||capable(CAPDACOVERRIDE)){eip=KSTKEIP(tsk);esp=KSTKESP(tsk);}}readunlock(&tasklistlock);/*FIXME!!Thisshouldbedoneafterth
elastuse*/wchan=getwchan(tsk);collectsigignsigcatch(tsk,&sigign,&sigcatch);if(tsk->tty)ttypgrp=tsk->tty->pgrp;elsettypgrp=-1;/*scalepriorityandniceval
uesfromtimeslicesto-20..20*//*tomakeitlooklikea"normal"Unixpriority/nicevalue*/priority=tsk->counter;priority=20-(priority*10+DEFPRIORITY/2)/DEFPRIORI
TY;nice=tsk->priority;nice=20-(nice*20+DEFPRIORITY/2)/DEFPRIORITY;returnsprintf(buffer,"%d(%s)%c%d%d%d%d%d%lu%lu\%lu%lu%lu%lu%lu%ld%ld%ld%ld%ld%ld%lu%
lu%ld%lu%lu%lu%lu%lu\%lu%lu%lu%lu%lu%lu%lu%lu%d%d\n",pid,tsk->comm,state,tsk->ppptr->pid,tsk->pgrp,tsk->session,tsk->tty?kdevttonr(tsk->tty->device):0
,ttypgrp,tsk->flags,tsk->minflt,tsk->cminflt,tsk->majflt,tsk->cmajflt,tsk->times.tmsutime,tsk->times.tmsstime,tsk->times.tmscutime,tsk->times.tmscstim
e,priority,nice,0UL/*removed*/,tsk->itrealvalue,tsk->starttime,vsize,tsk->mm?tsk->mm->rss:0,/*youmightwanttoshiftthisleft3*/tsk->rlim?tsk->rlim[RLIMIT
RSS].rlimcur:0,tsk->mm?tsk->mm->startcode:0,tsk->mm?tsk->mm->endcode:0,tsk->mm?tsk->mm->startstack:0,esp,eip,/*Thesignalinformationhereisobsolete.*Itm
ustbedecimalforLinux2.0compatibility.*Use/proc/#/statusforreal-timesignals.*/tsk->signal.sig[0]&0x7fffffffUL,tsk->blocked.sig[0]&0x7fffffffUL,sigign.s
ig[0]&0x7fffffffUL,sigcatch.sig[0]&0x7fffffffUL,wchan,tsk->nswap,tsk->cnswap,tsk->exitsignal,tsk->processor);}staticinlinevoidstatmpterange(pmdt*pmd,u
nsignedlongaddress,unsignedlongsize,int*pages,int*shared,int*dirty,int*total){ptet*pte;unsignedlongend;if(pmdnone(*pmd))return;if(pmdbad(*pmd)){printk
("statmpterange:badpmd(%08lx)\n",pmdval(*pmd));pmdclear(pmd);return;}pte=pteoffset(pmd,address);address&=~PMDMASK;end=address+size;if(end>PMDSIZE)end=
PMDSIZE;do{ptetpage=*pte;address+=PAGESIZE;pte++;if(ptenone(page))continue;++*total;if(!ptepresent(page))continue;++*pages;if(ptedirty(page))++*dirty;
if(MAPNR(ptepage(page))>=maxmapnr)continue;if(atomicread(&memmap[MAPNR(ptepage(page))].count)>1)++*shared;}while(address<end);}staticinlinevoidstatmpm
drange(pgdt*pgd,unsignedlongaddress,unsignedlongsize,int*pages,int*shared,int*dirty,int*total){pmdt*pmd;unsignedlongend;if(pgdnone(*pgd))return;if(pgd
bad(*pgd)){printk("statmpmdrange:badpgd(%08lx)\n",pgdval(*pgd));pgdclear(pgd);return;}pmd=pmdoffset(pgd,address);address&=~PGDIRMASK;end=address+size;
if(end>PGDIRSIZE)end=PGDIRSIZE;do{statmpterange(pmd,address,end-address,pages,shared,dirty,total);address=(address+PMDSIZE)&PMDMASK;pmd++;}while(addre
ss<end);}staticvoidstatmpgdrange(pgdt*pgd,unsignedlongaddress,unsignedlongend,int*pages,int*shared,int*dirty,int*total){while(address<end){statmpmdran
ge(pgd,address,end-address,pages,shared,dirty,total);address=(address+PGDIRSIZE)&PGDIRMASK;pgd++;}}staticintgetstatm(intpid,char*buffer){structtaskstr
uct*tsk;intsize=0,resident=0,share=0,trs=0,lrs=0,drs=0,dt=0;readlock(&tasklistlock);tsk=findtaskbypid(pid);readunlock(&tasklistlock);/*FIXME!!Thisshou
ldbedoneafterthelastuse*/if(!tsk)return0;if(tsk->mm&&tsk->mm!=&initmm){structvmareastruct*vma=tsk->mm->mmap;while(vma){pgdt*pgd=pgdoffset(tsk->mm,vma-
>vmstart);intpages=0,shared=0,dirty=0,total=0;statmpgdrange(pgd,vma->vmstart,vma->vmend,&pages,&shared,&dirty,&total);resident+=pages;share+=shared;dt
+=dirty;size+=total;if(vma->vmflags&VMEXECUTABLE)trs+=pages;/*text*/elseif(vma->vmflags&VMGROWSDOWN)drs+=pages;/*stack*/elseif(vma->vmend>0x60000000)l
rs+=pages;/*library*/elsedrs+=pages;vma=vma->vmnext;}}returnsprintf(buffer,"%d%d%d%d%d%d%d\n",size,resident,share,trs,lrs,drs,dt);}/**Thewaywesupports
yntheticfiles>4K*-withoutstoringtheircontentsinsomebufferand*-withoutwalkingthroughtheentiresyntheticfileuntilwereachthe*positionoftherequesteddata*is
tocleverlyencodethecurrentpositioninthefile'sfposfield.*Thereisnorequirementthataread()callwhichreturns`count'bytes*ofdataincreasesfposbyexactly`count
'.**ThisideaisLinus'one.Brunoimplementedit.*//**Forthe/proc/<pid>/mapsfile,weusefixedlengthrecords,eachcontaining*asingleline.*/#defineMAPSLINELENGTH4
096#defineMAPSLINESHIFT12/**fpos=(numberofthevmainthetask->mm->mmaplist)*MAPSLINELENGTH*+(indexintotheline)*//*forsystemswithsizeof(void*)==4:*/#defin
eMAPSLINEFORMAT4"%08lx-%08lx%s%08lx%s%lu"#defineMAPSLINEMAX449/*sumof8181418151101*//*forsystemswithsizeof(void*)==8:*/#defineMAPSLINEFORMAT8"%016lx-%
016lx%s%016lx%s%lu"#defineMAPSLINEMAX873/*sumof1611614116151101*/#defineMAPSLINEMAXMAPSLINEMAX8staticssizetreadmaps(intpid,structfile*file,char*buf,si
zetcount,lofft*ppos){structtaskstruct*p;structvmareastruct*map,*next;char*destptr=buf,*buffer;lofftlineno;ssizetcolumn,i;intvolatiletask;longretval;/*
*Wemightsleepgettingthepage,sogetitfirst.*/retval=-ENOMEM;buffer=(char*)getfreepage(GFPKERNEL);if(!buffer)gotoout;retval=-EINVAL;readlock(&tasklistloc
k);p=findtaskbypid(pid);readunlock(&tasklistlock);/*FIXME!!Thisshouldbedoneafterthelastuse*/if(!p)gotofreepageout;if(!p->mm||p->mm==&initmm||count==0)
gotogetlenout;/*Checkwhetherthemmapscouldchangeifwesleep*/volatiletask=(p!=current||atomicread(&p->mm->count)>1);/*decodefpos*/lineno=*ppos>>MAPSLINES
HIFT;column=*ppos&(MAPSLINELENGTH-1);/*quicklygotolinelineno*/for(map=p->mm->mmap,i=0;map&&(i<lineno);map=map->vmnext,i++)continue;for(;map;map=next){
/*producethenextline*/char*line;charstr[5],*cp=str;intflags;kdevtdev;unsignedlongino;intmaxlen=(sizeof(void*)==4)?MAPSLINEMAX4:MAPSLINEMAX8;intlen;/**
Getthenextvmanow(butitwon'tbeusedifwesleep).*/next=map->vmnext;flags=map->vmflags;*cp++=flags&VMREAD?'r':'-';*cp++=flags&VMWRITE?'w':'-';*cp++=flags&V
MEXEC?'x':'-';*cp++=flags&VMMAYSHARE?'s':'p';*cp++=0;dev=0;ino=0;if(map->vmfile!=NULL){dev=map->vmfile->fdentry->dinode->idev;ino=map->vmfile->fdentry
->dinode->iino;line=dpath(map->vmfile->fdentry,buffer,PAGESIZE);buffer[PAGESIZE-1]='\n';line-=maxlen;if(line<buffer)line=buffer;}elseline=buffer;len=s
printf(line,sizeof(void*)==4?MAPSLINEFORMAT4:MAPSLINEFORMAT8,map->vmstart,map->vmend,str,map->vmoffset,kdevname(dev),ino);if(map->vmfile){for(i=len;i<
maxlen;i++)line[i]='';len=buffer+PAGESIZE-line;}elseline[len++]='\n';if(column>=len){column=0;/*continuewithnextlineatcolumn0*/lineno++;continue;/*weh
aven'tslept*/}i=len-column;if(i>count)i=count;copytouser(destptr,line+column,i);/*mayhaveslept*/destptr+=i;count-=i;column+=i;if(column>=len){column=0
;/*nexttime:nextlineatcolumn0*/lineno++;}/*done?*/if(count==0)break;/*Bywritingtouserspace,wemighthaveslept.*Stoptheloop,toavoidaracecondition.*/if(vo
latiletask)break;}/*encodefpos*/*ppos=(lineno<<MAPSLINESHIFT)+column;getlenout:retval=destptr-buf;freepageout:freepage((unsignedlong)buffer);out:retur

Hosted by uCoz