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