Changeset a55d76b1 in mainline for uspace/lib/c/generic/fibril_synch.c


Ignore:
Timestamp:
2018-06-13T17:07:58Z (7 years ago)
Author:
Jiří Zárevúcky <jiri.zarevucky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
be2a20ac, c407b98
Parents:
899342e
git-author:
Jiří Zárevúcky <jiri.zarevucky@…> (2018-06-13 17:04:01)
git-committer:
Jiří Zárevúcky <jiri.zarevucky@…> (2018-06-13 17:07:58)
Message:

Implement a simple counting semaphore for fibrils.

File:
1 edited

Legend:

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

    r899342e ra55d76b1  
    629629}
    630630
     631/**
     632 * Initialize a semaphore with initial count set to the provided value.
     633 *
     634 * @param sem    Semaphore to initialize.
     635 * @param count  Initial count. Must not be negative.
     636 */
     637void fibril_semaphore_initialize(fibril_semaphore_t *sem, long count)
     638{
     639        /*
     640         * Negative count denotes the length of waitlist,
     641         * so it makes no sense as an initial value.
     642         */
     643        assert(count >= 0);
     644        sem->count = count;
     645        list_initialize(&sem->waiters);
     646}
     647
     648/**
     649 * Produce one token.
     650 * If there are fibrils waiting for tokens, this operation satisfies
     651 * exactly one waiting `fibril_semaphore_down()`.
     652 * This operation never blocks the fibril.
     653 *
     654 * @param sem  Semaphore to use.
     655 */
     656void fibril_semaphore_up(fibril_semaphore_t *sem)
     657{
     658        futex_down(&async_futex);
     659        sem->count++;
     660
     661        if (sem->count > 0) {
     662                futex_up(&async_futex);
     663                return;
     664        }
     665
     666        link_t *tmp = list_first(&sem->waiters);
     667        assert(tmp);
     668        list_remove(tmp);
     669
     670        futex_up(&async_futex);
     671
     672        awaiter_t *wdp = list_get_instance(tmp, awaiter_t, wu_event.link);
     673        fibril_add_ready(wdp->fid);
     674        optimize_execution_power();
     675}
     676
     677/**
     678 * Consume one token.
     679 * If there are no available tokens (count <= 0), this operation blocks until
     680 * another fibril produces a token using `fibril_semaphore_up()`.
     681 *
     682 * @param sem  Semaphore to use.
     683 */
     684void fibril_semaphore_down(fibril_semaphore_t *sem)
     685{
     686        futex_down(&async_futex);
     687        sem->count--;
     688
     689        if (sem->count >= 0) {
     690                futex_up(&async_futex);
     691                return;
     692        }
     693
     694        awaiter_t wdata;
     695        awaiter_initialize(&wdata);
     696
     697        wdata.fid = fibril_get_id();
     698        list_append(&wdata.wu_event.link, &sem->waiters);
     699        fibril_switch(FIBRIL_TO_MANAGER);
     700
     701        /* async_futex not held after fibril_switch() */
     702}
     703
    631704/** @}
    632705 */
Note: See TracChangeset for help on using the changeset viewer.