Import 2.1.89
[davej-history.git] / fs / proc / array.c
blobed7e383fb490c98d3e25811c6a504c873b33f1a6
1 /*
2 * linux/fs/proc/array.c
4 * Copyright (C) 1992 by Linus Torvalds
5 * based on ideas by Darren Senn
7 * Fixes:
8 * Michael. K. Johnson: stat,statm extensions.
9 * <johnsonm@stolaf.edu>
11 * Pauline Middelink : Made cmdline,envline only break at '\0's, to
12 * make sure SET_PROCTITLE works. Also removed
13 * bad '!' which forced address recalculation for
14 * EVERY character on the current page.
15 * <middelin@polyware.iaf.nl>
17 * Danny ter Haar : added cpuinfo
18 * <dth@cistron.nl>
20 * Alessandro Rubini : profile extension.
21 * <rubini@ipvvis.unipv.it>
23 * Jeff Tranter : added BogoMips field to cpuinfo
24 * <Jeff_Tranter@Mitel.COM>
26 * Bruno Haible : remove 4K limit for the maps file
27 * <haible@ma2s2.mathematik.uni-karlsruhe.de>
29 * Yves Arrouye : remove removal of trailing spaces in get_array.
30 * <Yves.Arrouye@marin.fdn.fr>
32 * Jerome Forissier : added per-cpu time information to /proc/stat
33 * and /proc/<pid>/cpu extension
34 * <forissier@isia.cma.fr>
35 * - Incorporation and non-SMP safe operation
36 * of forissier patch in 2.1.78 by
37 * Hans Marcus <crowbar@concepts.nl>
40 #include <linux/types.h>
41 #include <linux/errno.h>
42 #include <linux/sched.h>
43 #include <linux/kernel.h>
44 #include <linux/kernel_stat.h>
45 #include <linux/tty.h>
46 #include <linux/user.h>
47 #include <linux/a.out.h>
48 #include <linux/string.h>
49 #include <linux/mman.h>
50 #include <linux/proc_fs.h>
51 #include <linux/ioport.h>
52 #include <linux/config.h>
53 #include <linux/mm.h>
54 #include <linux/pagemap.h>
55 #include <linux/swap.h>
56 #include <linux/slab.h>
57 #include <linux/smp.h>
58 #include <linux/signal.h>
60 #include <asm/uaccess.h>
61 #include <asm/pgtable.h>
62 #include <asm/io.h>
64 #define LOAD_INT(x) ((x) >> FSHIFT)
65 #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
67 #ifdef CONFIG_DEBUG_MALLOC
68 intget_malloc(char* buffer);
69 #endif
72 static ssize_t read_core(struct file * file,char* buf,
73 size_t count, loff_t *ppos)
75 unsigned long p = *ppos, memsize;
76 ssize_t read;
77 ssize_t count1;
78 char* pnt;
79 struct user dump;
80 #if defined (__i386__) || defined (__mc68000__)
81 # define FIRST_MAPPED PAGE_SIZE/* we don't have page 0 mapped on x86.. */
82 #else
83 # define FIRST_MAPPED 0
84 #endif
86 memset(&dump,0,sizeof(struct user));
87 dump.magic = CMAGIC;
88 dump.u_dsize = max_mapnr;
89 #ifdef __alpha__
90 dump.start_data = PAGE_OFFSET;
91 #endif
93 memsize = (max_mapnr +1) << PAGE_SHIFT;
94 if(p >= memsize)
95 return0;
96 if(count > memsize - p)
97 count = memsize - p;
98 read =0;
100 if(p <sizeof(struct user) && count >0) {
101 count1 = count;
102 if(p + count1 >sizeof(struct user))
103 count1 =sizeof(struct user)-p;
104 pnt = (char*) &dump + p;
105 copy_to_user(buf,(void*) pnt, count1);
106 buf += count1;
107 p += count1;
108 count -= count1;
109 read += count1;
112 if(count >0&& p < PAGE_SIZE + FIRST_MAPPED) {
113 count1 = PAGE_SIZE + FIRST_MAPPED - p;
114 if(count1 > count)
115 count1 = count;
116 clear_user(buf, count1);
117 buf += count1;
118 p += count1;
119 count -= count1;
120 read += count1;
122 if(count >0) {
123 copy_to_user(buf, (void*) (PAGE_OFFSET+p-PAGE_SIZE), count);
124 read += count;
126 *ppos += read;
127 return read;
130 static struct file_operations proc_kcore_operations = {
131 NULL,/* lseek */
132 read_core,
135 struct inode_operations proc_kcore_inode_operations = {
136 &proc_kcore_operations,
140 * This function accesses profiling information. The returned data is
141 * binary: the sampling step and the actual contents of the profile
142 * buffer. Use of the program readprofile is recommended in order to
143 * get meaningful info out of these data.
145 static ssize_t read_profile(struct file *file,char*buf,
146 size_t count, loff_t *ppos)
148 unsigned long p = *ppos;
149 ssize_t read;
150 char* pnt;
151 unsigned int sample_step =1<< prof_shift;
153 if(p >= (prof_len+1)*sizeof(unsigned int))
154 return0;
155 if(count > (prof_len+1)*sizeof(unsigned int) - p)
156 count = (prof_len+1)*sizeof(unsigned int) - p;
157 read =0;
159 while(p <sizeof(unsigned int) && count >0) {
160 put_user(*((char*)(&sample_step)+p),buf);
161 buf++; p++; count--; read++;
163 pnt = (char*)prof_buffer + p -sizeof(unsigned int);
164 copy_to_user(buf,(void*)pnt,count);
165 read += count;
166 *ppos += read;
167 return read;
171 * Writing to /proc/profile resets the counters
173 * Writing a 'profiling multiplier' value into it also re-sets the profiling
174 * interrupt frequency, on architectures that support this.
176 static ssize_t write_profile(struct file * file,const char* buf,
177 size_t count, loff_t *ppos)
179 #ifdef __SMP__
180 externintsetup_profiling_timer(unsigned int multiplier);
182 if(count==sizeof(int)) {
183 unsigned int multiplier;
185 if(copy_from_user(&multiplier, buf,sizeof(int)))
186 return-EFAULT;
188 if(setup_profiling_timer(multiplier))
189 return-EINVAL;
191 #endif
193 memset(prof_buffer,0, prof_len *sizeof(*prof_buffer));
194 return count;
197 static struct file_operations proc_profile_operations = {
198 NULL,/* lseek */
199 read_profile,
200 write_profile,
203 struct inode_operations proc_profile_inode_operations = {
204 &proc_profile_operations,
208 static intget_loadavg(char* buffer)
210 int a, b, c;
212 a = avenrun[0] + (FIXED_1/200);
213 b = avenrun[1] + (FIXED_1/200);
214 c = avenrun[2] + (FIXED_1/200);
215 returnsprintf(buffer,"%d.%02d %d.%02d %d.%02d %d/%d %d\n",
216 LOAD_INT(a),LOAD_FRAC(a),
217 LOAD_INT(b),LOAD_FRAC(b),
218 LOAD_INT(c),LOAD_FRAC(c),
219 nr_running, nr_tasks, last_pid);
222 static intget_kstat(char* buffer)
224 int i, len;
225 unsigned sum =0;
226 externunsigned long total_forks;
227 unsigned long ticks;
229 ticks = jiffies * smp_num_cpus;
230 for(i =0; i < NR_IRQS ; i++)
231 sum +=kstat_irqs(i);
233 #ifdef __SMP__
234 len =sprintf(buffer,
235 "cpu %u %u %u %lu\n",
236 kstat.cpu_user,
237 kstat.cpu_nice,
238 kstat.cpu_system,
239 jiffies*smp_num_cpus - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system));
240 for(i =0; i < smp_num_cpus; i++)
241 len +=sprintf(buffer + len,"cpu%d %u %u %u %lu\n",
243 kstat.per_cpu_user[cpu_logical_map(i)],
244 kstat.per_cpu_nice[cpu_logical_map(i)],
245 kstat.per_cpu_system[cpu_logical_map(i)],
246 jiffies - ( kstat.per_cpu_user[cpu_logical_map(i)] \
247 + kstat.per_cpu_nice[cpu_logical_map(i)] \
248 + kstat.per_cpu_system[cpu_logical_map(i)]));
249 len +=sprintf(buffer + len,
250 "disk %u %u %u %u\n"
251 "disk_rio %u %u %u %u\n"
252 "disk_wio %u %u %u %u\n"
253 "disk_rblk %u %u %u %u\n"
254 "disk_wblk %u %u %u %u\n"
255 "page %u %u\n"
256 "swap %u %u\n"
257 "intr %u",
258 #else
259 len =sprintf(buffer,
260 "cpu %u %u %u %lu\n"
261 "disk %u %u %u %u\n"
262 "disk_rio %u %u %u %u\n"
263 "disk_wio %u %u %u %u\n"
264 "disk_rblk %u %u %u %u\n"
265 "disk_wblk %u %u %u %u\n"
266 "page %u %u\n"
267 "swap %u %u\n"
268 "intr %u",
269 kstat.cpu_user,
270 kstat.cpu_nice,
271 kstat.cpu_system,
272 ticks - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system),
273 #endif
274 kstat.dk_drive[0], kstat.dk_drive[1],
275 kstat.dk_drive[2], kstat.dk_drive[3],
276 kstat.dk_drive_rio[0], kstat.dk_drive_rio[1],
277 kstat.dk_drive_rio[2], kstat.dk_drive_rio[3],
278 kstat.dk_drive_wio[0], kstat.dk_drive_wio[1],
279 kstat.dk_drive_wio[2], kstat.dk_drive_wio[3],
280 kstat.dk_drive_rblk[0], kstat.dk_drive_rblk[1],
281 kstat.dk_drive_rblk[2], kstat.dk_drive_rblk[3],
282 kstat.dk_drive_wblk[0], kstat.dk_drive_wblk[1],
283 kstat.dk_drive_wblk[2], kstat.dk_drive_wblk[3],
284 kstat.pgpgin,
285 kstat.pgpgout,
286 kstat.pswpin,
287 kstat.pswpout,
288 sum);
289 for(i =0; i < NR_IRQS ; i++)
290 len +=sprintf(buffer + len," %u",kstat_irqs(i));
291 len +=sprintf(buffer + len,
292 "\nctxt %u\n"
293 "btime %lu\n"
294 "processes %lu\n",
295 kstat.context_swtch,
296 xtime.tv_sec - jiffies / HZ,
297 total_forks);
298 return len;
302 static intget_uptime(char* buffer)
304 unsigned long uptime;
305 unsigned long idle;
307 uptime = jiffies;
308 idle = task[0]->times.tms_utime + task[0]->times.tms_stime;
310 /* The formula for the fraction parts really is ((t * 100) / HZ) % 100, but
311 that would overflow about every five days at HZ == 100.
312 Therefore the identity a = (a / b) * b + a % b is used so that it is
313 calculated as (((t / HZ) * 100) + ((t % HZ) * 100) / HZ) % 100.
314 The part in front of the '+' always evaluates as 0 (mod 100). All divisions
315 in the above formulas are truncating. For HZ being a power of 10, the
316 calculations simplify to the version in the #else part (if the printf
317 format is adapted to the same number of digits as zeroes in HZ.
319 #if HZ!=100
320 returnsprintf(buffer,"%lu.%02lu %lu.%02lu\n",
321 uptime / HZ,
322 (((uptime % HZ) *100) / HZ) %100,
323 idle / HZ,
324 (((idle % HZ) *100) / HZ) %100);
325 #else
326 returnsprintf(buffer,"%lu.%02lu %lu.%02lu\n",
327 uptime / HZ,
328 uptime % HZ,
329 idle / HZ,
330 idle % HZ);
331 #endif
334 static intget_meminfo(char* buffer)
336 struct sysinfo i;
337 int len;
339 si_meminfo(&i);
340 si_swapinfo(&i);
341 len =sprintf(buffer," total: used: free: shared: buffers: cached:\n"
342 "Mem: %8lu %8lu %8lu %8lu %8lu %8lu\n"
343 "Swap: %8lu %8lu %8lu\n",
344 i.totalram, i.totalram-i.freeram, i.freeram, i.sharedram, i.bufferram, page_cache_size*PAGE_SIZE,
345 i.totalswap, i.totalswap-i.freeswap, i.freeswap);
347 * Tagged format, for easy grepping and expansion. The above will go away
348 * eventually, once the tools have been updated.
350 return len +sprintf(buffer+len,
351 "MemTotal: %8lu kB\n"
352 "MemFree: %8lu kB\n"
353 "MemShared: %8lu kB\n"
354 "Buffers: %8lu kB\n"
355 "Cached: %8lu kB\n"
356 "SwapTotal: %8lu kB\n"
357 "SwapFree: %8lu kB\n",
358 i.totalram >>10,
359 i.freeram >>10,
360 i.sharedram >>10,
361 i.bufferram >>10,
362 page_cache_size << (PAGE_SHIFT -10),
363 i.totalswap >>10,
364 i.freeswap >>10);
367 static intget_version(char* buffer)
369 externchar*linux_banner;
371 strcpy(buffer, linux_banner);
372 returnstrlen(buffer);
375 static intget_cmdline(char* buffer)
377 externchar saved_command_line[];
379 returnsprintf(buffer,"%s\n", saved_command_line);
382 static unsigned longget_phys_addr(struct task_struct * p,unsigned long ptr)
384 pgd_t *page_dir;
385 pmd_t *page_middle;
386 pte_t pte;
388 if(!p || !p->mm || ptr >= TASK_SIZE)
389 return0;
390 /* Check for NULL pgd .. shouldn't happen! */
391 if(!p->mm->pgd) {
392 printk("get_phys_addr: pid %d has NULL pgd!\n", p->pid);
393 return0;
396 page_dir =pgd_offset(p->mm,ptr);
397 if(pgd_none(*page_dir))
398 return0;
399 if(pgd_bad(*page_dir)) {
400 printk("bad page directory entry %08lx\n",pgd_val(*page_dir));
401 pgd_clear(page_dir);
402 return0;
404 page_middle =pmd_offset(page_dir,ptr);
405 if(pmd_none(*page_middle))
406 return0;
407 if(pmd_bad(*page_middle)) {
408 printk("bad page middle entry %08lx\n",pmd_val(*page_middle));
409 pmd_clear(page_middle);
410 return0;
412 pte = *pte_offset(page_middle,ptr);
413 if(!pte_present(pte))
414 return0;
415 returnpte_page(pte) + (ptr & ~PAGE_MASK);
418 static intget_array(struct task_struct *p,unsigned long start,unsigned long end,char* buffer)
420 unsigned long addr;
421 int size =0, result =0;
422 char c;
424 if(start >= end)
425 return result;
426 for(;;) {
427 addr =get_phys_addr(p, start);
428 if(!addr)
429 return result;
431 c = *(char*) addr;
432 if(!c)
433 result = size;
434 if(size < PAGE_SIZE)
435 buffer[size++] = c;
436 else
437 return result;
438 addr++;
439 start++;
440 if(!c && start >= end)
441 return result;
442 }while(addr & ~PAGE_MASK);
444 return result;
447 static intget_env(int pid,char* buffer)
449 struct task_struct *p =find_task_by_pid(pid);
451 if(!p || !p->mm)
452 return0;
453 returnget_array(p, p->mm->env_start, p->mm->env_end, buffer);
456 static intget_arg(int pid,char* buffer)
458 struct task_struct *p =find_task_by_pid(pid);
460 if(!p || !p->mm)
461 return0;
462 returnget_array(p, p->mm->arg_start, p->mm->arg_end, buffer);
466 * These bracket the sleeping functions..
468 externvoidscheduling_functions_start_here(void);
469 externvoidscheduling_functions_end_here(void);
470 #define first_sched ((unsigned long) scheduling_functions_start_here)
471 #define last_sched ((unsigned long) scheduling_functions_end_here)
473 static unsigned longget_wchan(struct task_struct *p)
475 if(!p || p == current || p->state == TASK_RUNNING)
476 return0;
477 #if defined(__i386__)
479 unsigned long ebp, eip;
480 unsigned long stack_page;
481 int count =0;
483 stack_page =4096+ (unsigned long)p;
484 if(!stack_page)
485 return0;
486 ebp = p->tss.ebp;
488 if(ebp < stack_page || ebp >=4092+stack_page)
489 return0;
490 eip = *(unsigned long*) (ebp+4);
491 if(eip < first_sched || eip >= last_sched)
492 return eip;
493 ebp = *(unsigned long*) ebp;
494 }while(count++ <16);
496 #elif defined(__alpha__)
498 * This one depends on the frame size of schedule(). Do a
499 * "disass schedule" in gdb to find the frame size. Also, the
500 * code assumes that sleep_on() follows immediately after
501 * interruptible_sleep_on() and that add_timer() follows
502 * immediately after interruptible_sleep(). Ugly, isn't it?
503 * Maybe adding a wchan field to task_struct would be better,
504 * after all...
507 unsigned long schedule_frame;
508 unsigned long pc;
510 pc =thread_saved_pc(&p->tss);
511 if(pc >= first_sched && pc < last_sched) {
512 schedule_frame = ((unsigned long*)p->tss.ksp)[6];
513 return((unsigned long*)schedule_frame)[12];
515 return pc;
517 #elif defined(__mc68000__)
519 unsigned long fp, pc;
520 unsigned long stack_page;
521 int count =0;
522 externintsys_pause(void);
524 stack_page = p->kernel_stack_page;
525 if(!stack_page)
526 return0;
527 fp = ((struct switch_stack *)p->tss.ksp)->a6;
529 if(fp < stack_page || fp >=4088+stack_page)
530 return0;
531 pc = ((unsigned long*)fp)[1];
532 /* FIXME: This depends on the order of these functions. */
533 if(pc < first_sched || pc >= last_sched)
534 return pc;
535 fp = *(unsigned long*) fp;
536 }while(count++ <16);
538 #elif defined(__powerpc__)
539 return(p->tss.wchan);
540 #endif
541 return0;
544 #if defined(__i386__)
545 # define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1019])
546 # define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022])
547 #elif defined(__alpha__)
549 * See arch/alpha/kernel/ptrace.c for details.
551 # define PT_REG(reg) (PAGE_SIZE - sizeof(struct pt_regs) \
552 + (long)&((struct pt_regs *)0)->reg)
553 # define KSTK_EIP(tsk) \
554 (*(unsigned long *)(PT_REG(pc) + PAGE_SIZE + (unsigned long)(tsk)))
555 # define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->tss.usp)
556 #elif defined(__mc68000__)
557 #define KSTK_EIP(tsk) \
558 ({ \
559 unsigned long eip = 0; \
560 if ((tsk)->tss.esp0 > PAGE_SIZE && \
561 MAP_NR((tsk)->tss.esp0) < max_mapnr) \
562 eip = ((struct pt_regs *) (tsk)->tss.esp0)->pc; \
563 eip; })
564 #define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->tss.usp)
565 #elif defined(__powerpc__)
566 #define KSTK_EIP(tsk) ((tsk)->tss.regs->nip)
567 #define KSTK_ESP(tsk) ((tsk)->tss.regs->gpr[1])
568 #elif defined (__sparc_v9__)
569 # define KSTK_EIP(tsk) ((tsk)->tss.kregs->tpc)
570 # define KSTK_ESP(tsk) ((tsk)->tss.kregs->u_regs[UREG_FP])
571 #elif defined(__sparc__)
572 # define KSTK_EIP(tsk) ((tsk)->tss.kregs->pc)
573 # define KSTK_ESP(tsk) ((tsk)->tss.kregs->u_regs[UREG_FP])
574 #endif
576 /* Gcc optimizes away "strlen(x)" for constant x */
577 #define ADDBUF(buffer, string) \
578 do { memcpy(buffer, string, strlen(string)); \
579 buffer += strlen(string); } while (0)
581 staticinlinechar*task_name(struct task_struct *p,char* buf)
583 int i;
584 char* name;
586 ADDBUF(buf,"Name:\t");
587 name = p->comm;
588 i =sizeof(p->comm);
590 unsigned char c = *name;
591 name++;
592 i--;
593 *buf = c;
594 if(!c)
595 break;
596 if(c =='\\') {
597 buf[1] = c;
598 buf +=2;
599 continue;
601 if(c =='\n') {
602 buf[0] ='\\';
603 buf[1] ='n';
604 buf +=2;
605 continue;
607 buf++;
608 }while(i);
609 *buf ='\n';
610 return buf+1;
614 * The task state array is a strange "bitmap" of
615 * reasons to sleep. Thus "running" is zero, and
616 * you can test for combinations of others with
617 * simple bit tests.
619 static const char*task_state_array[] = {
620 "R (running)",/* 0 */
621 "S (sleeping)",/* 1 */
622 "D (disk sleep)",/* 2 */
623 "Z (zombie)",/* 4 */
624 "T (stopped)",/* 8 */
625 "W (paging)"/* 16 */
628 staticinlineconst char*get_task_state(struct task_struct *tsk)
630 unsigned int state = tsk->state & (TASK_RUNNING |
631 TASK_INTERRUPTIBLE |
632 TASK_UNINTERRUPTIBLE |
633 TASK_ZOMBIE |
634 TASK_STOPPED |
635 TASK_SWAPPING);
636 const char**p = &task_state_array[0];
638 while(state) {
639 p++;
640 state >>=1;
642 return*p;
645 staticinlinechar*task_state(struct task_struct *p,char*buffer)
647 buffer +=sprintf(buffer,
648 "State:\t%s\n"
649 "Pid:\t%d\n"
650 "PPid:\t%d\n"
651 "Uid:\t%d\t%d\t%d\t%d\n"
652 "Gid:\t%d\t%d\t%d\t%d\n",
653 get_task_state(p),
654 p->pid, p->p_pptr->pid,
655 p->uid, p->euid, p->suid, p->fsuid,
656 p->gid, p->egid, p->sgid, p->fsgid);
657 return buffer;
660 staticinlinechar*task_mem(struct task_struct *p,char*buffer)
662 struct mm_struct * mm = p->mm;
664 if(mm && mm != &init_mm) {
665 struct vm_area_struct * vma = mm->mmap;
666 unsigned long data =0, stack =0;
667 unsigned long exec =0, lib =0;
669 for(vma = mm->mmap; vma; vma = vma->vm_next) {
670 unsigned long len = (vma->vm_end - vma->vm_start) >>10;
671 if(!vma->vm_file) {
672 data += len;
673 if(vma->vm_flags & VM_GROWSDOWN)
674 stack += len;
675 continue;
677 if(vma->vm_flags & VM_WRITE)
678 continue;
679 if(vma->vm_flags & VM_EXEC) {
680 exec += len;
681 if(vma->vm_flags & VM_EXECUTABLE)
682 continue;
683 lib += len;
686 buffer +=sprintf(buffer,
687 "VmSize:\t%8lu kB\n"
688 "VmLck:\t%8lu kB\n"
689 "VmRSS:\t%8lu kB\n"
690 "VmData:\t%8lu kB\n"
691 "VmStk:\t%8lu kB\n"
692 "VmExe:\t%8lu kB\n"
693 "VmLib:\t%8lu kB\n",
694 mm->total_vm << (PAGE_SHIFT-10),
695 mm->locked_vm << (PAGE_SHIFT-10),
696 mm->rss << (PAGE_SHIFT-10),
697 data - stack, stack,
698 exec - lib, lib);
700 return buffer;
703 char*render_sigset_t(sigset_t *set,char*buffer)
705 int i = _NSIG, x;
707 i -=4, x =0;
708 if(sigismember(set, i+1)) x |=1;
709 if(sigismember(set, i+2)) x |=2;
710 if(sigismember(set, i+3)) x |=4;
711 if(sigismember(set, i+4)) x |=8;
712 *buffer++ = (x <10?'0':'a'-10) + x;
713 }while(i >=4);
714 *buffer =0;
715 return buffer;
718 static voidcollect_sigign_sigcatch(struct task_struct *p, sigset_t *ign,
719 sigset_t *catch)
721 struct k_sigaction *k;
722 int i;
724 sigemptyset(ign);
725 sigemptyset(catch);
727 if(p->sig) {
728 k = p->sig->action;
729 for(i =1; i <= _NSIG; ++i, ++k) {
730 if(k->sa.sa_handler == SIG_IGN)
731 sigaddset(ign, i);
732 else if(k->sa.sa_handler != SIG_DFL)
733 sigaddset(catch, i);
738 staticinlinechar*task_sig(struct task_struct *p,char*buffer)
740 sigset_t ign,catch;
742 buffer +=sprintf(buffer,"SigPnd:\t");
743 buffer =render_sigset_t(&p->signal, buffer);
744 *buffer++ ='\n';
745 buffer +=sprintf(buffer,"SigBlk:\t");
746 buffer =render_sigset_t(&p->blocked, buffer);
747 *buffer++ ='\n';
749 collect_sigign_sigcatch(p, &ign, &catch);
750 buffer +=sprintf(buffer,"SigIgn:\t");
751 buffer =render_sigset_t(&ign, buffer);
752 *buffer++ ='\n';
753 buffer +=sprintf(buffer,"SigCat:\t");
754 buffer =render_sigset_t(&catch, buffer);
755 *buffer++ ='\n';
757 return buffer;
760 static intget_status(int pid,char* buffer)
762 char* orig = buffer;
763 struct task_struct *tsk =find_task_by_pid(pid);
765 if(!tsk)
766 return0;
767 buffer =task_name(tsk, buffer);
768 buffer =task_state(tsk, buffer);
769 buffer =task_mem(tsk, buffer);
770 buffer =task_sig(tsk, buffer);
771 return buffer - orig;
774 static intget_stat(int pid,char* buffer)
776 struct task_struct *tsk =find_task_by_pid(pid);
777 unsigned long vsize, eip, esp, wchan;
778 long priority, nice;
779 int tty_pgrp;
780 sigset_t sigign, sigcatch;
781 char signal_str[sizeof(sigset_t)*2+1];
782 char blocked_str[sizeof(sigset_t)*2+1];
783 char sigign_str[sizeof(sigset_t)*2+1];
784 char sigcatch_str[sizeof(sigset_t)*2+1];
785 char state;
787 if(!tsk)
788 return0;
789 state = *get_task_state(tsk);
790 vsize = eip = esp =0;
791 if(tsk->mm && tsk->mm != &init_mm) {
792 struct vm_area_struct *vma = tsk->mm->mmap;
793 while(vma) {
794 vsize += vma->vm_end - vma->vm_start;
795 vma = vma->vm_next;
797 eip =KSTK_EIP(tsk);
798 esp =KSTK_ESP(tsk);
801 wchan =get_wchan(tsk);
803 collect_sigign_sigcatch(tsk, &sigign, &sigcatch);
804 render_sigset_t(&tsk->signal, signal_str);
805 render_sigset_t(&tsk->blocked, blocked_str);
806 render_sigset_t(&sigign, sigign_str);
807 render_sigset_t(&sigcatch, sigcatch_str);
809 if(tsk->tty)
810 tty_pgrp = tsk->tty->pgrp;
811 else
812 tty_pgrp = -1;
814 /* scale priority and nice values from timeslices to -20..20 */
815 /* to make it look like a "normal" unix priority/nice value */
816 priority = tsk->counter;
817 priority =20- (priority *10+ DEF_PRIORITY /2) / DEF_PRIORITY;
818 nice = tsk->priority;
819 nice =20- (nice *20+ DEF_PRIORITY /2) / DEF_PRIORITY;
821 returnsprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
822 %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu \
823 %lu %s %s %s %s %lu %lu %lu\n",
824 pid,
825 tsk->comm,
826 state,
827 tsk->p_pptr->pid,
828 tsk->pgrp,
829 tsk->session,
830 tsk->tty ?kdev_t_to_nr(tsk->tty->device) :0,
831 tty_pgrp,
832 tsk->flags,
833 tsk->min_flt,
834 tsk->cmin_flt,
835 tsk->maj_flt,
836 tsk->cmaj_flt,
837 tsk->times.tms_utime,
838 tsk->times.tms_stime,
839 tsk->times.tms_cutime,
840 tsk->times.tms_cstime,
841 priority,
842 nice,
843 tsk->timeout,
844 tsk->it_real_value,
845 tsk->start_time,
846 vsize,
847 tsk->mm ? tsk->mm->rss :0,/* you might want to shift this left 3 */
848 tsk->rlim ? tsk->rlim[RLIMIT_RSS].rlim_cur :0,
849 tsk->mm ? tsk->mm->start_code :0,
850 tsk->mm ? tsk->mm->end_code :0,
851 tsk->mm ? tsk->mm->start_stack :0,
852 esp,
853 eip,
854 signal_str,
855 blocked_str,
856 sigign_str,
857 sigcatch_str,
858 wchan,
859 tsk->nswap,
860 tsk->cnswap);
863 staticinlinevoidstatm_pte_range(pmd_t * pmd,unsigned long address,unsigned long size,
864 int* pages,int* shared,int* dirty,int* total)
866 pte_t * pte;
867 unsigned long end;
869 if(pmd_none(*pmd))
870 return;
871 if(pmd_bad(*pmd)) {
872 printk("statm_pte_range: bad pmd (%08lx)\n",pmd_val(*pmd));
873 pmd_clear(pmd);
874 return;
876 pte =pte_offset(pmd, address);
877 address &= ~PMD_MASK;
878 end = address + size;
879 if(end > PMD_SIZE)
880 end = PMD_SIZE;
882 pte_t page = *pte;
884 address += PAGE_SIZE;
885 pte++;
886 if(pte_none(page))
887 continue;
888 ++*total;
889 if(!pte_present(page))
890 continue;
891 ++*pages;
892 if(pte_dirty(page))
893 ++*dirty;
894 if(MAP_NR(pte_page(page)) >= max_mapnr)
895 continue;
896 if(atomic_read(&mem_map[MAP_NR(pte_page(page))].count) >1)
897 ++*shared;
898 }while(address < end);
901 staticinlinevoidstatm_pmd_range(pgd_t * pgd,unsigned long address,unsigned long size,
902 int* pages,int* shared,int* dirty,int* total)
904 pmd_t * pmd;
905 unsigned long end;
907 if(pgd_none(*pgd))
908 return;
909 if(pgd_bad(*pgd)) {
910 printk("statm_pmd_range: bad pgd (%08lx)\n",pgd_val(*pgd));
911 pgd_clear(pgd);
912 return;
914 pmd =pmd_offset(pgd, address);
915 address &= ~PGDIR_MASK;
916 end = address + size;
917 if(end > PGDIR_SIZE)
918 end = PGDIR_SIZE;
920 statm_pte_range(pmd, address, end - address, pages, shared, dirty, total);
921 address = (address + PMD_SIZE) & PMD_MASK;
922 pmd++;
923 }while(address < end);
926 static voidstatm_pgd_range(pgd_t * pgd,unsigned long address,unsigned long end,
927 int* pages,int* shared,int* dirty,int* total)
929 while(address < end) {
930 statm_pmd_range(pgd, address, end - address, pages, shared, dirty, total);
931 address = (address + PGDIR_SIZE) & PGDIR_MASK;
932 pgd++;
936 static intget_statm(int pid,char* buffer)
938 struct task_struct *tsk =find_task_by_pid(pid);
939 int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
941 if(!tsk)
942 return0;
943 if(tsk->mm && tsk->mm != &init_mm) {
944 struct vm_area_struct * vma = tsk->mm->mmap;
946 while(vma) {
947 pgd_t *pgd =pgd_offset(tsk->mm, vma->vm_start);
948 int pages =0, shared =0, dirty =0, total =0;
950 statm_pgd_range(pgd, vma->vm_start, vma->vm_end, &pages, &shared, &dirty, &total);
951 resident += pages;
952 share += shared;
953 dt += dirty;
954 size += total;
955 if(vma->vm_flags & VM_EXECUTABLE)
956 trs += pages;/* text */
957 else if(vma->vm_flags & VM_GROWSDOWN)
958 drs += pages;/* stack */
959 else if(vma->vm_end >0x60000000)
960 lrs += pages;/* library */
961 else
962 drs += pages;
963 vma = vma->vm_next;
966 returnsprintf(buffer,"%d %d %d %d %d %d %d\n",
967 size, resident, share, trs, lrs, drs, dt);
971 * The way we support synthetic files > 4K
972 * - without storing their contents in some buffer and
973 * - without walking through the entire synthetic file until we reach the
974 * position of the requested data
975 * is to cleverly encode the current position in the file's f_pos field.
976 * There is no requirement that a read() call which returns `count' bytes
977 * of data increases f_pos by exactly `count'.
979 * This idea is Linus' one. Bruno implemented it.
983 * For the /proc/<pid>/maps file, we use fixed length records, each containing
984 * a single line.
986 #define MAPS_LINE_LENGTH 4096
987 #define MAPS_LINE_SHIFT 12
989 * f_pos = (number of the vma in the task->mm->mmap list) * MAPS_LINE_LENGTH
990 * + (index into the line)
992 /* for systems with sizeof(void*) == 4: */
993 #define MAPS_LINE_FORMAT4"%08lx-%08lx %s %08lx %s %lu"
994 #define MAPS_LINE_MAX4 49/* sum of 8 1 8 1 4 1 8 1 5 1 10 1 */
996 /* for systems with sizeof(void*) == 8: */
997 #define MAPS_LINE_FORMAT8"%016lx-%016lx %s %016lx %s %lu"
998 #define MAPS_LINE_MAX8 73/* sum of 16 1 16 1 4 1 16 1 5 1 10 1 */
1000 #define MAPS_LINE_MAX MAPS_LINE_MAX8
1003 static ssize_t read_maps(int pid,struct file * file,char* buf,
1004 size_t count, loff_t *ppos)
1006 struct task_struct *p;
1007 struct vm_area_struct * map, * next;
1008 char* destptr = buf, * buffer;
1009 loff_t lineno;
1010 ssize_t column, i;
1011 int volatile_task;
1012 long retval;
1015 * We might sleep getting the page, so get it first.
1017 retval = -ENOMEM;
1018 buffer = (char*)__get_free_page(GFP_KERNEL);
1019 if(!buffer)
1020 goto out;
1022 retval = -EINVAL;
1023 p =find_task_by_pid(pid);
1024 if(!p)
1025 goto freepage_out;
1027 if(!p->mm || p->mm == &init_mm || count ==0)
1028 goto getlen_out;
1030 /* Check whether the mmaps could change if we sleep */
1031 volatile_task = (p != current || p->mm->count >1);
1033 /* decode f_pos */
1034 lineno = *ppos >> MAPS_LINE_SHIFT;
1035 column = *ppos & (MAPS_LINE_LENGTH-1);
1037 /* quickly go to line lineno */
1038 for(map = p->mm->mmap, i =0; map && (i < lineno); map = map->vm_next, i++)
1039 continue;
1041 for( ; map ; map = next ) {
1042 /* produce the next line */
1043 char*line;
1044 char str[5], *cp = str;
1045 int flags;
1046 kdev_t dev;
1047 unsigned long ino;
1048 int maxlen = (sizeof(void*) ==4) ?
1049 MAPS_LINE_MAX4 : MAPS_LINE_MAX8;
1050 int len;
1053 * Get the next vma now (but it won't be used if we sleep).
1055 next = map->vm_next;
1056 flags = map->vm_flags;
1058 *cp++ = flags & VM_READ ?'r':'-';
1059 *cp++ = flags & VM_WRITE ?'w':'-';
1060 *cp++ = flags & VM_EXEC ?'x':'-';
1061 *cp++ = flags & VM_MAYSHARE ?'s':'p';
1062 *cp++ =0;
1064 dev =0;
1065 ino =0;
1066 if(map->vm_file != NULL) {
1067 dev = map->vm_file->f_dentry->d_inode->i_dev;
1068 ino = map->vm_file->f_dentry->d_inode->i_ino;
1069 line =d_path(map->vm_file->f_dentry, buffer, PAGE_SIZE);
1070 buffer[PAGE_SIZE-1] ='\n';
1071 line -= maxlen;
1072 if(line < buffer)
1073 line = buffer;
1074 }else
1075 line = buffer;
1077 len =sprintf(line,
1078 sizeof(void*) ==4? MAPS_LINE_FORMAT4 : MAPS_LINE_FORMAT8,
1079 map->vm_start, map->vm_end, str, map->vm_offset,
1080 kdevname(dev), ino);
1082 if(map->vm_file) {
1083 for(i = len; i < maxlen; i++)
1084 line[i] =' ';
1085 len = buffer + PAGE_SIZE - line;
1086 }else
1087 line[len++] ='\n';
1088 if(column >= len) {
1089 column =0;/* continue with next line at column 0 */
1090 lineno++;
1091 continue;/* we haven't slept */
1094 i = len-column;
1095 if(i > count)
1096 i = count;
1097 copy_to_user(destptr, line+column, i);/* may have slept */
1098 destptr += i;
1099 count -= i;
1100 column += i;
1101 if(column >= len) {
1102 column =0;/* next time: next line at column 0 */
1103 lineno++;
1106 /* done? */
1107 if(count ==0)
1108 break;
1110 /* By writing to user space, we might have slept.
1111 * Stop the loop, to avoid a race condition.
1113 if(volatile_task)
1114 break;
1117 /* encode f_pos */
1118 *ppos = (lineno << MAPS_LINE_SHIFT) + column;
1120 getlen_out:
1121 retval = destptr - buf;
1123 freepage_out:
1124 free_page((unsigned long)buffer);
1125 out:
1126 return retval;
1129 #ifdef __SMP__
1130 static intget_pidcpu(int pid,char* buffer)
1132 struct task_struct * tsk = current ;
1133 int i, len;
1135 if(pid != tsk->pid)
1136 tsk =find_task_by_pid(pid);
1138 if(tsk == NULL)
1139 return0;
1141 len =sprintf(buffer,
1142 "cpu %lu %lu\n",
1143 tsk->times.tms_utime,
1144 tsk->times.tms_stime);
1146 for(i =0; i < smp_num_cpus; i++)
1147 len +=sprintf(buffer + len,"cpu%d %lu %lu\n",
1149 tsk->per_cpu_utime[cpu_logical_map(i)],
1150 tsk->per_cpu_stime[cpu_logical_map(i)]);
1152 return len;
1154 #endif
1156 #ifdef CONFIG_MODULES
1157 externintget_module_list(char*);
1158 externintget_ksyms_list(char*,char**, off_t,int);
1159 #endif
1160 externintget_device_list(char*);
1161 externintget_filesystem_list(char*);
1162 externintget_filesystem_info(char* );
1163 externintget_irq_list(char*);
1164 externintget_dma_list(char*);
1165 externintget_cpuinfo(char*);
1166 externintget_pci_list(char*);
1167 externintget_md_status(char*);
1168 externintget_rtc_status(char*);
1169 externintget_locks_status(char*,char**, off_t,int);
1170 externintget_swaparea_info(char*);
1171 #ifdef CONFIG_ZORRO
1172 externintzorro_get_list(char*);
1173 #endif
1174 #if defined (CONFIG_AMIGA) || defined (CONFIG_ATARI)
1175 externintget_hardware_list(char*);
1176 #endif
1178 static longget_root_array(char* page,int type,char**start,
1179 off_t offset,unsigned long length)
1181 switch(type) {
1182 case PROC_LOADAVG:
1183 returnget_loadavg(page);
1185 case PROC_UPTIME:
1186 returnget_uptime(page);
1188 case PROC_MEMINFO:
1189 returnget_meminfo(page);
1191 #ifdef CONFIG_PCI_OLD_PROC
1192 case PROC_PCI:
1193 returnget_pci_list(page);
1194 #endif
1196 case PROC_CPUINFO:
1197 returnget_cpuinfo(page);
1199 case PROC_VERSION:
1200 returnget_version(page);
1202 #ifdef CONFIG_DEBUG_MALLOC
1203 case PROC_MALLOC:
1204 returnget_malloc(page);
1205 #endif
1207 #ifdef CONFIG_MODULES
1208 case PROC_MODULES:
1209 returnget_module_list(page);
1211 case PROC_KSYMS:
1212 returnget_ksyms_list(page, start, offset, length);
1213 #endif
1215 case PROC_STAT:
1216 returnget_kstat(page);
1218 case PROC_SLABINFO:
1219 returnget_slabinfo(page);
1221 case PROC_DEVICES:
1222 returnget_device_list(page);
1224 case PROC_INTERRUPTS:
1225 returnget_irq_list(page);
1227 case PROC_FILESYSTEMS:
1228 returnget_filesystem_list(page);
1230 case PROC_DMA:
1231 returnget_dma_list(page);
1233 case PROC_IOPORTS:
1234 returnget_ioport_list(page);
1235 #ifdef CONFIG_BLK_DEV_MD
1236 case PROC_MD:
1237 returnget_md_status(page);
1238 #endif
1239 case PROC_CMDLINE:
1240 returnget_cmdline(page);
1242 case PROC_MTAB:
1243 returnget_filesystem_info( page );
1245 case PROC_SWAP:
1246 returnget_swaparea_info(page);
1247 #ifdef CONFIG_RTC
1248 case PROC_RTC:
1249 returnget_rtc_status(page);
1250 #endif
1251 case PROC_LOCKS:
1252 returnget_locks_status(page, start, offset, length);
1253 #ifdef CONFIG_ZORRO
1254 case PROC_ZORRO:
1255 returnzorro_get_list(page);
1256 #endif
1257 #if defined (CONFIG_AMIGA) || defined (CONFIG_ATARI)
1258 case PROC_HARDWARE:
1259 returnget_hardware_list(page);
1260 #endif
1262 return-EBADF;
1265 static intget_process_array(char* page,int pid,int type)
1267 switch(type) {
1268 case PROC_PID_STATUS:
1269 returnget_status(pid, page);
1270 case PROC_PID_ENVIRON:
1271 returnget_env(pid, page);
1272 case PROC_PID_CMDLINE:
1273 returnget_arg(pid, page);
1274 case PROC_PID_STAT:
1275 returnget_stat(pid, page);
1276 case PROC_PID_STATM:
1277 returnget_statm(pid, page);
1278 #ifdef __SMP__
1279 case PROC_PID_CPU:
1280 returnget_pidcpu(pid, page);
1281 #endif
1283 return-EBADF;
1287 staticinlineintfill_array(char* page,int pid,int type,char**start, off_t offset,int length)
1289 if(pid)
1290 returnget_process_array(page, pid, type);
1291 returnget_root_array(page, type, start, offset, length);
1294 #define PROC_BLOCK_SIZE (3*1024)/* 4K page size but our output routines use some slack for overruns */
1296 static ssize_t array_read(struct file * file,char* buf,
1297 size_t count, loff_t *ppos)
1299 struct inode * inode = file->f_dentry->d_inode;
1300 unsigned long page;
1301 char*start;
1302 ssize_t length;
1303 ssize_t end;
1304 unsigned int type, pid;
1305 struct proc_dir_entry *dp;
1307 if(count > PROC_BLOCK_SIZE)
1308 count = PROC_BLOCK_SIZE;
1309 if(!(page =__get_free_page(GFP_KERNEL)))
1310 return-ENOMEM;
1311 type = inode->i_ino;
1312 pid = type >>16;
1313 type &=0x0000ffff;
1314 start = NULL;
1315 dp = (struct proc_dir_entry *) inode->u.generic_ip;
1316 if(dp->get_info)
1317 length = dp->get_info((char*)page, &start, *ppos,
1318 count,0);
1319 else
1320 length =fill_array((char*) page, pid, type,
1321 &start, *ppos, count);
1322 if(length <0) {
1323 free_page(page);
1324 return length;
1326 if(start != NULL) {
1327 /* We have had block-adjusting processing! */
1328 copy_to_user(buf, start, length);
1329 *ppos += length;
1330 count = length;
1331 }else{
1332 /* Static 4kB (or whatever) block capacity */
1333 if(*ppos >= length) {
1334 free_page(page);
1335 return0;
1337 if(count + *ppos > length)
1338 count = length - *ppos;
1339 end = count + *ppos;
1340 copy_to_user(buf, (char*) page + *ppos, count);
1341 *ppos = end;
1343 free_page(page);
1344 return count;
1347 static struct file_operations proc_array_operations = {
1348 NULL,/* array_lseek */
1349 array_read,
1350 NULL,/* array_write */
1351 NULL,/* array_readdir */
1352 NULL,/* array_poll */
1353 NULL,/* array_ioctl */
1354 NULL,/* mmap */
1355 NULL,/* no special open code */
1356 NULL,/* no special release code */
1357 NULL /* can't fsync */
1360 struct inode_operations proc_array_inode_operations = {
1361 &proc_array_operations,/* default base directory file-ops */
1362 NULL,/* create */
1363 NULL,/* lookup */
1364 NULL,/* link */
1365 NULL,/* unlink */
1366 NULL,/* symlink */
1367 NULL,/* mkdir */
1368 NULL,/* rmdir */
1369 NULL,/* mknod */
1370 NULL,/* rename */
1371 NULL,/* readlink */
1372 NULL,/* follow_link */
1373 NULL,/* readpage */
1374 NULL,/* writepage */
1375 NULL,/* bmap */
1376 NULL,/* truncate */
1377 NULL /* permission */
1380 static ssize_t arraylong_read(struct file * file,char* buf,
1381 size_t count, loff_t *ppos)
1383 struct inode * inode = file->f_dentry->d_inode;
1384 unsigned int pid = inode->i_ino >>16;
1385 unsigned int type = inode->i_ino &0x0000ffff;
1387 switch(type) {
1388 case PROC_PID_MAPS:
1389 returnread_maps(pid, file, buf, count, ppos);
1391 return-EINVAL;
1394 static struct file_operations proc_arraylong_operations = {
1395 NULL,/* array_lseek */
1396 arraylong_read,
1397 NULL,/* array_write */
1398 NULL,/* array_readdir */
1399 NULL,/* array_poll */
1400 NULL,/* array_ioctl */
1401 NULL,/* mmap */
1402 NULL,/* no special open code */
1403 NULL,/* no special release code */
1404 NULL /* can't fsync */
1407 struct inode_operations proc_arraylong_inode_operations = {
1408 &proc_arraylong_operations,/* default base directory file-ops */
1409 NULL,/* create */
1410 NULL,/* lookup */
1411 NULL,/* link */
1412 NULL,/* unlink */
1413 NULL,/* symlink */
1414 NULL,/* mkdir */
1415 NULL,/* rmdir */
1416 NULL,/* mknod */
1417 NULL,/* rename */
1418 NULL,/* readlink */
1419 NULL,/* follow_link */
1420 NULL,/* readpage */
1421 NULL,/* writepage */
1422 NULL,/* bmap */
1423 NULL,/* truncate */
1424 NULL /* permission */
close