source: mainline/kernel/generic/src/ps/ps.c@ 175ad5c6

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 175ad5c6 was 07640dfd, checked in by Stanislav Kozina <stanislav.kozina@…>, 15 years ago

Small changes on kernel & user accounting.

  • Property mode set to 100644
File size: 5.4 KB
Line 
1/*
2 * Copyright (c) 2010 Stanislav Kozina
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup genericps
30 * @{
31 */
32
33/**
34 * @file
35 * @brief Process listing.
36 */
37
38#include <proc/task.h>
39#include <proc/thread.h>
40#include <ps/ps.h>
41#include <ps/taskinfo.h>
42#include <adt/avl.h>
43#include <synch/waitq.h>
44#include <syscall/copy.h>
45#include <atomic.h>
46
47static size_t count;
48static size_t max_count;
49static task_t *selected_task;
50
51#define WRITE_TASK_ID(dst, i, src) copy_to_uspace(dst + i, src, sizeof(task_id_t))
52#define WRITE_THREAD_INFO(dst, i, src) copy_to_uspace(dst+i, src, sizeof(thread_info_t))
53
54static bool task_walker(avltree_node_t *node, void *arg)
55{
56 task_t *t = avltree_get_instance(node, task_t, tasks_tree_node);
57 task_id_t *ids = (task_id_t *)arg;
58
59 spinlock_lock(&t->lock);
60
61 ++count;
62 if (count > max_count) {
63 spinlock_unlock(&t->lock);
64 return false;
65 }
66
67 WRITE_TASK_ID(ids, count - 1, &t->taskid);
68
69 spinlock_unlock(&t->lock);
70 return true;
71}
72
73size_t sys_ps_get_tasks(task_id_t *uspace_ids, size_t size)
74{
75 ipl_t ipl;
76
77 /* Messing with task structures, avoid deadlock */
78 ipl = interrupts_disable();
79 spinlock_lock(&tasks_lock);
80
81 count = 0;
82 max_count = size / sizeof(task_id_t);
83 avltree_walk(&tasks_tree, task_walker, uspace_ids);
84
85 spinlock_unlock(&tasks_lock);
86 interrupts_restore(ipl);
87
88 return count;
89}
90
91static size_t get_pages_count(as_t *as)
92{
93 mutex_lock(&as->lock);
94
95 size_t result = 0;
96
97 link_t *cur;
98 for (cur = as->as_area_btree.leaf_head.next;
99 cur != &as->as_area_btree.leaf_head; cur = cur->next) {
100 btree_node_t *node;
101
102 node = list_get_instance(cur, btree_node_t, leaf_link);
103
104 unsigned int i;
105 for (i = 0; i < node->keys; i++) {
106 as_area_t *area = node->value[i];
107
108 mutex_lock(&area->lock);
109 result += area->pages;
110 mutex_unlock(&area->lock);
111 }
112 }
113
114 mutex_unlock(&as->lock);
115
116 return result;
117}
118
119int sys_ps_get_task_info(task_id_t *uspace_id, task_info_t *uspace_info)
120{
121 ipl_t ipl;
122 ipl = interrupts_disable();
123
124 task_id_t id;
125 copy_from_uspace(&id, uspace_id, sizeof(task_id_t));
126
127 spinlock_lock(&tasks_lock);
128 task_t *t = task_find_by_id(id);
129 spinlock_lock(&t->lock);
130 spinlock_unlock(&tasks_lock);
131
132 copy_to_uspace(uspace_info->name, t->name, sizeof(t->name));
133
134 uint64_t ucycles;
135 uint64_t kcycles;
136 uint64_t cycles = task_get_accounting(t, &ucycles, &kcycles);
137 copy_to_uspace(&uspace_info->cycles, &cycles, sizeof(cycles));
138 copy_to_uspace(&uspace_info->ucycles, &ucycles, sizeof(cycles));
139 copy_to_uspace(&uspace_info->kcycles, &kcycles, sizeof(cycles));
140
141 size_t pages = get_pages_count(t->as);
142 copy_to_uspace(&uspace_info->pages, &pages, sizeof(pages));
143
144 int thread_count = atomic_get(&t->refcount);
145 copy_to_uspace(&uspace_info->thread_count, &thread_count, sizeof(thread_count));
146
147 spinlock_unlock(&t->lock);
148 interrupts_restore(ipl);
149 return 0;
150}
151
152static bool thread_walker(avltree_node_t *node, void *arg)
153{
154 thread_t *t = avltree_get_instance(node, thread_t, threads_tree_node);
155 thread_info_t *infos = (thread_info_t *)arg;
156 thread_info_t result;
157
158 spinlock_lock(&t->lock);
159
160 if (t->task != selected_task) {
161 spinlock_unlock(&t->lock);
162 return true;
163 }
164
165 ++count;
166 if (count > max_count) {
167 spinlock_unlock(&t->lock);
168 return false;
169 }
170
171 result.tid = t->tid;
172 result.state = t->state;
173 result.priority = t->priority;
174 result.cycles = t->cycles;
175 result.ucycles = t->ucycles;
176 result.kcycles = t->kcycles;
177
178 if (t->cpu)
179 result.cpu = t->cpu->id;
180 else
181 result.cpu = -1;
182
183 WRITE_THREAD_INFO(infos, count - 1, &result);
184
185 spinlock_unlock(&t->lock);
186 return true;
187}
188
189int sys_ps_get_threads(task_id_t *uspace_id, thread_info_t *uspace_infos, size_t size)
190{
191 ipl_t ipl;
192 ipl = interrupts_disable();
193
194 task_id_t id;
195 copy_from_uspace(&id, uspace_id, sizeof(task_id_t));
196 spinlock_lock(&tasks_lock);
197 selected_task = task_find_by_id(id);
198 spinlock_unlock(&tasks_lock);
199
200 if (!selected_task) {
201 return 0;
202 }
203
204 spinlock_lock(&threads_lock);
205
206 count = 0;
207 max_count = size / sizeof(thread_info_t);
208 avltree_walk(&threads_tree, thread_walker, uspace_infos);
209
210 spinlock_unlock(&threads_lock);
211 interrupts_restore(ipl);
212 return count;
213}
214
215/** @}
216 */
Note: See TracBrowser for help on using the repository browser.