comparison src/core/ngx_shmtx.c @ 650:4d05413aebad NGINX_1_1_9

nginx 1.1.9 *) Change: now double quotes are encoded in an "echo" SSI-command output. Thanks to Zaur Abasmirzoev. *) Feature: the "valid" parameter of the "resolver" directive. By default TTL returned by a DNS server is used. Thanks to Kirill A. Korinskiy. *) Bugfix: nginx might hang after a worker process abnormal termination. *) Bugfix: a segmentation fault might occur in a worker process if SNI was used; the bug had appeared in 1.1.2. *) Bugfix: in the "keepalive_disable" directive; the bug had appeared in 1.1.8. Thanks to Alexander Usov. *) Bugfix: SIGWINCH signal did not work after first binary upgrade; the bug had appeared in 1.1.1. *) Bugfix: backend responses with length not matching "Content-Length" header line are no longer cached. *) Bugfix: in the "scgi_param" directive, if complex parameters were used. *) Bugfix: in the "epoll" event method. Thanks to Yichun Zhang. *) Bugfix: in the ngx_http_flv_module. Thanks to Piotr Sikora. *) Bugfix: in the ngx_http_mp4_module. *) Bugfix: IPv6 addresses are now handled properly in a request line and in a "Host" request header line. *) Bugfix: "add_header" and "expires" directives did not work if a request was proxied and response status code was 206. *) Bugfix: nginx could not be built on FreeBSD 10. *) Bugfix: nginx could not be built on AIX.
author Igor Sysoev <http://sysoev.ru>
date Mon, 28 Nov 2011 00:00:00 +0400
parents d4da38525468
children d0f7a625f27c
comparison
equal deleted inserted replaced
649:c5b99ec117cd 650:4d05413aebad
9 9
10 10
11 #if (NGX_HAVE_ATOMIC_OPS) 11 #if (NGX_HAVE_ATOMIC_OPS)
12 12
13 13
14 static void ngx_shmtx_wakeup(ngx_shmtx_t *mtx);
15
16
14 ngx_int_t 17 ngx_int_t
15 ngx_shmtx_create(ngx_shmtx_t *mtx, void *addr, u_char *name) 18 ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr, u_char *name)
16 { 19 {
17 mtx->lock = addr; 20 mtx->lock = &addr->lock;
18 21
19 if (mtx->spin == (ngx_uint_t) -1) { 22 if (mtx->spin == (ngx_uint_t) -1) {
20 return NGX_OK; 23 return NGX_OK;
21 } 24 }
22 25
23 mtx->spin = 2048; 26 mtx->spin = 2048;
24 27
25 #if (NGX_HAVE_POSIX_SEM) 28 #if (NGX_HAVE_POSIX_SEM)
29
30 mtx->wait = &addr->wait;
26 31
27 if (sem_init(&mtx->sem, 1, 0) == -1) { 32 if (sem_init(&mtx->sem, 1, 0) == -1) {
28 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno, 33 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
29 "sem_init() failed"); 34 "sem_init() failed");
30 } else { 35 } else {
54 59
55 60
56 ngx_uint_t 61 ngx_uint_t
57 ngx_shmtx_trylock(ngx_shmtx_t *mtx) 62 ngx_shmtx_trylock(ngx_shmtx_t *mtx)
58 { 63 {
59 ngx_atomic_uint_t val; 64 return (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid));
60
61 val = *mtx->lock;
62
63 return ((val & 0x80000000) == 0
64 && ngx_atomic_cmp_set(mtx->lock, val, val | 0x80000000));
65 } 65 }
66 66
67 67
68 void 68 void
69 ngx_shmtx_lock(ngx_shmtx_t *mtx) 69 ngx_shmtx_lock(ngx_shmtx_t *mtx)
70 { 70 {
71 ngx_uint_t i, n; 71 ngx_uint_t i, n;
72 ngx_atomic_uint_t val;
73 72
74 ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "shmtx lock"); 73 ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "shmtx lock");
75 74
76 for ( ;; ) { 75 for ( ;; ) {
77 76
78 val = *mtx->lock; 77 if (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)) {
79
80 if ((val & 0x80000000) == 0
81 && ngx_atomic_cmp_set(mtx->lock, val, val | 0x80000000))
82 {
83 return; 78 return;
84 } 79 }
85 80
86 if (ngx_ncpu > 1) { 81 if (ngx_ncpu > 1) {
87 82
89 84
90 for (i = 0; i < n; i++) { 85 for (i = 0; i < n; i++) {
91 ngx_cpu_pause(); 86 ngx_cpu_pause();
92 } 87 }
93 88
94 val = *mtx->lock; 89 if (*mtx->lock == 0
95 90 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid))
96 if ((val & 0x80000000) == 0
97 && ngx_atomic_cmp_set(mtx->lock, val, val | 0x80000000))
98 { 91 {
99 return; 92 return;
100 } 93 }
101 } 94 }
102 } 95 }
103 96
104 #if (NGX_HAVE_POSIX_SEM) 97 #if (NGX_HAVE_POSIX_SEM)
105 98
106 if (mtx->semaphore) { 99 if (mtx->semaphore) {
107 val = *mtx->lock; 100 (void) ngx_atomic_fetch_add(mtx->wait, 1);
108 101
109 if ((val & 0x80000000) 102 if (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)) {
110 && ngx_atomic_cmp_set(mtx->lock, val, val + 1)) 103 return;
111 { 104 }
112 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, 105
113 "shmtx wait %XA", val); 106 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
114 107 "shmtx wait %uA", *mtx->wait);
115 while (sem_wait(&mtx->sem) == -1) { 108
116 ngx_err_t err; 109 while (sem_wait(&mtx->sem) == -1) {
117 110 ngx_err_t err;
118 err = ngx_errno; 111
119 112 err = ngx_errno;
120 if (err != NGX_EINTR) { 113
121 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, err, 114 if (err != NGX_EINTR) {
122 "sem_wait() failed while waiting on shmtx"); 115 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, err,
123 break; 116 "sem_wait() failed while waiting on shmtx");
124 } 117 break;
125 } 118 }
126 119
127 ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, 120 ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
128 "shmtx awoke"); 121 "shmtx awoke");
129 } 122 }
139 132
140 133
141 void 134 void
142 ngx_shmtx_unlock(ngx_shmtx_t *mtx) 135 ngx_shmtx_unlock(ngx_shmtx_t *mtx)
143 { 136 {
144 ngx_atomic_uint_t val, old, wait;
145
146 if (mtx->spin != (ngx_uint_t) -1) { 137 if (mtx->spin != (ngx_uint_t) -1) {
147 ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "shmtx unlock"); 138 ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "shmtx unlock");
148 } 139 }
149 140
141 if (ngx_atomic_cmp_set(mtx->lock, ngx_pid, 0)) {
142 ngx_shmtx_wakeup(mtx);
143 }
144 }
145
146
147 ngx_uint_t
148 ngx_shmtx_force_unlock(ngx_shmtx_t *mtx, ngx_pid_t pid)
149 {
150 ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
151 "shmtx forced unlock");
152
153 if (ngx_atomic_cmp_set(mtx->lock, pid, 0)) {
154 ngx_shmtx_wakeup(mtx);
155 return 1;
156 }
157
158 return 0;
159 }
160
161
162 static void
163 ngx_shmtx_wakeup(ngx_shmtx_t *mtx)
164 {
165 #if (NGX_HAVE_POSIX_SEM)
166 ngx_atomic_uint_t wait;
167
168 if (!mtx->semaphore) {
169 return;
170 }
171
150 for ( ;; ) { 172 for ( ;; ) {
151 173
152 old = *mtx->lock; 174 wait = *mtx->wait;
153 wait = old & 0x7fffffff; 175
154 val = wait ? wait - 1 : 0; 176 if (wait == 0) {
155 177 return;
156 if (ngx_atomic_cmp_set(mtx->lock, old, val)) { 178 }
179
180 if (ngx_atomic_cmp_set(mtx->wait, wait, wait - 1)) {
157 break; 181 break;
158 } 182 }
159 } 183 }
160 184
161 #if (NGX_HAVE_POSIX_SEM)
162
163 if (wait == 0 || !mtx->semaphore) {
164 return;
165 }
166
167 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, 185 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
168 "shmtx wake %XA", old); 186 "shmtx wake %uA", wait);
169 187
170 if (sem_post(&mtx->sem) == -1) { 188 if (sem_post(&mtx->sem) == -1) {
171 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno, 189 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
172 "sem_post() failed while wake shmtx"); 190 "sem_post() failed while wake shmtx");
173 } 191 }
178 196
179 #else 197 #else
180 198
181 199
182 ngx_int_t 200 ngx_int_t
183 ngx_shmtx_create(ngx_shmtx_t *mtx, void *addr, u_char *name) 201 ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr, u_char *name)
184 { 202 {
185 if (mtx->name) { 203 if (mtx->name) {
186 204
187 if (ngx_strcmp(name, mtx->name) == 0) { 205 if (ngx_strcmp(name, mtx->name) == 0) {
188 mtx->name = name; 206 mtx->name = name;
278 } 296 }
279 297
280 ngx_log_abort(err, ngx_unlock_fd_n " %s failed", mtx->name); 298 ngx_log_abort(err, ngx_unlock_fd_n " %s failed", mtx->name);
281 } 299 }
282 300
283 #endif 301
302 ngx_uint_t
303 ngx_shmtx_force_unlock(ngx_shmtx_t *mtx, ngx_pid_t pid)
304 {
305 return 0;
306 }
307
308 #endif