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>