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/channel/channel_stack.h"
35 : #include <grpc/support/log.h>
36 :
37 : #include <stdlib.h>
38 : #include <string.h>
39 :
40 : int grpc_trace_channel = 0;
41 :
42 : /* Memory layouts.
43 :
44 : Channel stack is laid out as: {
45 : grpc_channel_stack stk;
46 : padding to GPR_MAX_ALIGNMENT
47 : grpc_channel_element[stk.count];
48 : per-filter memory, aligned to GPR_MAX_ALIGNMENT
49 : }
50 :
51 : Call stack is laid out as: {
52 : grpc_call_stack stk;
53 : padding to GPR_MAX_ALIGNMENT
54 : grpc_call_element[stk.count];
55 : per-filter memory, aligned to GPR_MAX_ALIGNMENT
56 : } */
57 :
58 : /* Given a size, round up to the next multiple of sizeof(void*) */
59 : #define ROUND_UP_TO_ALIGNMENT_SIZE(x) \
60 : (((x) + GPR_MAX_ALIGNMENT - 1u) & ~(GPR_MAX_ALIGNMENT - 1u))
61 :
62 18157 : size_t grpc_channel_stack_size(const grpc_channel_filter **filters,
63 : size_t filter_count) {
64 : /* always need the header, and size for the channel elements */
65 18157 : size_t size =
66 : ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_channel_stack)) +
67 18157 : ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_channel_element));
68 : size_t i;
69 :
70 : GPR_ASSERT((GPR_MAX_ALIGNMENT & (GPR_MAX_ALIGNMENT - 1)) == 0 &&
71 : "GPR_MAX_ALIGNMENT must be a power of two");
72 :
73 : /* add the size for each filter */
74 68354 : for (i = 0; i < filter_count; i++) {
75 50197 : size += ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data);
76 : }
77 :
78 18157 : return size;
79 : }
80 :
81 : #define CHANNEL_ELEMS_FROM_STACK(stk) \
82 : ((grpc_channel_element *)((char *)(stk) + ROUND_UP_TO_ALIGNMENT_SIZE( \
83 : sizeof(grpc_channel_stack))))
84 :
85 : #define CALL_ELEMS_FROM_STACK(stk) \
86 : ((grpc_call_element *)((char *)(stk) + \
87 : ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack))))
88 :
89 30565 : grpc_channel_element *grpc_channel_stack_element(
90 : grpc_channel_stack *channel_stack, size_t index) {
91 30565 : return CHANNEL_ELEMS_FROM_STACK(channel_stack) + index;
92 : }
93 :
94 13850 : grpc_channel_element *grpc_channel_stack_last_element(
95 : grpc_channel_stack *channel_stack) {
96 13850 : return grpc_channel_stack_element(channel_stack, channel_stack->count - 1);
97 : }
98 :
99 20823119 : grpc_call_element *grpc_call_stack_element(grpc_call_stack *call_stack,
100 : size_t index) {
101 20823119 : return CALL_ELEMS_FROM_STACK(call_stack) + index;
102 : }
103 :
104 9078 : void grpc_channel_stack_init(grpc_exec_ctx *exec_ctx,
105 : const grpc_channel_filter **filters,
106 : size_t filter_count, grpc_channel *master,
107 : const grpc_channel_args *channel_args,
108 : grpc_channel_stack *stack) {
109 9078 : size_t call_size =
110 : ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack)) +
111 9078 : ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_call_element));
112 : grpc_channel_element *elems;
113 : grpc_channel_element_args args;
114 : char *user_data;
115 : size_t i;
116 :
117 9078 : stack->count = filter_count;
118 9078 : elems = CHANNEL_ELEMS_FROM_STACK(stack);
119 9078 : user_data =
120 9078 : ((char *)elems) +
121 9078 : ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_channel_element));
122 :
123 : /* init per-filter data */
124 34178 : for (i = 0; i < filter_count; i++) {
125 25100 : args.master = master;
126 25100 : args.channel_args = channel_args;
127 25100 : args.is_first = i == 0;
128 25100 : args.is_last = i == (filter_count - 1);
129 25100 : elems[i].filter = filters[i];
130 25100 : elems[i].channel_data = user_data;
131 25100 : elems[i].filter->init_channel_elem(exec_ctx, &elems[i], &args);
132 25100 : user_data += ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data);
133 25100 : call_size += ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_call_data);
134 : }
135 :
136 9078 : GPR_ASSERT(user_data > (char *)stack);
137 9078 : GPR_ASSERT((gpr_uintptr)(user_data - (char *)stack) ==
138 : grpc_channel_stack_size(filters, filter_count));
139 :
140 9078 : stack->call_stack_size = call_size;
141 9078 : }
142 :
143 8943 : void grpc_channel_stack_destroy(grpc_exec_ctx *exec_ctx,
144 : grpc_channel_stack *stack) {
145 8943 : grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(stack);
146 8943 : size_t count = stack->count;
147 : size_t i;
148 :
149 : /* destroy per-filter data */
150 33680 : for (i = 0; i < count; i++) {
151 24737 : channel_elems[i].filter->destroy_channel_elem(exec_ctx, &channel_elems[i]);
152 : }
153 8943 : }
154 :
155 6603144 : void grpc_call_stack_init(grpc_exec_ctx *exec_ctx,
156 : grpc_channel_stack *channel_stack, int initial_refs,
157 : grpc_iomgr_cb_func destroy, void *destroy_arg,
158 : grpc_call_context_element *context,
159 : const void *transport_server_data,
160 : grpc_call_stack *call_stack) {
161 6603144 : grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(channel_stack);
162 : grpc_call_element_args args;
163 6603144 : size_t count = channel_stack->count;
164 : grpc_call_element *call_elems;
165 : char *user_data;
166 : size_t i;
167 :
168 6603144 : call_stack->count = count;
169 6603144 : gpr_ref_init(&call_stack->refcount.refs, initial_refs);
170 6606122 : grpc_closure_init(&call_stack->refcount.destroy, destroy, destroy_arg);
171 6604907 : call_elems = CALL_ELEMS_FROM_STACK(call_stack);
172 6604907 : user_data = ((char *)call_elems) +
173 6604907 : ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element));
174 :
175 : /* init per-filter data */
176 24422197 : for (i = 0; i < count; i++) {
177 17816027 : args.refcount = &call_stack->refcount;
178 17816027 : args.server_transport_data = transport_server_data;
179 17816027 : args.context = context;
180 17816027 : call_elems[i].filter = channel_elems[i].filter;
181 17816027 : call_elems[i].channel_data = channel_elems[i].channel_data;
182 17816027 : call_elems[i].call_data = user_data;
183 17816027 : call_elems[i].filter->init_call_elem(exec_ctx, &call_elems[i], &args);
184 17817290 : user_data +=
185 17817290 : ROUND_UP_TO_ALIGNMENT_SIZE(call_elems[i].filter->sizeof_call_data);
186 : }
187 6606170 : }
188 :
189 6609941 : void grpc_call_stack_set_pollset(grpc_exec_ctx *exec_ctx,
190 : grpc_call_stack *call_stack,
191 : grpc_pollset *pollset) {
192 6609941 : size_t count = call_stack->count;
193 : grpc_call_element *call_elems;
194 : char *user_data;
195 : size_t i;
196 :
197 6609941 : call_elems = CALL_ELEMS_FROM_STACK(call_stack);
198 6609653 : user_data = ((char *)call_elems) +
199 6609653 : ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element));
200 :
201 : /* init per-filter data */
202 24449942 : for (i = 0; i < count; i++) {
203 17843829 : call_elems[i].filter->set_pollset(exec_ctx, &call_elems[i], pollset);
204 17839204 : user_data +=
205 17839204 : ROUND_UP_TO_ALIGNMENT_SIZE(call_elems[i].filter->sizeof_call_data);
206 : }
207 6606113 : }
208 :
209 10941446 : void grpc_call_stack_ignore_set_pollset(grpc_exec_ctx *exec_ctx,
210 : grpc_call_element *elem,
211 10941446 : grpc_pollset *pollset) {}
212 :
213 6608217 : void grpc_call_stack_destroy(grpc_exec_ctx *exec_ctx, grpc_call_stack *stack) {
214 6608217 : grpc_call_element *elems = CALL_ELEMS_FROM_STACK(stack);
215 6608217 : size_t count = stack->count;
216 : size_t i;
217 :
218 : /* destroy per-filter data */
219 24410125 : for (i = 0; i < count; i++) {
220 17806100 : elems[i].filter->destroy_call_elem(exec_ctx, &elems[i]);
221 : }
222 6604025 : }
223 :
224 32949519 : void grpc_call_next_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
225 : grpc_transport_stream_op *op) {
226 32949519 : grpc_call_element *next_elem = elem + 1;
227 32949519 : next_elem->filter->start_transport_stream_op(exec_ctx, next_elem, op);
228 33191360 : }
229 :
230 3541 : char *grpc_call_next_get_peer(grpc_exec_ctx *exec_ctx,
231 : grpc_call_element *elem) {
232 3541 : grpc_call_element *next_elem = elem + 1;
233 3541 : return next_elem->filter->get_peer(exec_ctx, next_elem);
234 : }
235 :
236 26436 : void grpc_channel_next_op(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
237 : grpc_transport_op *op) {
238 26436 : grpc_channel_element *next_elem = elem + 1;
239 26436 : next_elem->filter->start_transport_op(exec_ctx, next_elem, op);
240 26437 : }
241 :
242 0 : grpc_channel_stack *grpc_channel_stack_from_top_element(
243 : grpc_channel_element *elem) {
244 0 : return (grpc_channel_stack *)((char *)(elem)-ROUND_UP_TO_ALIGNMENT_SIZE(
245 : sizeof(grpc_channel_stack)));
246 : }
247 :
248 2171296 : grpc_call_stack *grpc_call_stack_from_top_element(grpc_call_element *elem) {
249 2171296 : return (grpc_call_stack *)((char *)(elem)-ROUND_UP_TO_ALIGNMENT_SIZE(
250 : sizeof(grpc_call_stack)));
251 : }
252 :
253 48 : void grpc_call_element_send_cancel(grpc_exec_ctx *exec_ctx,
254 : grpc_call_element *cur_elem) {
255 : grpc_transport_stream_op op;
256 48 : memset(&op, 0, sizeof(op));
257 48 : op.cancel_with_status = GRPC_STATUS_CANCELLED;
258 48 : grpc_call_next_op(exec_ctx, cur_elem, &op);
259 48 : }
|