This source file includes following definitions.
- get_loadavg
- get_uptime
- get_meminfo
- get_version
- get_task
- get_phys_addr
- get_array
- get_env
- get_arg
- get_wchan
- get_stat
- get_statm
- array_read
1
2
3
4
5
6
7
8
9
10 #include <linux/types.h>
11 #include <linux/errno.h>
12 #include <linux/sched.h>
13 #include <linux/kernel.h>
14 #include <linux/tty.h>
15
16 #include <asm/segment.h>
17 #include <asm/io.h>
18
19 #define LOAD_INT(x) ((x) >> FSHIFT)
20 #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
21
22 #ifdef CONFIG_DEBUG_MALLOC
23 int get_malloc(char * buffer);
24 #endif
25
26 static int get_loadavg(char * buffer)
27 {
28 int a, b, c;
29
30 a = avenrun[0] + (FIXED_1/200);
31 b = avenrun[1] + (FIXED_1/200);
32 c = avenrun[2] + (FIXED_1/200);
33 return sprintf(buffer,"%d.%02d %d.%02d %d.%02d\n",
34 LOAD_INT(a), LOAD_FRAC(a),
35 LOAD_INT(b), LOAD_FRAC(b),
36 LOAD_INT(c), LOAD_FRAC(c));
37 }
38
39 static int get_uptime(char * buffer)
40 {
41 unsigned long uptime;
42 unsigned long idle;
43
44 uptime = jiffies + jiffies_offset;
45 idle = task[0]->utime + task[0]->stime;
46 return sprintf(buffer,"%d.%02d %d.%02d\n",
47 uptime / HZ,
48 uptime % HZ,
49 idle / HZ,
50 idle % HZ);
51 }
52
53 static int get_meminfo(char * buffer)
54 {
55 struct sysinfo i;
56
57 si_meminfo(&i);
58 si_swapinfo(&i);
59 return sprintf(buffer, " total: used: free: shared: buffers:\n"
60 "Mem: %8d %8d %8d %8d %8d\n"
61 "Swap: %8d %8d %8d\n",
62 i.totalram, i.totalram-i.freeram, i.freeram, i.sharedram, i.bufferram,
63 i.totalswap, i.totalswap-i.freeswap, i.freeswap);
64 }
65
66 static int get_version(char * buffer)
67 {
68 extern char *linux_banner;
69
70 strcpy(buffer, linux_banner);
71 return strlen(buffer);
72 }
73
74 static struct task_struct ** get_task(pid_t pid)
75 {
76 struct task_struct ** p;
77
78 p = task;
79 while (++p < task+NR_TASKS) {
80 if (*p && (*p)->pid == pid)
81 return p;
82 }
83 return NULL;
84 }
85
86 static unsigned long get_phys_addr(struct task_struct ** p, unsigned long ptr)
87 {
88 unsigned long page;
89
90 if (!p || !*p || ptr >= TASK_SIZE)
91 return 0;
92 page = *PAGE_DIR_OFFSET((*p)->tss.cr3,ptr);
93 if (!(page & 1))
94 return 0;
95 page &= PAGE_MASK;
96 page += PAGE_PTR(ptr);
97 page = *(unsigned long *) page;
98 if (!(page & 1))
99 return 0;
100 page &= PAGE_MASK;
101 page += ptr & ~PAGE_MASK;
102 return page;
103 }
104
105 static int get_array(struct task_struct ** p, unsigned long start, unsigned long end, char * buffer)
106 {
107 unsigned long addr;
108 int size = 0, result = 0;
109 char c;
110
111 if (start >= end)
112 return result;
113 for (;;) {
114 addr = get_phys_addr(p, start);
115 if (!addr)
116 return result;
117 do {
118 c = *(char *) addr;
119 if (!c)
120 result = size;
121 if (size < PAGE_SIZE)
122 buffer[size++] = c;
123 else
124 return result;
125 addr++;
126 start++;
127 if (start >= end)
128 return result;
129 } while (!(addr & ~PAGE_MASK));
130 }
131 }
132
133 static int get_env(int pid, char * buffer)
134 {
135 struct task_struct ** p = get_task(pid);
136
137 if (!p || !*p)
138 return 0;
139 return get_array(p, (*p)->env_start, (*p)->env_end, buffer);
140 }
141
142 static int get_arg(int pid, char * buffer)
143 {
144 struct task_struct ** p = get_task(pid);
145
146 if (!p || !*p)
147 return 0;
148 return get_array(p, (*p)->arg_start, (*p)->arg_end, buffer);
149 }
150
151 static unsigned long get_wchan(struct task_struct *p)
152 {
153 unsigned long ebp, eip;
154 unsigned long stack_page;
155 int count = 0;
156
157 if (!p || p == current || p->state == TASK_RUNNING)
158 return 0;
159 stack_page = p->kernel_stack_page;
160 if (!stack_page)
161 return 0;
162 ebp = p->tss.ebp;
163 do {
164 if (ebp < stack_page || ebp >= 4092+stack_page)
165 return 0;
166 eip = *(unsigned long *) (ebp+4);
167 if ((void *)eip != sleep_on &&
168 (void *)eip != interruptible_sleep_on)
169 return eip;
170 ebp = *(unsigned long *) ebp;
171 } while (count++ < 16);
172 return 0;
173 }
174
175 #define KSTK_EIP(stack) (((unsigned long *)stack)[1019])
176 #define KSTK_ESP(stack) (((unsigned long *)stack)[1022])
177
178 static int get_stat(int pid, char * buffer)
179 {
180 struct task_struct ** p = get_task(pid);
181 unsigned long sigignore=0, sigcatch=0, bit=1, wchan;
182 unsigned long vsize, eip, esp;
183 int i,tty_pgrp;
184 char state;
185
186 if (!p || !*p)
187 return 0;
188 if ((*p)->state < 0 || (*p)->state > 5)
189 state = '.';
190 else
191 state = "RSDZTD"[(*p)->state];
192 eip = esp = 0;
193 vsize = (*p)->kernel_stack_page;
194 if (vsize) {
195 eip = KSTK_EIP(vsize);
196 esp = KSTK_ESP(vsize);
197 vsize = (*p)->brk - (*p)->start_code + PAGE_SIZE-1;
198 if (esp)
199 vsize += TASK_SIZE - esp;
200 }
201 wchan = get_wchan(*p);
202 for(i=0; i<32; ++i) {
203 switch((int) (*p)->sigaction[i].sa_handler) {
204 case 1: sigignore |= bit; break;
205 case 0: break;
206 default: sigcatch |= bit;
207 } bit <<= 1;
208 }
209 tty_pgrp = (*p)->tty;
210 if (tty_pgrp > 0 && tty_table[tty_pgrp])
211 tty_pgrp = tty_table[tty_pgrp]->pgrp;
212 else
213 tty_pgrp = -1;
214 return sprintf(buffer,"%d (%s) %c %d %d %d %d %d %u %u \
215 %u %u %u %d %d %d %d %d %d %u %u %d %u %u %u %u %u %u %u %u %d \
216 %d %d %d %u\n",
217 pid,
218 (*p)->comm,
219 state,
220 (*p)->p_pptr->pid,
221 (*p)->pgrp,
222 (*p)->session,
223 (*p)->tty,
224 tty_pgrp,
225 (*p)->flags,
226 (*p)->min_flt,
227 (*p)->cmin_flt,
228 (*p)->maj_flt,
229 (*p)->cmaj_flt,
230 (*p)->utime,
231 (*p)->stime,
232 (*p)->cutime,
233 (*p)->cstime,
234 (*p)->counter,
235
236 (*p)->priority,
237
238 (*p)->timeout,
239 (*p)->it_real_value,
240 (*p)->start_time,
241 vsize,
242 (*p)->rss,
243 (*p)->rlim[RLIMIT_RSS].rlim_cur,
244 (*p)->start_code,
245 (*p)->end_code,
246 (*p)->start_stack,
247 esp,
248 eip,
249 (*p)->signal,
250 (*p)->blocked,
251 sigignore,
252 sigcatch,
253 wchan);
254 }
255
256 static int get_statm(int pid, char * buffer)
257 {
258 struct task_struct ** p = get_task(pid);
259 int i, tpag;
260 int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
261 unsigned long ptbl, *buf, *pte, *pagedir, map_nr;
262
263 if (!p || !*p)
264 return 0;
265 tpag = (*p)->end_code / PAGE_SIZE;
266 if ((*p)->state != TASK_ZOMBIE) {
267 pagedir = (unsigned long *) (*p)->tss.cr3;
268 for (i = 0; i < 0x300; ++i) {
269 if ((ptbl = pagedir[i]) == 0) {
270 tpag -= PTRS_PER_PAGE;
271 continue;
272 }
273 buf = (unsigned long *)(ptbl & PAGE_MASK);
274 for (pte = buf; pte < (buf + PTRS_PER_PAGE); ++pte) {
275 if (*pte != 0) {
276 ++size;
277 if (*pte & 1) {
278 ++resident;
279 if (tpag > 0)
280 ++trs;
281 else
282 ++drs;
283 if (i >= 15 && i < 0x2f0) {
284 ++lrs;
285 if (*pte & 0x40)
286 ++dt;
287 else
288 --drs;
289 }
290 map_nr = MAP_NR(*pte);
291 if (map_nr < (high_memory / PAGE_SIZE) && mem_map[map_nr] > 1)
292 ++share;
293 }
294 }
295 --tpag;
296 }
297 }
298 }
299 return sprintf(buffer,"%d %d %d %d %d %d %d\n",
300 size, resident, share, trs, lrs, drs, dt);
301 }
302
303 static int array_read(struct inode * inode, struct file * file,char * buf, int count)
304 {
305 char * page;
306 int length;
307 int end;
308 unsigned int type, pid;
309
310 if (count < 0)
311 return -EINVAL;
312 if (!(page = (char*) __get_free_page(GFP_KERNEL)))
313 return -ENOMEM;
314 type = inode->i_ino;
315 pid = type >> 16;
316 type &= 0x0000ffff;
317 switch (type) {
318 case 2:
319 length = get_loadavg(page);
320 break;
321 case 3:
322 length = get_uptime(page);
323 break;
324 case 4:
325 length = get_meminfo(page);
326 break;
327 case 6:
328 length = get_version(page);
329 break;
330 case 9:
331 length = get_env(pid, page);
332 break;
333 case 10:
334 length = get_arg(pid, page);
335 break;
336 case 11:
337 length = get_stat(pid, page);
338 break;
339 case 12:
340 length = get_statm(pid, page);
341 break;
342 #ifdef CONFIG_DEBUG_MALLOC
343 case 13:
344 length = get_malloc(page);
345 break;
346 #endif
347 default:
348 free_page((unsigned long) page);
349 return -EBADF;
350 }
351 if (file->f_pos >= length) {
352 free_page((unsigned long) page);
353 return 0;
354 }
355 if (count + file->f_pos > length)
356 count = length - file->f_pos;
357 end = count + file->f_pos;
358 memcpy_tofs(buf, page + file->f_pos, count);
359 free_page((unsigned long) page);
360 file->f_pos = end;
361 return count;
362 }
363
364 static struct file_operations proc_array_operations = {
365 NULL,
366 array_read,
367 NULL,
368 NULL,
369 NULL,
370 NULL,
371 NULL,
372 NULL,
373 NULL,
374 NULL
375 };
376
377 struct inode_operations proc_array_inode_operations = {
378 &proc_array_operations,
379 NULL,
380 NULL,
381 NULL,
382 NULL,
383 NULL,
384 NULL,
385 NULL,
386 NULL,
387 NULL,
388 NULL,
389 NULL,
390 NULL,
391 NULL,
392 NULL
393 };