Changeset 8119363 in mainline for uspace/lib/c/include


Ignore:
Timestamp:
2018-06-26T17:35:40Z (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:
6e569bf
Parents:
fbfe59d (diff), e768aea (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge some preliminary async/fibril framework changes.

Location:
uspace/lib/c/include
Files:
6 edited

Legend:

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

    rfbfe59d r8119363  
    108108typedef struct async_exch async_exch_t;
    109109
    110 #define async_manager() \
    111         do { \
    112                 futex_down(&async_futex); \
    113                 fibril_switch(FIBRIL_FROM_DEAD); \
    114         } while (0)
     110extern _Noreturn void async_manager(void);
    115111
    116112#define async_get_call(data) \
  • uspace/lib/c/include/fibril.h

    rfbfe59d r8119363  
    3636#define LIBC_FIBRIL_H_
    3737
    38 #include <context.h>
    3938#include <types/common.h>
    40 #include <adt/list.h>
    41 #include <libarch/tls.h>
    4239
    43 #define FIBRIL_WRITER   1
    44 
    45 struct fibril;
     40typedef struct fibril fibril_t;
    4641
    4742typedef struct {
    48         struct fibril *owned_by;
     43        fibril_t *owned_by;
    4944} fibril_owner_info_t;
    5045
    51 typedef enum {
    52         FIBRIL_PREEMPT,
    53         FIBRIL_TO_MANAGER,
    54         FIBRIL_FROM_MANAGER,
    55         FIBRIL_FROM_DEAD
    56 } fibril_switch_type_t;
    57 
    5846typedef sysarg_t fid_t;
    59 
    60 typedef struct fibril {
    61         link_t link;
    62         link_t all_link;
    63         context_t ctx;
    64         void *stack;
    65         void *arg;
    66         errno_t (*func)(void *);
    67         tcb_t *tcb;
    68 
    69         struct fibril *clean_after_me;
    70         errno_t retval;
    71         int flags;
    72 
    73         fibril_owner_info_t *waits_for;
    74 } fibril_t;
    7547
    7648/** Fibril-local variable specifier */
     
    8153extern fid_t fibril_create_generic(errno_t (*func)(void *), void *arg, size_t);
    8254extern void fibril_destroy(fid_t fid);
    83 extern fibril_t *fibril_setup(void);
    84 extern void fibril_teardown(fibril_t *f, bool locked);
    85 extern int fibril_switch(fibril_switch_type_t stype);
    8655extern void fibril_add_ready(fid_t fid);
    87 extern void fibril_add_manager(fid_t fid);
    88 extern void fibril_remove_manager(void);
    8956extern fid_t fibril_get_id(void);
     57extern void fibril_yield(void);
    9058
    9159static inline fid_t fibril_create(errno_t (*func)(void *), void *arg)
     
    9462}
    9563
    96 static inline int fibril_yield(void)
    97 {
    98         return fibril_switch(FIBRIL_PREEMPT);
    99 }
    100 
    10164#endif
    10265
  • uspace/lib/c/include/futex.h

    rfbfe59d r8119363  
    3636#define LIBC_FUTEX_H_
    3737
     38#include <assert.h>
    3839#include <atomic.h>
    3940#include <errno.h>
    4041#include <libc.h>
     42#include <time.h>
    4143
    4244typedef struct futex {
    4345        atomic_t val;
    44 #ifdef FUTEX_UPGRADABLE
    45         int upgraded;
     46#ifdef CONFIG_DEBUG_FUTEX
     47        _Atomic void *owner;
    4648#endif
    4749} futex_t;
    4850
    49 
    5051extern void futex_initialize(futex_t *futex, int value);
    5152
    52 #ifdef FUTEX_UPGRADABLE
    53 #include <rcu.h>
     53#ifdef CONFIG_DEBUG_FUTEX
    5454
    55 #define FUTEX_INITIALIZE(val) {{ (val) }, 0}
     55#define FUTEX_INITIALIZE(val) {{ (val) }, NULL }
     56#define FUTEX_INITIALIZER     FUTEX_INITIALIZE(1)
    5657
    57 #define futex_lock(fut) \
    58 ({ \
    59         rcu_read_lock(); \
    60         (fut)->upgraded = rcu_access(_upgrade_futexes); \
    61         if ((fut)->upgraded) \
    62                 (void) futex_down((fut)); \
    63 })
     58void __futex_assert_is_locked(futex_t *, const char *);
     59void __futex_assert_is_not_locked(futex_t *, const char *);
     60void __futex_lock(futex_t *, const char *);
     61void __futex_unlock(futex_t *, const char *);
     62bool __futex_trylock(futex_t *, const char *);
     63void __futex_give_to(futex_t *, void *, const char *);
    6464
    65 #define futex_trylock(fut) \
    66 ({ \
    67         rcu_read_lock(); \
    68         int _upgraded = rcu_access(_upgrade_futexes); \
    69         if (_upgraded) { \
    70                 int _acquired = futex_trydown((fut)); \
    71                 if (!_acquired) { \
    72                         rcu_read_unlock(); \
    73                 } else { \
    74                         (fut)->upgraded = true; \
    75                 } \
    76                 _acquired; \
    77         } else { \
    78                 (fut)->upgraded = false; \
    79                 1; \
    80         } \
    81 })
     65#define futex_lock(futex) __futex_lock((futex), #futex)
     66#define futex_unlock(futex) __futex_unlock((futex), #futex)
     67#define futex_trylock(futex) __futex_trylock((futex), #futex)
    8268
    83 #define futex_unlock(fut) \
    84 ({ \
    85         if ((fut)->upgraded) \
    86                 (void) futex_up((fut)); \
    87         rcu_read_unlock(); \
    88 })
    89 
    90 extern int _upgrade_futexes;
    91 
    92 extern void futex_upgrade_all_and_wait(void);
     69#define futex_give_to(futex, new_owner) __futex_give_to((futex), (new_owner), #futex)
     70#define futex_assert_is_locked(futex) __futex_assert_is_locked((futex), #futex)
     71#define futex_assert_is_not_locked(futex) __futex_assert_is_not_locked((futex), #futex)
    9372
    9473#else
    9574
    9675#define FUTEX_INITIALIZE(val) {{ (val) }}
     76#define FUTEX_INITIALIZER     FUTEX_INITIALIZE(1)
    9777
    9878#define futex_lock(fut)     (void) futex_down((fut))
     
    10080#define futex_unlock(fut)   (void) futex_up((fut))
    10181
     82#define futex_give_to(fut, owner) ((void)0)
     83#define futex_assert_is_locked(fut) assert((atomic_signed_t) (fut)->val.count <= 0)
     84#define futex_assert_is_not_locked(fut) ((void)0)
     85
    10286#endif
    103 
    104 #define FUTEX_INITIALIZER     FUTEX_INITIALIZE(1)
    10587
    10688/** Try to down the futex.
     
    11799}
    118100
    119 /** 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.
    120108 *
    121109 * @param futex Futex.
    122110 *
    123111 * @return ENOENT if there is no such virtual address.
     112 * @return ETIMEOUT if timeout expires.
    124113 * @return EOK on success.
    125114 * @return Error code from <errno.h> otherwise.
    126115 *
    127116 */
    128 static inline errno_t futex_down(futex_t *futex)
     117static inline errno_t futex_down_composable(futex_t *futex, struct timeval *expires)
    129118{
     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
    130137        if ((atomic_signed_t) atomic_predec(&futex->val) < 0)
    131                 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);
    132139
    133140        return EOK;
     
    151158}
    152159
     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
    153187#endif
    154188
  • uspace/lib/c/include/rcu.h

    rfbfe59d r8119363  
    9292#define rcu_access(ptr) ACCESS_ONCE(ptr)
    9393
    94 typedef enum blocking_mode {
    95         BM_BLOCK_FIBRIL,
    96         BM_BLOCK_THREAD
    97 } blocking_mode_t;
    98 
    9994extern void rcu_register_fibril(void);
    10095extern void rcu_deregister_fibril(void);
     
    105100extern bool rcu_read_locked(void);
    106101
    107 #define rcu_synchronize() _rcu_synchronize(BM_BLOCK_FIBRIL)
    108 
    109 extern void _rcu_synchronize(blocking_mode_t);
     102extern void rcu_synchronize(void);
    110103
    111104#endif
  • uspace/lib/c/include/stacktrace.h

    rfbfe59d r8119363  
    4343typedef struct {
    4444        errno_t (*read_uintptr)(void *, uintptr_t, uintptr_t *);
     45        int (*printf)(const char *, ...);
    4546} stacktrace_ops_t;
    4647
     
    5152
    5253extern void stacktrace_print(void);
     54extern void stacktrace_kio_print(void);
    5355extern void stacktrace_print_fp_pc(uintptr_t, uintptr_t);
    5456extern void stacktrace_print_generic(stacktrace_ops_t *, void *, uintptr_t,
  • uspace/lib/c/include/sys/time.h

    rfbfe59d r8119363  
    6969};
    7070
     71#define TIMEVAL_MAX ((struct timeval) { .tv_sec = LONG_MAX, .tv_usec = 999999 })
     72
    7173struct timezone {
    7274        int tz_minuteswest;  /* minutes W of Greenwich */
     
    7577
    7678extern void tv_add_diff(struct timeval *, suseconds_t);
    77 extern void tv_add(struct timeval *, struct timeval *);
    78 extern suseconds_t tv_sub_diff(struct timeval *, struct timeval *);
    79 extern void tv_sub(struct timeval *, struct timeval *);
    80 extern int tv_gt(struct timeval *, struct timeval *);
    81 extern int tv_gteq(struct timeval *, struct timeval *);
     79extern void tv_add(struct timeval *, const struct timeval *);
     80extern suseconds_t tv_sub_diff(const struct timeval *, const struct timeval *);
     81extern void tv_sub(struct timeval *, const struct timeval *);
     82extern int tv_gt(const struct timeval *, const struct timeval *);
     83extern int tv_gteq(const struct timeval *, const struct timeval *);
    8284extern void gettimeofday(struct timeval *, struct timezone *);
    8385extern void getuptime(struct timeval *);
Note: See TracChangeset for help on using the changeset viewer.