Changeset c124c985 in mainline
- Timestamp:
- 2018-07-16T15:38:16Z (7 years ago)
- 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)
- Location:
- uspace/lib/c
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/fibril.c
rc45dc5e1 rc124c985 344 344 } 345 345 346 static 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 */ 361 int 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 */ 385 void 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 */ 395 void 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 346 402 /** @} 347 403 */ -
uspace/lib/c/include/fibril.h
rc45dc5e1 rc124c985 61 61 extern void fibril_sleep(unsigned int); 62 62 63 extern void fibril_enable_multithreaded(void); 64 extern int fibril_test_spawn_runners(int); 65 66 extern void fibril_detach(fid_t fid); 67 63 68 static inline fid_t fibril_create(errno_t (*func)(void *), void *arg) 64 69 { -
uspace/lib/c/include/fibril_synch.h
rc45dc5e1 rc124c985 41 41 #include <sys/time.h> 42 42 #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 */ 61 typedef 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 83 static inline void fibril_rmutex_initialize(fibril_rmutex_t *m) 84 { 85 futex_initialize(&m->futex, 1); 86 } 87 88 static inline void fibril_rmutex_lock(fibril_rmutex_t *m) 89 { 90 futex_lock(&m->futex); 91 } 92 93 static inline bool fibril_rmutex_trylock(fibril_rmutex_t *m) 94 { 95 return futex_trylock(&m->futex); 96 } 97 98 static inline void fibril_rmutex_unlock(fibril_rmutex_t *m) 99 { 100 futex_unlock(&m->futex); 101 } 43 102 44 103 typedef struct {
Note:
See TracChangeset
for help on using the changeset viewer.