Line data Source code
1 : /*
2 : *
3 : * Copyright 2015, Google Inc.
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions are
8 : * met:
9 : *
10 : * * Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * * Redistributions in binary form must reproduce the above
13 : * copyright notice, this list of conditions and the following disclaimer
14 : * in the documentation and/or other materials provided with the
15 : * distribution.
16 : * * Neither the name of Google Inc. nor the names of its
17 : * contributors may be used to endorse or promote products derived from
18 : * this software without specific prior written permission.
19 : *
20 : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 : * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 : * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 : * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 : * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 : * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 : * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 : *
32 : */
33 :
34 : #include "src/core/transport/chttp2/internal.h"
35 :
36 : #include <grpc/support/log.h>
37 :
38 : #define TRANSPORT_FROM_GLOBAL(tg) \
39 : ((grpc_chttp2_transport *)((char *)(tg)-offsetof(grpc_chttp2_transport, \
40 : global)))
41 :
42 : #define STREAM_FROM_GLOBAL(sg) \
43 : ((grpc_chttp2_stream *)((char *)(sg)-offsetof(grpc_chttp2_stream, global)))
44 :
45 : #define TRANSPORT_FROM_WRITING(tw) \
46 : ((grpc_chttp2_transport *)((char *)(tw)-offsetof(grpc_chttp2_transport, \
47 : writing)))
48 :
49 : #define STREAM_FROM_WRITING(sw) \
50 : ((grpc_chttp2_stream *)((char *)(sw)-offsetof(grpc_chttp2_stream, writing)))
51 :
52 : #define TRANSPORT_FROM_PARSING(tp) \
53 : ((grpc_chttp2_transport *)((char *)(tp)-offsetof(grpc_chttp2_transport, \
54 : parsing)))
55 :
56 : #define STREAM_FROM_PARSING(sp) \
57 : ((grpc_chttp2_stream *)((char *)(sp)-offsetof(grpc_chttp2_stream, parsing)))
58 :
59 : /* core list management */
60 :
61 48145284 : static int stream_list_empty(grpc_chttp2_transport *t,
62 : grpc_chttp2_stream_list_id id) {
63 48148319 : return t->lists[id].head == NULL;
64 : }
65 :
66 154957123 : static int stream_list_pop(grpc_chttp2_transport *t,
67 : grpc_chttp2_stream **stream,
68 : grpc_chttp2_stream_list_id id) {
69 154957123 : grpc_chttp2_stream *s = t->lists[id].head;
70 154957123 : if (s) {
71 50652031 : grpc_chttp2_stream *new_head = s->links[id].next;
72 50652031 : GPR_ASSERT(s->included[id]);
73 50652031 : if (new_head) {
74 9883689 : t->lists[id].head = new_head;
75 9883689 : new_head->links[id].prev = NULL;
76 : } else {
77 40768342 : t->lists[id].head = NULL;
78 40768342 : t->lists[id].tail = NULL;
79 : }
80 50652031 : s->included[id] = 0;
81 : }
82 154957123 : *stream = s;
83 154957123 : return s != 0;
84 : }
85 :
86 4879910 : static void stream_list_remove(grpc_chttp2_transport *t, grpc_chttp2_stream *s,
87 : grpc_chttp2_stream_list_id id) {
88 4879910 : GPR_ASSERT(s->included[id]);
89 4879910 : s->included[id] = 0;
90 4879910 : if (s->links[id].prev) {
91 2660690 : s->links[id].prev->links[id].next = s->links[id].next;
92 : } else {
93 2219220 : GPR_ASSERT(t->lists[id].head == s);
94 2219220 : t->lists[id].head = s->links[id].next;
95 : }
96 4879910 : if (s->links[id].next) {
97 3063682 : s->links[id].next->links[id].prev = s->links[id].prev;
98 : } else {
99 1816228 : t->lists[id].tail = s->links[id].prev;
100 : }
101 4879910 : }
102 :
103 22157304 : static void stream_list_maybe_remove(grpc_chttp2_transport *t,
104 : grpc_chttp2_stream *s,
105 : grpc_chttp2_stream_list_id id) {
106 22157810 : if (s->included[id]) {
107 4880602 : stream_list_remove(t, s, id);
108 : }
109 22157045 : }
110 :
111 55710566 : static void stream_list_add_tail(grpc_chttp2_transport *t,
112 : grpc_chttp2_stream *s,
113 : grpc_chttp2_stream_list_id id) {
114 : grpc_chttp2_stream *old_tail;
115 55710566 : GPR_ASSERT(!s->included[id]);
116 55710566 : old_tail = t->lists[id].tail;
117 55710566 : s->links[id].next = NULL;
118 55710566 : s->links[id].prev = old_tail;
119 55710566 : if (old_tail) {
120 13123011 : old_tail->links[id].next = s;
121 : } else {
122 42587555 : t->lists[id].head = s;
123 : }
124 55710566 : t->lists[id].tail = s;
125 55710566 : s->included[id] = 1;
126 55710566 : }
127 :
128 151059691 : static int stream_list_add(grpc_chttp2_transport *t, grpc_chttp2_stream *s,
129 : grpc_chttp2_stream_list_id id) {
130 151066503 : if (s->included[id]) {
131 99901197 : return 0;
132 : }
133 51161543 : stream_list_add_tail(t, s, id);
134 51218856 : return 1;
135 : }
136 :
137 : /* wrappers for specializations */
138 :
139 15235105 : void grpc_chttp2_list_add_writable_stream(
140 : grpc_chttp2_transport_global *transport_global,
141 : grpc_chttp2_stream_global *stream_global) {
142 15235105 : GPR_ASSERT(stream_global->id != 0);
143 15235105 : stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
144 : STREAM_FROM_GLOBAL(stream_global), GRPC_CHTTP2_LIST_WRITABLE);
145 15243295 : }
146 :
147 42110388 : int grpc_chttp2_list_pop_writable_stream(
148 : grpc_chttp2_transport_global *transport_global,
149 : grpc_chttp2_transport_writing *transport_writing,
150 : grpc_chttp2_stream_global **stream_global,
151 : grpc_chttp2_stream_writing **stream_writing) {
152 : grpc_chttp2_stream *stream;
153 42110388 : int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
154 : GRPC_CHTTP2_LIST_WRITABLE);
155 42138615 : if (r != 0) {
156 7295137 : *stream_global = &stream->global;
157 7295137 : *stream_writing = &stream->writing;
158 : }
159 42138615 : return r;
160 : }
161 :
162 8876219 : void grpc_chttp2_list_remove_writable_stream(
163 : grpc_chttp2_transport_global *transport_global,
164 : grpc_chttp2_stream_global *stream_global) {
165 8876219 : stream_list_maybe_remove(TRANSPORT_FROM_GLOBAL(transport_global),
166 : STREAM_FROM_GLOBAL(stream_global),
167 : GRPC_CHTTP2_LIST_WRITABLE);
168 8877828 : }
169 :
170 12853174 : int grpc_chttp2_list_add_writing_stream(
171 : grpc_chttp2_transport_writing *transport_writing,
172 : grpc_chttp2_stream_writing *stream_writing) {
173 12853803 : return stream_list_add(TRANSPORT_FROM_WRITING(transport_writing),
174 : STREAM_FROM_WRITING(stream_writing),
175 : GRPC_CHTTP2_LIST_WRITING);
176 : }
177 :
178 39411611 : int grpc_chttp2_list_have_writing_streams(
179 : grpc_chttp2_transport_writing *transport_writing) {
180 39411611 : return !stream_list_empty(TRANSPORT_FROM_WRITING(transport_writing),
181 : GRPC_CHTTP2_LIST_WRITING);
182 : }
183 :
184 9653354 : int grpc_chttp2_list_pop_writing_stream(
185 : grpc_chttp2_transport_writing *transport_writing,
186 : grpc_chttp2_stream_writing **stream_writing) {
187 : grpc_chttp2_stream *stream;
188 9653354 : int r = stream_list_pop(TRANSPORT_FROM_WRITING(transport_writing), &stream,
189 : GRPC_CHTTP2_LIST_WRITING);
190 9653430 : if (r != 0) {
191 5041491 : *stream_writing = &stream->writing;
192 : }
193 9653430 : return r;
194 : }
195 :
196 5038793 : void grpc_chttp2_list_add_written_stream(
197 : grpc_chttp2_transport_writing *transport_writing,
198 : grpc_chttp2_stream_writing *stream_writing) {
199 5038793 : stream_list_add(TRANSPORT_FROM_WRITING(transport_writing),
200 : STREAM_FROM_WRITING(stream_writing),
201 : GRPC_CHTTP2_LIST_WRITTEN);
202 5039107 : }
203 :
204 9664512 : int grpc_chttp2_list_pop_written_stream(
205 : grpc_chttp2_transport_global *transport_global,
206 : grpc_chttp2_transport_writing *transport_writing,
207 : grpc_chttp2_stream_global **stream_global,
208 : grpc_chttp2_stream_writing **stream_writing) {
209 : grpc_chttp2_stream *stream;
210 9664512 : int r = stream_list_pop(TRANSPORT_FROM_WRITING(transport_writing), &stream,
211 : GRPC_CHTTP2_LIST_WRITTEN);
212 9663757 : if (r != 0) {
213 5040997 : *stream_global = &stream->global;
214 5040997 : *stream_writing = &stream->writing;
215 : }
216 9663757 : return r;
217 : }
218 :
219 2409474 : void grpc_chttp2_list_add_unannounced_incoming_window_available(
220 : grpc_chttp2_transport_global *transport_global,
221 : grpc_chttp2_stream_global *stream_global) {
222 2409474 : GPR_ASSERT(stream_global->id != 0);
223 2409474 : stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
224 : STREAM_FROM_GLOBAL(stream_global),
225 : GRPC_CHTTP2_LIST_UNANNOUNCED_INCOMING_WINDOW_AVAILABLE);
226 2409205 : }
227 :
228 4442135 : void grpc_chttp2_list_remove_unannounced_incoming_window_available(
229 : grpc_chttp2_transport_global *transport_global,
230 : grpc_chttp2_stream_global *stream_global) {
231 4442135 : stream_list_maybe_remove(
232 : TRANSPORT_FROM_GLOBAL(transport_global),
233 : STREAM_FROM_GLOBAL(stream_global),
234 : GRPC_CHTTP2_LIST_UNANNOUNCED_INCOMING_WINDOW_AVAILABLE);
235 4442003 : }
236 :
237 8486605 : int grpc_chttp2_list_pop_unannounced_incoming_window_available(
238 : grpc_chttp2_transport_global *transport_global,
239 : grpc_chttp2_transport_parsing *transport_parsing,
240 : grpc_chttp2_stream_global **stream_global,
241 : grpc_chttp2_stream_parsing **stream_parsing) {
242 : grpc_chttp2_stream *stream;
243 8486605 : int r =
244 8486605 : stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
245 : GRPC_CHTTP2_LIST_UNANNOUNCED_INCOMING_WINDOW_AVAILABLE);
246 8486675 : if (r != 0) {
247 1970864 : *stream_global = &stream->global;
248 1970864 : *stream_parsing = &stream->parsing;
249 : }
250 8486675 : return r;
251 : }
252 :
253 78411150 : void grpc_chttp2_list_add_parsing_seen_stream(
254 : grpc_chttp2_transport_parsing *transport_parsing,
255 : grpc_chttp2_stream_parsing *stream_parsing) {
256 78411150 : stream_list_add(TRANSPORT_FROM_PARSING(transport_parsing),
257 : STREAM_FROM_PARSING(stream_parsing),
258 : GRPC_CHTTP2_LIST_PARSING_SEEN);
259 78420743 : }
260 :
261 15233211 : int grpc_chttp2_list_pop_parsing_seen_stream(
262 : grpc_chttp2_transport_global *transport_global,
263 : grpc_chttp2_transport_parsing *transport_parsing,
264 : grpc_chttp2_stream_global **stream_global,
265 : grpc_chttp2_stream_parsing **stream_parsing) {
266 : grpc_chttp2_stream *stream;
267 15233211 : int r = stream_list_pop(TRANSPORT_FROM_PARSING(transport_parsing), &stream,
268 : GRPC_CHTTP2_LIST_PARSING_SEEN);
269 15233611 : if (r != 0) {
270 8718158 : *stream_global = &stream->global;
271 8718158 : *stream_parsing = &stream->parsing;
272 : }
273 15233611 : return r;
274 : }
275 :
276 2271892 : void grpc_chttp2_list_add_waiting_for_concurrency(
277 : grpc_chttp2_transport_global *transport_global,
278 : grpc_chttp2_stream_global *stream_global) {
279 2271892 : stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
280 : STREAM_FROM_GLOBAL(stream_global),
281 : GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY);
282 2272159 : }
283 :
284 6809121 : int grpc_chttp2_list_pop_waiting_for_concurrency(
285 : grpc_chttp2_transport_global *transport_global,
286 : grpc_chttp2_stream_global **stream_global) {
287 : grpc_chttp2_stream *stream;
288 6809121 : int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
289 : GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY);
290 6811449 : if (r != 0) {
291 2272142 : *stream_global = &stream->global;
292 : }
293 6811449 : return r;
294 : }
295 :
296 33287065 : void grpc_chttp2_list_add_check_read_ops(
297 : grpc_chttp2_transport_global *transport_global,
298 : grpc_chttp2_stream_global *stream_global) {
299 33287065 : stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
300 : STREAM_FROM_GLOBAL(stream_global),
301 : GRPC_CHTTP2_LIST_CHECK_READ_OPS);
302 33280976 : }
303 :
304 56193154 : int grpc_chttp2_list_pop_check_read_ops(
305 : grpc_chttp2_transport_global *transport_global,
306 : grpc_chttp2_stream_global **stream_global) {
307 : grpc_chttp2_stream *stream;
308 56193154 : int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
309 : GRPC_CHTTP2_LIST_CHECK_READ_OPS);
310 56288740 : if (r != 0) {
311 18333113 : *stream_global = &stream->global;
312 : }
313 56288740 : return r;
314 : }
315 :
316 6 : void grpc_chttp2_list_add_stalled_by_transport(
317 : grpc_chttp2_transport_writing *transport_writing,
318 : grpc_chttp2_stream_writing *stream_writing) {
319 6 : stream_list_add(TRANSPORT_FROM_WRITING(transport_writing),
320 : STREAM_FROM_WRITING(stream_writing),
321 : GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
322 6 : }
323 :
324 5879 : int grpc_chttp2_list_pop_stalled_by_transport(
325 : grpc_chttp2_transport_global *transport_global,
326 : grpc_chttp2_stream_global **stream_global) {
327 : grpc_chttp2_stream *stream;
328 5879 : int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
329 : GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
330 5879 : if (r != 0) {
331 6 : *stream_global = &stream->global;
332 : }
333 5879 : return r;
334 : }
335 :
336 2398123 : void grpc_chttp2_list_add_closed_waiting_for_parsing(
337 : grpc_chttp2_transport_global *transport_global,
338 : grpc_chttp2_stream_global *stream_global) {
339 2398123 : stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
340 : STREAM_FROM_GLOBAL(stream_global),
341 : GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_PARSING);
342 2398206 : }
343 :
344 8914697 : int grpc_chttp2_list_pop_closed_waiting_for_parsing(
345 : grpc_chttp2_transport_global *transport_global,
346 : grpc_chttp2_stream_global **stream_global) {
347 : grpc_chttp2_stream *stream;
348 8914697 : int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
349 : GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_PARSING);
350 8914739 : if (r != 0) {
351 2398864 : *stream_global = &stream->global;
352 : }
353 8914739 : return r;
354 : }
355 :
356 4443271 : void grpc_chttp2_register_stream(grpc_chttp2_transport *t,
357 : grpc_chttp2_stream *s) {
358 4443271 : stream_list_add_tail(t, s, GRPC_CHTTP2_LIST_ALL_STREAMS);
359 4443231 : }
360 :
361 8876893 : int grpc_chttp2_unregister_stream(grpc_chttp2_transport *t,
362 : grpc_chttp2_stream *s) {
363 8876665 : stream_list_maybe_remove(t, s, GRPC_CHTTP2_LIST_ALL_STREAMS);
364 8877976 : return stream_list_empty(t, GRPC_CHTTP2_LIST_ALL_STREAMS);
365 : }
366 :
367 2716 : int grpc_chttp2_has_streams(grpc_chttp2_transport *t) {
368 2716 : return !stream_list_empty(t, GRPC_CHTTP2_LIST_ALL_STREAMS);
369 : }
370 :
371 12142 : void grpc_chttp2_for_all_streams(
372 : grpc_chttp2_transport_global *transport_global, void *user_data,
373 : void (*cb)(grpc_chttp2_transport_global *transport_global, void *user_data,
374 : grpc_chttp2_stream_global *stream_global)) {
375 : grpc_chttp2_stream *s;
376 12038 : grpc_chttp2_transport *t = TRANSPORT_FROM_GLOBAL(transport_global);
377 24402 : for (s = t->lists[GRPC_CHTTP2_LIST_ALL_STREAMS].head; s != NULL;
378 118 : s = s->links[GRPC_CHTTP2_LIST_ALL_STREAMS].next) {
379 118 : cb(transport_global, user_data, &s->global);
380 : }
381 12142 : }
|