~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/proc/array.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  linux/fs/proc/array.c
  3  *
  4  *  Copyright (C) 1992  by Linus Torvalds
  5  *  based on ideas by Darren Senn
  6  *
  7  * Fixes:
  8  * Michael. K. Johnson: stat,statm extensions.
  9  *                      <johnsonm@stolaf.edu>
 10  *
 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>
 16  *
 17  * Danny ter Haar    :  added cpuinfo
 18  *                      <dth@cistron.nl>
 19  *
 20  * Alessandro Rubini :  profile extension.
 21  *                      <rubini@ipvvis.unipv.it>
 22  *
 23  * Jeff Tranter      :  added BogoMips field to cpuinfo
 24  *                      <Jeff_Tranter@Mitel.COM>
 25  *
 26  * Bruno Haible      :  remove 4K limit for the maps file
 27  *                      <haible@ma2s2.mathematik.uni-karlsruhe.de>
 28  *
 29  * Yves Arrouye      :  remove removal of trailing spaces in get_array.
 30  *                      <Yves.Arrouye@marin.fdn.fr>
 31  *
 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>
 38  *
 39  * aeb@cwi.nl        :  /proc/partitions
 40  *
 41  *
 42  * Alan Cox          :  security fixes.
 43  *                      <Alan.Cox@linux.org>
 44  *
 45  * Al Viro           :  safe handling of mm_struct
 46  *
 47  * Gerhard Wichert   :  added BIGMEM support
 48  * Siemens AG           <Gerhard.Wichert@pdb.siemens.de>
 49  *
 50  * Al Viro & Jeff Garzik :  moved most of the thing into base.c and
 51  *                       :  proc_misc.c. The rest may eventually go into
 52  *                       :  base.c too.
 53  */
 54 
 55 #include <linux/config.h>
 56 #include <linux/types.h>
 57 #include <linux/errno.h>
 58 #include <linux/sched.h>
 59 #include <linux/kernel.h>
 60 #include <linux/kernel_stat.h>
 61 #include <linux/tty.h>
 62 #include <linux/string.h>
 63 #include <linux/mman.h>
 64 #include <linux/proc_fs.h>
 65 #include <linux/ioport.h>
 66 #include <linux/mm.h>
 67 #include <linux/pagemap.h>
 68 #include <linux/swap.h>
 69 #include <linux/slab.h>
 70 #include <linux/smp.h>
 71 #include <linux/signal.h>
 72 #include <linux/highmem.h>
 73 
 74 #include <asm/uaccess.h>
 75 #include <asm/pgtable.h>
 76 #include <asm/io.h>
 77 #include <asm/processor.h>
 78 
 79 /* Gcc optimizes away "strlen(x)" for constant x */
 80 #define ADDBUF(buffer, string) \
 81 do { memcpy(buffer, string, strlen(string)); \
 82      buffer += strlen(string); } while (0)
 83 
 84 static inline char * task_name(struct task_struct *p, char * buf)
 85 {
 86         int i;
 87         char * name;
 88 
 89         ADDBUF(buf, "Name:\t");
 90         name = p->comm;
 91         i = sizeof(p->comm);
 92         do {
 93                 unsigned char c = *name;
 94                 name++;
 95                 i--;
 96                 *buf = c;
 97                 if (!c)
 98                         break;
 99                 if (c == '\\') {
100                         buf[1] = c;
101                         buf += 2;
102                         continue;
103                 }
104                 if (c == '\n') {
105                         buf[0] = '\\';
106                         buf[1] = 'n';
107                         buf += 2;
108                         continue;
109                 }
110                 buf++;
111         } while (i);
112         *buf = '\n';
113         return buf+1;
114 }
115 
116 /*
117  * The task state array is a strange "bitmap" of
118  * reasons to sleep. Thus "running" is zero, and
119  * you can test for combinations of others with
120  * simple bit tests.
121  */
122 static const char *task_state_array[] = {
123         "R (running)",          /*  0 */
124         "S (sleeping)",         /*  1 */
125         "D (disk sleep)",       /*  2 */
126         "Z (zombie)",           /*  4 */
127         "T (stopped)",          /*  8 */
128         "W (paging)"            /* 16 */
129 };
130 
131 static inline const char * get_task_state(struct task_struct *tsk)
132 {
133         unsigned int state = tsk->state & (TASK_RUNNING |
134                                            TASK_INTERRUPTIBLE |
135                                            TASK_UNINTERRUPTIBLE |
136                                            TASK_ZOMBIE |
137                                            TASK_STOPPED);
138         const char **p = &task_state_array[0];
139 
140         while (state) {
141                 p++;
142                 state >>= 1;
143         }
144         return *p;
145 }
146 
147 static inline char * task_state(struct task_struct *p, char *buffer)
148 {
149         int g;
150 
151         read_lock(&tasklist_lock);
152         buffer += sprintf(buffer,
153                 "State:\t%s\n"
154                 "Pid:\t%d\n"
155                 "PPid:\t%d\n"
156                 "TracerPid:\t%d\n"
157                 "Uid:\t%d\t%d\t%d\t%d\n"
158                 "Gid:\t%d\t%d\t%d\t%d\n",
159                 get_task_state(p),
160                 p->pid, p->p_opptr->pid, p->p_pptr->pid != p->p_opptr->pid ? p->p_pptr->pid : 0,
161                 p->uid, p->euid, p->suid, p->fsuid,
162                 p->gid, p->egid, p->sgid, p->fsgid);
163         read_unlock(&tasklist_lock);    
164         task_lock(p);
165         buffer += sprintf(buffer,
166                 "FDSize:\t%d\n"
167                 "Groups:\t",
168                 p->files ? p->files->max_fds : 0);
169         task_unlock(p);
170 
171         for (g = 0; g < p->ngroups; g++)
172                 buffer += sprintf(buffer, "%d ", p->groups[g]);
173 
174         buffer += sprintf(buffer, "\n");
175         return buffer;
176 }
177 
178 static inline char * task_mem(struct mm_struct *mm, char *buffer)
179 {
180         struct vm_area_struct * vma;
181         unsigned long data = 0, stack = 0;
182         unsigned long exec = 0, lib = 0;
183 
184         down(&mm->mmap_sem);
185         for (vma = mm->mmap; vma; vma = vma->vm_next) {
186                 unsigned long len = (vma->vm_end - vma->vm_start) >> 10;
187                 if (!vma->vm_file) {
188                         data += len;
189                         if (vma->vm_flags & VM_GROWSDOWN)
190                                 stack += len;
191                         continue;
192                 }
193                 if (vma->vm_flags & VM_WRITE)
194                         continue;
195                 if (vma->vm_flags & VM_EXEC) {
196                         exec += len;
197                         if (vma->vm_flags & VM_EXECUTABLE)
198                                 continue;
199                         lib += len;
200                 }
201         }
202         buffer += sprintf(buffer,
203                 "VmSize:\t%8lu kB\n"
204                 "VmLck:\t%8lu kB\n"
205                 "VmRSS:\t%8lu kB\n"
206                 "VmData:\t%8lu kB\n"
207                 "VmStk:\t%8lu kB\n"
208                 "VmExe:\t%8lu kB\n"
209                 "VmLib:\t%8lu kB\n",
210                 mm->total_vm << (PAGE_SHIFT-10),
211                 mm->locked_vm << (PAGE_SHIFT-10),
212                 mm->rss << (PAGE_SHIFT-10),
213                 data - stack, stack,
214                 exec - lib, lib);
215         up(&mm->mmap_sem);
216         return buffer;
217 }
218 
219 static void collect_sigign_sigcatch(struct task_struct *p, sigset_t *ign,
220                                     sigset_t *catch)
221 {
222         struct k_sigaction *k;
223         int i;
224 
225         sigemptyset(ign);
226         sigemptyset(catch);
227 
228         if (p->sig) {
229                 k = p->sig->action;
230                 for (i = 1; i <= _NSIG; ++i, ++k) {
231                         if (k->sa.sa_handler == SIG_IGN)
232                                 sigaddset(ign, i);
233                         else if (k->sa.sa_handler != SIG_DFL)
234                                 sigaddset(catch, i);
235                 }
236         }
237 }
238 
239 static inline char * task_sig(struct task_struct *p, char *buffer)
240 {
241         sigset_t ign, catch;
242 
243         buffer += sprintf(buffer, "SigPnd:\t");
244         buffer = render_sigset_t(&p->pending.signal, buffer);
245         *buffer++ = '\n';
246         buffer += sprintf(buffer, "SigBlk:\t");
247         buffer = render_sigset_t(&p->blocked, buffer);
248         *buffer++ = '\n';
249 
250         collect_sigign_sigcatch(p, &ign, &catch);
251         buffer += sprintf(buffer, "SigIgn:\t");
252         buffer = render_sigset_t(&ign, buffer);
253         *buffer++ = '\n';
254         buffer += sprintf(buffer, "SigCgt:\t"); /* Linux 2.0 uses "SigCgt" */
255         buffer = render_sigset_t(&catch, buffer);
256         *buffer++ = '\n';
257 
258         return buffer;
259 }
260 
261 extern inline char *task_cap(struct task_struct *p, char *buffer)
262 {
263     return buffer + sprintf(buffer, "CapInh:\t%016x\n"
264                             "CapPrm:\t%016x\n"
265                             "CapEff:\t%016x\n",
266                             cap_t(p->cap_inheritable),
267                             cap_t(p->cap_permitted),
268                             cap_t(p->cap_effective));
269 }
270 
271 
272 int proc_pid_status(struct task_struct *task, char * buffer)
273 {
274         char * orig = buffer;
275         struct mm_struct *mm;
276 #if defined(CONFIG_ARCH_S390)
277         int line,len;
278 #endif
279 
280         buffer = task_name(task, buffer);
281         buffer = task_state(task, buffer);
282         task_lock(task);
283         mm = task->mm;
284         if(mm)
285                 atomic_inc(&mm->mm_users);
286         task_unlock(task);
287         if (mm) {
288                 buffer = task_mem(mm, buffer);
289                 mmput(mm);
290         }
291         buffer = task_sig(task, buffer);
292         buffer = task_cap(task, buffer);
293 #if defined(CONFIG_ARCH_S390)
294         for(line=0;(len=sprintf_regs(line,buffer,task,NULL,NULL))!=0;line++)
295                 buffer+=len;
296 #endif
297         return buffer - orig;
298 }
299 
300 int proc_pid_stat(struct task_struct *task, char * buffer)
301 {
302         unsigned long vsize, eip, esp, wchan;
303         long priority, nice;
304         int tty_pgrp = -1, tty_nr = 0;
305         sigset_t sigign, sigcatch;
306         char state;
307         int res;
308         pid_t ppid;
309         struct mm_struct *mm;
310 
311         state = *get_task_state(task);
312         vsize = eip = esp = 0;
313         task_lock(task);
314         mm = task->mm;
315         if(mm)
316                 atomic_inc(&mm->mm_users);
317         if (task->tty) {
318                 tty_pgrp = task->tty->pgrp;
319                 tty_nr = kdev_t_to_nr(task->tty->device);
320         }
321         task_unlock(task);
322         if (mm) {
323                 struct vm_area_struct *vma;
324                 down(&mm->mmap_sem);
325                 vma = mm->mmap;
326                 while (vma) {
327                         vsize += vma->vm_end - vma->vm_start;
328                         vma = vma->vm_next;
329                 }
330                 eip = KSTK_EIP(task);
331                 esp = KSTK_ESP(task);
332                 up(&mm->mmap_sem);
333         }
334 
335         wchan = get_wchan(task);
336 
337         collect_sigign_sigcatch(task, &sigign, &sigcatch);
338 
339         /* scale priority and nice values from timeslices to -20..20 */
340         /* to make it look like a "normal" Unix priority/nice value  */
341         priority = task->counter;
342         priority = 20 - (priority * 10 + DEF_COUNTER / 2) / DEF_COUNTER;
343         nice = task->nice;
344 
345         read_lock(&tasklist_lock);
346         ppid = task->p_opptr->pid;
347         read_unlock(&tasklist_lock);
348         res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
349 %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu \
350 %lu %lu %lu %lu %lu %lu %lu %lu %d %d\n",
351                 task->pid,
352                 task->comm,
353                 state,
354                 ppid,
355                 task->pgrp,
356                 task->session,
357                 tty_nr,
358                 tty_pgrp,
359                 task->flags,
360                 task->min_flt,
361                 task->cmin_flt,
362                 task->maj_flt,
363                 task->cmaj_flt,
364                 task->times.tms_utime,
365                 task->times.tms_stime,
366                 task->times.tms_cutime,
367                 task->times.tms_cstime,
368                 priority,
369                 nice,
370                 0UL /* removed */,
371                 task->it_real_value,
372                 task->start_time,
373                 vsize,
374                 mm ? mm->rss : 0, /* you might want to shift this left 3 */
375                 task->rlim[RLIMIT_RSS].rlim_cur,
376                 mm ? mm->start_code : 0,
377                 mm ? mm->end_code : 0,
378                 mm ? mm->start_stack : 0,
379                 esp,
380                 eip,
381                 /* The signal information here is obsolete.
382                  * It must be decimal for Linux 2.0 compatibility.
383                  * Use /proc/#/status for real-time signals.
384                  */
385                 task->pending.signal.sig[0] & 0x7fffffffUL,
386                 task->blocked.sig[0] & 0x7fffffffUL,
387                 sigign      .sig[0] & 0x7fffffffUL,
388                 sigcatch    .sig[0] & 0x7fffffffUL,
389                 wchan,
390                 task->nswap,
391                 task->cnswap,
392                 task->exit_signal,
393                 task->processor);
394         if(mm)
395                 mmput(mm);
396         return res;
397 }
398                 
399 static inline void statm_pte_range(pmd_t * pmd, unsigned long address, unsigned long size,
400         int * pages, int * shared, int * dirty, int * total)
401 {
402         pte_t * pte;
403         unsigned long end;
404 
405         if (pmd_none(*pmd))
406                 return;
407         if (pmd_bad(*pmd)) {
408                 pmd_ERROR(*pmd);
409                 pmd_clear(pmd);
410                 return;
411         }
412         pte = pte_offset(pmd, address);
413         address &= ~PMD_MASK;
414         end = address + size;
415         if (end > PMD_SIZE)
416                 end = PMD_SIZE;
417         do {
418                 pte_t page = *pte;
419                 struct page *ptpage;
420 
421                 address += PAGE_SIZE;
422                 pte++;
423                 if (pte_none(page))
424                         continue;
425                 ++*total;
426                 if (!pte_present(page))
427                         continue;
428                 ++*pages;
429                 if (pte_dirty(page))
430                         ++*dirty;
431                 ptpage = pte_page(page);
432                 if ((!VALID_PAGE(ptpage)) || 
433                                         PageReserved(ptpage))
434                         continue;
435                 if (page_count(pte_page(page)) > 1)
436                         ++*shared;
437         } while (address < end);
438 }
439 
440 static inline void statm_pmd_range(pgd_t * pgd, unsigned long address, unsigned long size,
441         int * pages, int * shared, int * dirty, int * total)
442 {
443         pmd_t * pmd;
444         unsigned long end;
445 
446         if (pgd_none(*pgd))
447                 return;
448         if (pgd_bad(*pgd)) {
449                 pgd_ERROR(*pgd);
450                 pgd_clear(pgd);
451                 return;
452         }
453         pmd = pmd_offset(pgd, address);
454         address &= ~PGDIR_MASK;
455         end = address + size;
456         if (end > PGDIR_SIZE)
457                 end = PGDIR_SIZE;
458         do {
459                 statm_pte_range(pmd, address, end - address, pages, shared, dirty, total);
460                 address = (address + PMD_SIZE) & PMD_MASK;
461                 pmd++;
462         } while (address < end);
463 }
464 
465 static void statm_pgd_range(pgd_t * pgd, unsigned long address, unsigned long end,
466         int * pages, int * shared, int * dirty, int * total)
467 {
468         while (address < end) {
469                 statm_pmd_range(pgd, address, end - address, pages, shared, dirty, total);
470                 address = (address + PGDIR_SIZE) & PGDIR_MASK;
471                 pgd++;
472         }
473 }
474 
475 int proc_pid_statm(struct task_struct *task, char * buffer)
476 {
477         struct mm_struct *mm;
478         int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
479 
480         task_lock(task);
481         mm = task->mm;
482         if(mm)
483                 atomic_inc(&mm->mm_users);
484         task_unlock(task);
485         if (mm) {
486                 struct vm_area_struct * vma;
487                 down(&mm->mmap_sem);
488                 vma = mm->mmap;
489                 while (vma) {
490                         pgd_t *pgd = pgd_offset(mm, vma->vm_start);
491                         int pages = 0, shared = 0, dirty = 0, total = 0;
492 
493                         statm_pgd_range(pgd, vma->vm_start, vma->vm_end, &pages, &shared, &dirty, &total);
494                         resident += pages;
495                         share += shared;
496                         dt += dirty;
497                         size += total;
498                         if (vma->vm_flags & VM_EXECUTABLE)
499                                 trs += pages;   /* text */
500                         else if (vma->vm_flags & VM_GROWSDOWN)
501                                 drs += pages;   /* stack */
502                         else if (vma->vm_end > 0x60000000)
503                                 lrs += pages;   /* library */
504                         else
505                                 drs += pages;
506                         vma = vma->vm_next;
507                 }
508                 up(&mm->mmap_sem);
509                 mmput(mm);
510         }
511         return sprintf(buffer,"%d %d %d %d %d %d %d\n",
512                        size, resident, share, trs, lrs, drs, dt);
513 }
514 
515 /*
516  * The way we support synthetic files > 4K
517  * - without storing their contents in some buffer and
518  * - without walking through the entire synthetic file until we reach the
519  *   position of the requested data
520  * is to cleverly encode the current position in the file's f_pos field.
521  * There is no requirement that a read() call which returns `count' bytes
522  * of data increases f_pos by exactly `count'.
523  *
524  * This idea is Linus' one. Bruno implemented it.
525  */
526 
527 /*
528  * For the /proc/<pid>/maps file, we use fixed length records, each containing
529  * a single line.
530  */
531 #define MAPS_LINE_LENGTH        4096
532 #define MAPS_LINE_SHIFT         12
533 /*
534  * f_pos = (number of the vma in the task->mm->mmap list) * MAPS_LINE_LENGTH
535  *         + (index into the line)
536  */
537 /* for systems with sizeof(void*) == 4: */
538 #define MAPS_LINE_FORMAT4         "%08lx-%08lx %s %08lx %s %lu"
539 #define MAPS_LINE_MAX4  49 /* sum of 8  1  8  1 4 1 8 1 5 1 10 1 */
540 
541 /* for systems with sizeof(void*) == 8: */
542 #define MAPS_LINE_FORMAT8         "%016lx-%016lx %s %016lx %s %lu"
543 #define MAPS_LINE_MAX8  73 /* sum of 16  1  16  1 4 1 16 1 5 1 10 1 */
544 
545 #define MAPS_LINE_MAX   MAPS_LINE_MAX8
546 
547 
548 ssize_t proc_pid_read_maps (struct task_struct *task, struct file * file, char * buf,
549                           size_t count, loff_t *ppos)
550 {
551         struct mm_struct *mm;
552         struct vm_area_struct * map, * next;
553         char * destptr = buf, * buffer;
554         loff_t lineno;
555         ssize_t column, i;
556         int volatile_task;
557         long retval;
558 
559         /*
560          * We might sleep getting the page, so get it first.
561          */
562         retval = -ENOMEM;
563         buffer = (char*)__get_free_page(GFP_KERNEL);
564         if (!buffer)
565                 goto out;
566 
567         if (count == 0)
568                 goto getlen_out;
569         task_lock(task);
570         mm = task->mm;
571         if (mm)
572                 atomic_inc(&mm->mm_users);
573         task_unlock(task);
574         if (!mm)
575                 goto getlen_out;
576 
577         /* Check whether the mmaps could change if we sleep */
578         volatile_task = (task != current || atomic_read(&mm->mm_users) > 2);
579 
580         /* decode f_pos */
581         lineno = *ppos >> MAPS_LINE_SHIFT;
582         column = *ppos & (MAPS_LINE_LENGTH-1);
583 
584         /* quickly go to line lineno */
585         down(&mm->mmap_sem);
586         for (map = mm->mmap, i = 0; map && (i < lineno); map = map->vm_next, i++)
587                 continue;
588 
589         for ( ; map ; map = next ) {
590                 /* produce the next line */
591                 char *line;
592                 char str[5], *cp = str;
593                 int flags;
594                 kdev_t dev;
595                 unsigned long ino;
596                 int maxlen = (sizeof(void*) == 4) ?
597                         MAPS_LINE_MAX4 :  MAPS_LINE_MAX8;
598                 int len;
599 
600                 /*
601                  * Get the next vma now (but it won't be used if we sleep).
602                  */
603                 next = map->vm_next;
604                 flags = map->vm_flags;
605 
606                 *cp++ = flags & VM_READ ? 'r' : '-';
607                 *cp++ = flags & VM_WRITE ? 'w' : '-';
608                 *cp++ = flags & VM_EXEC ? 'x' : '-';
609                 *cp++ = flags & VM_MAYSHARE ? 's' : 'p';
610                 *cp++ = 0;
611 
612                 dev = 0;
613                 ino = 0;
614                 if (map->vm_file != NULL) {
615                         dev = map->vm_file->f_dentry->d_inode->i_dev;
616                         ino = map->vm_file->f_dentry->d_inode->i_ino;
617                         line = d_path(map->vm_file->f_dentry,
618                                       map->vm_file->f_vfsmnt,
619                                       buffer, PAGE_SIZE);
620                         buffer[PAGE_SIZE-1] = '\n';
621                         line -= maxlen;
622                         if(line < buffer)
623                                 line = buffer;
624                 } else
625                         line = buffer;
626 
627                 len = sprintf(line,
628                               sizeof(void*) == 4 ? MAPS_LINE_FORMAT4 : MAPS_LINE_FORMAT8,
629                               map->vm_start, map->vm_end, str, map->vm_pgoff << PAGE_SHIFT,
630                               kdevname(dev), ino);
631 
632                 if(map->vm_file) {
633                         for(i = len; i < maxlen; i++)
634                                 line[i] = ' ';
635                         len = buffer + PAGE_SIZE - line;
636                 } else
637                         line[len++] = '\n';
638                 if (column >= len) {
639                         column = 0; /* continue with next line at column 0 */
640                         lineno++;
641                         continue; /* we haven't slept */
642                 }
643 
644                 i = len-column;
645                 if (i > count)
646                         i = count;
647                 up(&mm->mmap_sem);
648                 copy_to_user(destptr, line+column, i); /* may have slept */
649                 down(&mm->mmap_sem);
650                 destptr += i;
651                 count   -= i;
652                 column  += i;
653                 if (column >= len) {
654                         column = 0; /* next time: next line at column 0 */
655                         lineno++;
656                 }
657 
658                 /* done? */
659                 if (count == 0)
660                         break;
661 
662                 /* By writing to user space, we might have slept.
663                  * Stop the loop, to avoid a race condition.
664                  */
665                 if (volatile_task)
666                         break;
667         }
668         up(&mm->mmap_sem);
669 
670         /* encode f_pos */
671         *ppos = (lineno << MAPS_LINE_SHIFT) + column;
672         mmput(mm);
673 
674 getlen_out:
675         retval = destptr - buf;
676         free_page((unsigned long)buffer);
677 out:
678         return retval;
679 }
680 
681 #ifdef CONFIG_SMP
682 int proc_pid_cpu(struct task_struct *task, char * buffer)
683 {
684         int i, len;
685 
686         len = sprintf(buffer,
687                 "cpu  %lu %lu\n",
688                 task->times.tms_utime,
689                 task->times.tms_stime);
690                 
691         for (i = 0 ; i < smp_num_cpus; i++)
692                 len += sprintf(buffer + len, "cpu%d %lu %lu\n",
693                         i,
694                         task->per_cpu_utime[cpu_logical_map(i)],
695                         task->per_cpu_stime[cpu_logical_map(i)]);
696 
697         return len;
698 }
699 #endif
700 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.