Changeset 4667b5c in mainline


Ignore:
Timestamp:
2019-08-07T11:10:46Z (5 years ago)
Author:
Matthieu Riolo <matthieu.riolo@…>
Children:
bb57a00
Parents:
130ba46
git-author:
Michal Koutný <xm.koutny+hos@…> (2015-11-13 01:56:10)
git-committer:
Matthieu Riolo <matthieu.riolo@…> (2019-08-07 11:10:46)
Message:

taskman: Add method to dump events of already running tasks

It's crafted for early startup of sysman.

Location:
uspace
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/taskman.c

    r130ba46 r4667b5c  
    4545
    4646async_sess_t *session_taskman = NULL;
     47
     48/*
     49 * Private functions
     50 */
    4751
    4852void __task_init(async_sess_t *sess)
     
    119123}
    120124
     125/*
     126 * Public functions
     127 */
     128
     129int taskman_dump_events(void)
     130{
     131        assert(session_taskman);
     132
     133        async_exch_t *exch = async_exchange_begin(session_taskman);
     134        int rc = async_req_0_0(exch, TASKMAN_DUMP_EVENTS);
     135        taskman_exchange_end(exch);
     136
     137        return rc;
     138}
     139
     140async_sess_t *taskman_get_session(void)
     141{
     142        return session_taskman;
     143}
     144
    121145/** Introduce as loader to taskman
    122146 *
     
    158182}
    159183
    160 async_sess_t *taskman_get_session(void)
    161 {
    162         return session_taskman;
    163 }
    164 
    165184
    166185
  • uspace/lib/c/include/ipc/taskman.h

    r130ba46 r4667b5c  
    4444        TASKMAN_EVENT_CALLBACK,
    4545        TASKMAN_NEW_TASK,
    46         TASKMAN_I_AM_NS
     46        TASKMAN_I_AM_NS,
     47        TASKMAN_DUMP_EVENTS
    4748} taskman_request_t;
    4849
  • uspace/lib/c/include/taskman.h

    r130ba46 r4667b5c  
    4040#endif
    4141
     42extern int taskman_dump_events(void);
     43
    4244/* Internal functions to be used by loader only */
    4345#ifndef TASKMAN_DISABLE_ASYNC
  • uspace/srv/taskman/event.c

    r130ba46 r4667b5c  
    4242#include "event.h"
    4343#include "task.h"
     44#include "taskman.h"
    4445
    4546/** Pending task wait structure. */
     
    8586}
    8687
    87 static void event_notify(task_t *sender)
    88 {
    89         // TODO should rlock task_hash_table?
     88static void event_notify(task_t *sender, async_sess_t *sess)
     89{
    9090        int flags = event_flags(sender);
    9191        if (flags == 0) {
     
    9393        }
    9494
     95        async_exch_t *exch = async_exchange_begin(sess);
     96        aid_t req = async_send_5(exch, TASKMAN_EV_TASK,
     97            LOWER32(sender->id),
     98            UPPER32(sender->id),
     99            flags,
     100            sender->exit,
     101            sender->retval,
     102            NULL);
     103
     104        async_exchange_end(exch);
     105
     106        /* Just send a notification and don't wait for anything */
     107        async_forget(req);
     108}
     109
     110/** Notify all registered listeners about sender's event
     111 *
     112 * @note Assumes share lock of task_hash_table is held.
     113 */
     114static void event_notify_all(task_t *sender)
     115{
     116        int flags = event_flags(sender);
     117        if (flags == 0) {
     118                return;
     119        }
     120
    95121        fibril_rwlock_read_lock(&listeners_lock);
    96122        list_foreach(listeners, listeners, task_t, t) {
    97123                assert(t->sess);
    98                 async_exch_t *exch = async_exchange_begin(t->sess);
    99                 aid_t req = async_send_5(exch, TASKMAN_EV_TASK,
    100                     LOWER32(sender->id),
    101                     UPPER32(sender->id),
    102                     flags,
    103                     sender->exit,
    104                     sender->retval,
    105                     NULL);
    106 
    107                 async_exchange_end(exch);
    108 
    109                 /* Just send a notification and don't wait for anything */
    110                 async_forget(req);
     124                event_notify(sender, t->sess);
    111125        }
    112126        fibril_rwlock_read_unlock(&listeners_lock);
     
    195209}
    196210
     211static bool dump_walker(task_t *t, void *arg)
     212{
     213        event_notify(t, arg);
     214        return true;
     215}
     216
     217void dump_events(task_id_t receiver_id, ipc_callid_t iid)
     218{
     219        int rc = EOK;
     220        /*
     221         * We have shared lock of tasks structures so that we can guarantee
     222         * that dump receiver will receive tasks correctly ordered (retval,
     223         * exit updates are serialized via exclusive lock).
     224         */
     225        fibril_rwlock_read_lock(&task_hash_table_lock);
     226
     227        task_t *receiver = task_get_by_id(receiver_id);
     228        if (receiver == NULL) {
     229                rc = ENOENT;
     230                goto finish;
     231        }
     232        if (receiver->sess == NULL) {
     233                rc = ENOENT;
     234                goto finish;
     235        }
     236
     237        /*
     238         * Answer caller first, so that they are not unnecessarily waiting
     239         * while we dump events.
     240         */
     241        async_answer_0(iid, rc);
     242        task_foreach(&dump_walker, receiver->sess);
     243
     244finish:
     245        fibril_rwlock_read_unlock(&task_hash_table_lock);
     246        if (rc != EOK) {
     247                async_answer_0(iid, rc);
     248        }
     249}
     250
    197251void wait_for_task(task_id_t id, int flags, ipc_callid_t callid,
    198252     task_id_t waiter_id)
     
    284338        t->retval_type = wait_for_exit ? RVAL_SET_EXIT : RVAL_SET;
    285339       
    286         event_notify(t);
     340        event_notify_all(t);
    287341        process_pending_wait();
    288342       
     
    313367        }
    314368
    315         event_notify(t);
    316         process_pending_wait();
    317 
    318         hash_table_remove_item(&task_hash_table, &t->link);
    319 
     369        /*
     370         * First remove terminated task from listeners and only after that
     371         * notify all others.
     372         */
    320373        fibril_rwlock_write_lock(&listeners_lock);
    321374        list_remove(&t->listeners);
    322375        fibril_rwlock_write_unlock(&listeners_lock);
     376
     377        event_notify_all(t);
     378        process_pending_wait();
     379
     380        /* Eventually, get rid of task_t. */
     381        task_remove(&t);
    323382
    324383finish:
  • uspace/srv/taskman/event.h

    r130ba46 r4667b5c  
    4242
    4343extern int event_register_listener(task_id_t, async_sess_t *);
     44extern void dump_events(task_id_t, ipc_callid_t);
    4445extern void wait_for_task(task_id_t, int, ipc_callid_t, task_id_t);
    4546extern int task_set_retval(task_id_t, int, bool);
  • uspace/srv/taskman/main.c

    r130ba46 r4667b5c  
    5454#include "taskman.h"
    5555
    56 //#define DPRINTF(...) printf(__VA_ARGS__)
    57 #define DPRINTF(...) /* empty */
    5856
    5957typedef struct {
     
    199197}
    200198
     199static void taskman_ctl_dump_events(ipc_callid_t iid, ipc_call_t *icall)
     200{
     201        DPRINTF("%s:%i from %llu\n", __func__, __LINE__, icall->in_task_id);
     202
     203        dump_events(icall->in_task_id, iid);
     204}
     205
    201206static void task_exit_event(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    202207{
     
    257262        case TASKMAN_EVENT_CALLBACK:
    258263                taskman_ctl_ev_callback(iid, icall);
     264                break;
     265        case TASKMAN_DUMP_EVENTS:
     266                taskman_ctl_dump_events(iid, icall);
    259267                break;
    260268        default:
     
    340348        /* Initialization */
    341349        prodcons_initialize(&sess_queue);
    342         int rc = task_init();
     350        int rc = tasks_init();
    343351        if (rc != EOK) {
    344352                return rc;
  • uspace/srv/taskman/task.c

    r130ba46 r4667b5c  
    4242#include "taskman.h"
    4343
    44 static size_t task_key_hash(void *key)
     44typedef struct {
     45        task_walker_t walker;
     46        void *arg;
     47} walker_context_t;
     48       
     49/*
     50 * Forwards
     51 */
     52
     53static void task_destroy(task_t **);
     54
     55/*
     56 * Hash table functions
     57 */
     58
     59static size_t ht_task_key_hash(void *key)
    4560{
    4661        return *(task_id_t*)key;
    4762}
    4863
    49 static size_t task_hash(const ht_link_t  *item)
     64static size_t ht_task_hash(const ht_link_t  *item)
    5065{
    5166        task_t *ht = hash_table_get_inst(item, task_t, link);
     
    5368}
    5469
    55 static bool task_key_equal(void *key, const ht_link_t *item)
     70static bool ht_task_key_equal(void *key, const ht_link_t *item)
    5671{
    5772        task_t *ht = hash_table_get_inst(item, task_t, link);
     
    6075
    6176/** Perform actions after removal of item from the hash table. */
    62 static void task_remove(ht_link_t *item)
    63 {
    64         free(hash_table_get_inst(item, task_t, link));
     77static void ht_task_remove(ht_link_t *item)
     78{
     79        task_t *t = hash_table_get_inst(item, task_t, link);
     80        task_destroy(&t);
    6581}
    6682
    6783/** Operations for task hash table. */
    6884static hash_table_ops_t task_hash_table_ops = {
    69         .hash = task_hash,
    70         .key_hash = task_key_hash,
    71         .key_equal = task_key_equal,
     85        .hash = ht_task_hash,
     86        .key_hash = ht_task_key_hash,
     87        .key_equal = ht_task_key_equal,
    7288        .equal = NULL,
    73         .remove_callback = task_remove
     89        .remove_callback = ht_task_remove
    7490};
    7591
    7692/** Task hash table structure. */
    77 hash_table_t task_hash_table;
     93static hash_table_t task_hash_table;
    7894fibril_rwlock_t task_hash_table_lock;
    7995
    80 int task_init(void)
    81 {
    82         if (!hash_table_create(&task_hash_table, 0, 0, &task_hash_table_ops)) {
    83                 printf(NAME ": No memory available for tasks\n");
    84                 return ENOMEM;
    85         }
    86 
    87         fibril_rwlock_initialize(&task_hash_table_lock);
    88        
    89         return EOK;
    90 }
    91 
    92 /** Find task by its ID
    93  *
    94  * Assumes held lock of task_hash_table.
    95  *
    96  * @param[in]  id
    97  * @return task structure
    98  * @return NULL when no task with given ID exists
    99  */
    100 task_t *task_get_by_id(task_id_t id)
    101 {
    102         ht_link_t *link = hash_table_find(&task_hash_table, &id);
    103         if (!link) {
    104                 return NULL;
    105         }
    106        
    107         task_t *t = hash_table_get_inst(link, task_t, link);
    108         return t;
    109 }
    110 
    111 int task_intro(task_id_t id)
    112 {
    113         int rc = EOK;
    114 
    115         fibril_rwlock_write_lock(&task_hash_table_lock);
    116 
    117         task_t *t = task_get_by_id(id);
    118         if (t != NULL) {
    119                 rc = EEXISTS;
    120                 goto finish;
    121         }
    122        
    123         t = malloc(sizeof(task_t));
    124         if (t == NULL) {
    125                 rc = ENOMEM;
    126                 goto finish;
    127         }
    128 
    129         /*
    130          * Insert into the main table.
    131          */
    132         t->id = id;
     96static void task_init(task_t *t)
     97{
    13398        t->exit = TASK_EXIT_RUNNING;
    13499        t->failed = false;
     
    137102        link_initialize(&t->listeners);
    138103        t->sess = NULL;
     104}
     105
     106static void task_destroy(task_t **t_ptr)
     107{
     108        task_t *t = *t_ptr;
     109        if (t == NULL) {
     110                return;
     111        }
     112
     113        if (t->sess != NULL) {
     114                async_hangup(t->sess);
     115        }
     116        free(t);
     117
     118        *t_ptr = NULL;
     119}
     120
     121int tasks_init(void)
     122{
     123        if (!hash_table_create(&task_hash_table, 0, 0, &task_hash_table_ops)) {
     124                printf(NAME ": No memory available for tasks\n");
     125                return ENOMEM;
     126        }
     127
     128        fibril_rwlock_initialize(&task_hash_table_lock);
     129       
     130        return EOK;
     131}
     132
     133/** Find task by its ID
     134 *
     135 * Assumes held lock of task_hash_table.
     136 *
     137 * @param[in]  id
     138 * @return task structure
     139 * @return NULL when no task with given ID exists
     140 */
     141task_t *task_get_by_id(task_id_t id)
     142{
     143        ht_link_t *link = hash_table_find(&task_hash_table, &id);
     144        if (!link) {
     145                return NULL;
     146        }
     147       
     148        task_t *t = hash_table_get_inst(link, task_t, link);
     149        return t;
     150}
     151
     152static bool internal_walker(ht_link_t *ht_link, void *arg)
     153{
     154        task_t *t = hash_table_get_inst(ht_link, task_t, link);
     155        walker_context_t *ctx = arg;
     156        return ctx->walker(t, ctx->arg);
     157}
     158
     159/** Iterate over all tasks
     160 *
     161 * @note Assumes task_hash_table lock is held.
     162 *
     163 * @param[in]  walker
     164 * @param[in]  arg     generic argument passed to walker function
     165 */
     166void task_foreach(task_walker_t walker, void *arg)
     167{
     168        walker_context_t ctx;
     169        ctx.walker = walker;
     170        ctx.arg = arg;
     171
     172        hash_table_apply(&task_hash_table, &internal_walker, &ctx);
     173}
     174
     175/** Remove task from our structures
     176 *
     177 * @note Assumes task_hash_table exclusive lock is held.
     178 *
     179 * @param[in|out]  ptr_t  Pointer to task pointer that should be removed, nulls
     180 *                        task pointer.
     181 */
     182void task_remove(task_t **ptr_t)
     183{
     184        task_t *t = *ptr_t;
     185        if (t == NULL) {
     186                return;
     187        }
     188
     189        hash_table_remove_item(&task_hash_table, &t->link);
     190        *ptr_t = NULL;
     191}
     192
     193int task_intro(task_id_t id)
     194{
     195        int rc = EOK;
     196
     197        fibril_rwlock_write_lock(&task_hash_table_lock);
     198
     199        task_t *t = task_get_by_id(id);
     200        if (t != NULL) {
     201                rc = EEXISTS;
     202                goto finish;
     203        }
     204       
     205        t = malloc(sizeof(task_t));
     206        if (t == NULL) {
     207                rc = ENOMEM;
     208                goto finish;
     209        }
     210
     211        /*
     212         * Insert into the main table.
     213         */
     214        task_init(t);
     215        t->id = id;
    139216
    140217        hash_table_insert(&task_hash_table, &t->link);
    141         printf("%s: %llu\n", __func__, t->id);
     218        DPRINTF("%s: %llu\n", __func__, t->id);
    142219       
    143220finish:
  • uspace/srv/taskman/task.h

    r130ba46 r4667b5c  
    6363} task_t;
    6464
    65 extern hash_table_t task_hash_table;
     65typedef bool (* task_walker_t)(task_t *, void *);
     66
    6667extern fibril_rwlock_t task_hash_table_lock;
    6768
    68 extern int task_init(void);
     69extern int tasks_init(void);
    6970
    7071extern task_t *task_get_by_id(task_id_t);
     72
     73extern void task_foreach(task_walker_t, void *);
     74
     75extern void task_remove(task_t **);
    7176
    7277extern int task_intro(task_id_t);
  • uspace/srv/taskman/taskman.h

    r130ba46 r4667b5c  
    3434#define TASKMAN_TASKMAN_H__
    3535
     36#include <stdio.h>
     37
    3638#define NAME  "taskman"
     39
     40//#define DPRINTF(...) printf(__VA_ARGS__)
     41#define DPRINTF(...) /* empty */
    3742
    3843#endif
Note: See TracChangeset for help on using the changeset viewer.