#include "util.h" #include "atomic.h" #include "spinlock.h" void TASLock::lock() { while (state.getAndSet(true)) {} } void TASLock::unlock() { state.set(false); } void TTASLock::lock() { while (true) { while (state.get()) {} if (!state.getAndSet(true)) return; } } void TTASLock::unlock() { state.set(false); } void FIFOTicketLock::lock() { int myTicket = ticket.getAndIncrement(); while (myTicket != token) {} } void FIFOTicketLock::unlock() { token++; } void BackoffLock::lock() { // 等待的时间可以任意设置 Backoff backoff; while (true) { while (state.get()) {} if (!state.getAndSet(true)) return; else backoff.backoff(); } } void BackoffLock::unlock() { state.set(false); } // 定义Cache线的宽度,不同类型的CPU可能不同 #define CACHE_LINE_WIDTH 4 ALock::ALock(int capacity) { size = capacity; flag = new bool[size * CACHE_LINE_WIDTH]; flag[0] = true; for (int i = 1; i < size; i++) flag[i * CACHE_LINE_WIDTH] = false; } ALock::~ALock() { delete[] flag; } int ALock::mySlotIndex = 0; void ALock::lock() { int slot = tail.getAndIncrement() % size; mySlotIndex = slot; while (!flag[slot * CACHE_LINE_WIDTH]) {} } void ALock::unlock() { int slot = mySlotIndex; flag[slot * CACHE_LINE_WIDTH] = false; slot = (slot+1) % size; flag[slot * CACHE_LINE_WIDTH] = true; } MCSLock::MCSLock():tail(0) { } MCSLock::QNode MCSLock::myNode; void MCSLock::lock() { myNode.next = 0; QNode * pred = tail.getAndSet(&myNode); if (pred != 0) { myNode.locked = true; pred->next = &myNode; while (myNode.locked) {} } } void MCSLock::unlock() { if (myNode.next == 0) { if (tail.compareAndSet(&myNode, 0)) return; // wait until predecessor fills in its next field while (myNode.next == 0) {} } // 一个线程访问另一个线程的TLS空间时,必须保证后者没有结束 myNode.next->locked = false; myNode.next = 0; } TOLock::TOLock():tail(0) { } TOLock::QNode TOLock::AVAILABLE; TOLock::QNode * TOLock::myNode = 0; // 姑且用CPU的时钟周期作为时间单位 // 本函数需要申请、释放内存,因此很耗时 // 前面线程超时后,后面线程要帮它释放内存,导致后面线程也超时 bool TOLock::tryLock(TIME_TYPE cycle) { QNode * qnode = new QNode; qnode->pred = 0; myNode = qnode; QNode * myPred = tail.getAndSet(qnode); if (myPred == 0) return true; TIME_TYPE endTime = get_clock() + cycle; do { QNode * predPred = myPred->pred; if (predPred == &AVAILABLE) { // 如果释放锁的线程不在队尾,在此释放内存 delete myPred; return true; } else if (predPred != 0) { // 如果超时的线程不在队尾,在此释放内存 delete myPred; myPred = predPred; } } while (!timeout(endTime)); // 如果超时的线程在队尾,在此释放内存 if (tail.compareAndSet(qnode, myPred)) delete qnode; else qnode->pred = myPred; return false; } void TOLock::lock() { QNode * qnode = new QNode; qnode->pred = 0; myNode = qnode; QNode * myPred = tail.getAndSet(qnode); if (myPred == 0) return; do { QNode * predPred = myPred->pred; if (predPred == &AVAILABLE) { // 如果释放锁的线程不在队尾,在此释放内存 delete myPred; return; } if (predPred != 0) { // 如果超时的线程不在队尾,在此释放内存 delete myPred; myPred = predPred; } } while (true); } void TOLock::unlock() { // 如果释放锁的线程在队尾,在此释放内存 if (tail.compareAndSet(myNode, 0)) delete myNode; else myNode->pred = &AVAILABLE; } TO2Lock::TO2Lock():tail(0) { } TO2Lock::QNode TO2Lock::AVAILABLE; TO2Lock::QNode TO2Lock::myNode; bool TO2Lock::tryLock(TIME_TYPE cycle) { // 如果上次加锁超时,等待后续线程将其踢出队列 while (myNode.pred != 0) {} QNode * myPred = tail.getAndSet(&myNode); if (myPred == 0) return true; TIME_TYPE endTime = get_clock() + cycle; do { QNode * predPred = myPred->pred; if (predPred == &AVAILABLE) { // 如果释放锁的线程不在队尾,在此踢出队列 myPred->pred = 0; return true; } else if (predPred != 0) { // 如果超时的线程不在队尾,在此踢出队列 myPred->pred = 0; myPred = predPred; } } while (!timeout(endTime)); // 如果超时的线程不在队尾,则等后续线程踢出队列 if (!tail.compareAndSet(&myNode, myPred)) myNode.pred = myPred; return false; } void TO2Lock::lock() { QNode * myPred = tail.getAndSet(&myNode); if (myPred == 0) return; do { QNode * predPred = myPred->pred; if (predPred == &AVAILABLE) { // 如果释放锁的线程不在队尾,在此踢出队列 myPred->pred = 0; return; } else if (predPred != 0) { // 如果超时的线程不在队尾,在此踢出队列 myPred->pred = 0; myPred = predPred; } } while (true); } void TO2Lock::unlock() { // 如果释放锁的线程不在队尾,则等后续线程踢出队列 if (!tail.compareAndSet(&myNode, 0)) { myNode.pred = &AVAILABLE; // 必须等后续线程访问完了,本线程才能退出 // 否则后续线程会访问无效空间 while (myNode.pred != 0) {} } } CompositeLock::CompositeLock(int _size):tail(0) { size = _size; waiting = new QNode[size]; for (int i = 0; i < size; i++) { waiting[i].state.set(FREE); waiting[i].pred = 0; } } CompositeLock::~CompositeLock() { delete[] waiting; } CompositeLock::QNode * CompositeLock::myNode = 0; bool CompositeLock::tryLock(TIME_TYPE cycle) { TIME_TYPE endTime = get_clock() + cycle; QNode * node = acquireQNode(endTime); if (node == 0) return false; QNode * pred = spliceQNode(node); if (pred == 0) { myNode = node; return true; } else return waitForPredecessor(pred, node, endTime); } void CompositeLock::unlock() { // 通知下一个线程进入互斥区,由下一个线程释放节点 myNode->state.set(RELEASED); myNode = 0; } CompositeLock::QNode * CompositeLock::acquireQNode(TIME_TYPE endTime) { // 等待的时间可以任意设置 Backoff backoff; // 随机获取一个节点 QNode * node = &waiting[get_clock() % size]; QNode * currTail; int currStamp = 0; while (true) { // 如果节点空闲就立即返回 if (node->state.compareAndSet(FREE, WAITING)) return node; currTail = tail.get(currStamp); State state = (State)node->state.get(); if (state == ABORTED || state == RELEASED) { if (node == currTail) { QNode * myPred = 0; if (state == ABORTED) myPred = node->pred; if (tail.compareAndSet(currTail, myPred, currStamp, currStamp+1)) { node->state.set(WAITING); return node; } } } // 节点不空闲则等待 backoff.backoff(); // 测试是否超时 if (timeout(endTime)) return 0; } } CompositeLock::QNode * CompositeLock::spliceQNode(QNode * node) { // 这个函数原本可以用getAndSet实现,为了修改邮戳只好牺牲了 // 这个循环不大可能超时,除非一直有人修改队尾 QNode * currTail; int currStamp = 0; do { currTail = tail.get(currStamp); } while (!tail.compareAndSet(currTail, node, currStamp, currStamp+1)); return currTail; } bool CompositeLock::waitForPredecessor(QNode * pred, QNode * node, TIME_TYPE endTime) { State predState = (State)pred->state.get(); while (predState != RELEASED) { if (predState == ABORTED) { QNode * temp = pred; pred = pred->pred; temp->state.set(FREE); } // 如果超时则设置为ABORTED if (timeout(endTime)) { node->pred = pred; node->state.set(ABORTED); return false; } predState = (State)pred->state.get(); } pred->state.set(FREE); myNode = node; return true; } #define FASTPATH_LOCK 0x80000000 // 窃取最高位作为快速加锁的标识 bool CompositeFastPathLock::tryLock(TIME_TYPE cycle) { if (fastPathLock()) return true; if (!CompositeLock::tryLock(cycle)) return false; while ((tail.getStamp() & FASTPATH_LOCK) != 0) {} return true; } bool CompositeFastPathLock::fastPathLock() { int oldStamp, newStamp; QNode * qnode = tail.get(oldStamp); if (qnode !