void mutex_lock(mutex_t *lock) { XEDGE(trylock, loop_out); int expected; do { expected = 0; } while (!L(trylock, lock->locked.compare_exchange_weak(expected, 1))); LPOST(loop_out); }
void lock() { XEDGE(lock, out); Node::Ptr unlocked(nullptr, 0); if (!L(lock, tail_.compare_exchange_strong(unlocked, Node::Ptr(nullptr, 1)))){ LS(lock, slowpathLock(unlocked)); } LPOST(out); }
void mutex2_lock(mutex2_t *lock) { //XEDGE(take, check); // I /think/ maybe we don't need this depending. XEDGE(check, loop_out); int ticket = L(take, lock->next.fetch_add(1)); while (ticket != L(check, lock->owner)) continue; LPOST(loop_out); }
rmc_noinline optional<T> MSQueue<T>::dequeue() { auto guard = Epoch::pin(); // Core message passing: reading the data out of the node comes // after getting the pointer to it. XEDGE(get_next, node_use); // Make sure we see at least head's init XEDGE(get_head, get_next); // Need to make sure anything visible through the next pointer // stays visible when it gets republished at the head or tail VEDGE(get_next, dequeue); lf_ptr<MSQueueNode> head, next; for (;;) { head = L(get_head, this->head_); next = L(get_next, head->next_); // Consistency check; see note above if (head != this->head_) continue; // Is the queue empty? if (next == nullptr) { return optional<T> {}; } else { // OK, now we try to actually read the thing out. if (L(dequeue, this->head_.compare_exchange_weak(head, next))) { break; } } } LPOST(node_use); // OK, everything set up. // next contains the value we are reading // head can be freed guard.unlinked(head); optional<T> ret(std::move(next->data_)); next->data_ = optional<T> {}; // destroy the object return ret; }
void lock() { XEDGE(acquire, out); uintptr_t locked; for (;;) { locked = locked_; if (!writeLocked(locked)) { if (L(acquire, locked_.compare_exchange_weak( locked, locked|kWriterLocked))) { break; } } } while (readLocked(locked)) { locked = L(acquire, locked_); } LPOST(out); }
rmc_noinline optional<T> MSQueue<T>::dequeue() { // Core message passing: reading the data out of the node comes // after getting the pointer to it. XEDGE(get_next, node_use); // Make sure we see at least head's init XEDGE(get_head, get_next); // XXX: another part of maintaining the awful head != tail -> // next != null invariant that causes like a billion constraints. // Think about it a bit more to make sure this is right. // This is awful, so many barriers. XEDGE(get_head, get_tail); // If we see an updated tail (so that head != tail), make sure that // we see update to head->next. XEDGE(get_tail, get_next); // Need to make sure anything visible through the next pointer // stays visible when it gets republished at the head or tail VEDGE(get_next, catchup_swing); VEDGE(get_next, dequeue); // Make sure the read out of next executes before the verification // that it read from a sensible place: XEDGE(get_next, verify_head); NodePtr head, tail, next; universal data; for (;;) { head = L(get_head, this->head_); tail = L(get_tail, this->tail_); // XXX: really? next = L(get_next, head->next_); // Consistency check; see note above if (head != L(verify_head, this->head_)) continue; // Check if the queue *might* be empty // XXX: is it necessary to have the empty check under this if (head == tail) { // Ok, so, the queue might be empty, but it also might // be that the tail pointer has just fallen behind. // If the next pointer is null, then it is actually empty if (next == nullptr) { return optional<T> {}; } else { // not empty: tail falling behind; since it is super // not ok for the head to advance past the tail, // try advancing the tail // XXX weak v strong? L(catchup_swing, this->tail_.compare_exchange_strong_gen(tail, next)); } } else { // OK, now we try to actually read the thing out. assert_ne(next.ptr(), nullptr); // We need to read the data out of the node // *before* we try to dequeue it or else it could get // reused before we read it out. data = L(node_use, next->data_); if (L(dequeue, this->head_.compare_exchange_weak_gen(head, next))) { break; } } } LPOST(node_use); // OK, everything set up. // head can be freed MSQueueNode::freelist.unlinked(head); optional<T> ret(data.extract<T>()); return ret; }