Return to ngx_shmtx.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / nginx / src / core |
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