Changeset 4667b5c in mainline
- Timestamp:
- 2019-08-07T11:10:46Z (5 years ago)
- 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)
- Location:
- uspace
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/taskman.c
r130ba46 r4667b5c 45 45 46 46 async_sess_t *session_taskman = NULL; 47 48 /* 49 * Private functions 50 */ 47 51 48 52 void __task_init(async_sess_t *sess) … … 119 123 } 120 124 125 /* 126 * Public functions 127 */ 128 129 int 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 140 async_sess_t *taskman_get_session(void) 141 { 142 return session_taskman; 143 } 144 121 145 /** Introduce as loader to taskman 122 146 * … … 158 182 } 159 183 160 async_sess_t *taskman_get_session(void)161 {162 return session_taskman;163 }164 165 184 166 185 -
uspace/lib/c/include/ipc/taskman.h
r130ba46 r4667b5c 44 44 TASKMAN_EVENT_CALLBACK, 45 45 TASKMAN_NEW_TASK, 46 TASKMAN_I_AM_NS 46 TASKMAN_I_AM_NS, 47 TASKMAN_DUMP_EVENTS 47 48 } taskman_request_t; 48 49 -
uspace/lib/c/include/taskman.h
r130ba46 r4667b5c 40 40 #endif 41 41 42 extern int taskman_dump_events(void); 43 42 44 /* Internal functions to be used by loader only */ 43 45 #ifndef TASKMAN_DISABLE_ASYNC -
uspace/srv/taskman/event.c
r130ba46 r4667b5c 42 42 #include "event.h" 43 43 #include "task.h" 44 #include "taskman.h" 44 45 45 46 /** Pending task wait structure. */ … … 85 86 } 86 87 87 static void event_notify(task_t *sender) 88 { 89 // TODO should rlock task_hash_table? 88 static void event_notify(task_t *sender, async_sess_t *sess) 89 { 90 90 int flags = event_flags(sender); 91 91 if (flags == 0) { … … 93 93 } 94 94 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 */ 114 static void event_notify_all(task_t *sender) 115 { 116 int flags = event_flags(sender); 117 if (flags == 0) { 118 return; 119 } 120 95 121 fibril_rwlock_read_lock(&listeners_lock); 96 122 list_foreach(listeners, listeners, task_t, t) { 97 123 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); 111 125 } 112 126 fibril_rwlock_read_unlock(&listeners_lock); … … 195 209 } 196 210 211 static bool dump_walker(task_t *t, void *arg) 212 { 213 event_notify(t, arg); 214 return true; 215 } 216 217 void 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 244 finish: 245 fibril_rwlock_read_unlock(&task_hash_table_lock); 246 if (rc != EOK) { 247 async_answer_0(iid, rc); 248 } 249 } 250 197 251 void wait_for_task(task_id_t id, int flags, ipc_callid_t callid, 198 252 task_id_t waiter_id) … … 284 338 t->retval_type = wait_for_exit ? RVAL_SET_EXIT : RVAL_SET; 285 339 286 event_notify (t);340 event_notify_all(t); 287 341 process_pending_wait(); 288 342 … … 313 367 } 314 368 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 */ 320 373 fibril_rwlock_write_lock(&listeners_lock); 321 374 list_remove(&t->listeners); 322 375 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); 323 382 324 383 finish: -
uspace/srv/taskman/event.h
r130ba46 r4667b5c 42 42 43 43 extern int event_register_listener(task_id_t, async_sess_t *); 44 extern void dump_events(task_id_t, ipc_callid_t); 44 45 extern void wait_for_task(task_id_t, int, ipc_callid_t, task_id_t); 45 46 extern int task_set_retval(task_id_t, int, bool); -
uspace/srv/taskman/main.c
r130ba46 r4667b5c 54 54 #include "taskman.h" 55 55 56 //#define DPRINTF(...) printf(__VA_ARGS__)57 #define DPRINTF(...) /* empty */58 56 59 57 typedef struct { … … 199 197 } 200 198 199 static 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 201 206 static void task_exit_event(ipc_callid_t iid, ipc_call_t *icall, void *arg) 202 207 { … … 257 262 case TASKMAN_EVENT_CALLBACK: 258 263 taskman_ctl_ev_callback(iid, icall); 264 break; 265 case TASKMAN_DUMP_EVENTS: 266 taskman_ctl_dump_events(iid, icall); 259 267 break; 260 268 default: … … 340 348 /* Initialization */ 341 349 prodcons_initialize(&sess_queue); 342 int rc = task _init();350 int rc = tasks_init(); 343 351 if (rc != EOK) { 344 352 return rc; -
uspace/srv/taskman/task.c
r130ba46 r4667b5c 42 42 #include "taskman.h" 43 43 44 static size_t task_key_hash(void *key) 44 typedef struct { 45 task_walker_t walker; 46 void *arg; 47 } walker_context_t; 48 49 /* 50 * Forwards 51 */ 52 53 static void task_destroy(task_t **); 54 55 /* 56 * Hash table functions 57 */ 58 59 static size_t ht_task_key_hash(void *key) 45 60 { 46 61 return *(task_id_t*)key; 47 62 } 48 63 49 static size_t task_hash(const ht_link_t *item)64 static size_t ht_task_hash(const ht_link_t *item) 50 65 { 51 66 task_t *ht = hash_table_get_inst(item, task_t, link); … … 53 68 } 54 69 55 static bool task_key_equal(void *key, const ht_link_t *item)70 static bool ht_task_key_equal(void *key, const ht_link_t *item) 56 71 { 57 72 task_t *ht = hash_table_get_inst(item, task_t, link); … … 60 75 61 76 /** 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)); 77 static 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); 65 81 } 66 82 67 83 /** Operations for task hash table. */ 68 84 static 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, 72 88 .equal = NULL, 73 .remove_callback = task_remove89 .remove_callback = ht_task_remove 74 90 }; 75 91 76 92 /** Task hash table structure. */ 77 hash_table_t task_hash_table;93 static hash_table_t task_hash_table; 78 94 fibril_rwlock_t task_hash_table_lock; 79 95 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; 96 static void task_init(task_t *t) 97 { 133 98 t->exit = TASK_EXIT_RUNNING; 134 99 t->failed = false; … … 137 102 link_initialize(&t->listeners); 138 103 t->sess = NULL; 104 } 105 106 static 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 121 int 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 */ 141 task_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 152 static 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 */ 166 void 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 */ 182 void 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 193 int 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; 139 216 140 217 hash_table_insert(&task_hash_table, &t->link); 141 printf("%s: %llu\n", __func__, t->id);218 DPRINTF("%s: %llu\n", __func__, t->id); 142 219 143 220 finish: -
uspace/srv/taskman/task.h
r130ba46 r4667b5c 63 63 } task_t; 64 64 65 extern hash_table_t task_hash_table; 65 typedef bool (* task_walker_t)(task_t *, void *); 66 66 67 extern fibril_rwlock_t task_hash_table_lock; 67 68 68 extern int task _init(void);69 extern int tasks_init(void); 69 70 70 71 extern task_t *task_get_by_id(task_id_t); 72 73 extern void task_foreach(task_walker_t, void *); 74 75 extern void task_remove(task_t **); 71 76 72 77 extern int task_intro(task_id_t); -
uspace/srv/taskman/taskman.h
r130ba46 r4667b5c 34 34 #define TASKMAN_TASKMAN_H__ 35 35 36 #include <stdio.h> 37 36 38 #define NAME "taskman" 39 40 //#define DPRINTF(...) printf(__VA_ARGS__) 41 #define DPRINTF(...) /* empty */ 37 42 38 43 #endif
Note:
See TracChangeset
for help on using the changeset viewer.