Changeset a6302ae in mainline for kernel/generic/src/sysinfo/stats.c


Ignore:
Timestamp:
2019-12-11T10:49:48Z (4 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
fe7bcf1
Parents:
ad211c8
Message:

add basic support for IPC statistics

Dumping of phone connections is supported right now.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/sysinfo/stats.c

    rad211c8 ra6302ae  
    6969#define LOAD_INTERVAL  5
    7070
     71/** IPC connections statistics state */
     72typedef struct {
     73        bool counting;
     74        size_t count;
     75        size_t i;
     76        stats_ipcc_t *data;
     77} ipccs_state_t;
     78
    7179/** Fixed-point representation of
    7280 *
     
    371379
    372380        return ((void *) stats_threads);
     381}
     382
     383/** Produce IPC connection statistics
     384 *
     385 * Summarize IPC connection information into IPC connection statistics.
     386 *
     387 * @param cap Phone capability.
     388 * @param arg State variable.
     389 *
     390 */
     391static bool produce_stats_ipcc_cb(cap_t *cap, void *arg)
     392{
     393        phone_t *phone = cap->kobject->phone;
     394        ipccs_state_t *state = (ipccs_state_t *) arg;
     395
     396        if (state->counting) {
     397                /*
     398                 * Simply update the number of entries
     399                 * in case we are in the counting mode.
     400                 */
     401
     402                state->count++;
     403                return true;
     404        }
     405
     406        /* We are in the gathering mode */
     407
     408        if ((state->data == NULL) || (state->i >= state->count)) {
     409                /*
     410                 * Do nothing if we have no buffer
     411                 * to store the data to (meaning we are
     412                 * in a dry run) or the buffer is already
     413                 * full.
     414                 */
     415
     416                return true;
     417        }
     418
     419        mutex_lock(&phone->lock);
     420
     421        if (phone->state == IPC_PHONE_CONNECTED) {
     422                state->data[state->i].caller = phone->caller->taskid;
     423                state->data[state->i].callee = phone->callee->task->taskid;
     424                state->i++;
     425        }
     426
     427        mutex_unlock(&phone->lock);
     428
     429        return true;
     430}
     431
     432/** Get IPC connections statistics
     433 *
     434 * @param item    Sysinfo item (unused).
     435 * @param size    Size of the returned data.
     436 * @param dry_run Do not get the data, just calculate the size.
     437 * @param data    Unused.
     438 *
     439 * @return Data containing several stats_ipccs_t structures.
     440 *         If the return value is not NULL, it should be freed
     441 *         in the context of the sysinfo request.
     442 *
     443 */
     444static void *get_stats_ipccs(struct sysinfo_item *item, size_t *size,
     445    bool dry_run, void *data)
     446{
     447        /* Messing with tasks structures, avoid deadlock */
     448        irq_spinlock_lock(&tasks_lock, true);
     449
     450        ipccs_state_t state = {
     451                .counting = true,
     452                .count = 0,
     453                .i = 0,
     454                .data = NULL
     455        };
     456
     457        /* Compute the number of IPC connections */
     458        task_t *task = task_first();
     459        while (task != NULL) {
     460                task_hold(task);
     461                irq_spinlock_unlock(&tasks_lock, true);
     462
     463                caps_apply_to_kobject_type(task, KOBJECT_TYPE_PHONE,
     464                    produce_stats_ipcc_cb, &state);
     465
     466                irq_spinlock_lock(&tasks_lock, true);
     467
     468                task = task_next(task);
     469        }
     470
     471        state.counting = false;
     472        *size = sizeof(stats_ipcc_t) * state.count;
     473
     474        if (!dry_run)
     475                state.data = (stats_ipcc_t *) malloc(*size);
     476
     477        /* Gather the statistics for each task */
     478        task = task_first();
     479        while (task != NULL) {
     480                /* We already hold a reference to the task */
     481                irq_spinlock_unlock(&tasks_lock, true);
     482
     483                caps_apply_to_kobject_type(task, KOBJECT_TYPE_PHONE,
     484                    produce_stats_ipcc_cb, &state);
     485
     486                irq_spinlock_lock(&tasks_lock, true);
     487                task_release(task);
     488
     489                task = task_next(task);
     490        }
     491
     492        irq_spinlock_unlock(&tasks_lock, true);
     493
     494        return ((void *) state.data);
    373495}
    374496
     
    754876        sysinfo_set_item_gen_data("system.tasks", NULL, get_stats_tasks, NULL);
    755877        sysinfo_set_item_gen_data("system.threads", NULL, get_stats_threads, NULL);
     878        sysinfo_set_item_gen_data("system.ipccs", NULL, get_stats_ipccs, NULL);
    756879        sysinfo_set_item_gen_data("system.exceptions", NULL, get_stats_exceptions, NULL);
    757880        sysinfo_set_subtree_fn("system.tasks", NULL, get_stats_task, NULL);
Note: See TracChangeset for help on using the changeset viewer.