Changeset e1b6742 in mainline for kernel/generic/src/sysinfo/stats.c
- Timestamp:
- 2010-04-18T12:17:11Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- e535eeb
- Parents:
- bbda5ab
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/sysinfo/stats.c
rbbda5ab re1b6742 40 40 #include <time/clock.h> 41 41 #include <mm/frame.h> 42 #include <proc/task.h> 42 43 #include <proc/thread.h> 43 44 #include <str.h> … … 127 128 } 128 129 129 /** Count number of tasks130 * 131 * AVL t ask tree walker for counting tasks.132 * 133 * @param node AVL t ask tree node (unused).134 * @param arg Pointer to the counter .130 /** Count number of nodes in an AVL tree 131 * 132 * AVL tree walker for counting nodes. 133 * 134 * @param node AVL tree node (unused). 135 * @param arg Pointer to the counter (size_t). 135 136 * 136 137 * @param Always true (continue the walk). 137 138 * 138 139 */ 139 static bool task_count_walker(avltree_node_t *node, void *arg)140 static bool avl_count_walker(avltree_node_t *node, void *arg) 140 141 { 141 142 size_t *count = (size_t *) arg; … … 192 193 /* First walk the task tree to count the tasks */ 193 194 size_t count = 0; 194 avltree_walk(&tasks_tree, task_count_walker, (void *) &count);195 avltree_walk(&tasks_tree, avl_count_walker, (void *) &count); 195 196 196 197 if (count == 0) { … … 228 229 229 230 return ((void *) task_ids); 231 } 232 233 /** Gather threads 234 * 235 * AVL three tree walker for gathering thread IDs. Interrupts should 236 * be already disabled while walking the tree. 237 * 238 * @param node AVL thread tree node. 239 * @param arg Pointer to the iterator into the array of thread IDs. 240 * 241 * @param Always true (continue the walk). 242 * 243 */ 244 static bool thread_serialize_walker(avltree_node_t *node, void *arg) 245 { 246 thread_id_t **ids = (thread_id_t **) arg; 247 thread_t *thread = avltree_get_instance(node, thread_t, threads_tree_node); 248 249 /* Interrupts are already disabled */ 250 spinlock_lock(&(thread->lock)); 251 252 /* Record the ID and increment the iterator */ 253 **ids = thread->tid; 254 (*ids)++; 255 256 spinlock_unlock(&(thread->lock)); 257 258 return true; 259 } 260 261 /** Get thread IDs 262 * 263 * @param item Sysinfo item (unused). 264 * @param size Size of the returned data. 265 * @param dry_run Do not get the data, just calculate the size. 266 * 267 * @return Data containing thread IDs of all threads. 268 * If the return value is not NULL, it should be freed 269 * in the context of the sysinfo request. 270 */ 271 static void *get_stats_threads(struct sysinfo_item *item, size_t *size, 272 bool dry_run) 273 { 274 /* Messing with threads structures, avoid deadlock */ 275 ipl_t ipl = interrupts_disable(); 276 spinlock_lock(&threads_lock); 277 278 /* First walk the thread tree to count the threads */ 279 size_t count = 0; 280 avltree_walk(&threads_tree, avl_count_walker, (void *) &count); 281 282 if (count == 0) { 283 /* No threads found (strange) */ 284 spinlock_unlock(&threads_lock); 285 interrupts_restore(ipl); 286 287 *size = 0; 288 return NULL; 289 } 290 291 *size = sizeof(thread_id_t) * count; 292 if (dry_run) { 293 spinlock_unlock(&threads_lock); 294 interrupts_restore(ipl); 295 return NULL; 296 } 297 298 thread_id_t *thread_ids = (thread_id_t *) malloc(*size, FRAME_ATOMIC); 299 if (thread_ids == NULL) { 300 /* No free space for allocation */ 301 spinlock_unlock(&threads_lock); 302 interrupts_restore(ipl); 303 304 *size = 0; 305 return NULL; 306 } 307 308 /* Walk tha thread tree again to gather the IDs */ 309 thread_id_t *iterator = thread_ids; 310 avltree_walk(&threads_tree, thread_serialize_walker, (void *) &iterator); 311 312 spinlock_unlock(&threads_lock); 313 interrupts_restore(ipl); 314 315 return ((void *) thread_ids); 230 316 } 231 317 … … 271 357 * but it is still reasonable for the given purpose). 272 358 * 273 * @param name Task ID (string-encoded number). 359 * @param name Task ID (string-encoded number). 360 * @param dry_run Do not get the data, just calculate the size. 274 361 * 275 362 * @return Sysinfo return holder. The type of the returned … … 281 368 * 282 369 */ 283 static sysinfo_return_t get_stats_task(const char *name )370 static sysinfo_return_t get_stats_task(const char *name, bool dry_run) 284 371 { 285 372 /* Initially no return value */ … … 292 379 return ret; 293 380 294 /* Allocate stats_task_t structure */295 stats_task_t *stats_task =296 (stats_task_t *) malloc(sizeof(stats_task_t), FRAME_ATOMIC);297 if (stats_task == NULL)298 return ret;299 300 381 /* Messing with task structures, avoid deadlock */ 301 382 ipl_t ipl = interrupts_disable(); … … 307 388 spinlock_unlock(&tasks_lock); 308 389 interrupts_restore(ipl); 309 free(stats_task);310 390 return ret; 311 391 } 312 392 313 /* Hand-over-hand locking */ 314 spinlock_lock(&task->lock); 315 spinlock_unlock(&tasks_lock); 316 317 /* Copy task's statistics */ 318 str_cpy(stats_task->name, TASK_NAME_BUFLEN, task->name); 319 stats_task->virtmem = get_task_virtmem(task->as); 320 stats_task->threads = atomic_get(&task->refcount); 321 task_get_accounting(task, &(stats_task->ucycles), 322 &(stats_task->kcycles)); 323 stats_task->ipc_info = task->ipc_info; 324 325 spinlock_unlock(&task->lock); 393 if (dry_run) { 394 ret.tag = SYSINFO_VAL_FUNCTION_DATA; 395 ret.data.data = NULL; 396 ret.data.size = sizeof(stats_task_t); 397 398 spinlock_unlock(&tasks_lock); 399 } else { 400 /* Allocate stats_task_t structure */ 401 stats_task_t *stats_task = 402 (stats_task_t *) malloc(sizeof(stats_task_t), FRAME_ATOMIC); 403 if (stats_task == NULL) { 404 spinlock_unlock(&tasks_lock); 405 interrupts_restore(ipl); 406 return ret; 407 } 408 409 /* Correct return value */ 410 ret.tag = SYSINFO_VAL_FUNCTION_DATA; 411 ret.data.data = (void *) stats_task; 412 ret.data.size = sizeof(stats_task_t); 413 414 /* Hand-over-hand locking */ 415 spinlock_lock(&task->lock); 416 spinlock_unlock(&tasks_lock); 417 418 /* Copy task's statistics */ 419 str_cpy(stats_task->name, TASK_NAME_BUFLEN, task->name); 420 stats_task->virtmem = get_task_virtmem(task->as); 421 stats_task->threads = atomic_get(&task->refcount); 422 task_get_accounting(task, &(stats_task->ucycles), 423 &(stats_task->kcycles)); 424 stats_task->ipc_info = task->ipc_info; 425 426 spinlock_unlock(&task->lock); 427 } 428 326 429 interrupts_restore(ipl); 327 430 328 /* Correct return value */ 329 ret.tag = SYSINFO_VAL_FUNCTION_DATA; 330 ret.data.data = (void *) stats_task; 331 ret.data.size = sizeof(stats_task_t); 431 return ret; 432 } 433 434 /** Get thread statistics 435 * 436 * Get statistics of a given thread. The thread ID is passed 437 * as a string (current limitation of the sysinfo interface, 438 * but it is still reasonable for the given purpose). 439 * 440 * @param name Thread ID (string-encoded number). 441 * @param dry_run Do not get the data, just calculate the size. 442 * 443 * @return Sysinfo return holder. The type of the returned 444 * data is either SYSINFO_VAL_UNDEFINED (unknown 445 * thread ID or memory allocation error) or 446 * SYSINFO_VAL_FUNCTION_DATA (in that case the 447 * generated data should be freed within the 448 * sysinfo request context). 449 * 450 */ 451 static sysinfo_return_t get_stats_thread(const char *name, bool dry_run) 452 { 453 /* Initially no return value */ 454 sysinfo_return_t ret; 455 ret.tag = SYSINFO_VAL_UNDEFINED; 456 457 /* Parse the thread ID */ 458 thread_id_t thread_id; 459 if (str_uint64(name, NULL, 0, true, &thread_id) != EOK) 460 return ret; 461 462 /* Messing with threads structures, avoid deadlock */ 463 ipl_t ipl = interrupts_disable(); 464 spinlock_lock(&threads_lock); 465 466 thread_t *thread = thread_find_by_id(thread_id); 467 if (thread == NULL) { 468 /* No thread with this ID */ 469 spinlock_unlock(&threads_lock); 470 interrupts_restore(ipl); 471 return ret; 472 } 473 474 if (dry_run) { 475 ret.tag = SYSINFO_VAL_FUNCTION_DATA; 476 ret.data.data = NULL; 477 ret.data.size = sizeof(stats_thread_t); 478 479 spinlock_unlock(&threads_lock); 480 } else { 481 /* Allocate stats_thread_t structure */ 482 stats_thread_t *stats_thread = 483 (stats_thread_t *) malloc(sizeof(stats_thread_t), FRAME_ATOMIC); 484 if (stats_thread == NULL) { 485 spinlock_unlock(&threads_lock); 486 interrupts_restore(ipl); 487 return ret; 488 } 489 490 /* Correct return value */ 491 ret.tag = SYSINFO_VAL_FUNCTION_DATA; 492 ret.data.data = (void *) stats_thread; 493 ret.data.size = sizeof(stats_thread_t); 494 495 /* Hand-over-hand locking */ 496 spinlock_lock(&thread->lock); 497 spinlock_unlock(&threads_lock); 498 499 /* Copy thread's statistics */ 500 stats_thread->task_id = thread->task->taskid; 501 stats_thread->state = thread->state; 502 stats_thread->priority = thread->priority; 503 stats_thread->ucycles = thread->ucycles; 504 stats_thread->kcycles = thread->kcycles; 505 506 if (thread->cpu != NULL) { 507 stats_thread->on_cpu = true; 508 stats_thread->cpu = thread->cpu->id; 509 } else 510 stats_thread->on_cpu = false; 511 512 spinlock_unlock(&thread->lock); 513 } 514 515 interrupts_restore(ipl); 332 516 333 517 return ret; … … 477 661 sysinfo_set_item_fn_data("system.load", NULL, get_stats_load); 478 662 sysinfo_set_item_fn_data("system.tasks", NULL, get_stats_tasks); 663 sysinfo_set_item_fn_data("system.threads", NULL, get_stats_threads); 479 664 sysinfo_set_subtree_fn("system.tasks", NULL, get_stats_task); 665 sysinfo_set_subtree_fn("system.threads", NULL, get_stats_thread); 480 666 } 481 667
Note:
See TracChangeset
for help on using the changeset viewer.