Changeset d4ec49e in mainline
- Timestamp:
- 2019-08-07T05:25:59Z (6 years ago)
- Children:
- 3ea98e8
- Parents:
- 55fe220
- git-author:
- Michal Koutný <xm.koutny+hos@…> (2015-10-14 23:13:41)
- git-committer:
- Matthieu Riolo <matthieu.riolo@…> (2019-08-07 05:25:59)
- Location:
- uspace
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/tester/proc/task_wait.c
r55fe220 rd4ec49e 74 74 75 75 TPRINTF("waiting..."); 76 rc = task_wait(&wait, &texit, &retval); 77 TPRINTF("done.\n"); 78 TASSERT(rc == EOK); 76 texit = TASK_EXIT_RUNNING; retval = 255; 77 rc = task_wait(&wait, &texit, &retval); 78 TPRINTF("done.\n"); 79 TASSERT(rc == EOK); 80 TASSERT(task_wait_get(&wait) == 0); 79 81 TASSERT(texit == TASK_EXIT_UNEXPECTED); 80 82 TPRINTF("OK\n"); … … 88 90 89 91 TPRINTF("waiting..."); 92 texit = TASK_EXIT_RUNNING; retval = 255; 90 93 rc = task_wait(&wait, &texit, &retval); 91 94 TPRINTF("done.\n"); 92 95 TASSERT(rc == EINVAL); 96 TASSERT(task_wait_get(&wait) == 0); 93 97 TPRINTF("OK\n"); 94 98 /* ---- */ … … 101 105 102 106 TPRINTF("waiting..."); 103 rc = task_wait(&wait, &texit, &retval); 104 TPRINTF("done.\n"); 105 TASSERT(rc == EOK); 107 texit = TASK_EXIT_RUNNING; retval = 255; 108 rc = task_wait(&wait, &texit, &retval); 109 TPRINTF("done.\n"); 110 TASSERT(rc == EOK); 111 TASSERT(task_wait_get(&wait) == 0); 106 112 TASSERT(texit == TASK_EXIT_UNEXPECTED); 107 113 /* retval is undefined */ … … 109 115 /* ---- */ 110 116 111 TPRINTF("21 ignore retval \n");117 TPRINTF("21 ignore retval and still wait for exit\n"); 112 118 113 119 task_wait_set(&wait, TASK_WAIT_EXIT); 114 rc = dummy_task_spawn(&tid, &wait, STR_JOB_OK); 115 TASSERT(rc == EOK); 116 117 TPRINTF("waiting..."); 118 rc = task_wait(&wait, &texit, &retval); 119 TPRINTF("done.\n"); 120 TASSERT(rc == EOK); 120 /* STR_JOB_OK to emulate daemon that eventually terminates */ 121 rc = dummy_task_spawn(&tid, &wait, STR_JOB_OK); 122 TASSERT(rc == EOK); 123 124 TPRINTF("waiting..."); 125 texit = TASK_EXIT_RUNNING; retval = 255; 126 rc = task_wait(&wait, &texit, &retval); 127 TPRINTF("done.\n"); 128 TASSERT(rc == EOK); 129 TASSERT(task_wait_get(&wait) == 0); 121 130 TASSERT(texit == TASK_EXIT_NORMAL); 122 131 /* retval is unknown */ … … 131 140 132 141 TPRINTF("waiting..."); 133 rc = task_wait(&wait, &texit, &retval); 134 TPRINTF("done.\n"); 135 TASSERT(rc == EOK); 142 texit = TASK_EXIT_RUNNING; retval = 255; 143 rc = task_wait(&wait, &texit, &retval); 144 TPRINTF("done.\n"); 145 TASSERT(rc == EOK); 146 TASSERT(task_wait_get(&wait) == 0); 136 147 /* exit is not expected */ 137 148 TASSERT(retval == EOK); … … 142 153 TPRINTF("23 partial match (non-exited task)\n"); 143 154 144 // TODO should update wait for synchronized exit waiting145 155 task_wait_set(&wait, TASK_WAIT_RETVAL | TASK_WAIT_EXIT); 146 156 rc = dummy_task_spawn(&tid, &wait, STR_DAEMON); … … 148 158 149 159 TPRINTF("waiting..."); 150 rc = task_wait(&wait, &texit, &retval); 151 TPRINTF("done.\n"); 152 TASSERT(rc == EOK); 160 texit = TASK_EXIT_RUNNING; retval = 255; 161 rc = task_wait(&wait, &texit, &retval); 162 TPRINTF("done.\n"); 163 TASSERT(rc == EOK); 164 TASSERT(task_wait_get(&wait) == TASK_WAIT_EXIT); 153 165 /* exit is not expected */ 154 166 TASSERT(retval == EOK); … … 164 176 165 177 TPRINTF("waiting..."); 166 rc = task_wait(&wait, &texit, &retval); 167 TPRINTF("done.\n"); 168 TASSERT(rc == EOK); 178 texit = TASK_EXIT_RUNNING; retval = 255; 179 rc = task_wait(&wait, &texit, &retval); 180 TPRINTF("done.\n"); 181 TASSERT(rc == EOK); 182 TASSERT(task_wait_get(&wait) == 0); 169 183 TASSERT(texit == TASK_EXIT_NORMAL); 170 184 /* retval is unknown */ … … 180 194 181 195 TPRINTF("waiting..."); 182 rc = task_wait(&wait, &texit, &retval); 183 TPRINTF("done.\n"); 184 TASSERT(rc == EOK); 196 texit = TASK_EXIT_RUNNING; retval = 255; 197 rc = task_wait(&wait, &texit, &retval); 198 TPRINTF("done.\n"); 199 TASSERT(rc == EOK); 200 /* Job atomically exited, so there's nothing more to wait for. */ 201 TASSERT(task_wait_get(&wait) == 0); 185 202 /* exit is unknown */ 186 203 TASSERT(retval == EOK); … … 198 215 199 216 TPRINTF("waiting..."); 200 rc = task_wait(&wait, &texit, &retval); 201 TPRINTF("done.\n"); 202 TASSERT(rc == EOK); 217 texit = TASK_EXIT_RUNNING; retval = 255; 218 rc = task_wait(&wait, &texit, &retval); 219 TPRINTF("done.\n"); 220 TASSERT(rc == EOK); 221 TASSERT(task_wait_get(&wait) == 0); 222 TASSERT(texit == TASK_EXIT_NORMAL); 223 TASSERT(retval == EOK); 224 TPRINTF("OK\n"); 225 /* ---- */ 226 227 TPRINTF("14 partially lost wait\n"); 228 229 task_wait_set(&wait, TASK_WAIT_BOTH); 230 rc = dummy_task_spawn(&tid, &wait, STR_FAIL); 231 TASSERT(rc == EOK); 232 233 TPRINTF("waiting..."); 234 texit = TASK_EXIT_RUNNING; retval = 255; 235 rc = task_wait(&wait, &texit, &retval); 236 TPRINTF("done.\n"); 237 TASSERT(rc == EINVAL); 238 TASSERT(task_wait_get(&wait) == 0); 239 TASSERT(texit == TASK_EXIT_UNEXPECTED); 240 /* retval is undefined */ 241 TPRINTF("OK\n"); 242 /* ---- */ 243 244 TPRINTF("24 repeated wait\n"); 245 246 task_wait_set(&wait, TASK_WAIT_BOTH); 247 rc = dummy_task_spawn(&tid, &wait, STR_DAEMON); 248 TASSERT(rc == EOK); 249 250 TPRINTF("waiting..."); 251 texit = TASK_EXIT_RUNNING; retval = 255; 252 rc = task_wait(&wait, &texit, &retval); 253 TPRINTF("done.\n"); 254 TASSERT(rc == EOK); 255 TASSERT(task_wait_get(&wait) == TASK_WAIT_EXIT); 256 TASSERT(retval == EOK); 257 task_kill(tid); /* Terminate daemon */ 258 TPRINTF("waiting 2..."); 259 texit = TASK_EXIT_RUNNING; retval = 255; 260 rc = task_wait(&wait, &texit, &retval); 261 TPRINTF("done.\n"); 262 TASSERT(rc == EOK); 263 TASSERT(task_wait_get(&wait) == 0); 264 //TASSERT(texit == TASK_EXIT_UNEXPECTED); // TODO resolve this in taskman/kernel 265 TPRINTF("OK\n"); 266 /* ---- */ 267 268 TPRINTF("34 double wait in one\n"); 269 270 task_wait_set(&wait, TASK_WAIT_BOTH); 271 rc = dummy_task_spawn(&tid, &wait, STR_JOB_OK); 272 TASSERT(rc == EOK); 273 274 TPRINTF("waiting..."); 275 texit = TASK_EXIT_RUNNING; retval = 255; 276 rc = task_wait(&wait, &texit, &retval); 277 TPRINTF("done.\n"); 278 TASSERT(rc == EOK); 279 TASSERT(task_wait_get(&wait) == 0); 203 280 TASSERT(texit == TASK_EXIT_NORMAL); 204 281 TASSERT(retval == EOK); -
uspace/lib/c/generic/task.c
r55fe220 rd4ec49e 128 128 * 129 129 * @return EOK on success, else error code. 130 * @return TODO check this doesn't return EINVAL -- clash with task_wait 130 131 */ 131 132 static errno_t task_setup_wait(task_id_t id, task_wait_t *wait) 132 133 { 133 134 assert(wait->flags); 135 if (wait->flags & TASK_WAIT_BOTH) { 136 wait->flags |= (TASK_WAIT_RETVAL | TASK_WAIT_EXIT); 137 } 138 wait->tid = id; 134 139 async_exch_t *exch = taskman_exchange_begin(); 135 140 if (exch == NULL) … … 391 396 * @param retval Store return value of the task here. 392 397 * 393 * @return EOK on success, else error code. 398 * @return EOK on success 399 * @return EINVAL on lost wait TODO other error codes 394 400 */ 395 401 errno_t task_wait(task_wait_t *wait, task_exit_t *texit, int *retval) … … 397 403 errno_t rc; 398 404 async_wait_for(wait->aid, &rc); 399 400 if (rc == EOK ) {405 406 if (rc == EOK || rc == EINVAL) { 401 407 if (wait->flags & TASK_WAIT_EXIT && texit) 402 408 *texit = ipc_get_arg1(wait->result); 403 409 if (wait->flags & TASK_WAIT_RETVAL && retval) 404 410 *retval = ipc_get_arg2(wait->result); 411 412 } 413 414 if (rc == EOK) { 415 /* Is there another wait to be done? Wait for it! */ 416 int old_flags = wait->flags; 417 wait->flags = ipc_get_arg3(wait->result); 418 if (wait->flags != 0 && (old_flags & TASK_WAIT_BOTH)) { 419 rc = task_setup_wait(wait->tid, wait); 420 } 421 } else { 422 wait->flags = 0; 405 423 } 406 424 -
uspace/lib/c/include/task.h
r55fe220 rd4ec49e 44 44 #define TASK_WAIT_EXIT 0x1 45 45 #define TASK_WAIT_RETVAL 0x2 46 #define TASK_WAIT_BOTH 0x4 46 47 47 48 typedef struct { … … 49 50 ipc_call_t result; 50 51 aid_t aid; 52 task_id_t tid; 51 53 } task_wait_t; 52 54 … … 54 56 { 55 57 wait->flags = flags; 58 } 59 60 static inline int task_wait_get(task_wait_t *wait) 61 { 62 return wait->flags; 56 63 } 57 64 … … 84 91 85 92 extern errno_t task_retval(int); 86 //TODO87 //extern int task_exit(int);88 93 89 94 #endif -
uspace/srv/taskman/main.c
r55fe220 rd4ec49e 115 115 static void taskman_ctl_retval(ipc_callid_t iid, ipc_call_t *icall) 116 116 { 117 printf("%s:%i \n", __func__, __LINE__);117 printf("%s:%i from %llu\n", __func__, __LINE__, icall->in_task_id); 118 118 int rc = task_set_retval(icall); 119 119 async_answer_0(iid, rc); … … 122 122 static void task_exit_event(ipc_callid_t iid, ipc_call_t *icall, void *arg) 123 123 { 124 printf("%s:%i\n", __func__, __LINE__);125 124 // TODO design substitution for taskmon (monitoring) 126 125 task_id_t id = MERGE_LOUP32(IPC_GET_ARG1(*icall), IPC_GET_ARG2(*icall)); 126 printf("%s:%i from %llu/%i\n", __func__, __LINE__, id, (task_exit_t)arg); 127 127 task_terminated(id, (task_exit_t)arg); 128 128 } -
uspace/srv/taskman/task.c
r55fe220 rd4ec49e 110 110 typedef struct { 111 111 link_t link; 112 task_id_t id; /**< Task ID. */ 112 task_id_t id; /**< Task ID who we wait for. */ 113 task_id_t waiter_id; /**< Task ID who waits. */ 113 114 ipc_callid_t callid; /**< Call ID waiting for the connection */ 114 115 int flags; /**< Wait flags */ … … 154 155 } 155 156 157 /* 158 * In current implementation you can wait for single retval, 159 * thus it can be never present in rest flags. 160 */ 161 int rest = (~notify_flags & pr->flags) & ~TASK_WAIT_RETVAL; 162 rest &= ~TASK_WAIT_BOTH; 156 163 int match = notify_flags & pr->flags; 157 164 bool answer = !(pr->callid & IPC_CALLID_NOTIFICATION); 165 printf("%s: %x; %x, %x\n", __func__, pr->flags, rest, match); 158 166 159 167 if (match == 0) { … … 168 176 } 169 177 } 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); 178 if ((pr->flags & TASK_WAIT_BOTH) && match == TASK_WAIT_EXIT) { 179 async_answer_1(pr->callid, EINVAL, ht->exit); 180 } else { 181 /* Send both exit status and retval, caller 182 * should know what is valid */ 183 async_answer_3(pr->callid, EOK, ht->exit, 184 ht->retval, rest); 185 } 186 187 /* Pending wait has one more chance */ 188 if (rest && (pr->flags & TASK_WAIT_BOTH)) { 189 pr->flags = rest | TASK_WAIT_BOTH; 190 continue; 191 } 173 192 } 174 193 … … 183 202 void wait_for_task(task_id_t id, int flags, ipc_callid_t callid, ipc_call_t *call) 184 203 { 204 assert(!(flags & TASK_WAIT_BOTH) || 205 ((flags & TASK_WAIT_RETVAL) && (flags & TASK_WAIT_EXIT))); 206 185 207 fibril_rwlock_read_lock(&task_hash_table_lock); 186 208 ht_link_t *link = hash_table_find(&task_hash_table, &id); … … 197 219 198 220 if (ht->exit != TASK_EXIT_RUNNING) { 199 task_exit_t texit = ht->exit;200 async_answer_ 2(callid, EOK, texit, ht->retval);221 //TODO are flags BOTH processed correctly here? 222 async_answer_3(callid, EOK, ht->exit, ht->retval, 0); 201 223 return; 202 224 } 203 225 204 /* Add to pending list */ 205 pending_wait_t *pr = 206 (pending_wait_t *) malloc(sizeof(pending_wait_t)); 207 if (!pr) { 208 // TODO why IPC_CALLID_NOTIFICATION? explain! 209 if (!(callid & IPC_CALLID_NOTIFICATION)) 210 async_answer_0(callid, ENOMEM); 211 return; 212 } 213 214 link_initialize(&pr->link); 215 pr->id = id; 216 pr->flags = flags; 217 pr->callid = callid; 218 226 /* 227 * Add request to pending list or reuse existing item for a second 228 * wait. 229 */ 230 task_id_t waiter_id = call->in_task_id; 219 231 fibril_rwlock_write_lock(&pending_wait_lock); 220 list_append(&pr->link, &pending_wait); 232 pending_wait_t *pr = NULL; 233 list_foreach(pending_wait, link, pending_wait_t, it) { 234 if (it->id == id && it->waiter_id == waiter_id) { 235 pr = it; 236 break; 237 } 238 } 239 240 int rc = EOK; 241 bool reuse = false; 242 if (pr == NULL) { 243 pr = malloc(sizeof(pending_wait_t)); 244 if (!pr) { 245 rc = ENOMEM; 246 goto finish; 247 } 248 249 link_initialize(&pr->link); 250 pr->id = id; 251 pr->waiter_id = waiter_id; 252 pr->flags = flags; 253 pr->callid = callid; 254 255 list_append(&pr->link, &pending_wait); 256 rc = EOK; 257 } else if (!(pr->flags & TASK_WAIT_BOTH)) { 258 /* 259 * One task can wait for another task only once (per task, not 260 * fibril). 261 */ 262 rc = EEXISTS; 263 } else { 264 /* 265 * Reuse pending wait for the second time. 266 */ 267 pr->flags &= ~TASK_WAIT_BOTH; // TODO maybe new flags should be set? 268 pr->callid = callid; 269 reuse = true; 270 } 271 printf("%s: %llu: %x, %x, %i\n", __func__, pr->id, flags, pr->flags, reuse); 272 273 finish: 221 274 fibril_rwlock_write_unlock(&pending_wait_lock); 275 // TODO why IPC_CALLID_NOTIFICATION? explain! 276 if (rc != EOK && !(callid & IPC_CALLID_NOTIFICATION)) 277 async_answer_0(callid, rc); 278 222 279 } 223 280 … … 249 306 250 307 hash_table_insert(&task_hash_table, &ht->link); 308 printf("%s: %llu\n", __func__, ht->id); 251 309 252 310 finish: … … 260 318 task_id_t id = call->in_task_id; 261 319 262 fibril_rwlock_ read_lock(&task_hash_table_lock);320 fibril_rwlock_write_lock(&task_hash_table_lock); 263 321 ht_link_t *link = hash_table_find(&task_hash_table, &id); 264 322 … … 277 335 278 336 finish: 279 fibril_rwlock_ read_unlock(&task_hash_table_lock);337 fibril_rwlock_write_unlock(&task_hash_table_lock); 280 338 return rc; 281 339 } … … 292 350 hashed_task_t *ht = hash_table_get_inst(link, hashed_task_t, link); 293 351 294 if (ht->retval_type == RVAL_UNSET) { 352 /* 353 * If daemon returns a value and then fails/is killed, it's unexpected 354 * termination. 355 */ 356 if (ht->retval_type == RVAL_UNSET || texit == TASK_EXIT_UNEXPECTED) { 295 357 ht->exit = TASK_EXIT_UNEXPECTED; 296 358 } else {
Note:
See TracChangeset
for help on using the changeset viewer.