3737#include " bthread/task_group.h"
3838#include " bthread/timer_thread.h"
3939
40+ #ifdef __x86_64__
41+ #include < x86intrin.h>
42+ #endif // __x86_64__
43+
44+ #ifdef __ARM_NEON
45+ #include < arm_neon.h>
46+ #endif // __ARM_NEON
47+
4048namespace bthread {
4149
4250static const bthread_attr_t BTHREAD_ATTR_TASKGROUP = {
@@ -69,10 +77,6 @@ BAIDU_VOLATILE_THREAD_LOCAL(void*, tls_unique_user_ptr, NULL);
6977
7078const TaskStatistics EMPTY_STAT = { 0 , 0 , 0 };
7179
72- const size_t OFFSET_TABLE[] = {
73- #include " bthread/offset_inl.list"
74- };
75-
7680void * (*g_create_span_func)() = NULL ;
7781
7882void * run_create_span_func () {
@@ -82,6 +86,39 @@ void* run_create_span_func() {
8286 return BAIDU_GET_VOLATILE_THREAD_LOCAL (tls_bls).rpcz_parent_span ;
8387}
8488
89+ AtomicInteger128::Value AtomicInteger128::load () const {
90+ #if __x86_64__ || __ARM_NEON
91+ // Supress compiler warning.
92+ (void )_mutex;
93+ #endif // __x86_64__ || __ARM_NEON
94+
95+ #if __x86_64__ || __ARM_NEON
96+ #ifdef __x86_64__
97+ __m128i value = _mm_load_si128 (reinterpret_cast <const __m128i*>(&_value));
98+ #else // __ARM_NEON
99+ int64x2_t value = vld1q_s64 (reinterpret_cast <const int64_t *>(&_value));
100+ #endif // __x86_64__
101+ return {value[0 ], value[1 ]};
102+ #else // __x86_64__ || __ARM_NEON
103+ BAIDU_SCOPED_LOCK (_mutex);
104+ return _value;
105+ #endif // __x86_64__ || __ARM_NEON
106+ }
107+
108+ void AtomicInteger128::store (Value value) {
109+ #if __x86_64__
110+ __m128i v = _mm_load_si128 (reinterpret_cast <__m128i*>(&value));
111+ _mm_store_si128 (reinterpret_cast <__m128i*>(&_value), v);
112+ #elif __ARM_NEON
113+ int64x2_t v = vld1q_s64 (reinterpret_cast <int64_t *>(&value));
114+ vst1q_s64 (reinterpret_cast <int64_t *>(&_value), v);
115+ #else
116+ BAIDU_SCOPED_LOCK (_mutex);
117+ _value = value;
118+ #endif // __x86_64__ || __ARM_NEON
119+ }
120+
121+
85122int TaskGroup::get_attr (bthread_t tid, bthread_attr_t * out) {
86123 TaskMeta* const m = address_meta (tid);
87124 if (m != NULL ) {
@@ -148,6 +185,16 @@ static double get_cumulated_cputime_from_this(void* arg) {
148185 return static_cast <TaskGroup*>(arg)->cumulated_cputime_ns () / 1000000000.0 ;
149186}
150187
188+ int64_t TaskGroup::cumulated_cputime_ns () const {
189+ CPUTimeStat cpu_time_stat = _cpu_time_stat.load ();
190+ // Add the elapsed time of running bthread.
191+ int64_t cumulated_cputime_ns = cpu_time_stat.cumulated_cputime_ns ();
192+ if (!cpu_time_stat.is_main_task ()) {
193+ cumulated_cputime_ns += butil::cpuwide_time_ns () - cpu_time_stat.last_run_ns ();
194+ }
195+ return cumulated_cputime_ns;
196+ }
197+
151198void TaskGroup::run_main_task () {
152199 bvar::PassiveStatus<double > cumulated_cputime (
153200 get_cumulated_cputime_from_this, this );
@@ -156,11 +203,11 @@ void TaskGroup::run_main_task() {
156203 TaskGroup* dummy = this ;
157204 bthread_t tid;
158205 while (wait_task (&tid)) {
159- TaskGroup:: sched_to (&dummy, tid);
206+ sched_to (&dummy, tid);
160207 DCHECK_EQ (this , dummy);
161208 DCHECK_EQ (_cur_meta->stack , _main_stack);
162209 if (_cur_meta->tid != _main_tid) {
163- TaskGroup:: task_runner (1 /* skip remained*/ );
210+ task_runner (1 /* skip remained*/ );
164211 }
165212 if (FLAGS_show_per_worker_usage_in_vars && !usage_bvar) {
166213 char name[32 ];
@@ -176,31 +223,12 @@ void TaskGroup::run_main_task() {
176223 }
177224 }
178225 // Don't forget to add elapse of last wait_task.
179- current_task ()->stat .cputime_ns += butil::cpuwide_time_ns () - _last_run_ns;
226+ current_task ()->stat .cputime_ns +=
227+ butil::cpuwide_time_ns () - _cpu_time_stat.load_unsafe ().last_run_ns ();
180228}
181229
182230TaskGroup::TaskGroup (TaskControl* c)
183- : _cur_meta(NULL )
184- , _control(c)
185- , _num_nosignal(0 )
186- , _nsignaled(0 )
187- , _last_run_ns(butil::cpuwide_time_ns())
188- , _cumulated_cputime_ns(0 )
189- , _nswitch(0 )
190- , _last_context_remained(NULL )
191- , _last_context_remained_arg(NULL )
192- , _pl(NULL )
193- , _main_stack(NULL )
194- , _main_tid(0 )
195- , _remote_num_nosignal(0 )
196- , _remote_nsignaled(0 )
197- #ifndef NDEBUG
198- , _sched_recursive_guard(0 )
199- #endif
200- , _tag(BTHREAD_TAG_DEFAULT)
201- , _tid(-1 ) {
202- _steal_seed = butil::fast_rand ();
203- _steal_offset = OFFSET_TABLE[_steal_seed % ARRAY_SIZE (OFFSET_TABLE)];
231+ : _control(c) {
204232 CHECK (c);
205233}
206234
@@ -292,8 +320,12 @@ int TaskGroup::init(size_t runqueue_capacity) {
292320 _cur_meta = m;
293321 _main_tid = m->tid ;
294322 _main_stack = stk;
295- _last_run_ns = butil::cpuwide_time_ns ();
323+
324+ CPUTimeStat cpu_time_stat;
325+ cpu_time_stat.set_last_run_ns (m->cpuwide_start_ns , true );
326+ _cpu_time_stat.store (cpu_time_stat);
296327 _last_cpu_clock_ns = 0 ;
328+
297329 return 0 ;
298330}
299331
@@ -414,7 +446,7 @@ void TaskGroup::task_runner(intptr_t skip_remained) {
414446
415447 g->_control ->_nbthreads << -1 ;
416448 g->_control ->tag_nbthreads (g->tag ()) << -1 ;
417- g->set_remained (TaskGroup:: _release_last_context, m);
449+ g->set_remained (_release_last_context, m);
418450 ending_sched (&g);
419451
420452 } while (g->_cur_meta ->tid != g->_main_tid );
@@ -491,9 +523,7 @@ int TaskGroup::start_foreground(TaskGroup** pg,
491523 fn = ready_to_run_in_worker;
492524 }
493525 ReadyToRunArgs args = {
494- g->tag (),
495- g->_cur_meta ,
496- (bool )(using_attr.flags & BTHREAD_NOSIGNAL)
526+ g->tag (), g->_cur_meta , (bool )(using_attr.flags & BTHREAD_NOSIGNAL)
497527 };
498528 g->set_remained (fn, &args);
499529 sched_to (pg, m->tid );
@@ -678,14 +708,18 @@ void TaskGroup::sched_to(TaskGroup** pg, TaskMeta* next_meta, bool cur_ending) {
678708 }
679709#endif
680710 // Save errno so that errno is bthread-specific.
681- const int saved_errno = errno;
711+ int saved_errno = errno;
682712 void * saved_unique_user_ptr = tls_unique_user_ptr;
683713
684714 TaskMeta* const cur_meta = g->_cur_meta ;
685- const int64_t now = butil::cpuwide_time_ns ();
686- const int64_t elp_ns = now - g->_last_run_ns ;
687- g-> _last_run_ns = now;
715+ int64_t now = butil::cpuwide_time_ns ();
716+ CPUTimeStat cpu_time_stat = g->_cpu_time_stat . load_unsafe () ;
717+ int64_t elp_ns = now - cpu_time_stat. last_run_ns () ;
688718 cur_meta->stat .cputime_ns += elp_ns;
719+ // Update cpu_time_stat.
720+ cpu_time_stat.set_last_run_ns (now, is_main_task (g, next_meta->tid ));
721+ cpu_time_stat.add_cumulated_cputime_ns (elp_ns, is_main_task (g, cur_meta->tid ));
722+ g->_cpu_time_stat .store (cpu_time_stat);
689723
690724 if (FLAGS_bthread_enable_cpu_clock_stat) {
691725 const int64_t cpu_thread_time = butil::cputhread_time_ns ();
@@ -696,10 +730,7 @@ void TaskGroup::sched_to(TaskGroup** pg, TaskMeta* next_meta, bool cur_ending) {
696730 } else {
697731 g->_last_cpu_clock_ns = 0 ;
698732 }
699-
700- if (cur_meta->tid != g->main_tid ()) {
701- g->_cumulated_cputime_ns += elp_ns;
702- }
733+
703734 ++cur_meta->stat .nswitch ;
704735 ++ g->_nswitch ;
705736 // Switch to the task
0 commit comments