Changeset 43e2cbc in mainline
- Timestamp:
- 2016-09-10T13:56:43Z (8 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 0b00599
- Parents:
- 838ea8aa
- Location:
- kernel/generic/src/ipc
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/ipc.c
r838ea8aa r43e2cbc 59 59 #include <ipc/irq.h> 60 60 61 static void ipc_forget_call(call_t *); 62 61 63 /** Open channel that is assigned automatically to new tasks */ 62 64 answerbox_t *ipc_phone_0 = NULL; … … 209 211 return rc; 210 212 } 211 // TODO: forget the call if interrupted 212 (void) ipc_wait_for_call(mybox, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE); 213 214 call_t *answer = ipc_wait_for_call(mybox, SYNCH_NO_TIMEOUT, 215 SYNCH_FLAGS_INTERRUPTIBLE); 216 if (!answer) { 217 218 /* 219 * The sleep was interrupted. 220 * 221 * There are two possibilities now: 222 * 1) the call gets answered before we manage to forget it 223 * 2) we manage to forget the call before it gets answered 224 */ 225 226 spinlock_lock(&request->forget_lock); 227 spinlock_lock(&TASK->active_calls_lock); 228 229 ASSERT(!request->forget); 230 231 bool answered = !request->active; 232 if (!answered) { 233 /* 234 * The call is not yet answered and we won the race to 235 * forget it. 236 */ 237 ipc_forget_call(request); /* releases locks */ 238 rc = EINTR; 239 240 } else { 241 spinlock_unlock(&TASK->active_calls_lock); 242 spinlock_unlock(&request->forget_lock); 243 } 244 245 if (answered) { 246 /* 247 * The other side won the race to answer the call. 248 * It is safe to wait for the answer uninterruptibly 249 * now. 250 */ 251 answer = ipc_wait_for_call(mybox, SYNCH_NO_TIMEOUT, 252 SYNCH_FLAGS_NONE); 253 } 254 } 255 ASSERT(!answer || request == answer); 213 256 214 257 slab_free(ipc_answerbox_slab, mybox); 215 return EOK;258 return rc; 216 259 } 217 260 … … 621 664 } 622 665 666 static void ipc_forget_call(call_t *call) 667 { 668 ASSERT(spinlock_locked(&TASK->active_calls_lock)); 669 ASSERT(spinlock_locked(&call->forget_lock)); 670 671 /* 672 * Forget the call and donate it to the task which holds up the answer. 673 */ 674 675 call->forget = true; 676 call->sender = NULL; 677 list_remove(&call->ta_link); 678 679 /* 680 * The call may be freed by _ipc_answer_free_call() before we are done 681 * with it; to avoid working with a destroyed call_t structure, we 682 * must hold a reference to it. 683 */ 684 ipc_call_hold(call); 685 686 spinlock_unlock(&call->forget_lock); 687 spinlock_unlock(&TASK->active_calls_lock); 688 689 atomic_dec(&call->caller_phone->active_calls); 690 691 SYSIPC_OP(request_forget, call); 692 693 ipc_call_release(call); 694 } 695 623 696 static void ipc_forget_all_active_calls(void) 624 697 { … … 649 722 } 650 723 651 /* 652 * Forget the call and donate it to the task which holds up the answer. 653 */ 654 655 call->forget = true; 656 call->sender = NULL; 657 list_remove(&call->ta_link); 658 659 /* 660 * The call may be freed by _ipc_answer_free_call() before we are done 661 * with it; to avoid working with a destroyed call_t structure, we 662 * must hold a reference to it. 663 */ 664 ipc_call_hold(call); 665 666 spinlock_unlock(&call->forget_lock); 667 spinlock_unlock(&TASK->active_calls_lock); 668 669 atomic_dec(&call->caller_phone->active_calls); 670 671 SYSIPC_OP(request_forget, call); 672 673 ipc_call_release(call); 724 ipc_forget_call(call); 674 725 675 726 goto restart; -
kernel/generic/src/ipc/sysipc.c
r838ea8aa r43e2cbc 285 285 #endif 286 286 287 rc = ipc_call_sync(phone, call); 287 ipc_call_hold(call); 288 rc = ipc_call_sync(phone, call); 289 spinlock_lock(&call->forget_lock); 290 bool forgotten = call->forget; 291 spinlock_unlock(&call->forget_lock); 292 ipc_call_release(call); 288 293 289 294 #ifdef CONFIG_UDEBUG … … 291 296 #endif 292 297 293 if (rc != EOK) 294 return EINTR; 298 if (rc != EOK) { 299 if (!forgotten) { 300 /* 301 * There was an error, but it did not result 302 * in the call being forgotten. In fact, the 303 * call was not even sent. We are still 304 * its owners and are responsible for its 305 * deallocation. 306 */ 307 ipc_call_free(call); 308 } else { 309 /* 310 * The call was forgotten and it changed hands. 311 * We are no longer expected to free it. 312 */ 313 ASSERT(rc == EINTR); 314 } 315 return rc; 316 } 295 317 296 318 process_answer(call);
Note:
See TracChangeset
for help on using the changeset viewer.