annotate src/core/ngx_rwlock.c @ 6520:9070ba416284

HTTP/2: send the output queue after emitting WINDOW_UPDATE. The WINDOW_UPDATE frame could be left in the output queue for an indefinite period of time resulting in the request timeout. This might happen if reading of the body was triggered by an event unrelated to client connection, e.g. by the limit_req timer.
author Valentin Bartenev <vbart@nginx.com>
date Tue, 19 Apr 2016 17:38:49 +0300
parents e769cc88f996
children 12efcdcb8a4b
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
6101
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
1
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
2 /*
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
3 * Copyright (C) Ruslan Ermilov
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
4 * Copyright (C) Nginx, Inc.
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
5 */
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
6
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
7
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
8 #include <ngx_config.h>
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
9 #include <ngx_core.h>
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
10
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
11
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
12 #if (NGX_HAVE_ATOMIC_OPS)
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
13
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
14
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
15 #define NGX_RWLOCK_SPIN 2048
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
16 #define NGX_RWLOCK_WLOCK ((ngx_atomic_uint_t) -1)
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
17
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
18
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
19 void
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
20 ngx_rwlock_wlock(ngx_atomic_t *lock)
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
21 {
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
22 ngx_uint_t i, n;
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
23
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
24 for ( ;; ) {
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
25
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
26 if (*lock == 0 && ngx_atomic_cmp_set(lock, 0, NGX_RWLOCK_WLOCK)) {
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
27 return;
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
28 }
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
29
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
30 if (ngx_ncpu > 1) {
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
31
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
32 for (n = 1; n < NGX_RWLOCK_SPIN; n <<= 1) {
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
33
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
34 for (i = 0; i < n; i++) {
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
35 ngx_cpu_pause();
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
36 }
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
37
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
38 if (*lock == 0
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
39 && ngx_atomic_cmp_set(lock, 0, NGX_RWLOCK_WLOCK))
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
40 {
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
41 return;
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
42 }
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
43 }
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
44 }
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
45
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
46 ngx_sched_yield();
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
47 }
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
48 }
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
49
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
50
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
51 void
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
52 ngx_rwlock_rlock(ngx_atomic_t *lock)
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
53 {
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
54 ngx_uint_t i, n;
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
55 ngx_atomic_uint_t readers;
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
56
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
57 for ( ;; ) {
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
58 readers = *lock;
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
59
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
60 if (readers != NGX_RWLOCK_WLOCK
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
61 && ngx_atomic_cmp_set(lock, readers, readers + 1))
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
62 {
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
63 return;
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
64 }
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
65
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
66 if (ngx_ncpu > 1) {
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
67
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
68 for (n = 1; n < NGX_RWLOCK_SPIN; n <<= 1) {
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
69
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
70 for (i = 0; i < n; i++) {
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
71 ngx_cpu_pause();
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
72 }
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
73
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
74 readers = *lock;
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
75
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
76 if (readers != NGX_RWLOCK_WLOCK
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
77 && ngx_atomic_cmp_set(lock, readers, readers + 1))
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
78 {
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
79 return;
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
80 }
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
81 }
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
82 }
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
83
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
84 ngx_sched_yield();
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
85 }
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
86 }
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
87
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
88
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
89 void
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
90 ngx_rwlock_unlock(ngx_atomic_t *lock)
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
91 {
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
92 ngx_atomic_uint_t readers;
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
93
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
94 readers = *lock;
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
95
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
96 if (readers == NGX_RWLOCK_WLOCK) {
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
97 *lock = 0;
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
98 return;
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
99 }
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
100
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
101 for ( ;; ) {
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
102
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
103 if (ngx_atomic_cmp_set(lock, readers, readers - 1)) {
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
104 return;
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
105 }
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
106
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
107 readers = *lock;
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
108 }
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
109 }
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
110
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
111
6103
79ddb0bdb273 Upstream: the "zone" directive.
Ruslan Ermilov <ru@nginx.com>
parents: 6101
diff changeset
112 #else
79ddb0bdb273 Upstream: the "zone" directive.
Ruslan Ermilov <ru@nginx.com>
parents: 6101
diff changeset
113
6270
e769cc88f996 Core: read/write locks are also required by the Stream module.
Piotr Sikora <piotrsikora@google.com>
parents: 6103
diff changeset
114 #if (NGX_HTTP_UPSTREAM_ZONE || NGX_STREAM_UPSTREAM_ZONE)
6103
79ddb0bdb273 Upstream: the "zone" directive.
Ruslan Ermilov <ru@nginx.com>
parents: 6101
diff changeset
115
79ddb0bdb273 Upstream: the "zone" directive.
Ruslan Ermilov <ru@nginx.com>
parents: 6101
diff changeset
116 #error ngx_atomic_cmp_set() is not defined!
79ddb0bdb273 Upstream: the "zone" directive.
Ruslan Ermilov <ru@nginx.com>
parents: 6101
diff changeset
117
6101
682d8222c6b1 Core: read/write locks.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
118 #endif
6103
79ddb0bdb273 Upstream: the "zone" directive.
Ruslan Ermilov <ru@nginx.com>
parents: 6101
diff changeset
119
79ddb0bdb273 Upstream: the "zone" directive.
Ruslan Ermilov <ru@nginx.com>
parents: 6101
diff changeset
120 #endif