| 266 | __thread TaskGroup* tls_task_group_nosignal = NULL; |
| 267 | |
| 268 | BUTIL_FORCE_INLINE int |
| 269 | start_from_non_worker(bthread_t* __restrict tid, |
| 270 | const bthread_attr_t* __restrict attr, |
| 271 | void* (*fn)(void*), |
| 272 | void* __restrict arg) { |
| 273 | TaskControl* c = get_or_new_task_control(); |
| 274 | if (NULL == c) { |
| 275 | return ENOMEM; |
| 276 | } |
| 277 | auto tag = BTHREAD_TAG_DEFAULT; |
| 278 | if (attr != NULL && attr->tag != BTHREAD_TAG_INVALID) { |
| 279 | tag = attr->tag; |
| 280 | } |
| 281 | if (attr != NULL && (attr->flags & BTHREAD_NOSIGNAL)) { |
| 282 | // Remember the TaskGroup to insert NOSIGNAL tasks for 2 reasons: |
| 283 | // 1. NOSIGNAL is often for creating many bthreads in batch, |
| 284 | // inserting into the same TaskGroup maximizes the batch. |
| 285 | // 2. bthread_flush() needs to know which TaskGroup to flush. |
| 286 | auto g = tls_task_group_nosignal; |
| 287 | if (NULL == g) { |
| 288 | g = c->choose_one_group(tag); |
| 289 | tls_task_group_nosignal = g; |
| 290 | } |
| 291 | return g->start_background<true>(tid, attr, fn, arg); |
| 292 | } |
| 293 | return c->choose_one_group(tag)->start_background<true>(tid, attr, fn, arg); |
| 294 | } |
| 295 | |
| 296 | // Meet one of the three conditions, can run in thread local |
| 297 | // attr is nullptr |
no test coverage detected