Changeset d4ec49e in mainline for uspace/srv/taskman/task.c
- 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)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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.