| 492 | } |
| 493 | |
| 494 | int TaskGroup::start_foreground(TaskGroup** pg, |
| 495 | bthread_t* __restrict th, |
| 496 | const bthread_attr_t* __restrict attr, |
| 497 | void * (*fn)(void*), |
| 498 | void* __restrict arg) { |
| 499 | if (__builtin_expect(!fn, 0)) { |
| 500 | return EINVAL; |
| 501 | } |
| 502 | const int64_t start_ns = butil::cpuwide_time_ns(); |
| 503 | const bthread_attr_t using_attr = (attr ? *attr : BTHREAD_ATTR_NORMAL); |
| 504 | butil::ResourceId<TaskMeta> slot; |
| 505 | TaskMeta* m = butil::get_resource(&slot); |
| 506 | if (BAIDU_UNLIKELY(NULL == m)) { |
| 507 | return ENOMEM; |
| 508 | } |
| 509 | CHECK(m->current_waiter.load(butil::memory_order_relaxed) == NULL); |
| 510 | m->sleep_failed = false; |
| 511 | m->stop = false; |
| 512 | m->interrupted = false; |
| 513 | m->about_to_quit = false; |
| 514 | m->fn = fn; |
| 515 | m->arg = arg; |
| 516 | CHECK(m->stack == NULL); |
| 517 | m->attr = using_attr; |
| 518 | m->local_storage = LOCAL_STORAGE_INIT; |
| 519 | if (using_attr.flags & BTHREAD_INHERIT_SPAN) { |
| 520 | if (g_create_bthread_span) { |
| 521 | m->local_storage.rpcz_parent_span = g_create_bthread_span(); |
| 522 | } else { |
| 523 | m->local_storage.rpcz_parent_span = BAIDU_GET_VOLATILE_THREAD_LOCAL(tls_bls).rpcz_parent_span; |
| 524 | } |
| 525 | } |
| 526 | m->cpuwide_start_ns = start_ns; |
| 527 | m->stat = EMPTY_STAT; |
| 528 | m->tid = make_tid(*m->version_butex, slot); |
| 529 | *th = m->tid; |
| 530 | if (using_attr.flags & BTHREAD_LOG_START_AND_FINISH) { |
| 531 | LOG(INFO) << "Started bthread " << m->tid; |
| 532 | } |
| 533 | |
| 534 | TaskGroup* g = *pg; |
| 535 | g->_control->_nbthreads << 1; |
| 536 | g->_control->tag_nbthreads(g->tag()) << 1; |
| 537 | #ifdef BRPC_BTHREAD_TRACER |
| 538 | g->_control->_task_tracer.set_status(TASK_STATUS_CREATED, m); |
| 539 | #endif // BRPC_BTHREAD_TRACER |
| 540 | if (g->is_current_pthread_task()) { |
| 541 | // never create foreground task in pthread. |
| 542 | g->ready_to_run(m, using_attr.flags & BTHREAD_NOSIGNAL); |
| 543 | } else { |
| 544 | // NOSIGNAL affects current task, not the new task. |
| 545 | RemainedFn fn = NULL; |
| 546 | auto& cur_attr = g->_cur_meta->attr; |
| 547 | if (g->_control->_enable_priority_queue && cur_attr.flags & BTHREAD_GLOBAL_PRIORITY) { |
| 548 | fn = priority_to_run; |
| 549 | } else if (g->current_task()->about_to_quit) { |
| 550 | fn = ready_to_run_in_worker_ignoresignal; |
| 551 | } else { |
nothing calls this directly
no test coverage detected