source: mainline/kernel/generic/src/ps/ps.c@ acc3f745

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

sys_get_task_info bugfix (cheking task id)

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