#include <stdint.h>#include <assert.h>#include <stdio.h>#include <pthread.h>#include <unistd.h>#define SPIN_LOCK 1static uint32_t atomic_cmp_set(uint32_t *lock, uint32_t old, uint32_t set){ uint8_t rslt = 0; asm volatile ("lock;" // lock if SMP "cmpxchgl %3, %1;" "sete %0;" : "=a" (rslt) : "m" (*lock), "a" (old), "r" (set) : "cc", "memory"); return rslt;}static uint32_t g_continue = 1;static volatile uint32_t g_count1 = 0;static volatile uint32_t g_count2 = 0;static uint32_t g_lock = 0;static void *thread_func(void *p_param){ while (g_continue) { #if SPIN_LOCK while (!atomic_cmp_set(&g_lock, 0, 1)) { sched_yield(); } #endif ++g_count1; ++g_count2; #if SPIN_LOCK g_lock = 0; #endif } return NULL;}int main(int argc, char *argv[]){ pthread_t t1 = 0, t2 = 0; pthread_create(&t1, NULL, &thread_func, NULL); pthread_create(&t2, NULL, &thread_func, NULL); sleep(1); g_continue = 0; pthread_join(t1, NULL); pthread_join(t2, NULL); fprintf(stderr, "%u, %u\n", g_count1, g_count2); return 0;}####################################################################################################################################################################################增加進程同步#include <stdint.h>#include <stdlib.h>#include <stdio.h>#include <assert.h>#include <stdio.h>#include <pthread.h>#include <unistd.h>#include <sys/shm.h>#include <sys/wait.h>#define THREAD 0#define SPIN_LOCK 1#if SPIN_LOCKstatic uint32_t atomic_cmp_set(uint32_t *lock, uint32_t old, uint32_t set){ uint8_t rslt = 0; assert(NULL != lock); asm volatile ("lock;" // lock if SMP "cmpxchgl %3, %1;" "sete %0;" : "=a" (rslt) : "m" (*lock), "a" (old), "r" (set) : "cc", "memory"); return rslt;}#endif#if THREADstatic uint32_t g_continue = 1;#elsestatic void *gp_continue = NULL;#endif#if THREADstatic volatile uint32_t g_count1 = 0;static volatile uint32_t g_count2 = 0;#elsestatic volatile void *gp_count1 = 0;static volatile void *gp_count2 = 0;#endifstatic int shmid = 0;#if SPIN_LOCK#if THREADstatic uint32_t g_lock = 0;#elsestatic void *gp_lock = NULL;#endif#endifstatic void *thread_func(void *p_param){#if THREAD while (g_continue) {#else while (*(uint32_t *)gp_continue) {#endif #if SPIN_LOCK #if THREAD while (!atomic_cmp_set(&g_lock, 0, 1)) { #else while (!atomic_cmp_set((uint32_t *)gp_lock, 0, 1)) { #endif sched_yield(); } #endif #if THREAD ++g_count1; ++g_count2; #else ++(*(volatile uint32_t *)gp_count1); ++(*(volatile uint32_t *)gp_count2); #endif #if SPIN_LOCK #if THREAD g_lock = 0; #else *(uint32_t *)gp_lock = 0; #endif /* THEAD */ #endif }#if SPIN_LOCK#if !THREAD shmdt(gp_lock);#endif#endif return NULL;}int main(int argc, char *argv[]){ // 建立共用記憶體 shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT | 0600); if (-1 == shmid) { return -1; }#if THREAD pthread_t t1 = 0, t2 = 0; pthread_create(&t1, NULL, &thread_func, NULL); pthread_create(&t2, NULL, &thread_func, NULL); sleep(1); g_continue = 0; pthread_join(t1, NULL); pthread_join(t2, NULL);#else#if SPIN_LOCK gp_lock = shmat(shmid, 0, 0); *(uint32_t *)gp_lock = 0;#endif gp_continue = ((char *)shmat(shmid, 0, 0)) + 4; *(uint32_t *)gp_continue = 1; gp_count1 = ((char *)shmat(shmid, 0, 0)) + 8; *(uint32_t *)gp_count1 = 0; gp_count2 = ((char *)shmat(shmid, 0, 0)) + 12; *(uint32_t *)gp_count2 = 0; switch (fork()) { case 0: break; case -1: exit(-1); default: { int x = fork(); if (x > 0) { sleep(1); *(uint32_t *)gp_continue = 0; wait(NULL); shmdt(gp_continue); (void)shmctl(shmid, IPC_RMID, 0); exit(0); } } } thread_func(NULL);#endif fprintf(stderr, "%u, %u\n", #if THREAD g_count1, g_count2); #else *(volatile uint32_t *)gp_count1, *(volatile uint32_t *)gp_count2); #endif return 0;}
ps: 彙編代碼源自nginx,CAS機制只能實現自旋鎖,因為使用者態無法掛起喚醒線程,可以藉助futex實現互斥鎖。