自己实现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