Changeset c124c985 in mainline


Ignore:
Timestamp:
2018-07-16T15:38:16Z (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:
38d8849
Parents:
c45dc5e1
git-author:
Jiří Zárevúcky <jiri.zarevucky@…> (2018-07-13 23:18:58)
git-committer:
Jiří Zárevúcky <jiri.zarevucky@…> (2018-07-16 15:38:16)
Message:

Add fibril_rmutex_t type and fibril multithreading enablement.

Location:
uspace/lib/c
Files:
3 edited

Legend:

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

    rc45dc5e1 rc124c985  
    344344}
    345345
     346static void _runner_fn(void *arg)
     347{
     348        futex_lock(&async_futex);
     349        (void) fibril_switch(FIBRIL_FROM_BLOCKED);
     350        __builtin_unreachable();
     351}
     352
     353/**
     354 * Spawn a given number of runners (i.e. OS threads) immediately, and
     355 * unconditionally. This is meant to be used for tests and debugging.
     356 * Regular programs should just use `fibril_enable_multithreaded()`.
     357 *
     358 * @param n  Number of runners to spawn.
     359 * @return   Number of runners successfully spawned.
     360 */
     361int fibril_test_spawn_runners(int n)
     362{
     363        errno_t rc;
     364
     365        for (int i = 0; i < n; i++) {
     366                thread_id_t tid;
     367                rc = thread_create(_runner_fn, NULL, "fibril runner", &tid);
     368                if (rc != EOK)
     369                        return i;
     370                thread_detach(tid);
     371        }
     372
     373        return n;
     374}
     375
     376/**
     377 * Opt-in to have more than one runner thread.
     378 *
     379 * Currently, a task only ever runs in one thread because multithreading
     380 * might break some existing code.
     381 *
     382 * Eventually, the number of runner threads for a given task should become
     383 * configurable in the environment and this function becomes no-op.
     384 */
     385void fibril_enable_multithreaded(void)
     386{
     387        // TODO: Implement better.
     388        //       For now, 4 total runners is a sensible default.
     389        fibril_test_spawn_runners(3);
     390}
     391
     392/**
     393 * Detach a fibril.
     394 */
     395void fibril_detach(fid_t f)
     396{
     397        // TODO: Currently all fibrils are detached by default, but they
     398        //       won't always be. Code that explicitly spawns fibrils with
     399        //       limited lifetime should call this function.
     400}
     401
    346402/** @}
    347403 */
  • uspace/lib/c/include/fibril.h

    rc45dc5e1 rc124c985  
    6161extern void fibril_sleep(unsigned int);
    6262
     63extern void fibril_enable_multithreaded(void);
     64extern int fibril_test_spawn_runners(int);
     65
     66extern void fibril_detach(fid_t fid);
     67
    6368static inline fid_t fibril_create(errno_t (*func)(void *), void *arg)
    6469{
  • uspace/lib/c/include/fibril_synch.h

    rc45dc5e1 rc124c985  
    4141#include <sys/time.h>
    4242#include <stdbool.h>
     43#include <futex.h>
     44
     45/**
     46 * "Restricted" fibril mutex.
     47 *
     48 * Similar to `fibril_mutex_t`, but has a set of restrictions placed on its
     49 * use. Within a rmutex critical section, you
     50 *         - may not use any other synchronization primitive,
     51 *           save for another `fibril_rmutex_t`. This includes nonblocking
     52 *           operations like cvar signal and mutex unlock.
     53 *         - may not read IPC messages
     54 *         - may not start a new thread/fibril
     55 *           (creating fibril without starting is fine)
     56 *
     57 * Additionally, locking with a timeout is not possible on this mutex,
     58 * and there is no associated condition variable type.
     59 * This is a design constraint, not a lack of implementation effort.
     60 */
     61typedef struct {
     62        // TODO: At this point, this is just silly handwaving to hide current
     63        //       futex use behind a fibril based abstraction. Later, the imple-
     64        //       mentation will change, but the restrictions placed on this type
     65        //       will allow it to be simpler and faster than a regular mutex.
     66        //       There might also be optional debug checking of the assumptions.
     67        //
     68        //       Note that a consequence of the restrictions is that if we are
     69        //       running on a single thread, no other fibril can ever get to run
     70        //       while a fibril has a rmutex locked. That means that for
     71        //       single-threaded programs, we can reduce all rmutex locks and
     72        //       unlocks to simple branches on a global bool variable.
     73
     74        futex_t futex;
     75} fibril_rmutex_t;
     76
     77#define FIBRIL_RMUTEX_INITIALIZER(name) \
     78        { .futex = FUTEX_INITIALIZE(1) }
     79
     80#define FIBRIL_RMUTEX_INITIALIZE(name) \
     81        fibril_rmutex_t name = FIBRIL_RMUTEX_INITIALIZER(name)
     82
     83static inline void fibril_rmutex_initialize(fibril_rmutex_t *m)
     84{
     85        futex_initialize(&m->futex, 1);
     86}
     87
     88static inline void fibril_rmutex_lock(fibril_rmutex_t *m)
     89{
     90        futex_lock(&m->futex);
     91}
     92
     93static inline bool fibril_rmutex_trylock(fibril_rmutex_t *m)
     94{
     95        return futex_trylock(&m->futex);
     96}
     97
     98static inline void fibril_rmutex_unlock(fibril_rmutex_t *m)
     99{
     100        futex_unlock(&m->futex);
     101}
    43102
    44103typedef struct {
Note: See TracChangeset for help on using the changeset viewer.