Annotation of embedaddon/nginx/src/os/unix/ngx_gcc_atomic_x86.h, revision 1.1.1.1

1.1       misho       1: 
                      2: /*
                      3:  * Copyright (C) Igor Sysoev
                      4:  * Copyright (C) Nginx, Inc.
                      5:  */
                      6: 
                      7: 
                      8: #if (NGX_SMP)
                      9: #define NGX_SMP_LOCK  "lock;"
                     10: #else
                     11: #define NGX_SMP_LOCK
                     12: #endif
                     13: 
                     14: 
                     15: /*
                     16:  * "cmpxchgl  r, [m]":
                     17:  *
                     18:  *     if (eax == [m]) {
                     19:  *         zf = 1;
                     20:  *         [m] = r;
                     21:  *     } else {
                     22:  *         zf = 0;
                     23:  *         eax = [m];
                     24:  *     }
                     25:  *
                     26:  *
                     27:  * The "r" means the general register.
                     28:  * The "=a" and "a" are the %eax register.
                     29:  * Although we can return result in any register, we use "a" because it is
                     30:  * used in cmpxchgl anyway.  The result is actually in %al but not in %eax,
                     31:  * however, as the code is inlined gcc can test %al as well as %eax,
                     32:  * and icc adds "movzbl %al, %eax" by itself.
                     33:  *
                     34:  * The "cc" means that flags were changed.
                     35:  */
                     36: 
                     37: static ngx_inline ngx_atomic_uint_t
                     38: ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old,
                     39:     ngx_atomic_uint_t set)
                     40: {
                     41:     u_char  res;
                     42: 
                     43:     __asm__ volatile (
                     44: 
                     45:          NGX_SMP_LOCK
                     46:     "    cmpxchgl  %3, %1;   "
                     47:     "    sete      %0;       "
                     48: 
                     49:     : "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "cc", "memory");
                     50: 
                     51:     return res;
                     52: }
                     53: 
                     54: 
                     55: /*
                     56:  * "xaddl  r, [m]":
                     57:  *
                     58:  *     temp = [m];
                     59:  *     [m] += r;
                     60:  *     r = temp;
                     61:  *
                     62:  *
                     63:  * The "+r" means the general register.
                     64:  * The "cc" means that flags were changed.
                     65:  */
                     66: 
                     67: 
                     68: #if !(( __GNUC__ == 2 && __GNUC_MINOR__ <= 7 ) || ( __INTEL_COMPILER >= 800 ))
                     69: 
                     70: /*
                     71:  * icc 8.1 and 9.0 compile broken code with -march=pentium4 option:
                     72:  * ngx_atomic_fetch_add() always return the input "add" value,
                     73:  * so we use the gcc 2.7 version.
                     74:  *
                     75:  * icc 8.1 and 9.0 with -march=pentiumpro option or icc 7.1 compile
                     76:  * correct code.
                     77:  */
                     78: 
                     79: static ngx_inline ngx_atomic_int_t
                     80: ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add)
                     81: {
                     82:     __asm__ volatile (
                     83: 
                     84:          NGX_SMP_LOCK
                     85:     "    xaddl  %0, %1;   "
                     86: 
                     87:     : "+r" (add) : "m" (*value) : "cc", "memory");
                     88: 
                     89:     return add;
                     90: }
                     91: 
                     92: 
                     93: #else
                     94: 
                     95: /*
                     96:  * gcc 2.7 does not support "+r", so we have to use the fixed
                     97:  * %eax ("=a" and "a") and this adds two superfluous instructions in the end
                     98:  * of code, something like this: "mov %eax, %edx / mov %edx, %eax".
                     99:  */
                    100: 
                    101: static ngx_inline ngx_atomic_int_t
                    102: ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add)
                    103: {
                    104:     ngx_atomic_uint_t  old;
                    105: 
                    106:     __asm__ volatile (
                    107: 
                    108:          NGX_SMP_LOCK
                    109:     "    xaddl  %2, %1;   "
                    110: 
                    111:     : "=a" (old) : "m" (*value), "a" (add) : "cc", "memory");
                    112: 
                    113:     return old;
                    114: }
                    115: 
                    116: #endif
                    117: 
                    118: 
                    119: /*
                    120:  * on x86 the write operations go in a program order, so we need only
                    121:  * to disable the gcc reorder optimizations
                    122:  */
                    123: 
                    124: #define ngx_memory_barrier()    __asm__ volatile ("" ::: "memory")
                    125: 
                    126: /* old "as" does not support "pause" opcode */
                    127: #define ngx_cpu_pause()         __asm__ (".byte 0xf3, 0x90")

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>