自己实现spinlock
#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#define ADD_CNT 10000
#define THREAD_NUM 10
pthread_t tids[THREAD_NUM];
int g_cnt = 0;
//--------------------------------------------------------------------------------------------
#define LOCK_FLAG 1
#define UN_LOCK_FLAG 0
typedef struct spinlock_t {
int32_t num;
} spinlock_t;
int xchg(volatile int *addr, int newval) {
int result;
asm volatile("lock xchg %0, %2" : "+m"(*addr), "=a"(result) : "a"(newval));
return result;
}
void spinlock_init(spinlock_t *lock) { lock->num = LOCK_FLAG; }
void spinlock_lock(spinlock_t *lock) {
int r = 0;
retry:
r = xchg(&(lock->num), UN_LOCK_FLAG);
if (r == UN_LOCK_FLAG)
goto retry;
assert(r == LOCK_FLAG);
}
void spinlock_unlock(spinlock_t *lock) { xchg(&(lock->num), LOCK_FLAG); }
//--------------------------------------------------------------------------------------------
spinlock_t lock;
void printids(const char *s) {
pid_t pid;
pthread_t tid;
pid = getpid();
tid = pthread_self();
printf("%s pid %lu tid %lu (0x%lx)\n", s, (unsigned long)pid,
(unsigned long)tid, (unsigned long)tid);
}
void *thr_fn(void *arg) {
char buf[128];
snprintf(buf, sizeof(buf), "new thread: index:%ld ", (int64_t)arg);
printids(buf);
for (int i = 0; i < ADD_CNT; ++i) {
spinlock_lock(&lock);
g_cnt++;
spinlock_unlock(&lock);
}
return ((void *)0);
}
int main(void) {
printf("begin g_cnt:%d \n", g_cnt);
spinlock_init(&lock);
for (int i = 0; i < THREAD_NUM; ++i) {
int err;
int64_t i64 = i;
err = pthread_create(&tids[i], NULL, thr_fn, (void *)i64);
if (err != 0) {
fprintf(stderr, "can't create thread, err:%d \n", err);
exit(-1);
}
}
printids("main thread:");
for (int i = 0; i < THREAD_NUM; ++i) {
pthread_join(tids[i], NULL);
}
printf("end g_cnt:%d \n", g_cnt);
exit(0);
}
#if 0
int main() {
int a = 3;
int r = xchg(&a, 6);
printf("a=%d, r=%d \n", a, r);
r = xchg(&a, 7);
printf("a=%d, r=%d \n", a, r);
}
#endif