enum State {
RWNONE,
RWREAD,
- RWWRITE
+ RWWRITE,
+ RWEXCL,
};
static const char *get_state_name(State s) {
switch (s) {
case RWNONE: return "none";
case RWREAD: return "read";
case RWWRITE: return "write";
+ case RWEXCL: return "excl";
default: return "???";
}
}
return true;
case RWWRITE:
return false;
+ case RWEXCL:
+ return false;
default:
assert(0 == "unhandled case");
return false;
return true;
case RWREAD:
return false;
+ case RWEXCL:
+ return false;
default:
assert(0 == "unhandled case");
return false;
}
}
+ bool get_excl_lock() {
+ switch (state) {
+ case RWNONE:
+ assert(count == 0);
+ state = RWEXCL;
+ count = 1;
+ return true;
+ case RWWRITE:
+ return false;
+ case RWREAD:
+ return false;
+ case RWEXCL:
+ return false;
+ default:
+ assert(0 == "unhandled case");
+ return false;
+ }
+ }
+ bool get_excl(OpRequestRef op) {
+ if (get_excl_lock()) {
+ return true;
+ } // else
+ if (op)
+ waiters.push_back(op);
+ return false;
+ }
/// same as get_write_lock, but ignore starvation
bool take_write_lock() {
if (state == RWWRITE) {
assert(state == RWWRITE);
dec(requeue);
}
+ void put_excl(list<OpRequestRef> *requeue) {
+ assert(state == RWEXCL);
+ dec(requeue);
+ }
bool empty() const { return state == RWNONE; }
} rwstate;
bool get_write(OpRequestRef op) {
return rwstate.get_write(op, false);
}
+ bool get_excl(OpRequestRef op) {
+ return rwstate.get_excl(op);
+ }
+ bool get_lock_type(OpRequestRef op, RWState::State type) {
+ switch (type) {
+ case RWState::RWWRITE:
+ return get_write(op);
+ case RWState::RWREAD:
+ return get_read(op);
+ case RWState::RWEXCL:
+ return get_excl(op);
+ default:
+ assert(0 == "invalid lock type");
+ return true;
+ }
+ }
bool get_write_greedy(OpRequestRef op) {
return rwstate.get_write(op, true);
}
void put_read(list<OpRequestRef> *to_wake) {
rwstate.put_read(to_wake);
}
+ void put_excl(list<OpRequestRef> *to_wake,
+ bool *requeue_recovery,
+ bool *requeue_snaptrimmer) {
+ rwstate.put_excl(to_wake);
+ if (rwstate.empty() && rwstate.recovery_read_marker) {
+ rwstate.recovery_read_marker = false;
+ *requeue_recovery = true;
+ }
+ if (rwstate.empty() && rwstate.snaptrimmer_write_marker) {
+ rwstate.snaptrimmer_write_marker = false;
+ *requeue_snaptrimmer = true;
+ }
+ }
void put_write(list<OpRequestRef> *to_wake,
bool *requeue_recovery,
bool *requeue_snaptrimmer) {