Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/fibril_synch.c

    r2654afb r45cbcaf4  
    105105        fibril_t *f = (fibril_t *) fibril_get_id();
    106106
     107        if (fibril_get_sercount() != 0)
     108                abort();
     109
    107110        futex_down(&async_futex);
    108111        if (fm->counter-- <= 0) {
     
    194197        fibril_t *f = (fibril_t *) fibril_get_id();
    195198       
     199        if (fibril_get_sercount() != 0)
     200                abort();
     201
    196202        futex_down(&async_futex);
    197203        if (frw->writers) {
     
    218224        fibril_t *f = (fibril_t *) fibril_get_id();
    219225       
     226        if (fibril_get_sercount() != 0)
     227                abort();
     228
    220229        futex_down(&async_futex);
    221230        if (frw->writers || frw->readers) {
     
    371380        if (timeout) {
    372381                getuptime(&wdata.to_event.expires);
    373                 tv_add_diff(&wdata.to_event.expires, timeout);
     382                tv_add(&wdata.to_event.expires, timeout);
    374383                async_insert_timeout(&wdata);
    375384        }
     
    439448        int rc;
    440449
    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);
     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);
     460                }
     461
     462                if (timer->state == fts_cleanup)
    448463                        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;
     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);
    465472                }
    466473        }
    467474
    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 
     475        fibril_mutex_unlock(&timer->lock);
    473476        return 0;
    474477}
     
    478481 * @return              New timer on success, @c NULL if out of memory.
    479482 */
    480 fibril_timer_t *fibril_timer_create(fibril_mutex_t *lock)
     483fibril_timer_t *fibril_timer_create(void)
    481484{
    482485        fid_t fid;
     
    498501        timer->fibril = fid;
    499502        timer->state = fts_not_set;
    500         timer->lockp = (lock != NULL) ? lock : &timer->lock;
    501503
    502504        fibril_add_ready(fid);
     505
    503506        return timer;
    504507}
     
    510513void fibril_timer_destroy(fibril_timer_t *timer)
    511514{
    512         fibril_mutex_lock(timer->lockp);
    513         assert(timer->state == fts_not_set || timer->state == fts_fired);
    514 
    515         /* Request timer fibril to terminate. */
     515        fibril_mutex_lock(&timer->lock);
     516        assert(timer->state != fts_active);
    516517        timer->state = fts_cleanup;
    517518        fibril_condvar_broadcast(&timer->cv);
    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);
     519        fibril_mutex_unlock(&timer->lock);
    525520}
    526521
     
    538533    fibril_timer_fun_t fun, void *arg)
    539534{
    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);
     535        fibril_mutex_lock(&timer->lock);
    560536        timer->state = fts_active;
    561537        timer->delay = delay;
     
    563539        timer->arg = arg;
    564540        fibril_condvar_broadcast(&timer->cv);
     541        fibril_mutex_unlock(&timer->lock);
    565542}
    566543
     
    580557        fibril_timer_state_t old_state;
    581558
    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 
     559        fibril_mutex_lock(&timer->lock);
    620560        old_state = timer->state;
    621561        timer->state = fts_not_set;
     
    625565        timer->arg = NULL;
    626566        fibril_condvar_broadcast(&timer->cv);
     567        fibril_mutex_unlock(&timer->lock);
    627568
    628569        return old_state;
Note: See TracChangeset for help on using the changeset viewer.