MCPcopy Create free account
hub / github.com/apache/brpc / mutex_lock_contended_impl

Function mutex_lock_contended_impl

src/bthread/mutex.cpp:1052–1089  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1050const int MAX_SPIN_ITER = 4;
1051
1052inline int mutex_lock_contended_impl(bthread_mutex_t* __restrict m,
1053 const struct timespec* __restrict abstime) {
1054 BTHREAD_MUTEX_CHECK_OWNER;
1055 // When a bthread first contends for a lock, active spinning makes sense.
1056 // Spin only few times and only if local `rq' is empty.
1057 TaskGroup* g = BAIDU_GET_VOLATILE_THREAD_LOCAL(tls_task_group);
1058 if (BAIDU_UNLIKELY(NULL == g || g->rq_size() == 0)) {
1059 for (int i = 0; i < MAX_SPIN_ITER; ++i) {
1060 cpu_relax();
1061 }
1062 }
1063
1064 bool queue_lifo = false;
1065 bool first_wait = true;
1066 auto whole = (butil::atomic<unsigned>*)m->butex;
1067 while (whole->exchange(BTHREAD_MUTEX_CONTENDED) & BTHREAD_MUTEX_LOCKED) {
1068 if (bthread::butex_wait(whole, BTHREAD_MUTEX_CONTENDED, abstime, queue_lifo) < 0 &&
1069 errno != EWOULDBLOCK && errno != EINTR/*note*/) {
1070 // A mutex lock should ignore interruptions in general since
1071 // user code is unlikely to check the return value.
1072 return errno;
1073 }
1074 // Ignore EWOULDBLOCK and EINTR.
1075 if (first_wait && 0 == errno) {
1076 first_wait = false;
1077 }
1078 if (!first_wait) {
1079 // Normally, bthreads are queued in FIFO order. But competing with new
1080 // arriving bthreads over the ownership of mutex, a woken up bthread
1081 // has good chances of losing. Because new arriving bthreads are already
1082 // running on CPU and there can be lots of them. In such case, for fairness,
1083 // to avoid starvation, it is queued at the head of the waiter queue.
1084 queue_lifo = true;
1085 }
1086 }
1087 BTHREAD_MUTEX_SET_OWNER;
1088 return 0;
1089}
1090
1091#ifdef BTHREAD_USE_FAST_PTHREAD_MUTEX
1092namespace internal {

Callers 2

bthread_mutex_lock_implFunction · 0.85

Calls 3

butex_waitFunction · 0.85
rq_sizeMethod · 0.80
exchangeMethod · 0.45

Tested by

no test coverage detected