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>