Annotation of embedaddon/nginx/src/core/ngx_shmtx.c, revision 1.1.1.1

1.1       misho       1: 
                      2: /*
                      3:  * Copyright (C) Igor Sysoev
                      4:  * Copyright (C) Nginx, Inc.
                      5:  */
                      6: 
                      7: 
                      8: #include <ngx_config.h>
                      9: #include <ngx_core.h>
                     10: 
                     11: 
                     12: #if (NGX_HAVE_ATOMIC_OPS)
                     13: 
                     14: 
                     15: static void ngx_shmtx_wakeup(ngx_shmtx_t *mtx);
                     16: 
                     17: 
                     18: ngx_int_t
                     19: ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr, u_char *name)
                     20: {
                     21:     mtx->lock = &addr->lock;
                     22: 
                     23:     if (mtx->spin == (ngx_uint_t) -1) {
                     24:         return NGX_OK;
                     25:     }
                     26: 
                     27:     mtx->spin = 2048;
                     28: 
                     29: #if (NGX_HAVE_POSIX_SEM)
                     30: 
                     31:     mtx->wait = &addr->wait;
                     32: 
                     33:     if (sem_init(&mtx->sem, 1, 0) == -1) {
                     34:         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
                     35:                       "sem_init() failed");
                     36:     } else {
                     37:         mtx->semaphore = 1;
                     38:     }
                     39: 
                     40: #endif
                     41: 
                     42:     return NGX_OK;
                     43: }
                     44: 
                     45: 
                     46: void
                     47: ngx_shmtx_destroy(ngx_shmtx_t *mtx)
                     48: {
                     49: #if (NGX_HAVE_POSIX_SEM)
                     50: 
                     51:     if (mtx->semaphore) {
                     52:         if (sem_destroy(&mtx->sem) == -1) {
                     53:             ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
                     54:                           "sem_destroy() failed");
                     55:         }
                     56:     }
                     57: 
                     58: #endif
                     59: }
                     60: 
                     61: 
                     62: ngx_uint_t
                     63: ngx_shmtx_trylock(ngx_shmtx_t *mtx)
                     64: {
                     65:     return (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid));
                     66: }
                     67: 
                     68: 
                     69: void
                     70: ngx_shmtx_lock(ngx_shmtx_t *mtx)
                     71: {
                     72:     ngx_uint_t         i, n;
                     73: 
                     74:     ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "shmtx lock");
                     75: 
                     76:     for ( ;; ) {
                     77: 
                     78:         if (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)) {
                     79:             return;
                     80:         }
                     81: 
                     82:         if (ngx_ncpu > 1) {
                     83: 
                     84:             for (n = 1; n < mtx->spin; n <<= 1) {
                     85: 
                     86:                 for (i = 0; i < n; i++) {
                     87:                     ngx_cpu_pause();
                     88:                 }
                     89: 
                     90:                 if (*mtx->lock == 0
                     91:                     && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid))
                     92:                 {
                     93:                     return;
                     94:                 }
                     95:             }
                     96:         }
                     97: 
                     98: #if (NGX_HAVE_POSIX_SEM)
                     99: 
                    100:         if (mtx->semaphore) {
                    101:             (void) ngx_atomic_fetch_add(mtx->wait, 1);
                    102: 
                    103:             if (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)) {
                    104:                 return;
                    105:             }
                    106: 
                    107:             ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
                    108:                            "shmtx wait %uA", *mtx->wait);
                    109: 
                    110:             while (sem_wait(&mtx->sem) == -1) {
                    111:                 ngx_err_t  err;
                    112: 
                    113:                 err = ngx_errno;
                    114: 
                    115:                 if (err != NGX_EINTR) {
                    116:                     ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, err,
                    117:                                   "sem_wait() failed while waiting on shmtx");
                    118:                     break;
                    119:                 }
                    120:             }
                    121: 
                    122:             ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
                    123:                            "shmtx awoke");
                    124: 
                    125:             continue;
                    126:         }
                    127: 
                    128: #endif
                    129: 
                    130:         ngx_sched_yield();
                    131:     }
                    132: }
                    133: 
                    134: 
                    135: void
                    136: ngx_shmtx_unlock(ngx_shmtx_t *mtx)
                    137: {
                    138:     if (mtx->spin != (ngx_uint_t) -1) {
                    139:         ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "shmtx unlock");
                    140:     }
                    141: 
                    142:     if (ngx_atomic_cmp_set(mtx->lock, ngx_pid, 0)) {
                    143:         ngx_shmtx_wakeup(mtx);
                    144:     }
                    145: }
                    146: 
                    147: 
                    148: ngx_uint_t
                    149: ngx_shmtx_force_unlock(ngx_shmtx_t *mtx, ngx_pid_t pid)
                    150: {
                    151:     ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
                    152:                    "shmtx forced unlock");
                    153: 
                    154:     if (ngx_atomic_cmp_set(mtx->lock, pid, 0)) {
                    155:         ngx_shmtx_wakeup(mtx);
                    156:         return 1;
                    157:     }
                    158: 
                    159:     return 0;
                    160: }
                    161: 
                    162: 
                    163: static void
                    164: ngx_shmtx_wakeup(ngx_shmtx_t *mtx)
                    165: {
                    166: #if (NGX_HAVE_POSIX_SEM)
                    167:     ngx_atomic_uint_t  wait;
                    168: 
                    169:     if (!mtx->semaphore) {
                    170:         return;
                    171:     }
                    172: 
                    173:     for ( ;; ) {
                    174: 
                    175:         wait = *mtx->wait;
                    176: 
                    177:         if (wait == 0) {
                    178:             return;
                    179:         }
                    180: 
                    181:         if (ngx_atomic_cmp_set(mtx->wait, wait, wait - 1)) {
                    182:             break;
                    183:         }
                    184:     }
                    185: 
                    186:     ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
                    187:                    "shmtx wake %uA", wait);
                    188: 
                    189:     if (sem_post(&mtx->sem) == -1) {
                    190:         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
                    191:                       "sem_post() failed while wake shmtx");
                    192:     }
                    193: 
                    194: #endif
                    195: }
                    196: 
                    197: 
                    198: #else
                    199: 
                    200: 
                    201: ngx_int_t
                    202: ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr, u_char *name)
                    203: {
                    204:     if (mtx->name) {
                    205: 
                    206:         if (ngx_strcmp(name, mtx->name) == 0) {
                    207:             mtx->name = name;
                    208:             return NGX_OK;
                    209:         }
                    210: 
                    211:         ngx_shmtx_destroy(mtx);
                    212:     }
                    213: 
                    214:     mtx->fd = ngx_open_file(name, NGX_FILE_RDWR, NGX_FILE_CREATE_OR_OPEN,
                    215:                             NGX_FILE_DEFAULT_ACCESS);
                    216: 
                    217:     if (mtx->fd == NGX_INVALID_FILE) {
                    218:         ngx_log_error(NGX_LOG_EMERG, ngx_cycle->log, ngx_errno,
                    219:                       ngx_open_file_n " \"%s\" failed", name);
                    220:         return NGX_ERROR;
                    221:     }
                    222: 
                    223:     if (ngx_delete_file(name) == NGX_FILE_ERROR) {
                    224:         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
                    225:                       ngx_delete_file_n " \"%s\" failed", name);
                    226:     }
                    227: 
                    228:     mtx->name = name;
                    229: 
                    230:     return NGX_OK;
                    231: }
                    232: 
                    233: 
                    234: void
                    235: ngx_shmtx_destroy(ngx_shmtx_t *mtx)
                    236: {
                    237:     if (ngx_close_file(mtx->fd) == NGX_FILE_ERROR) {
                    238:         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
                    239:                       ngx_close_file_n " \"%s\" failed", mtx->name);
                    240:     }
                    241: }
                    242: 
                    243: 
                    244: ngx_uint_t
                    245: ngx_shmtx_trylock(ngx_shmtx_t *mtx)
                    246: {
                    247:     ngx_err_t  err;
                    248: 
                    249:     err = ngx_trylock_fd(mtx->fd);
                    250: 
                    251:     if (err == 0) {
                    252:         return 1;
                    253:     }
                    254: 
                    255:     if (err == NGX_EAGAIN) {
                    256:         return 0;
                    257:     }
                    258: 
                    259: #if __osf__ /* Tru64 UNIX */
                    260: 
                    261:     if (err == NGX_EACCESS) {
                    262:         return 0;
                    263:     }
                    264: 
                    265: #endif
                    266: 
                    267:     ngx_log_abort(err, ngx_trylock_fd_n " %s failed", mtx->name);
                    268: 
                    269:     return 0;
                    270: }
                    271: 
                    272: 
                    273: void
                    274: ngx_shmtx_lock(ngx_shmtx_t *mtx)
                    275: {
                    276:     ngx_err_t  err;
                    277: 
                    278:     err = ngx_lock_fd(mtx->fd);
                    279: 
                    280:     if (err == 0) {
                    281:         return;
                    282:     }
                    283: 
                    284:     ngx_log_abort(err, ngx_lock_fd_n " %s failed", mtx->name);
                    285: }
                    286: 
                    287: 
                    288: void
                    289: ngx_shmtx_unlock(ngx_shmtx_t *mtx)
                    290: {
                    291:     ngx_err_t  err;
                    292: 
                    293:     err = ngx_unlock_fd(mtx->fd);
                    294: 
                    295:     if (err == 0) {
                    296:         return;
                    297:     }
                    298: 
                    299:     ngx_log_abort(err, ngx_unlock_fd_n " %s failed", mtx->name);
                    300: }
                    301: 
                    302: 
                    303: ngx_uint_t
                    304: ngx_shmtx_force_unlock(ngx_shmtx_t *mtx, ngx_pid_t pid)
                    305: {
                    306:     return 0;
                    307: }
                    308: 
                    309: #endif

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