Changeset 5626277 in mainline
- 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
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
arch/amd64/src/interrupt.c
r407862e r5626277 45 45 #include <synch/spinlock.h> 46 46 #include <arch/ddi/ddi.h> 47 #include <interrupt.h> 48 #include <ipc/sysipc.h> 47 49 48 50 void print_info_errcode(int n, istate_t *istate) … … 154 156 155 157 } 158 159 static void ipc_int(int n, istate_t *istate) 160 { 161 trap_virtual_eoi(); 162 ipc_irq_send_notif(n-IVT_IRQBASE); 163 } 164 165 166 /* Reregister irq to be IPC-ready */ 167 void irq_ipc_bind_arch(__native irq) 168 { 169 if (irq == IRQ_CLK) 170 return; 171 exc_register(IVT_IRQBASE+irq, "ipc_int", ipc_int); 172 } -
arch/ia32/src/interrupt.c
r407862e r5626277 44 44 #include <synch/spinlock.h> 45 45 #include <arch/ddi/ddi.h> 46 #include <ipc/sysipc.h> 47 #include <interrupt.h> 46 48 47 49 /* … … 185 187 186 188 } 189 190 static void ipc_int(int n, istate_t *istate) 191 { 192 trap_virtual_eoi(); 193 ipc_irq_send_notif(n-IVT_IRQBASE); 194 } 195 196 197 /* Reregister irq to be IPC-ready */ 198 void irq_ipc_bind_arch(__native irq) 199 { 200 if (irq == IRQ_CLK) 201 return; 202 exc_register(IVT_IRQBASE+irq, "ipc_int", ipc_int); 203 } -
arch/mips32/include/interrupt.h
r407862e r5626277 34 34 #define IVT_ITEMS 40 35 35 #define INT_OFFSET 32 36 #define IRQ_COUNT 8 36 37 37 38 #define int_register(it, name, handler) exc_register(((it)+INT_OFFSET),name,handler) -
arch/mips32/src/interrupt.c
r407862e r5626277 34 34 #include <time/clock.h> 35 35 #include <arch/drivers/arc.h> 36 37 #include <ipc/sysipc.h> 36 38 37 39 /** Disable interrupts. … … 84 86 { 85 87 cp0_cause_write(cp0_cause_read() & ~(1 << 8)); /* clear SW0 interrupt */ 88 ipc_irq_send_notif(0); 86 89 } 87 90 … … 89 92 { 90 93 cp0_cause_write(cp0_cause_read() & ~(1 << 9)); /* clear SW1 interrupt */ 94 ipc_irq_send_notif(1); 91 95 } 92 96 … … 98 102 int_register(1, "swint1", swint1); 99 103 } 104 105 #include <print.h> 106 static void ipc_int(int n, istate_t *istate) 107 { 108 ipc_irq_send_notif(n-INT_OFFSET); 109 } 110 111 /* Reregister irq to be IPC-ready */ 112 void irq_ipc_bind_arch(__native irq) 113 { 114 /* Do not allow to redefine timer */ 115 /* Swint0, Swint1 are already handled */ 116 if (irq == TIMER_IRQ || irq < 2) 117 return; 118 int_register(irq, "ipc_int", ipc_int); 119 } -
generic/include/errno.h
r407862e r5626277 41 41 * to close the connection. Used by answerbox 42 42 * to close the connection. */ 43 #define EEXISTS -8 /* Entry already exists */ 43 44 44 45 #endif -
generic/include/ipc/ipc.h
r407862e r5626277 44 44 #define IPC_CALL_FORWARDED (1<<3) /* Call was forwarded */ 45 45 #define IPC_CALL_CONN_ME_TO (1<<4) /* Identify connect_me_to */ 46 #define IPC_CALL_NOTIF (1<<5) /* Interrupt notification */ 46 47 47 48 /* Flags for ipc_wait_for_call */ … … 120 121 */ 121 122 #define IPC_M_PHONE_HUNGUP 3 123 /** Interrupt notification */ 124 #define IPC_M_INTERRUPT 4 122 125 123 126 … … 155 158 156 159 link_t answers; /**< Answered calls */ 160 161 SPINLOCK_DECLARE(irq_lock); 162 link_t irq_notifs; /**< Notifications from IRQ handlers */ 157 163 }; 158 164 … … 196 202 extern void ipc_phone_connect(phone_t *phone, answerbox_t *box); 197 203 extern void ipc_call_free(call_t *call); 198 extern call_t * ipc_call_alloc( void);204 extern call_t * ipc_call_alloc(int flags); 199 205 extern void ipc_answerbox_init(answerbox_t *box); 200 206 extern void ipc_call_static_init(call_t *call); … … 205 211 extern void ipc_backsend_err(phone_t *phone, call_t *call, __native err); 206 212 213 extern int ipc_irq_register(answerbox_t *box, int irq); 214 extern void ipc_irq_send_notif(int irq); 215 extern void ipc_irq_unregister(answerbox_t *box, int irq); 216 217 207 218 extern answerbox_t *ipc_phone_0; 208 219 -
generic/include/ipc/sysipc.h
r407862e r5626277 30 30 #define __SYSIPC_H__ 31 31 32 #include <ipc/ipc.h> 33 32 34 __native sys_ipc_call_sync_fast(__native phoneid, __native method, 33 35 __native arg1, ipc_data_t *data); … … 44 46 __native method, __native arg1); 45 47 __native sys_ipc_hangup(int phoneid); 48 __native sys_ipc_register_irq(__native irq); 49 __native sys_ipc_unregister_irq(__native irq); 46 50 51 void irq_ipc_bind_arch(__native irq); 47 52 48 53 #endif -
generic/include/syscall/syscall.h
r407862e r5626277 52 52 SYS_IPC_WAIT, 53 53 SYS_IPC_HANGUP, 54 SYS_IPC_REGISTER_IRQ, 55 SYS_IPC_UNREGISTER_IRQ, 54 56 SYS_MAP_PHYSMEM, 55 57 SYS_IOSPACE_ENABLE, -
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 -
generic/src/ipc/sysipc.c
r407862e r5626277 37 37 #include <ipc/sysipc.h> 38 38 #include <ipc/ipcrsc.h> 39 39 #include <arch/interrupt.h> 40 40 41 41 #include <print.h> … … 275 275 GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL); 276 276 277 call = ipc_call_alloc( );277 call = ipc_call_alloc(0); 278 278 IPC_SET_METHOD(call->data, method); 279 279 IPC_SET_ARG1(call->data, arg1); … … 303 303 GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL); 304 304 305 call = ipc_call_alloc( );305 call = ipc_call_alloc(0); 306 306 copy_from_uspace(&call->data.args, &data->args, sizeof(call->data.args)); 307 307 if (!(res=request_preprocess(call))) … … 442 442 return 0; 443 443 444 if (call->flags & IPC_CALL_NOTIF) { 445 ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC)); 446 STRUCT_TO_USPACE(&calldata->args, &call->data.args); 447 ipc_call_free(call); 448 449 return ((__native)call) | IPC_CALLID_NOTIFICATION; 450 } 451 444 452 if (call->flags & IPC_CALL_ANSWERED) { 445 453 process_answer(call); … … 468 476 return (__native)call; 469 477 } 478 479 /** Connect irq handler to task */ 480 __native sys_ipc_register_irq(__native irq) 481 { 482 if (irq >= IRQ_COUNT) 483 return -ELIMIT; 484 485 irq_ipc_bind_arch(irq); 486 return ipc_irq_register(&TASK->answerbox, irq); 487 } 488 489 /* Disconnect irq handler from task */ 490 __native sys_ipc_unregister_irq(__native irq) 491 { 492 if (irq >= IRQ_COUNT) 493 return -ELIMIT; 494 495 ipc_irq_unregister(&TASK->answerbox, irq); 496 497 return 0; 498 } -
generic/src/syscall/syscall.c
r407862e r5626277 97 97 sys_ipc_wait_for_call, 98 98 sys_ipc_hangup, 99 99 sys_ipc_register_irq, 100 sys_ipc_unregister_irq, 101 100 102 /* DDI related syscalls. */ 101 103 sys_physmem_map,
Note:
See TracChangeset
for help on using the changeset viewer.