polyrabbit commented on a change in pull request #1031:
URL: https://github.com/apache/incubator-brpc/pull/1031#discussion_r820148410
##########
File path: src/bthread/rwlock.cpp
##########
@@ -0,0 +1,163 @@
+#include <pthread.h>
+#include <execinfo.h>
+#include <dlfcn.h> // dlsym
+#include <fcntl.h> // O_RDONLY
+#include "butil/atomicops.h"
+#include "bvar/bvar.h"
+#include "bvar/collector.h"
+#include "butil/macros.h" // BAIDU_CASSERT
+#include "butil/containers/flat_map.h"
+#include "butil/iobuf.h"
+#include "butil/fd_guard.h"
+#include "butil/files/file.h"
+#include "butil/files/file_path.h"
+#include "butil/file_util.h"
+#include "butil/unique_ptr.h"
+#include "butil/third_party/murmurhash3/murmurhash3.h"
+#include "butil/logging.h"
+#include "butil/object_pool.h"
+#include "bthread/butex.h" // butex_*
+#include "bthread/processor.h" // cpu_relax, barrier
+#include "bthread/bthread.h"
+#include "bthread/sys_futex.h"
+#include "bthread/log.h"
+
+
+namespace bthread {
+
+inline int rwlock_unrlock(bthread_rwlock_t* rwlock) {
+ butil::atomic<unsigned>* whole =
+ (butil::atomic<unsigned>*)rwlock->lock_flag;
+
+ while(1) {
+ unsigned r = whole->load();
+ if(r==0 || (r>>31) != 0) {
+ LOG(ERROR) << "wrong unrlock!";
+ return 0;
+ }
+ if(!(whole->compare_exchange_weak(r, r-1))) {
+ continue;
+ }
+ //wake up write waiter
+ bthread::butex_wake(whole);
+ return 0;
+ }
+
+}
+
+
+inline int rwlock_unwlock(bthread_rwlock_t* rwlock) {
+ butil::atomic<unsigned>* whole =
+ (butil::atomic<unsigned>*)rwlock->lock_flag;
+
+ while(1) {
+ unsigned r = whole->load();
+ if(r != (unsigned)(1<<31) ) {
+ LOG(ERROR) << "wrong unwlock!";
+ return 0;
+ }
+ if(!whole->compare_exchange_weak(r, 0)) {
+ continue;
+ }
+ //wake up write waiter first
+ bthread::butex_wake(whole);
+ butil::atomic<unsigned>* w_wait_count =
(butil::atomic<unsigned>*)rwlock->w_wait_count;
+ //try reduce wait_count for read waiters,and wake up read waiters
+ w_wait_count->fetch_sub(1);
+ bthread::butex_wake_all(w_wait_count);
+ return 0;
+ }
+
+}
+
+
+inline int rwlock_unlock(bthread_rwlock_t* rwlock) {
+ butil::atomic<unsigned>* whole =
+ (butil::atomic<unsigned>*)rwlock->lock_flag;
+ if ((whole->load(butil::memory_order_relaxed) >> 31) != 0) {
+ return rwlock_unwlock(rwlock);
+ } else {
+ return rwlock_unrlock(rwlock);
+ }
+}
+
+inline int rwlock_rlock(bthread_rwlock_t* rwlock) {
+ butil::atomic<unsigned>* whole =
+ (butil::atomic<unsigned>*)rwlock->lock_flag;
+
+ butil::atomic<unsigned>* w_wait_count =
(butil::atomic<unsigned>*)rwlock->w_wait_count;
+ while (1) {
+ unsigned w = w_wait_count->load();
+ if( w > 0) {
+ if(bthread::butex_wait(w_wait_count, w, NULL) < 0 &&
+ errno != EWOULDBLOCK && errno != EINTR) {
+ return errno;
+ }
+ continue;
+ }
+ //FIXME!! we don't consider read_wait_count overflow yet,2^31 should
be enough here
+ unsigned r = whole->load();
+ if((r >> 31) == 0) {
+ if(whole->compare_exchange_weak(r, r + 1)) {
+ return 0;
+ }
+ }
+ }
+
+}
+
+inline int rwlock_wlock(bthread_rwlock_t* rwlock) {
+ butil::atomic<unsigned>* w_wait_count =
(butil::atomic<unsigned>*)rwlock->w_wait_count;
+ butil::atomic<unsigned>* whole =
(butil::atomic<unsigned>*)rwlock->lock_flag;
+ //we don't consider w_wait_count overflow yet,2^32 should be enough here
+ w_wait_count->fetch_add(1);
+ while(1) {
+ unsigned r = whole->load();
+ if(r != 0) {
+ if(bthread::butex_wait(whole, r, NULL) < 0 &&
+ errno != EWOULDBLOCK && errno != EINTR) {
+ whole->fetch_sub(1);
Review comment:
这里需要减一的为啥是`whole`?我感觉应该是`w_wait_count`吧?
--
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]