Changes in uspace/lib/c/generic/fibril_synch.c [45cbcaf4:2654afb] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/fibril_synch.c
r45cbcaf4 r2654afb 105 105 fibril_t *f = (fibril_t *) fibril_get_id(); 106 106 107 if (fibril_get_sercount() != 0)108 abort();109 110 107 futex_down(&async_futex); 111 108 if (fm->counter-- <= 0) { … … 197 194 fibril_t *f = (fibril_t *) fibril_get_id(); 198 195 199 if (fibril_get_sercount() != 0)200 abort();201 202 196 futex_down(&async_futex); 203 197 if (frw->writers) { … … 224 218 fibril_t *f = (fibril_t *) fibril_get_id(); 225 219 226 if (fibril_get_sercount() != 0)227 abort();228 229 220 futex_down(&async_futex); 230 221 if (frw->writers || frw->readers) { … … 380 371 if (timeout) { 381 372 getuptime(&wdata.to_event.expires); 382 tv_add (&wdata.to_event.expires, timeout);373 tv_add_diff(&wdata.to_event.expires, timeout); 383 374 async_insert_timeout(&wdata); 384 375 } … … 448 439 int rc; 449 440 450 fibril_mutex_lock(&timer->lock); 451 452 while (true) { 453 while (timer->state != fts_active && 454 timer->state != fts_cleanup) { 455 456 if (timer->state == fts_cleanup) 457 break; 458 459 fibril_condvar_wait(&timer->cv, &timer->lock); 441 fibril_mutex_lock(timer->lockp); 442 443 while (timer->state != fts_cleanup) { 444 switch (timer->state) { 445 case fts_not_set: 446 case fts_fired: 447 fibril_condvar_wait(&timer->cv, timer->lockp); 448 break; 449 case fts_active: 450 rc = fibril_condvar_wait_timeout(&timer->cv, 451 timer->lockp, timer->delay); 452 if (rc == ETIMEOUT && timer->state == fts_active) { 453 timer->state = fts_fired; 454 timer->handler_fid = fibril_get_id(); 455 fibril_mutex_unlock(timer->lockp); 456 timer->fun(timer->arg); 457 fibril_mutex_lock(timer->lockp); 458 timer->handler_fid = 0; 459 } 460 break; 461 case fts_cleanup: 462 case fts_clean: 463 assert(false); 464 break; 460 465 } 461 462 if (timer->state == fts_cleanup) 463 break; 464 465 rc = fibril_condvar_wait_timeout(&timer->cv, &timer->lock, 466 timer->delay); 467 if (rc == ETIMEOUT) { 468 timer->state = fts_fired; 469 fibril_mutex_unlock(&timer->lock); 470 timer->fun(timer->arg); 471 fibril_mutex_lock(&timer->lock); 472 } 473 } 474 475 fibril_mutex_unlock(&timer->lock); 466 } 467 468 /* Acknowledge timer fibril has finished cleanup. */ 469 timer->state = fts_clean; 470 fibril_condvar_broadcast(&timer->cv); 471 fibril_mutex_unlock(timer->lockp); 472 476 473 return 0; 477 474 } … … 481 478 * @return New timer on success, @c NULL if out of memory. 482 479 */ 483 fibril_timer_t *fibril_timer_create( void)480 fibril_timer_t *fibril_timer_create(fibril_mutex_t *lock) 484 481 { 485 482 fid_t fid; … … 501 498 timer->fibril = fid; 502 499 timer->state = fts_not_set; 500 timer->lockp = (lock != NULL) ? lock : &timer->lock; 503 501 504 502 fibril_add_ready(fid); 505 506 503 return timer; 507 504 } … … 513 510 void fibril_timer_destroy(fibril_timer_t *timer) 514 511 { 515 fibril_mutex_lock(&timer->lock); 516 assert(timer->state != fts_active); 512 fibril_mutex_lock(timer->lockp); 513 assert(timer->state == fts_not_set || timer->state == fts_fired); 514 515 /* Request timer fibril to terminate. */ 517 516 timer->state = fts_cleanup; 518 517 fibril_condvar_broadcast(&timer->cv); 519 fibril_mutex_unlock(&timer->lock); 518 519 /* Wait for timer fibril to terminate */ 520 while (timer->state != fts_clean) 521 fibril_condvar_wait(&timer->cv, timer->lockp); 522 fibril_mutex_unlock(timer->lockp); 523 524 free(timer); 520 525 } 521 526 … … 533 538 fibril_timer_fun_t fun, void *arg) 534 539 { 535 fibril_mutex_lock(&timer->lock); 540 fibril_mutex_lock(timer->lockp); 541 fibril_timer_set_locked(timer, delay, fun, arg); 542 fibril_mutex_unlock(timer->lockp); 543 } 544 545 /** Set locked timer. 546 * 547 * Set timer to execute a callback function after the specified 548 * interval. Must be called when the timer is locked. 549 * 550 * @param timer Timer 551 * @param delay Delay in microseconds 552 * @param fun Callback function 553 * @param arg Argument for @a fun 554 */ 555 void fibril_timer_set_locked(fibril_timer_t *timer, suseconds_t delay, 556 fibril_timer_fun_t fun, void *arg) 557 { 558 assert(fibril_mutex_is_locked(timer->lockp)); 559 assert(timer->state == fts_not_set || timer->state == fts_fired); 536 560 timer->state = fts_active; 537 561 timer->delay = delay; … … 539 563 timer->arg = arg; 540 564 fibril_condvar_broadcast(&timer->cv); 541 fibril_mutex_unlock(&timer->lock);542 565 } 543 566 … … 557 580 fibril_timer_state_t old_state; 558 581 559 fibril_mutex_lock(&timer->lock); 582 fibril_mutex_lock(timer->lockp); 583 old_state = fibril_timer_clear_locked(timer); 584 fibril_mutex_unlock(timer->lockp); 585 586 return old_state; 587 } 588 589 /** Clear locked timer. 590 * 591 * Clears (cancels) timer and returns last state of the timer. 592 * This can be one of: 593 * - fts_not_set If the timer has not been set or has been cleared 594 * - fts_active Timer was set but did not fire 595 * - fts_fired Timer fired 596 * Must be called when the timer is locked. 597 * 598 * @param timer Timer 599 * @return Last timer state 600 */ 601 fibril_timer_state_t fibril_timer_clear_locked(fibril_timer_t *timer) 602 { 603 fibril_timer_state_t old_state; 604 605 assert(fibril_mutex_is_locked(timer->lockp)); 606 607 while (timer->handler_fid != 0) { 608 if (timer->handler_fid == fibril_get_id()) { 609 printf("Deadlock detected.\n"); 610 stacktrace_print(); 611 printf("Fibril %zx is trying to clear timer %p from " 612 "inside its handler %p.\n", 613 fibril_get_id(), timer, timer->fun); 614 abort(); 615 } 616 617 fibril_condvar_wait(&timer->cv, timer->lockp); 618 } 619 560 620 old_state = timer->state; 561 621 timer->state = fts_not_set; … … 565 625 timer->arg = NULL; 566 626 fibril_condvar_broadcast(&timer->cv); 567 fibril_mutex_unlock(&timer->lock);568 627 569 628 return old_state;
Note:
See TracChangeset
for help on using the changeset viewer.