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 11552 : 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 11552 : size_t size =
66 : ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_channel_stack)) +
67 11552 : 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 44440 : for (i = 0; i < filter_count; i++) {
75 32888 : size += ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data);
76 : }
77 :
78 11552 : 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 18305 : grpc_channel_element *grpc_channel_stack_element(
90 : grpc_channel_stack *channel_stack, size_t index) {
91 18305 : return CHANNEL_ELEMS_FROM_STACK(channel_stack) + index;
92 : }
93 :
94 7560 : grpc_channel_element *grpc_channel_stack_last_element(
95 : grpc_channel_stack *channel_stack) {
96 7560 : return grpc_channel_stack_element(channel_stack, channel_stack->count - 1);
97 : }
98 :
99 12358017 : grpc_call_element *grpc_call_stack_element(grpc_call_stack *call_stack,
100 : size_t index) {
101 12358017 : return CALL_ELEMS_FROM_STACK(call_stack) + index;
102 : }
103 :
104 5775 : 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 *args,
108 : grpc_mdctx *metadata_context,
109 : grpc_channel_stack *stack) {
110 5775 : size_t call_size =
111 : ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack)) +
112 5775 : ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_call_element));
113 : grpc_channel_element *elems;
114 : char *user_data;
115 : size_t i;
116 :
117 5775 : stack->count = filter_count;
118 5775 : elems = CHANNEL_ELEMS_FROM_STACK(stack);
119 5775 : user_data =
120 5775 : ((char *)elems) +
121 5775 : ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_channel_element));
122 :
123 : /* init per-filter data */
124 22221 : for (i = 0; i < filter_count; i++) {
125 16445 : elems[i].filter = filters[i];
126 16445 : elems[i].channel_data = user_data;
127 32890 : elems[i].filter->init_channel_elem(exec_ctx, &elems[i], master, args,
128 : metadata_context, i == 0,
129 16445 : i == (filter_count - 1));
130 16446 : user_data += ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data);
131 16446 : call_size += ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_call_data);
132 : }
133 :
134 5776 : GPR_ASSERT(user_data > (char *)stack);
135 5776 : GPR_ASSERT((gpr_uintptr)(user_data - (char *)stack) ==
136 : grpc_channel_stack_size(filters, filter_count));
137 :
138 5776 : stack->call_stack_size = call_size;
139 5776 : }
140 :
141 5778 : void grpc_channel_stack_destroy(grpc_exec_ctx *exec_ctx,
142 : grpc_channel_stack *stack) {
143 5778 : grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(stack);
144 5778 : size_t count = stack->count;
145 : size_t i;
146 :
147 : /* destroy per-filter data */
148 22226 : for (i = 0; i < count; i++) {
149 16448 : channel_elems[i].filter->destroy_channel_elem(exec_ctx, &channel_elems[i]);
150 : }
151 5778 : }
152 :
153 4105273 : void grpc_call_stack_init(grpc_exec_ctx *exec_ctx,
154 : grpc_channel_stack *channel_stack,
155 : const void *transport_server_data,
156 : grpc_transport_stream_op *initial_op,
157 : grpc_call_stack *call_stack) {
158 4105273 : grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(channel_stack);
159 4105273 : size_t count = channel_stack->count;
160 : grpc_call_element *call_elems;
161 : char *user_data;
162 : size_t i;
163 :
164 4105273 : call_stack->count = count;
165 4105273 : call_elems = CALL_ELEMS_FROM_STACK(call_stack);
166 4105273 : user_data = ((char *)call_elems) +
167 4105273 : ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element));
168 :
169 : /* init per-filter data */
170 14898855 : for (i = 0; i < count; i++) {
171 10794181 : call_elems[i].filter = channel_elems[i].filter;
172 10794181 : call_elems[i].channel_data = channel_elems[i].channel_data;
173 10794181 : call_elems[i].call_data = user_data;
174 10794181 : call_elems[i].filter->init_call_elem(exec_ctx, &call_elems[i],
175 : transport_server_data, initial_op);
176 10793582 : user_data +=
177 10793582 : ROUND_UP_TO_ALIGNMENT_SIZE(call_elems[i].filter->sizeof_call_data);
178 : }
179 4104674 : }
180 :
181 4108910 : void grpc_call_stack_destroy(grpc_exec_ctx *exec_ctx, grpc_call_stack *stack) {
182 4108910 : grpc_call_element *elems = CALL_ELEMS_FROM_STACK(stack);
183 4108910 : size_t count = stack->count;
184 : size_t i;
185 :
186 : /* destroy per-filter data */
187 14902690 : for (i = 0; i < count; i++) {
188 10797972 : elems[i].filter->destroy_call_elem(exec_ctx, &elems[i]);
189 : }
190 4104718 : }
191 :
192 20828101 : void grpc_call_next_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
193 : grpc_transport_stream_op *op) {
194 20828101 : grpc_call_element *next_elem = elem + 1;
195 20828101 : next_elem->filter->start_transport_stream_op(exec_ctx, next_elem, op);
196 20923980 : }
197 :
198 3075 : char *grpc_call_next_get_peer(grpc_exec_ctx *exec_ctx,
199 : grpc_call_element *elem) {
200 3075 : grpc_call_element *next_elem = elem + 1;
201 3075 : return next_elem->filter->get_peer(exec_ctx, next_elem);
202 : }
203 :
204 17444 : void grpc_channel_next_op(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
205 : grpc_transport_op *op) {
206 17444 : grpc_channel_element *next_elem = elem + 1;
207 17444 : next_elem->filter->start_transport_op(exec_ctx, next_elem, op);
208 17444 : }
209 :
210 0 : grpc_channel_stack *grpc_channel_stack_from_top_element(
211 : grpc_channel_element *elem) {
212 0 : return (grpc_channel_stack *)((char *)(elem)-ROUND_UP_TO_ALIGNMENT_SIZE(
213 : sizeof(grpc_channel_stack)));
214 : }
215 :
216 1302014 : grpc_call_stack *grpc_call_stack_from_top_element(grpc_call_element *elem) {
217 1302014 : return (grpc_call_stack *)((char *)(elem)-ROUND_UP_TO_ALIGNMENT_SIZE(
218 : sizeof(grpc_call_stack)));
219 : }
220 :
221 0 : void grpc_call_element_send_cancel(grpc_exec_ctx *exec_ctx,
222 : grpc_call_element *cur_elem) {
223 : grpc_transport_stream_op op;
224 0 : memset(&op, 0, sizeof(op));
225 0 : op.cancel_with_status = GRPC_STATUS_CANCELLED;
226 0 : grpc_call_next_op(exec_ctx, cur_elem, &op);
227 0 : }
|