about summary refs log tree commit diff
path: root/src/rt/sync/spin_lock.cpp
blob: 11a5cb201afb146936092919c8631c8ca769b0f2 (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
44
45
46
47
/*
 * Your average spin lock.
 */

#include "globals.h"

// #define TRACE

spin_lock::spin_lock() {
    unlock();
}

spin_lock::~spin_lock() {
}

static inline unsigned xchg32(void *ptr, unsigned x) {
    __asm__ __volatile__("xchgl %0,%1"
                :"=r" ((unsigned) x)
                :"m" (*(volatile unsigned *)ptr), "0" (x)
                :"memory");
    return x;
}

void spin_lock::lock() {
    while (true) {
        if (!xchg32(&ticket, 1)) {
            return;
        }
        while (ticket) {
            pause();
        }
    }
#ifdef TRACE
    printf("  lock: %d", ticket);
#endif
}

void spin_lock::unlock() {
    ticket = 0;
#ifdef TRACE
    printf("unlock:");
#endif
}

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