MCPcopy Create free account
hub / github.com/F-Stack/f-stack / __rw_try_upgrade_int

Function __rw_try_upgrade_int

freebsd/kern/kern_rwlock.c:1278–1347  ·  view source on GitHub ↗

* Attempt to do a non-blocking upgrade from a read lock to a write * lock. This will only succeed if this thread holds a single read * lock. Returns true if the upgrade succeeded and false otherwise. */

Source from the content-addressed store, hash-verified

1276 * lock. Returns true if the upgrade succeeded and false otherwise.
1277 */
1278int
1279__rw_try_upgrade_int(struct rwlock *rw LOCK_FILE_LINE_ARG_DEF)
1280{
1281 uintptr_t v, setv, tid;
1282 struct turnstile *ts;
1283 int success;
1284
1285 if (SCHEDULER_STOPPED())
1286 return (1);
1287
1288 KASSERT(rw->rw_lock != RW_DESTROYED,
1289 ("rw_try_upgrade() of destroyed rwlock @ %s:%d", file, line));
1290 __rw_assert(&rw->rw_lock, RA_RLOCKED, file, line);
1291
1292 /*
1293 * Attempt to switch from one reader to a writer. If there
1294 * are any write waiters, then we will have to lock the
1295 * turnstile first to prevent races with another writer
1296 * calling turnstile_wait() before we have claimed this
1297 * turnstile. So, do the simple case of no waiters first.
1298 */
1299 tid = (uintptr_t)curthread;
1300 success = 0;
1301 v = RW_READ_VALUE(rw);
1302 for (;;) {
1303 if (RW_READERS(v) > 1)
1304 break;
1305 if (!(v & RW_LOCK_WAITERS)) {
1306 success = atomic_fcmpset_acq_ptr(&rw->rw_lock, &v, tid);
1307 if (!success)
1308 continue;
1309 break;
1310 }
1311
1312 /*
1313 * Ok, we think we have waiters, so lock the turnstile.
1314 */
1315 ts = turnstile_trywait(&rw->lock_object);
1316 v = RW_READ_VALUE(rw);
1317retry_ts:
1318 if (RW_READERS(v) > 1) {
1319 turnstile_cancel(ts);
1320 break;
1321 }
1322 /*
1323 * Try to switch from one reader to a writer again. This time
1324 * we honor the current state of the waiters flags.
1325 * If we obtain the lock with the flags set, then claim
1326 * ownership of the turnstile.
1327 */
1328 setv = tid | (v & RW_LOCK_WAITERS);
1329 success = atomic_fcmpset_ptr(&rw->rw_lock, &v, setv);
1330 if (success) {
1331 if (v & RW_LOCK_WAITERS)
1332 turnstile_claim(ts);
1333 else
1334 turnstile_cancel(ts);
1335 break;

Callers

nothing calls this directly

Calls 4

__rw_assertFunction · 0.85
turnstile_trywaitFunction · 0.85
turnstile_cancelFunction · 0.85
turnstile_claimFunction · 0.85

Tested by

no test coverage detected