Changeset 2f44fafd in mainline
- Timestamp:
- 2019-08-07T04:33:20Z (5 years ago)
- Children:
- e0e7eba
- Parents:
- 62273d1
- git-author:
- Michal Koutný <xm.koutny+hos@…> (2015-10-12 21:58:23)
- git-committer:
- Matthieu Riolo <matthieu.riolo@…> (2019-08-07 04:33:20)
- Location:
- uspace
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/libc.c
r62273d1 r2f44fafd 190 190 if (env_setup) { 191 191 __stdio_done(); 192 task_retval (status);192 task_retval_internal(status, true); 193 193 } 194 194 -
uspace/lib/c/generic/private/task.h
r62273d1 r2f44fafd 40 40 void __task_init(async_sess_t *); 41 41 42 int task_retval_internal(int, bool); 43 42 44 #endif 43 45 -
uspace/lib/c/generic/task.c
r62273d1 r2f44fafd 131 131 static errno_t task_setup_wait(task_id_t id, task_wait_t *wait) 132 132 { 133 assert(wait->flags); 133 134 async_exch_t *exch = taskman_exchange_begin(); 134 135 if (exch == NULL) … … 435 436 } 436 437 437 errno_t task_retval (int val)438 errno_t task_retval_internal(int val, bool wait_for_exit) 438 439 { 439 440 async_exch_t *exch = taskman_exchange_begin(); … … 441 442 return EIO; 442 443 443 int rc = (int) async_req_1_0(exch, TASKMAN_RETVAL, val);444 errno_t rc = (int) async_req_2_0(exch, TASKMAN_RETVAL, val, wait_for_exit); 444 445 taskman_exchange_end(exch); 445 446 … … 447 448 } 448 449 450 errno_t task_retval(int val) 451 { 452 return task_retval_internal(val, false); 453 } 454 449 455 450 456 void __task_init(async_sess_t *sess) -
uspace/srv/taskman/main.c
r62273d1 r2f44fafd 58 58 static void connect_to_loader(ipc_callid_t iid, ipc_call_t *icall) 59 59 { 60 / /TODO explain why we don't explicitly accept connection request61 /* Spawn aloader. */60 /* We don't accept the connection request, we forward it instead to 61 * freshly spawned loader. */ 62 62 int rc = loader_spawn("loader"); 63 63 … … 79 79 async_exchange_end(exch); 80 80 81 // TODO leak? what happens with referenced sessions 81 /* After forward we can dispose all session-related resources */ 82 async_hangup(sess_ref->sess); 82 83 free(sess_ref); 83 84 … … 153 154 static void control_connection(ipc_callid_t iid, ipc_call_t *icall) 154 155 { 156 /* TODO remove/redesign the workaround 157 * Call task_intro here for boot-time tasks, 158 * probably they should announce themselves explicitly 159 * or taskman should detect them from kernel's list of tasks. 160 */ 161 int rc = task_intro(icall, false); 162 155 163 /* First, accept connection */ 156 async_answer_0(iid, EOK); 157 158 // TODO register task to hash table 164 async_answer_0(iid, rc); 165 166 if (rc != EOK) { 167 return; 168 } 169 159 170 control_connection_loop(); 160 171 } … … 174 185 sess_ref->sess = async_callback_receive_start(EXCHANGE_ATOMIC, icall); 175 186 if (sess_ref->sess == NULL) { 176 //TODO different error code?177 187 async_answer_0(iid, EINVAL); 178 188 return; … … 180 190 181 191 /* Remember task_id */ 182 int rc = task_i d_intro(icall);192 int rc = task_intro(icall, true); 183 193 184 194 if (rc != EOK) { … … 222 232 case TASKMAN_LOADER_CALLBACK: 223 233 loader_callback(iid, icall); 224 // TODO register task to hashtable225 234 control_connection_loop(); 226 235 break; … … 245 254 } 246 255 247 rc = async_event_subscribe(EVENT_EXIT, task_exit_event, (void *) EVENT_EXIT);256 rc = async_event_subscribe(EVENT_EXIT, task_exit_event, (void *)TASK_EXIT_NORMAL); 248 257 if (rc != EOK) { 249 258 printf("Cannot register for exit events (%i).\n", rc); … … 251 260 } 252 261 253 rc = async_event_subscribe(EVENT_FAULT, task_exit_event, (void *) EVENT_FAULT);262 rc = async_event_subscribe(EVENT_FAULT, task_exit_event, (void *)TASK_EXIT_UNEXPECTED); 254 263 if (rc != EOK) { 255 264 printf("Cannot register for fault events (%i).\n", rc); -
uspace/srv/taskman/task.c
r62273d1 r2f44fafd 1 1 /* 2 * Copyright (c) 2009 Martin Decky3 * Copyright (c) 2009 Jiri Svoboda4 * Copyright (c) 2015 Michal Koutny5 * All rights reserved.6 * 7 * Redistribution and use in source and binary forms, with or without2 * copyright (c) 2009 martin decky 3 * copyright (c) 2009 jiri svoboda 4 * copyright (c) 2015 michal koutny 5 * all rights reserved. 6 * 7 * redistribution and use in source and binary forms, with or without 8 8 * modification, are permitted provided that the following conditions 9 9 * are met: 10 10 * 11 * - Redistributions of source code must retain the above copyright11 * - redistributions of source code must retain the above copyright 12 12 * notice, this list of conditions and the following disclaimer. 13 * - Redistributions in binary form must reproduce the above copyright13 * - redistributions in binary form must reproduce the above copyright 14 14 * notice, this list of conditions and the following disclaimer in the 15 15 * documentation and/or other materials provided with the distribution. 16 * - The name of the author may not be used to endorse or promote products16 * - the name of the author may not be used to endorse or promote products 17 17 * derived from this software without specific prior written permission. 18 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT27 * ( INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.19 * this software is provided by the author ``as is'' and any express or 20 * implied warranties, including, but not limited to, the implied warranties 21 * of merchantability and fitness for a particular purpose are disclaimed. 22 * in no event shall the author be liable for any direct, indirect, 23 * incidental, special, exemplary, or consequential damages (including, but 24 * not limited to, procurement of substitute goods or services; loss of use, 25 * data, or profits; or business interruption) however caused and on any 26 * theory of liability, whether in contract, strict liability, or tort 27 * (including negligence or otherwise) arising in any way out of the use of 28 * this software, even if advised of the possibility of such damage. 29 29 */ 30 30 31 /** @addtogroup taskman 31 /** 32 * locking order: 33 * - task_hash_table_lock, 34 * - pending_wait_lock. 35 * 36 * @addtogroup taskman 32 37 * @{ 33 38 */ … … 37 42 #include <async.h> 38 43 #include <errno.h> 44 #include <fibril_synch.h> 39 45 #include <macros.h> 40 46 #include <malloc.h> 41 47 #include <stdbool.h> 42 48 #include <stdio.h> 49 #include <task.h> 43 50 #include <types/task.h> 44 51 … … 46 53 #include "taskman.h" 47 54 48 49 /** Task hash table item. */ 55 /** what type of retval from the task we have */ 56 typedef enum { 57 RVAL_UNSET, /**< unset */ 58 RVAL_SET, /**< retval set, e.g. by server */ 59 RVAL_SET_EXIT /**< retval set, wait for expected task exit */ 60 } retval_t; 61 62 /** task hash table item. */ 50 63 typedef struct { 51 64 ht_link_t link; 52 65 53 task_id_t id; /**< Task ID. */54 task_exit_t exit; /**< Task is done. */55 bool have_rval; /**< Task returned a value. */56 int retval; /**< The return value. */66 task_id_t id; /**< task id. */ 67 task_exit_t exit; /**< task is done. */ 68 retval_t retval_type; /**< task returned a value. */ 69 int retval; /**< the return value. */ 57 70 } hashed_task_t; 58 71 … … 75 88 } 76 89 77 /** Perform actions after removal of item from the hash table. */90 /** perform actions after removal of item from the hash table. */ 78 91 static void task_remove(ht_link_t *item) 79 92 { … … 81 94 } 82 95 83 /** Operations for task hash table. */96 /** operations for task hash table. */ 84 97 static hash_table_ops_t task_hash_table_ops = { 85 98 .hash = task_hash, … … 92 105 /** Task hash table structure. */ 93 106 static hash_table_t task_hash_table; 94 95 typedef struct { 96 ht_link_t link; 97 sysarg_t in_phone_hash; /**< Incoming phone hash. */ 98 task_id_t id; /**< Task ID. */ 99 } p2i_entry_t; 100 101 /* phone-to-id hash table operations */ 102 103 static size_t p2i_key_hash(void *key) 104 { 105 sysarg_t in_phone_hash = *(sysarg_t*)key; 106 return in_phone_hash; 107 } 108 109 static size_t p2i_hash(const ht_link_t *item) 110 { 111 p2i_entry_t *entry = hash_table_get_inst(item, p2i_entry_t, link); 112 return entry->in_phone_hash; 113 } 114 115 static bool p2i_key_equal(void *key, const ht_link_t *item) 116 { 117 sysarg_t in_phone_hash = *(sysarg_t*)key; 118 p2i_entry_t *entry = hash_table_get_inst(item, p2i_entry_t, link); 119 120 return (in_phone_hash == entry->in_phone_hash); 121 } 122 123 /** Perform actions after removal of item from the hash table. 124 * 125 * @param item Item that was removed from the hash table. 126 * 127 */ 128 static void p2i_remove(ht_link_t *item) 129 { 130 assert(item); 131 free(hash_table_get_inst(item, p2i_entry_t, link)); 132 } 133 134 /** Operations for task hash table. */ 135 static hash_table_ops_t p2i_ops = { 136 .hash = p2i_hash, 137 .key_hash = p2i_key_hash, 138 .key_equal = p2i_key_equal, 139 .equal = NULL, 140 .remove_callback = p2i_remove 141 }; 142 143 /** Map phone hash to task ID */ 144 static hash_table_t phone_to_id; 107 static FIBRIL_RWLOCK_INITIALIZE(task_hash_table_lock); 145 108 146 109 /** Pending task wait structure. */ … … 149 112 task_id_t id; /**< Task ID. */ 150 113 ipc_callid_t callid; /**< Call ID waiting for the connection */ 151 int flags; /**< Wait flags TODO*/114 int flags; /**< Wait flags */ 152 115 } pending_wait_t; 153 116 154 117 static list_t pending_wait; 118 static FIBRIL_RWLOCK_INITIALIZE(pending_wait_lock); 155 119 156 120 int task_init(void) … … 161 125 } 162 126 163 if (!hash_table_create(&phone_to_id, 0, 0, &p2i_ops)) {164 printf(NAME ": No memory available for tasks\n");165 return ENOMEM;166 }167 168 127 list_initialize(&pending_wait); 169 128 return EOK; 170 129 } 171 130 172 /** Process pending wait requests */ 131 /** Process pending wait requests 132 * 133 * Assumes task_hash_table_lock is hold (at least read) 134 */ 173 135 void process_pending_wait(void) 174 136 { 175 task_exit_t texit; 176 137 fibril_rwlock_write_lock(&pending_wait_lock); 177 138 loop: 178 // W lock179 139 list_foreach(pending_wait, link, pending_wait_t, pr) { 180 // R lock task_hash_table181 140 ht_link_t *link = hash_table_find(&task_hash_table, &pr->id); 182 // R unlock task_hash_table183 141 if (!link) 184 142 continue; 185 143 186 144 hashed_task_t *ht = hash_table_get_inst(link, hashed_task_t, link); 187 if (ht->exit == TASK_EXIT_RUNNING) 188 continue; 189 190 if (!(pr->callid & IPC_CALLID_NOTIFICATION)) { 191 texit = ht->exit; 192 async_answer_2(pr->callid, EOK, texit, 193 ht->retval); 145 int notify_flags = 0; 146 if (ht->exit != TASK_EXIT_RUNNING) { 147 notify_flags |= TASK_WAIT_EXIT; 148 if (ht->retval_type == RVAL_SET_EXIT) { 149 notify_flags |= TASK_WAIT_RETVAL; 150 } 194 151 } 152 if (ht->retval_type == RVAL_SET) { 153 notify_flags |= TASK_WAIT_RETVAL; 154 } 155 156 int match = notify_flags & pr->flags; 157 bool answer = !(pr->callid & IPC_CALLID_NOTIFICATION); 158 159 if (match == 0) { 160 if (notify_flags & TASK_WAIT_EXIT) { 161 /* Nothing to wait for anymore */ 162 if (answer) { 163 async_answer_0(pr->callid, EINVAL); 164 } 165 } else { 166 /* Maybe later */ 167 continue; 168 } 169 } else if (answer) { 170 /* Send both exit status and retval, caller should know 171 * what is valid */ 172 async_answer_2(pr->callid, EOK, ht->exit, ht->retval); 173 } 174 195 175 196 176 list_remove(&pr->link); … … 198 178 goto loop; 199 179 } 200 // W unlock180 fibril_rwlock_write_unlock(&pending_wait_lock); 201 181 } 202 182 203 183 void wait_for_task(task_id_t id, int flags, ipc_callid_t callid, ipc_call_t *call) 204 184 { 205 // R lock185 fibril_rwlock_read_lock(&task_hash_table_lock); 206 186 ht_link_t *link = hash_table_find(&task_hash_table, &id); 207 // R unlock 187 fibril_rwlock_read_unlock(&task_hash_table_lock); 188 208 189 hashed_task_t *ht = (link != NULL) ? 209 190 hash_table_get_inst(link, hashed_task_t, link) : NULL; … … 235 216 pr->flags = flags; 236 217 pr->callid = callid; 237 // W lock 218 219 fibril_rwlock_write_lock(&pending_wait_lock); 238 220 list_append(&pr->link, &pending_wait); 239 // W unlock 240 } 241 242 int task_id_intro(ipc_call_t *call) 243 { 244 // TODO think about task_id reuse and this 245 // R lock 221 fibril_rwlock_write_unlock(&pending_wait_lock); 222 } 223 224 int task_intro(ipc_call_t *call, bool check_unique) 225 { 226 int rc = EOK; 227 228 fibril_rwlock_write_lock(&task_hash_table_lock); 229 246 230 ht_link_t *link = hash_table_find(&task_hash_table, &call->in_task_id); 247 // R unlock 248 if (link != NULL) 249 return EEXISTS; 231 if (link != NULL) { 232 rc = EEXISTS; 233 goto finish; 234 } 250 235 251 236 hashed_task_t *ht = (hashed_task_t *) malloc(sizeof(hashed_task_t)); 252 if (ht == NULL) 253 return ENOMEM; 237 if (ht == NULL) { 238 rc = ENOMEM; 239 goto finish; 240 } 254 241 255 242 /* … … 258 245 ht->id = call->in_task_id; 259 246 ht->exit = TASK_EXIT_RUNNING; 260 ht-> have_rval = false;247 ht->retval_type = RVAL_UNSET; 261 248 ht->retval = -1; 262 // W lock 249 263 250 hash_table_insert(&task_hash_table, &ht->link); 264 // W unlock 265 266 return EOK; 251 252 finish: 253 fibril_rwlock_write_unlock(&task_hash_table_lock); 254 return rc; 267 255 } 268 256 269 257 int task_set_retval(ipc_call_t *call) 270 258 { 259 int rc = EOK; 271 260 task_id_t id = call->in_task_id; 272 261 273 // R lock262 fibril_rwlock_read_lock(&task_hash_table_lock); 274 263 ht_link_t *link = hash_table_find(&task_hash_table, &id); 275 // R unlock 264 276 265 hashed_task_t *ht = (link != NULL) ? 277 266 hash_table_get_inst(link, hashed_task_t, link) : NULL; 278 267 279 if ((ht == NULL) || (ht->exit != TASK_EXIT_RUNNING)) 280 r eturnEINVAL;281 282 // TODO process additional flag to retval283 ht->have_rval = true;268 if ((ht == NULL) || (ht->exit != TASK_EXIT_RUNNING)) { 269 rc = EINVAL; 270 goto finish; 271 } 272 284 273 ht->retval = IPC_GET_ARG1(*call); 274 ht->retval_type = IPC_GET_ARG2(*call) ? RVAL_SET_EXIT : RVAL_SET; 285 275 286 276 process_pending_wait(); 287 277 288 return EOK; 278 finish: 279 fibril_rwlock_read_unlock(&task_hash_table_lock); 280 return rc; 289 281 } 290 282 … … 292 284 { 293 285 /* Mark task as finished. */ 294 // R lock286 fibril_rwlock_write_lock(&task_hash_table_lock); 295 287 ht_link_t *link = hash_table_find(&task_hash_table, &id); 296 // R unlock297 if (link == NULL)298 return;288 if (link == NULL) { 289 goto finish; 290 } 299 291 300 292 hashed_task_t *ht = hash_table_get_inst(link, hashed_task_t, link); 301 293 302 ht->exit = texit; 294 if (ht->retval_type == RVAL_UNSET) { 295 ht->exit = TASK_EXIT_UNEXPECTED; 296 } else { 297 ht->exit = texit; 298 } 303 299 process_pending_wait(); 304 300 305 // W lock306 301 hash_table_remove_item(&task_hash_table, &ht->link); 307 // W unlock 302 finish: 303 fibril_rwlock_write_unlock(&task_hash_table_lock); 308 304 } 309 305 -
uspace/srv/taskman/task.h
r62273d1 r2f44fafd 44 44 extern int task_set_retval(ipc_call_t *); 45 45 46 extern int task_i d_intro(ipc_call_t *);46 extern int task_intro(ipc_call_t *, bool); 47 47 extern void task_terminated(task_id_t, task_exit_t); 48 48
Note:
See TracChangeset
for help on using the changeset viewer.