two-headBoy commented on code in PR #3633:
URL: https://github.com/apache/brpc/pull/3633#discussion_r4399924127


##########
src/bthread/task_group_inl.h:
##########
@@ -93,11 +93,100 @@ inline void TaskGroup::push_rq(bthread_t tid) {
         //   brpc)
         flush_nosignal_tasks();
         LOG_EVERY_SECOND(ERROR) << "_rq is full, capacity=" << _rq.capacity();
-        // TODO(gejun): May cause deadlock when all workers are spinning here.
-        // A better solution is to pop and run existing bthreads, however which
-        // make set_remained()-callbacks do context switches and need extensive
-        // reviews on related code.
-        ::usleep(1000);
+        if (is_current_pthread_task() && !is_current_main_task()) {
+            // A pthread-mode bthread runs on _main_stack and cannot be
+            // scheduled out, fall back to waiting.
+            ::usleep(1000);
+            continue;
+        }
+        const auto pop_task = [this](bthread_t* t) -> bool {
+#ifndef BTHREAD_FAIR_WSQ
+            return _rq.pop(t);
+#else

Review Comment:
   Under BTHREAD_FAIR_WSQ, pop_task() uses _rq.steal() rather than an 
owner-side pop. If steal() has different semantics (end of deque, fairness, or 
concurrency assumptions) than the owner-consumption path, this may change 
scheduling behavior in the overload path. Prefer using the owner pop API if it 
exists in the fair-WSQ implementation; otherwise, add an explicit comment 
explaining why steal() is the correct/safe choice for the owning worker here.



##########
src/bthread/task_group_inl.h:
##########
@@ -93,11 +93,100 @@ inline void TaskGroup::push_rq(bthread_t tid) {
         //   brpc)
         flush_nosignal_tasks();
         LOG_EVERY_SECOND(ERROR) << "_rq is full, capacity=" << _rq.capacity();
-        // TODO(gejun): May cause deadlock when all workers are spinning here.
-        // A better solution is to pop and run existing bthreads, however which
-        // make set_remained()-callbacks do context switches and need extensive
-        // reviews on related code.
-        ::usleep(1000);
+        if (is_current_pthread_task() && !is_current_main_task()) {
+            // A pthread-mode bthread runs on _main_stack and cannot be
+            // scheduled out, fall back to waiting.
+            ::usleep(1000);
+            continue;
+        }
+        const auto pop_task = [this](bthread_t* t) -> bool {
+#ifndef BTHREAD_FAIR_WSQ
+            return _rq.pop(t);
+#else

Review Comment:
   Under BTHREAD_FAIR_WSQ, pop_task() uses _rq.steal() rather than an 
owner-side pop. If steal() has different semantics (end of deque, fairness, or 
concurrency assumptions) than the owner-consumption path, this may change 
scheduling behavior in the overload path. Prefer using the owner pop API if it 
exists in the fair-WSQ implementation; otherwise, add an explicit comment 
explaining why steal() is the correct/safe choice for the owning worker here.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to