Changeset e9d15d9 in mainline for kernel/generic/src/ipc/irq.c
- Timestamp:
- 2017-08-18T21:15:26Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 24abb85d
- Parents:
- 1c85bae
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/irq.c
r1c85bae re9d15d9 84 84 #include <print.h> 85 85 #include <macros.h> 86 #include <kobject/kobject.h> 86 87 87 88 static void ranges_unmap(irq_pio_range_t *ranges, size_t rangecount) … … 298 299 * @param ucode Uspace pointer to top-half pseudocode. 299 300 * 300 * @return EOK on success or a negative error code. 301 * @return IRQ capability. 302 * @return Negative error code. 301 303 * 302 304 */ … … 321 323 322 324 /* 323 * Allocate and populate the IRQ structure.325 * Allocate and populate the IRQ kernel object. 324 326 */ 325 irq_t *irq = malloc(sizeof(irq_t), 0); 326 327 int cap = kobject_alloc(TASK); 328 if (cap < 0) 329 return cap; 330 kobject_t *kobj = kobject_get_current(cap, KOBJECT_TYPE_ALLOCATED); 331 assert(kobj); 332 kobj->type = KOBJECT_TYPE_IRQ; 333 334 irq_t *irq = &kobj->irq; 327 335 irq_initialize(irq); 328 336 irq->devno = devno; … … 351 359 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true); 352 360 353 free(irq);361 kobject_free(TASK, cap); 354 362 return EEXIST; 355 363 } … … 366 374 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true); 367 375 368 return EOK;376 return cap; 369 377 } 370 378 371 379 /** Unsubscribe task from IRQ notification. 372 380 * 373 * @param box Answerbox associated with the notification. 374 * @param inr IRQ number. 375 * @param devno Device number. 381 * @param box Answerbox associated with the notification. 382 * @param irq_cap IRQ capability. 376 383 * 377 384 * @return EOK on success or a negative error code. 378 385 * 379 386 */ 380 int ipc_irq_unsubscribe(answerbox_t *box, inr_t inr, devno_t devno) 381 { 382 sysarg_t key[] = { 383 (sysarg_t) inr, 384 (sysarg_t) devno 385 }; 386 387 if ((inr < 0) || (inr > last_inr)) 388 return ELIMIT; 389 387 int ipc_irq_unsubscribe(answerbox_t *box, int irq_cap) 388 { 389 kobject_t *kobj = kobject_get_current(irq_cap, KOBJECT_TYPE_IRQ); 390 if (!kobj) 391 return ENOENT; 392 irq_t *irq = &kobj->irq; 393 390 394 irq_spinlock_lock(&irq_uspace_hash_table_lock, true); 391 link_t *lnk = hash_table_find(&irq_uspace_hash_table, key); 392 if (!lnk) { 393 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true); 394 return ENOENT; 395 } 396 397 irq_t *irq = hash_table_get_instance(lnk, irq_t, link); 398 399 /* irq is locked */ 395 irq_spinlock_lock(&irq->lock, false); 400 396 irq_spinlock_lock(&box->irq_lock, false); 401 397 … … 405 401 list_remove(&irq->notif_cfg.link); 406 402 407 /*408 * We need to drop the IRQ lock now because hash_table_remove() will try409 * to reacquire it. That basically violates the natural locking order,410 * but a deadlock in hash_table_remove() is prevented by the fact that411 * we already held the IRQ lock and didn't drop the hash table lock in412 * the meantime.413 */414 irq_spinlock_unlock(&irq->lock, false);415 416 403 /* Remove the IRQ from the uspace IRQ hash table. */ 417 hash_table_remove (&irq_uspace_hash_table, key, 2);404 hash_table_remove_item(&irq_uspace_hash_table, &irq->link); 418 405 419 406 irq_spinlock_unlock(&box->irq_lock, false); 407 /* irq->lock unlocked by the hash table remove_callback */ 420 408 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true); 421 409 … … 423 411 code_free(irq->notif_cfg.code); 424 412 425 /* Free up the IRQ structure. */426 free(irq);413 /* Free up the IRQ kernel object. */ 414 kobject_free(TASK, irq_cap); 427 415 428 416 return EOK; … … 431 419 /** Disconnect all IRQ notifications from an answerbox. 432 420 * 433 * This function is effective because the answerbox contains 434 * list of all irq_t structures that are subscribed to 435 * send notifications to it. 421 * This function is effective because the answerbox contains list of all irq_t 422 * structures that are subscribed to send notifications to it. 436 423 * 437 424 * @param box Answerbox for which we want to carry out the cleanup. … … 460 447 } 461 448 462 sysarg_t key[2];463 key[0] = irq->inr;464 key[1] = irq->devno;465 466 449 assert(irq->notif_cfg.answerbox == box); 467 450 … … 469 452 list_remove(&irq->notif_cfg.link); 470 453 471 /*472 * We need to drop the IRQ lock now because hash_table_remove()473 * will try to reacquire it. That basically violates the natural474 * locking order, but a deadlock in hash_table_remove() is475 * prevented by the fact that we already held the IRQ lock and476 * didn't drop the hash table lock in the meantime.477 */478 irq_spinlock_unlock(&irq->lock, false);479 480 454 /* Remove from the hash table. */ 481 hash_table_remove (&irq_uspace_hash_table, key, 2);455 hash_table_remove_item(&irq_uspace_hash_table, &irq->link); 482 456 483 457 /* … … 488 462 489 463 code_free(irq->notif_cfg.code); 490 free(irq); 464 465 // XXX: what to do about the irq capability? The task is in 466 // clean-up anyway. 491 467 492 468 /* Reacquire both locks before taking another round. */
Note:
See TracChangeset
for help on using the changeset viewer.