Nginx provides its own atomic operation on a processor that does not support atomic operations, but the atomic operation is simulated using the C language:
Static Ngx_inline Ngx_atomic_uint_tngx_atomic_cmp_set (ngx_atomic_t *lock, ngx_atomic_uint_t old, ngx_atomic_ uint_t set) { if (*lock = = old) { *lock = set; return 1; } return 0;}
Static Ngx_inline Ngx_atomic_int_tngx_atomic_fetch_add (ngx_atomic_t *value, ngx_atomic_int_t add) { ngx_atomic_ int_t old ; Old = *value; *value + = add; return old;}
for processors that support atomic operations (take x86 as an example):
#define Ngx_smp_lock "LOCK;" /** "Cmpxchgl R, [m]":* * if (eax = = [M]) {* ZF = 1;* [m] = r;* } else {* ZF = 0;* eax = [m];*< c8/>}*** the "R" means the general register.* the "=a" and "a" is the%eax register.* although we can return result in an Y register, we use the "a" because it is* used in Cmpxchgl anyway. The result is actually in%al but not in%eax,* However, as the code was inlined gcc can test%al as well as%eax,* and ICC Adds "Movzbl%al,%eax" by itself.** the "CC" means that flags were changed.*/static ngx_inline Ngx_atomic_uint_tngx_atom Ic_cmp_set (ngx_atomic_t *lock, ngx_atomic_uint_t old, ngx_atomic_uint_t set) { U_char res; __asm__ volatile ( ngx_smp_lock " cmpxchgl %3,%1; " " Sete %0; " :" =a "(res):" M "(*lock)," a "(old)," R "(SET):" CC "," Memory "); return res;}
/** "Xaddl R, [m]":* * temp = [m];* [m] + = r;* r = temp;*** the "+r" means the general register.* the "CC" means that flags were changed.*/static ngx_inline ngx_atomic_int_tngx_atomic_fetch_add (ngx_atomic_t *value, ngx_atomic _int_t add) { ngx_atomic_uint_t old ; __asm__ volatile ( ngx_smp_lock " xaddl %2,%1; " : "=a" (old): "M" (*value), "a" (add): "CC" , "Memory"); return old;}
Spin Lock:
/* old ' as ' does not ' support ' pause ' opcode */#define NGX_CPU_PAUSE () __asm__ (". Byte 0xf3, 0x90") #define Ngx_sched_yi Eld () Sched_yield () voidngx_spinlock (ngx_atomic_t *lock, ngx_atomic_int_t value, ngx_uint_t spin) {#if (ngx_have_ Atomic_ops) ngx_uint_t i, N; for (;;) { if (*lock = = 0 && ngx_atomic_cmp_set (lock, 0, value)) { return; } if (Ngx_ncpu > 1) {for (n = 1; n < spin, n <<= 1) {for (i = 0; i < n; i++) { Ngx_cpu_pause ( ); } if (*lock = = 0 && ngx_atomic_cmp_set (lock, 0, value)) { return; }} } Ngx_sched_yield (); }
Signal:
Ngx_int_tngx_init_signals (ngx_log_t *log) { ngx_signal_t *sig; struct sigaction sa; for (sig = Signals; Sig->signo! = 0; sig++) { Ngx_memzero (&sa, sizeof (struct sigaction)); Sa.sa_handler = sig->handler; Sigemptyset (&sa.sa_mask); if (Sigaction (Sig->signo, &sa, NULL) = =-1) {#if (ngx_valgrind) ngx_log_error (Ngx_log_alert, log, Ngx_errno, "Sigaction (%s) failed, ignored", sig->signame); #else ngx_log_error (Ngx_log_emerg, log, Ngx_errno, "Sigaction (%s) failed", sig->signame); return ngx_error; #endif } } return NGX_OK;}
The above describes the operation of the atom in Nginx, including the aspects of the content, I hope that the PHP tutorial interested in a friend helpful.