| 1252 | } |
| 1253 | |
| 1254 | int bthread_mutex_unlock(bthread_mutex_t* m) { |
| 1255 | auto whole = (butil::atomic<unsigned>*)m->butex; |
| 1256 | bthread_contention_site_t saved_csite = {0, 0}; |
| 1257 | bool is_valid = bthread::is_contention_site_valid(m->csite); |
| 1258 | if (is_valid) { |
| 1259 | saved_csite = m->csite; |
| 1260 | bthread::make_contention_site_invalid(&m->csite); |
| 1261 | } |
| 1262 | MUTEX_RESET_OWNER_COMMON(m->owner); |
| 1263 | const unsigned prev = whole->exchange(0, butil::memory_order_release); |
| 1264 | // CAUTION: the mutex may be destroyed, check comments before butex_create |
| 1265 | if (prev == BTHREAD_MUTEX_LOCKED) { |
| 1266 | return 0; |
| 1267 | } |
| 1268 | // Wakeup one waiter |
| 1269 | if (!is_valid) { |
| 1270 | bthread::butex_wake(whole); |
| 1271 | return 0; |
| 1272 | } |
| 1273 | const int64_t unlock_start_ns = butil::cpuwide_time_ns(); |
| 1274 | bthread::butex_wake(whole); |
| 1275 | const int64_t unlock_end_ns = butil::cpuwide_time_ns(); |
| 1276 | saved_csite.duration_ns += unlock_end_ns - unlock_start_ns; |
| 1277 | bthread::submit_contention(saved_csite, unlock_end_ns); |
| 1278 | return 0; |
| 1279 | } |
| 1280 | |
| 1281 | int bthread_mutexattr_init(bthread_mutexattr_t* attr) { |
| 1282 | attr->enable_csite = true; |