| 737 | extern void CheckBthreadScheSafety(); |
| 738 | |
| 739 | void TaskGroup::sched_to(TaskGroup** pg, TaskMeta* next_meta) { |
| 740 | TaskGroup* g = *pg; |
| 741 | #ifndef NDEBUG |
| 742 | if ((++g->_sched_recursive_guard) > 1) { |
| 743 | LOG(FATAL) << "Recursively(" << g->_sched_recursive_guard - 1 |
| 744 | << ") call sched_to(" << g << ")"; |
| 745 | } |
| 746 | #endif |
| 747 | // Save errno so that errno is bthread-specific. |
| 748 | int saved_errno = errno; |
| 749 | void* saved_unique_user_ptr = tls_unique_user_ptr; |
| 750 | |
| 751 | TaskMeta* const cur_meta = g->_cur_meta; |
| 752 | int64_t now = butil::cpuwide_time_ns(); |
| 753 | CPUTimeStat cpu_time_stat = g->_cpu_time_stat.load_unsafe(); |
| 754 | int64_t elp_ns = now - cpu_time_stat.last_run_ns(); |
| 755 | cur_meta->stat.cputime_ns += elp_ns; |
| 756 | // Update cpu_time_stat. |
| 757 | cpu_time_stat.set_last_run_ns(now, is_main_task(g, next_meta->tid)); |
| 758 | cpu_time_stat.add_cumulated_cputime_ns(elp_ns, is_main_task(g, cur_meta->tid)); |
| 759 | g->_cpu_time_stat.store(cpu_time_stat); |
| 760 | |
| 761 | if (FLAGS_bthread_enable_cpu_clock_stat) { |
| 762 | const int64_t cpu_thread_time = butil::cputhread_time_ns(); |
| 763 | if (g->_last_cpu_clock_ns != 0) { |
| 764 | cur_meta->stat.cpu_usage_ns += cpu_thread_time - g->_last_cpu_clock_ns; |
| 765 | } |
| 766 | g->_last_cpu_clock_ns = cpu_thread_time; |
| 767 | } else { |
| 768 | g->_last_cpu_clock_ns = 0; |
| 769 | } |
| 770 | |
| 771 | ++cur_meta->stat.nswitch; |
| 772 | ++ g->_nswitch; |
| 773 | // Switch to the task |
| 774 | if (__builtin_expect(next_meta != cur_meta, 1)) { |
| 775 | g->_cur_meta = next_meta; |
| 776 | // Switch tls_bls |
| 777 | cur_meta->local_storage = BAIDU_GET_VOLATILE_THREAD_LOCAL(tls_bls); |
| 778 | BAIDU_SET_VOLATILE_THREAD_LOCAL(tls_bls, next_meta->local_storage); |
| 779 | |
| 780 | // Logging must be done after switching the local storage, since the logging lib |
| 781 | // use bthread local storage internally, or will cause memory leak. |
| 782 | if ((cur_meta->attr.flags & BTHREAD_LOG_CONTEXT_SWITCH) || |
| 783 | (next_meta->attr.flags & BTHREAD_LOG_CONTEXT_SWITCH)) { |
| 784 | LOG(INFO) << "Switch bthread: " << cur_meta->tid << " -> " |
| 785 | << next_meta->tid; |
| 786 | } |
| 787 | |
| 788 | if (cur_meta->stack != NULL) { |
| 789 | if (next_meta->stack != cur_meta->stack) { |
| 790 | CheckBthreadScheSafety(); |
| 791 | #ifdef BRPC_BTHREAD_TRACER |
| 792 | g->_control->_task_tracer.set_status(TASK_STATUS_JUMPING, cur_meta); |
| 793 | g->_control->_task_tracer.set_status(TASK_STATUS_JUMPING, next_meta); |
| 794 | #endif // BRPC_BTHREAD_TRACER |
| 795 | { |
| 796 | BTHREAD_SCOPED_ASAN_FIBER_SWITCHER(next_meta->stack->storage); |
nothing calls this directly
no test coverage detected