source: mainline/kernel/generic/src/ps/ps.c@ 452268a1

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

top echoes also task list

  • Property mode set to 100644
File size: 5.5 KB
RevLine 
[18b5402c]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
[8f56d93]132 copy_to_uspace(&uspace_info->taskid, &t->taskid, sizeof(task_id_t));
[18b5402c]133 copy_to_uspace(uspace_info->name, t->name, sizeof(t->name));
134
[a2a00e8]135 uint64_t ucycles;
136 uint64_t kcycles;
137 uint64_t cycles = task_get_accounting(t, &ucycles, &kcycles);
[18b5402c]138 copy_to_uspace(&uspace_info->cycles, &cycles, sizeof(cycles));
[07640dfd]139 copy_to_uspace(&uspace_info->ucycles, &ucycles, sizeof(cycles));
140 copy_to_uspace(&uspace_info->kcycles, &kcycles, sizeof(cycles));
[18b5402c]141
142 size_t pages = get_pages_count(t->as);
143 copy_to_uspace(&uspace_info->pages, &pages, sizeof(pages));
144
145 int thread_count = atomic_get(&t->refcount);
146 copy_to_uspace(&uspace_info->thread_count, &thread_count, sizeof(thread_count));
147
148 spinlock_unlock(&t->lock);
149 interrupts_restore(ipl);
150 return 0;
151}
152
153static bool thread_walker(avltree_node_t *node, void *arg)
154{
155 thread_t *t = avltree_get_instance(node, thread_t, threads_tree_node);
156 thread_info_t *infos = (thread_info_t *)arg;
157 thread_info_t result;
158
159 spinlock_lock(&t->lock);
160
161 if (t->task != selected_task) {
162 spinlock_unlock(&t->lock);
163 return true;
164 }
165
166 ++count;
167 if (count > max_count) {
168 spinlock_unlock(&t->lock);
169 return false;
170 }
171
172 result.tid = t->tid;
173 result.state = t->state;
174 result.priority = t->priority;
175 result.cycles = t->cycles;
[07640dfd]176 result.ucycles = t->ucycles;
177 result.kcycles = t->kcycles;
[18b5402c]178
[34bba0e]179 if (t->cpu)
180 result.cpu = t->cpu->id;
181 else
182 result.cpu = -1;
183
[18b5402c]184 WRITE_THREAD_INFO(infos, count - 1, &result);
185
186 spinlock_unlock(&t->lock);
187 return true;
188}
189
190int sys_ps_get_threads(task_id_t *uspace_id, thread_info_t *uspace_infos, size_t size)
191{
192 ipl_t ipl;
193 ipl = interrupts_disable();
194
195 task_id_t id;
196 copy_from_uspace(&id, uspace_id, sizeof(task_id_t));
197 spinlock_lock(&tasks_lock);
198 selected_task = task_find_by_id(id);
199 spinlock_unlock(&tasks_lock);
200
[34bba0e]201 if (!selected_task) {
202 return 0;
203 }
204
[18b5402c]205 spinlock_lock(&threads_lock);
206
207 count = 0;
208 max_count = size / sizeof(thread_info_t);
209 avltree_walk(&threads_tree, thread_walker, uspace_infos);
210
211 spinlock_unlock(&threads_lock);
212 interrupts_restore(ipl);
213 return count;
214}
215
216/** @}
217 */
Note: See TracBrowser for help on using the repository browser.