Changeset b59318e in mainline for uspace/lib/c/include/futex.h


Ignore:
Timestamp:
2018-06-26T17:34:48Z (6 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:
ab6edb6
Parents:
f6372be9
git-author:
Jiří Zárevúcky <jiri.zarevucky@…> (2018-06-26 17:01:43)
git-committer:
Jiří Zárevúcky <jiri.zarevucky@…> (2018-06-26 17:34:48)
Message:

Make futex able to time out.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/include/futex.h

    rf6372be9 rb59318e  
    3636#define LIBC_FUTEX_H_
    3737
     38#include <assert.h>
    3839#include <atomic.h>
    3940#include <errno.h>
     
    9899}
    99100
    100 /** Down the futex.
     101/** Down the futex with timeout, composably.
     102 *
     103 * This means that when the operation fails due to a timeout or being
     104 * interrupted, the next futex_up() is ignored, which allows certain kinds of
     105 * composition of synchronization primitives.
     106 *
     107 * In most other circumstances, regular futex_down_timeout() is a better choice.
    101108 *
    102109 * @param futex Futex.
    103110 *
    104111 * @return ENOENT if there is no such virtual address.
     112 * @return ETIMEOUT if timeout expires.
    105113 * @return EOK on success.
    106114 * @return Error code from <errno.h> otherwise.
    107115 *
    108116 */
    109 static inline errno_t futex_down(futex_t *futex)
     117static inline errno_t futex_down_composable(futex_t *futex, struct timeval *expires)
    110118{
     119        // TODO: Add tests for this.
     120
     121        /* No timeout by default. */
     122        suseconds_t timeout = 0;
     123
     124        if (expires) {
     125                struct timeval tv;
     126                getuptime(&tv);
     127                if (tv_gteq(&tv, expires)) {
     128                        /* We can't just return ETIMEOUT. That wouldn't be composable. */
     129                        timeout = 1;
     130                } else {
     131                        timeout = tv_sub_diff(expires, &tv);
     132                }
     133
     134                assert(timeout > 0);
     135        }
     136
    111137        if ((atomic_signed_t) atomic_predec(&futex->val) < 0)
    112                 return (errno_t) __SYSCALL1(SYS_FUTEX_SLEEP, (sysarg_t) &futex->val.count);
     138                return (errno_t) __SYSCALL2(SYS_FUTEX_SLEEP, (sysarg_t) &futex->val.count, (sysarg_t) timeout);
    113139
    114140        return EOK;
     
    132158}
    133159
     160static inline errno_t futex_down_timeout(futex_t *futex, struct timeval *expires)
     161{
     162        /*
     163         * This combination of a "composable" sleep followed by futex_up() on
     164         * failure is necessary to prevent breakage due to certain race
     165         * conditions.
     166         */
     167        errno_t rc = futex_down_composable(futex, expires);
     168        if (rc != EOK)
     169                futex_up(futex);
     170        return rc;
     171}
     172
     173/** Down the futex.
     174 *
     175 * @param futex Futex.
     176 *
     177 * @return ENOENT if there is no such virtual address.
     178 * @return EOK on success.
     179 * @return Error code from <errno.h> otherwise.
     180 *
     181 */
     182static inline errno_t futex_down(futex_t *futex)
     183{
     184        return futex_down_timeout(futex, NULL);
     185}
     186
    134187#endif
    135188
Note: See TracChangeset for help on using the changeset viewer.