Changeset 51ec40f in mainline
- Timestamp:
- 2007-05-18T10:27:01Z (18 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f6d2c81
- Parents:
- ddf1255
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/ipcrsc.c
rddf1255 r51ec40f 35 35 /* IPC resources management 36 36 * 37 * The goal of this source code is to properly manage IPC resources 38 * and allowstraight and clean clean-up procedure upon task termination.37 * The goal of this source code is to properly manage IPC resources and allow 38 * straight and clean clean-up procedure upon task termination. 39 39 * 40 40 * The pattern of usage of the resources is: … … 48 48 * Locking strategy 49 49 * 50 * - To use a phone, disconnect a phone etc., the phone must be 51 * first locked andthen checked that it is connected52 * - To connect an allocated phone it need not be locked (assigning 53 * pointer isatomic on all platforms)50 * - To use a phone, disconnect a phone etc., the phone must be first locked and 51 * then checked that it is connected 52 * - To connect an allocated phone it need not be locked (assigning pointer is 53 * atomic on all platforms) 54 54 * 55 55 * - To find an empty phone slot, the TASK must be locked 56 56 * - To answer a message, the answerbox must be locked 57 57 * - The locking of phone and answerbox is done at the ipc_ level. 58 * It is perfectly correct to pass unconnected phone to these functions 59 * andproper reply will be generated.58 * It is perfectly correct to pass unconnected phone to these functions and 59 * proper reply will be generated. 60 60 * 61 61 * Locking order … … 63 63 * - first phone, then answerbox 64 64 * + Easy locking on calls 65 * - Very hard traversing list of phones when disconnecting because 66 * the phones may disconnect during traversal of list of connected phones.67 * The onlypossibility is try_lock with restart of list traversal.65 * - Very hard traversing list of phones when disconnecting because the phones 66 * may disconnect during traversal of list of connected phones. The only 67 * possibility is try_lock with restart of list traversal. 68 68 * 69 69 * Destroying is less frequent, this approach is taken. … … 72 72 * 73 73 * *** Connect_me_to *** 74 * The caller sends IPC_M_CONNECT_ME_TO to an answerbox. The server 75 * receives 'phoneid' of the connecting phone as an ARG3. If it answers76 * with RETVAL=0,the phonecall is accepted, otherwise it is refused.74 * The caller sends IPC_M_CONNECT_ME_TO to an answerbox. The server receives 75 * 'phoneid' of the connecting phone as an ARG3. If it answers with RETVAL=0, 76 * the phonecall is accepted, otherwise it is refused. 77 77 * 78 78 * *** Connect_to_me *** 79 * The caller sends IPC_M_CONNECT_TO_ME, with special 80 * The server receives an automatically 81 * opened phoneid. If it accepts (RETVAL=0), it can use the phoneid 82 * immediately. 83 * Possible race condition can arise, when the client receives messages 84 * from new connection before getting response for connect_to_me message. 85 * Userspace should implement handshake protocol that would control it. 79 * The caller sends IPC_M_CONNECT_TO_ME. 80 * The server receives an automatically opened phoneid. If it accepts 81 * (RETVAL=0), it can use the phoneid immediately. 82 * Possible race condition can arise, when the client receives messages from new 83 * connection before getting response for connect_to_me message. Userspace 84 * should implement handshake protocol that would control it. 86 85 * 87 86 * Phone hangup … … 89 88 * *** The caller hangs up (sys_ipc_hangup) *** 90 89 * - The phone is disconnected (no more messages can be sent over this phone), 91 * all in-progress messages are correctly handled. The an werbox receives90 * all in-progress messages are correctly handled. The answerbox receives 92 91 * IPC_M_PHONE_HUNGUP call from the phone that hung up. When all async 93 92 * calls are answered, the phone is deallocated. -
kernel/generic/src/ipc/sysipc.c
rddf1255 r51ec40f 50 50 #include <print.h> 51 51 52 #define GET_CHECK_PHONE(phone, phoneid,err) { \52 #define GET_CHECK_PHONE(phone, phoneid, err) { \ 53 53 if (phoneid > IPC_MAX_PHONES) { err; } \ 54 54 phone = &TASK->phones[phoneid]; \ 55 55 } 56 56 57 #define STRUCT_TO_USPACE(dst, src) copy_to_uspace(dst,src,sizeof(*(src)))57 #define STRUCT_TO_USPACE(dst, src) copy_to_uspace(dst, src, sizeof(*(src))) 58 58 59 59 /** Return true if the method is a system method */ … … 72 72 static inline int is_forwardable(unative_t method) 73 73 { 74 if (method == IPC_M_PHONE_HUNGUP || method == IPC_M_AS_AREA_SEND \75 ||method == IPC_M_AS_AREA_RECV)74 if (method == IPC_M_PHONE_HUNGUP || method == IPC_M_AS_AREA_SEND || 75 method == IPC_M_AS_AREA_RECV) 76 76 return 0; /* This message is meant only for the receiver */ 77 77 return 1; … … 131 131 } else { 132 132 /* The connection was accepted */ 133 phone_connect(phoneid, &answer->sender->answerbox);133 phone_connect(phoneid, &answer->sender->answerbox); 134 134 /* Set 'phone identification' as arg3 of response */ 135 IPC_SET_ARG3(answer->data, (unative_t)&TASK->phones[phoneid]); 135 IPC_SET_ARG3(answer->data, 136 (unative_t) &TASK->phones[phoneid]); 136 137 } 137 138 } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_ME_TO) { 138 139 /* If the users accepted call, connect */ 139 140 if (!IPC_GET_RETVAL(answer->data)) { 140 ipc_phone_connect((phone_t *) IPC_GET_ARG3(*olddata),141 141 ipc_phone_connect((phone_t *) IPC_GET_ARG3(*olddata), 142 &TASK->answerbox); 142 143 } 143 144 } else if (IPC_GET_METHOD(*olddata) == IPC_M_AS_AREA_SEND) { 144 if (!IPC_GET_RETVAL(answer->data)) { /* Accepted, handle as_area receipt */ 145 if (!IPC_GET_RETVAL(answer->data)) { 146 /* Accepted, handle as_area receipt */ 145 147 ipl_t ipl; 146 148 int rc; … … 153 155 interrupts_restore(ipl); 154 156 155 rc = as_area_share(as, IPC_GET_ARG1(*olddata), IPC_GET_ARG2(*olddata), 156 AS, IPC_GET_ARG1(answer->data), IPC_GET_ARG3(*olddata)); 157 rc = as_area_share(as, IPC_GET_ARG1(*olddata), 158 IPC_GET_ARG2(*olddata), AS, 159 IPC_GET_ARG1(answer->data), IPC_GET_ARG3(*olddata)); 157 160 IPC_SET_RETVAL(answer->data, rc); 158 161 return rc; … … 170 173 interrupts_restore(ipl); 171 174 172 rc = as_area_share(AS, IPC_GET_ARG1(answer->data), IPC_GET_ARG2(*olddata), 173 as, IPC_GET_ARG1(*olddata), IPC_GET_ARG2(answer->data)); 175 rc = as_area_share(AS, IPC_GET_ARG1(answer->data), 176 IPC_GET_ARG2(*olddata), as, IPC_GET_ARG1(*olddata), 177 IPC_GET_ARG2(answer->data)); 174 178 IPC_SET_RETVAL(answer->data, rc); 175 179 } … … 193 197 return ELIMIT; 194 198 /* Set arg3 for server */ 195 IPC_SET_ARG3(call->data, (unative_t) &TASK->phones[newphid]);199 IPC_SET_ARG3(call->data, (unative_t) &TASK->phones[newphid]); 196 200 call->flags |= IPC_CALL_CONN_ME_TO; 197 201 call->priv = newphid; … … 218 222 static void process_answer(call_t *call) 219 223 { 220 if (IPC_GET_RETVAL(call->data) == EHANGUP && \221 call->flags & IPC_CALL_FORWARDED)224 if (IPC_GET_RETVAL(call->data) == EHANGUP && 225 (call->flags & IPC_CALL_FORWARDED)) 222 226 IPC_SET_RETVAL(call->data, EFORWARD); 223 227 … … 234 238 * @return 0 - the call should be passed to userspace, 1 - ignore call 235 239 */ 236 static int process_request(answerbox_t *box, call_t *call)240 static int process_request(answerbox_t *box, call_t *call) 237 241 { 238 242 int phoneid; … … 255 259 -2 on 'Too many async request, handle answers first 256 260 */ 257 unative_t sys_ipc_call_sync_fast(unative_t phoneid, unative_t method, 258 261 unative_t sys_ipc_call_sync_fast(unative_t phoneid, unative_t method, 262 unative_t arg1, ipc_data_t *data) 259 263 { 260 264 call_t call; … … 279 283 280 284 /** Synchronous IPC call allowing to send whole message */ 281 unative_t sys_ipc_call_sync(unative_t phoneid, ipc_data_t *question, 282 285 unative_t sys_ipc_call_sync(unative_t phoneid, ipc_data_t *question, 286 ipc_data_t *reply) 283 287 { 284 288 call_t call; … … 288 292 289 293 ipc_call_static_init(&call); 290 rc = copy_from_uspace(&call.data.args, &question->args, sizeof(call.data.args)); 294 rc = copy_from_uspace(&call.data.args, &question->args, 295 sizeof(call.data.args)); 291 296 if (rc != 0) 292 297 return (unative_t) rc; … … 325 330 -2 on 'Too many async request, handle answers first 326 331 */ 327 unative_t sys_ipc_call_async_fast(unative_t phoneid, unative_t method, 328 332 unative_t sys_ipc_call_async_fast(unative_t phoneid, unative_t method, 333 unative_t arg1, unative_t arg2) 329 334 { 330 335 call_t *call; … … 343 348 IPC_SET_ARG3(call->data, 0); 344 349 345 if (!(res =request_preprocess(call)))350 if (!(res = request_preprocess(call))) 346 351 ipc_call(phone, call); 347 352 else … … 368 373 369 374 call = ipc_call_alloc(0); 370 rc = copy_from_uspace(&call->data.args, &data->args, sizeof(call->data.args)); 375 rc = copy_from_uspace(&call->data.args, &data->args, 376 sizeof(call->data.args)); 371 377 if (rc != 0) { 372 378 ipc_call_free(call); 373 379 return (unative_t) rc; 374 380 } 375 if (!(res =request_preprocess(call)))381 if (!(res = request_preprocess(call))) 376 382 ipc_call(phone, call); 377 383 else … … 389 395 */ 390 396 unative_t sys_ipc_forward_fast(unative_t callid, unative_t phoneid, 391 397 unative_t method, unative_t arg1) 392 398 { 393 399 call_t *call; … … 430 436 431 437 /** Send IPC answer */ 432 unative_t sys_ipc_answer_fast(unative_t callid, unative_t retval, 433 438 unative_t sys_ipc_answer_fast(unative_t callid, unative_t retval, 439 unative_t arg1, unative_t arg2) 434 440 { 435 441 call_t *call; … … 481 487 } 482 488 rc = copy_from_uspace(&call->data.args, &data->args, 483 489 sizeof(call->data.args)); 484 490 if (rc != 0) 485 491 return rc; … … 509 515 /** Wait for incoming ipc call or answer 510 516 * 511 * @param calldata Pointer to buffer where the call/answer data is stored 512 * @param usec Timeout. See waitq_sleep_timeout() for explanation. 513 * @param flags Select mode of sleep operation. See waitq_sleep_timeout() for explanation. 517 * @param calldata Pointer to buffer where the call/answer data is stored. 518 * @param usec Timeout. See waitq_sleep_timeout() for explanation. 519 * @param flags Select mode of sleep operation. See waitq_sleep_timeout() 520 * for explanation. 514 521 * 515 522 * @return Callid, if callid & 1, then the call is answer … … 520 527 521 528 restart: 522 call = ipc_wait_for_call(&TASK->answerbox, usec, flags | SYNCH_FLAGS_INTERRUPTIBLE); 529 call = ipc_wait_for_call(&TASK->answerbox, usec, 530 flags | SYNCH_FLAGS_INTERRUPTIBLE); 523 531 if (!call) 524 532 return 0; … … 575 583 * @return EPERM or a return code returned by ipc_irq_register(). 576 584 */ 577 unative_t sys_ipc_register_irq(inr_t inr, devno_t devno, unative_t method, irq_code_t *ucode) 585 unative_t sys_ipc_register_irq(inr_t inr, devno_t devno, unative_t method, 586 irq_code_t *ucode) 578 587 { 579 588 if (!(cap_get(TASK) & CAP_IRQ_REG)) -
uspace/libc/generic/ipc.c
rddf1255 r51ec40f 418 418 } 419 419 420 /** Ask destination to do a callback connection 421 * 422 * @return 0 - OK, error code 423 */ 424 int ipc_connect_to_me(int phoneid, int arg1, int arg2, ipcarg_t *phone) 425 { 426 return ipc_call_sync_3(phoneid, IPC_M_CONNECT_TO_ME, arg1, 427 arg2, 0, 0, 0, phone); 428 } 429 430 /** Ask through phone for a new connection to some service 431 * 432 * @return new phoneid - OK, error code 420 /** Ask destination to do a callback connection. 421 * 422 * @param phoneid Phone ID used for contacting the other side. 423 * @param arg1 User defined argument. 424 * @param arg2 User defined argument. 425 * @param phonehash Pointer to a place where the library will store an opaque 426 * identifier of the phone that will be used for incoming 427 * calls. 428 * @return Zero on success or a negative error code. 429 */ 430 int ipc_connect_to_me(int phoneid, int arg1, int arg2, ipcarg_t *phonehash) 431 { 432 return ipc_call_sync_3(phoneid, IPC_M_CONNECT_TO_ME, arg1, arg2, 0, 0, 0, 433 phonehash); 434 } 435 436 /** Ask through phone for a new connection to some service. 437 * 438 * @param phoneid Phone ID used for contacting the other side. 439 * @param arg1 User defined argument. 440 * @param arg2 User defined argument. 441 * 442 * @return New phone ID on success or a negative error code. 433 443 */ 434 444 int ipc_connect_me_to(int phoneid, int arg1, int arg2) … … 437 447 int res; 438 448 439 res = ipc_call_sync_3(phoneid, IPC_M_CONNECT_ME_TO, arg1, 440 arg2, 0, 0, 0,&newphid);449 res = ipc_call_sync_3(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, 0, 0, 0, 450 &newphid); 441 451 if (res) 442 452 return res;
Note:
See TracChangeset
for help on using the changeset viewer.