source: mainline/kernel/generic/src/ps/ps.c@ 1ba37fa

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

Removed useless cycles sum, using ucycles + kcycles instead.

  • 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#include <errno.h>
47
48static size_t count;
49static size_t max_count;
50static task_t *selected_task;
51
52#define WRITE_TASK_ID(dst, i, src) copy_to_uspace(dst + i, src, sizeof(task_id_t))
53#define WRITE_THREAD_INFO(dst, i, src) copy_to_uspace(dst+i, src, sizeof(thread_info_t))
54
55static bool task_walker(avltree_node_t *node, void *arg)
56{
57 task_t *t = avltree_get_instance(node, task_t, tasks_tree_node);
58 task_id_t *ids = (task_id_t *)arg;
59
60 spinlock_lock(&t->lock);
61
62 ++count;
63 if (count > max_count) {
64 spinlock_unlock(&t->lock);
65 return false;
66 }
67
68 WRITE_TASK_ID(ids, count - 1, &t->taskid);
69
70 spinlock_unlock(&t->lock);
71 return true;
72}
73
74size_t sys_ps_get_tasks(task_id_t *uspace_ids, size_t size)
75{
76 ipl_t ipl;
77
78 /* Messing with task structures, avoid deadlock */
79 ipl = interrupts_disable();
80 spinlock_lock(&tasks_lock);
81
82 count = 0;
83 max_count = size / sizeof(task_id_t);
84 avltree_walk(&tasks_tree, task_walker, uspace_ids);
85
86 spinlock_unlock(&tasks_lock);
87 interrupts_restore(ipl);
88
89 return count;
90}
91
92static size_t get_pages_count(as_t *as)
93{
94 mutex_lock(&as->lock);
95
96 size_t result = 0;
97
98 link_t *cur;
99 for (cur = as->as_area_btree.leaf_head.next;
100 cur != &as->as_area_btree.leaf_head; cur = cur->next) {
101 btree_node_t *node;
102
103 node = list_get_instance(cur, btree_node_t, leaf_link);
104
105 unsigned int i;
106 for (i = 0; i < node->keys; i++) {
107 as_area_t *area = node->value[i];
108
109 mutex_lock(&area->lock);
110 result += area->pages;
111 mutex_unlock(&area->lock);
112 }
113 }
114
115 mutex_unlock(&as->lock);
116
117 return result;
118}
119
120int sys_ps_get_task_info(task_id_t *uspace_id, task_info_t *uspace_info)
121{
122 ipl_t ipl;
123 ipl = interrupts_disable();
124
125 task_id_t id;
126 copy_from_uspace(&id, uspace_id, sizeof(task_id_t));
127
128 spinlock_lock(&tasks_lock);
129 task_t *t = task_find_by_id(id);
130 if (!t) {
131 spinlock_unlock(&tasks_lock);
132 return ENOENT;
133 }
134 spinlock_lock(&t->lock);
135 spinlock_unlock(&tasks_lock);
136
137 copy_to_uspace(&uspace_info->taskid, &t->taskid, sizeof(task_id_t));
138 copy_to_uspace(uspace_info->name, t->name, sizeof(t->name));
139
140 uint64_t ucycles;
141 uint64_t kcycles;
142 task_get_accounting(t, &ucycles, &kcycles);
143 copy_to_uspace(&uspace_info->ucycles, &ucycles, sizeof(uint64_t));
144 copy_to_uspace(&uspace_info->kcycles, &kcycles, sizeof(uint64_t));
145
146 size_t pages = get_pages_count(t->as);
147 copy_to_uspace(&uspace_info->pages, &pages, sizeof(pages));
148
149 int thread_count = atomic_get(&t->refcount);
150 copy_to_uspace(&uspace_info->thread_count, &thread_count, sizeof(thread_count));
151
152 spinlock_unlock(&t->lock);
153 interrupts_restore(ipl);
154 return 0;
155}
156
157static bool thread_walker(avltree_node_t *node, void *arg)
158{
159 thread_t *t = avltree_get_instance(node, thread_t, threads_tree_node);
160 thread_info_t *infos = (thread_info_t *)arg;
161 thread_info_t result;
162
163 spinlock_lock(&t->lock);
164
165 if (t->task != selected_task) {
166 spinlock_unlock(&t->lock);
167 return true;
168 }
169
170 ++count;
171 if (count > max_count) {
172 spinlock_unlock(&t->lock);
173 return false;
174 }
175
176 result.tid = t->tid;
177 result.state = t->state;
178 result.priority = t->priority;
179 result.ucycles = t->ucycles;
180 result.kcycles = t->kcycles;
181
182 if (t->cpu)
183 result.cpu = t->cpu->id;
184 else
185 result.cpu = -1;
186
187 WRITE_THREAD_INFO(infos, count - 1, &result);
188
189 spinlock_unlock(&t->lock);
190 return true;
191}
192
193int sys_ps_get_threads(task_id_t *uspace_id, thread_info_t *uspace_infos, size_t size)
194{
195 ipl_t ipl;
196 ipl = interrupts_disable();
197
198 task_id_t id;
199 copy_from_uspace(&id, uspace_id, sizeof(task_id_t));
200 spinlock_lock(&tasks_lock);
201 selected_task = task_find_by_id(id);
202 spinlock_unlock(&tasks_lock);
203
204 if (!selected_task) {
205 return 0;
206 }
207
208 spinlock_lock(&threads_lock);
209
210 count = 0;
211 max_count = size / sizeof(thread_info_t);
212 avltree_walk(&threads_tree, thread_walker, uspace_infos);
213
214 spinlock_unlock(&threads_lock);
215 interrupts_restore(ipl);
216 return count;
217}
218
219/** @}
220 */
Note: See TracBrowser for help on using the repository browser.