about summary refs log tree commit diff
path: root/src/rt/sync/fair_ticket_lock.cpp
blob: 0306ee1df39537a8fe0d3ca488ddbd6e6b7083bb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/*
 * This works well as long as the number of contending threads
 * is less than the number of processors. This is because of
 * the fair locking scheme. If the thread that is next in line
 * for acquiring the lock is not currently running, no other
 * thread can acquire the lock. This is terrible for performance,
 * and it seems that all fair locking schemes suffer from this
 * behavior.
 */

// #define TRACE

fair_ticket_lock::fair_ticket_lock() {
    next_ticket = now_serving = 0;
}

fair_ticket_lock::~fair_ticket_lock() {

}

void fair_ticket_lock::lock() {
    unsigned ticket = __sync_fetch_and_add(&next_ticket, 1);
    while (now_serving != ticket) {
        pause();
    }
#ifdef TRACE
    printf("locked   nextTicket: %d nowServing: %d",
            next_ticket, now_serving);
#endif
}

void fair_ticket_lock::unlock() {
    now_serving++;
#ifdef TRACE
    printf("unlocked nextTicket: %d nowServing: %d",
            next_ticket, now_serving);
#endif
}

void fair_ticket_lock::pause() {
    asm volatile("pause\n" : : : "memory");
}