Nginx 소스 코드 완전 주석 (11) ngxspinlock

6006 단어 nginx
Nginx 는 다 중 프로 세 스 모드 입 니 다. 하나의 master 와 여러 workers 는 보통 다 중 핵 CPU 에서 작 동 하기 때문에 자 물 쇠 를 사용 해 야 합 니 다.Nginx 의 자 회전 자물쇠 의 정 의 는 ngx 에 있 습 니 다.spinlock. c 에 서 는 다음 과 같 습 니 다.
void ngx_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 ( ;; ) { // lock    ,      // ngx_atomic_cmp_set       ,          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(); } #else #if (NGX_THREADS) #error ngx_spinlock() or ngx_atomic_cmp_set() are not defined ! #endif #endif } 

그 중에서 lock 이라는 성형 변수 로 자 물 쇠 를 표시 하 는데 필자 의 기계 (Darwin 12.0) 에서 다음 과 같이 정의 된다.
typedef volatile ngx_atomic_uint_t ngx_atomic_t; 

다시 위 spinlock 의 소스 코드 분석 으로 돌아 가면 ngxncpu (CPU 의 핵심 수 를 나타 내 는 것) 가 1 개 이상, 즉 다 핵 CPU 를 초과 하면 대기 / 재 시도 해 야 합 니 다.예 를 들 어 spin 이 80 이면 처음으로 ngx 1 개 를 기다린다.cpu_pause () 작업 을 한 다음 잠 금 이 사용 가능 한 지 다시 확인 합 니 다.다음 라운드 마다 각각 2 개, 4 개, 8 개, 16 개, 32 개, 64 개 ngxcpu_pause () 조작 후 다시 시도 합 니 다.이 중간 과정 에서 자물쇠 가 풀 려 사용 할 수 있 는 상황 이 발생 하면 순환 이 중단 되 고 spinlock 함수 가 값 을 되 돌려 줍 니 다.재 시도 에 성공 하지 못 하면 ngx 를 실행 합 니 다.sched_yield, 그리고 위의 조작 을 반복 합 니 다.
그리고 그 중의 ngxatomic_cmp_set 함수 도 탐구 가치 가 있 습 니 다.Darwin 12.0 에 서 는 다음 과 같은 매크로 정의 가 있 습 니 다.
#define ngx_atomic_cmp_set(lock, old, new) \ OSAtomicCompareAndSwap64Barrier(old, new, (int64_t *) lock) 

제 친구 의 Linux 환경 (구체 적 으로 잊 어 버 렸 지만 x86) 은 다음 과 같 습 니 다.그 중의 내 연 어 셈 블 리 는 본 블 로그 내의 GCC 내 연 어 셈 블 리 의 두 편의 박문 을 참고 할 수 있다.그 중 SMP 는 버스 자물쇠 다.
static ngx_inline ngx_atomic_uint_t ngx_atomic_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; } 

이 출력 은 res 로 eax 레지스터 에 저 장 됩 니 다.* lock (내장), old (eax 중), set (r 는 유 니 버 설 레지스터 를 표시 합 니 다.이렇게% 0 은 res,% 1 은 * lock,% 2 는 old,% 3 은 set 입 니 다.
* lock 과 old 가 같 으 면 이 또는 (cmpxchgl) 가 0 이면 ZF 는 1 이 고 sete 는 res (% 0) 의 값 을 1 로 설정 하고 되 돌려 줍 니 다.* lock 과 old 가 같 지 않 으 면 이화 치가 0 이 아니 기 때문에 ZF 가 0 이 아니면 sete 는 동작 을 수행 하지 않 습 니 다. 즉, res 값 이 0 이 고 ngx 를 호출 합 니 다.atomic_cmp_set 실패.
cmpxchgl 은 ZF (Zero Flag) 표지 위치 에 영향 을 줄 수 있 습 니 다.

좋은 웹페이지 즐겨찾기