Annotation of embedaddon/nginx/src/core/ngx_shmtx.c, revision 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>