Thread-local group of tasks. Notice that most methods involving context switching are static otherwise pointer `this' may change after wakeup. The **pg parameters in following function are updated before returning.
| 82 | // pointer `this' may change after wakeup. The **pg parameters in following |
| 83 | // function are updated before returning. |
| 84 | class TaskGroup { |
| 85 | public: |
| 86 | // Create task `fn(arg)' with attributes `attr' in TaskGroup *pg and put |
| 87 | // the identifier into `tid'. Switch to the new task and schedule old task |
| 88 | // to run. |
| 89 | // Return 0 on success, errno otherwise. |
| 90 | static int start_foreground(TaskGroup** pg, |
| 91 | bthread_t* __restrict tid, |
| 92 | const bthread_attr_t* __restrict attr, |
| 93 | void * (*fn)(void*), |
| 94 | void* __restrict arg); |
| 95 | |
| 96 | // Create task `fn(arg)' with attributes `attr' in this TaskGroup, put the |
| 97 | // identifier into `tid'. Schedule the new thread to run. |
| 98 | // Called from worker: start_background<false> |
| 99 | // Called from non-worker: start_background<true> |
| 100 | // Return 0 on success, errno otherwise. |
| 101 | template <bool REMOTE> |
| 102 | int start_background(bthread_t* __restrict tid, |
| 103 | const bthread_attr_t* __restrict attr, |
| 104 | void * (*fn)(void*), |
| 105 | void* __restrict arg); |
| 106 | |
| 107 | // Suspend caller and run next bthread in TaskGroup *pg. |
| 108 | static void sched(TaskGroup** pg); |
| 109 | static void ending_sched(TaskGroup** pg); |
| 110 | |
| 111 | // Suspend caller and run bthread `next_tid' in TaskGroup *pg. |
| 112 | // Purpose of this function is to avoid pushing `next_tid' to _rq and |
| 113 | // then being popped by sched(pg), which is not necessary. |
| 114 | static void sched_to(TaskGroup** pg, TaskMeta* next_meta); |
| 115 | static void sched_to(TaskGroup** pg, bthread_t next_tid); |
| 116 | static void exchange(TaskGroup** pg, TaskMeta* next_meta); |
| 117 | |
| 118 | // The callback will be run in the beginning of next-run bthread. |
| 119 | // Can't be called by current bthread directly because it often needs |
| 120 | // the target to be suspended already. |
| 121 | typedef void (*RemainedFn)(void*); |
| 122 | void set_remained(RemainedFn cb, void* arg) { |
| 123 | _last_context_remained = cb; |
| 124 | _last_context_remained_arg = arg; |
| 125 | } |
| 126 | |
| 127 | // Suspend caller for at least |timeout_us| microseconds. |
| 128 | // If |timeout_us| is 0, this function does nothing. |
| 129 | // If |group| is NULL or current thread is non-bthread, call usleep(3) |
| 130 | // instead. This function does not create thread-local TaskGroup. |
| 131 | // Returns: 0 on success, -1 otherwise and errno is set. |
| 132 | static int usleep(TaskGroup** pg, uint64_t timeout_us); |
| 133 | |
| 134 | // Suspend caller and run another bthread. When the caller will resume |
| 135 | // is undefined. |
| 136 | static void yield(TaskGroup** pg); |
| 137 | |
| 138 | // Suspend caller until bthread `tid' terminates. |
| 139 | static int join(bthread_t tid, void** return_value); |
| 140 | |
| 141 | // Returns true iff the bthread `tid' still exists. Notice that it is |
nothing calls this directly
no test coverage detected