Changeset 5626277 in mainline for generic/src/ipc/ipc.c
- Timestamp:
- 2006-04-29T22:12:40Z (19 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 51a7dc1
- Parents:
- 407862e
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
generic/src/ipc/ipc.c
r407862e r5626277 44 44 #include <print.h> 45 45 #include <proc/thread.h> 46 #include <arch/interrupt.h> 46 47 47 48 /* Open channel that is assigned automatically to new tasks */ … … 49 50 50 51 static slab_cache_t *ipc_call_slab; 52 53 typedef struct { 54 SPINLOCK_DECLARE(lock); 55 answerbox_t *box; 56 } ipc_irq_t; 57 58 static ipc_irq_t *irq_conns = NULL; 59 static int irq_conns_size; 51 60 52 61 /* Initialize new call */ … … 62 71 * The call is initialized, so that the reply will be directed 63 72 * to TASK->answerbox 64 */ 65 call_t * ipc_call_alloc(void) 73 * 74 * @param flags Parameters for slab_alloc (ATOMIC, etc.) 75 */ 76 call_t * ipc_call_alloc(int flags) 66 77 { 67 78 call_t *call; 68 79 69 call = slab_alloc(ipc_call_slab, 0);80 call = slab_alloc(ipc_call_slab, flags); 70 81 _ipc_call_init(call); 71 82 … … 91 102 { 92 103 spinlock_initialize(&box->lock, "ipc_box_lock"); 104 spinlock_initialize(&box->irq_lock, "ipc_box_irqlock"); 93 105 waitq_initialize(&box->wq); 94 106 list_initialize(&box->connected_phones); … … 96 108 list_initialize(&box->dispatched_calls); 97 109 list_initialize(&box->answers); 110 list_initialize(&box->irq_notifs); 98 111 box->task = TASK; 99 112 } … … 262 275 spinlock_unlock(&box->lock); 263 276 264 call = ipc_call_alloc( );277 call = ipc_call_alloc(0); 265 278 IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP); 266 279 call->flags |= IPC_CALL_DISCARD_ANSWER; … … 302 315 { 303 316 call_t *request; 317 ipl_t ipl; 304 318 305 319 restart: … … 311 325 312 326 spinlock_lock(&box->lock); 313 if (!list_empty(&box->answers)) { 327 if (!list_empty(&box->irq_notifs)) { 328 ipl = interrupts_disable(); 329 spinlock_lock(&box->irq_lock); 330 331 request = list_get_instance(box->answers.next, call_t, list); 332 list_remove(&request->list); 333 334 spinlock_unlock(&box->irq_lock); 335 interrupts_restore(ipl); 336 } else if (!list_empty(&box->answers)) { 314 337 /* Handle asynchronous answers */ 315 338 request = list_get_instance(box->answers.next, call_t, list); … … 334 357 } 335 358 336 /** Initilize ipc subsystem */337 void ipc_init(void)338 {339 ipc_call_slab = slab_cache_create("ipc_call",340 sizeof(call_t),341 0,342 NULL, NULL, 0);343 }344 345 359 /** Answer all calls from list with EHANGUP msg */ 346 360 static void ipc_cleanup_call_list(link_t *lst) … … 354 368 IPC_SET_RETVAL(call->data, EHANGUP); 355 369 _ipc_answer_free_call(call); 370 } 371 } 372 373 /** Disconnect all irq's notifications 374 * 375 * TODO: It may be better to do some linked list, so that 376 * we wouldn't need to go through whole array every cleanup 377 */ 378 static void ipc_irq_cleanup(answerbox_t *box) 379 { 380 int i; 381 ipl_t ipl; 382 383 for (i=0; i < irq_conns_size; i++) { 384 ipl = interrupts_disable(); 385 spinlock_lock(&irq_conns[i].lock); 386 if (irq_conns[i].box == box) 387 irq_conns[i].box = NULL; 388 spinlock_unlock(&irq_conns[i].lock); 389 interrupts_restore(ipl); 356 390 } 357 391 } … … 370 404 for (i=0;i < IPC_MAX_PHONES; i++) 371 405 ipc_phone_hangup(&task->phones[i]); 406 407 /* Disconnect all connected irqs */ 408 ipc_irq_cleanup(&task->answerbox); 372 409 373 410 /* Disconnect all phones connected to our answerbox */ … … 406 443 } 407 444 } 445 446 /** Initialize table of interrupt handlers */ 447 static void ipc_irq_make_table(int irqcount) 448 { 449 int i; 450 451 irq_conns_size = irqcount; 452 irq_conns = malloc(irqcount * (sizeof(*irq_conns)), 0); 453 for (i=0; i < irqcount; i++) { 454 spinlock_initialize(&irq_conns[i].lock, "irq_ipc_lock"); 455 irq_conns[i].box = NULL; 456 } 457 } 458 459 void ipc_irq_unregister(answerbox_t *box, int irq) 460 { 461 ipl_t ipl; 462 463 ipl = interrupts_disable(); 464 spinlock_lock(&irq_conns[irq].lock); 465 if (irq_conns[irq].box == box) 466 irq_conns[irq].box = NULL; 467 468 spinlock_unlock(&irq_conns[irq].lock); 469 interrupts_restore(ipl); 470 } 471 472 /** Register an answerbox as a receiving end of interrupts notifications */ 473 int ipc_irq_register(answerbox_t *box, int irq) 474 { 475 ipl_t ipl; 476 477 ASSERT(irq_conns); 478 479 ipl = interrupts_disable(); 480 spinlock_lock(&irq_conns[irq].lock); 481 482 if (irq_conns[irq].box) { 483 spinlock_unlock(&irq_conns[irq].lock); 484 interrupts_restore(ipl); 485 return EEXISTS; 486 } 487 irq_conns[irq].box = box; 488 spinlock_unlock(&irq_conns[irq].lock); 489 interrupts_restore(ipl); 490 491 return 0; 492 } 493 494 /** Notify process that an irq had happend 495 * 496 * We expect interrupts to be disabled 497 */ 498 void ipc_irq_send_notif(int irq) 499 { 500 call_t *call; 501 502 ASSERT(irq_conns); 503 spinlock_lock(&irq_conns[irq].lock); 504 505 if (irq_conns[irq].box) { 506 call = ipc_call_alloc(FRAME_ATOMIC); 507 call->flags |= IPC_CALL_NOTIF; 508 IPC_SET_METHOD(call->data, IPC_M_INTERRUPT); 509 IPC_SET_ARG1(call->data, irq); 510 511 spinlock_lock(&irq_conns[irq].box->irq_lock); 512 list_append(&call->list, &irq_conns[irq].box->irq_notifs); 513 spinlock_unlock(&irq_conns[irq].box->irq_lock); 514 515 waitq_wakeup(&irq_conns[irq].box->wq, 0); 516 } 517 518 spinlock_unlock(&irq_conns[irq].lock); 519 } 520 521 /** Initilize ipc subsystem */ 522 void ipc_init(void) 523 { 524 ipc_call_slab = slab_cache_create("ipc_call", 525 sizeof(call_t), 526 0, 527 NULL, NULL, 0); 528 ipc_irq_make_table(IRQ_COUNT); 529 } 530
Note:
See TracChangeset
for help on using the changeset viewer.