blob: 20f5753004994cb378d232b8d699d83e3c6468a9 [file] [log] [blame]
Craig Tiller178edfa2016-02-17 20:54:46 -08001/*
2 *
Craig Tiller9b524122016-02-18 08:23:08 -08003 * Copyright 2016, Google Inc.
Craig Tiller178edfa2016-02-17 20:54:46 -08004 * 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
Craig Tiller9533d042016-03-25 17:11:06 -070034#include "src/core/lib/surface/channel_init.h"
Craig Tiller178edfa2016-02-17 20:54:46 -080035
36#include <grpc/support/alloc.h>
37#include <grpc/support/useful.h>
38
39typedef struct stage_slot {
40 grpc_channel_init_stage fn;
41 void *arg;
42 int priority;
43 size_t insertion_order;
44} stage_slot;
45
46typedef struct stage_slots {
47 stage_slot *slots;
48 size_t num_slots;
49 size_t cap_slots;
50} stage_slots;
51
52static stage_slots g_slots[GRPC_NUM_CHANNEL_STACK_TYPES];
53static bool g_finalized;
54
55void grpc_channel_init_init(void) {
56 for (int i = 0; i < GRPC_NUM_CHANNEL_STACK_TYPES; i++) {
57 g_slots[i].slots = NULL;
58 g_slots[i].num_slots = 0;
59 g_slots[i].cap_slots = 0;
60 }
61 g_finalized = false;
62}
63
64void grpc_channel_init_register_stage(grpc_channel_stack_type type,
65 int priority,
66 grpc_channel_init_stage stage,
67 void *stage_arg) {
68 GPR_ASSERT(!g_finalized);
69 if (g_slots[type].cap_slots == g_slots[type].num_slots) {
70 g_slots[type].cap_slots = GPR_MAX(8, 3 * g_slots[type].cap_slots / 2);
71 g_slots[type].slots =
72 gpr_realloc(g_slots[type].slots,
73 g_slots[type].cap_slots * sizeof(*g_slots[type].slots));
74 }
75 stage_slot *s = &g_slots[type].slots[g_slots[type].num_slots++];
76 s->insertion_order = g_slots[type].num_slots;
77 s->priority = priority;
78 s->fn = stage;
79 s->arg = stage_arg;
80}
81
82static int compare_slots(const void *a, const void *b) {
83 const stage_slot *sa = a;
84 const stage_slot *sb = b;
85
86 int c = GPR_ICMP(sa->priority, sb->priority);
87 if (c != 0) return c;
88 return GPR_ICMP(sa->insertion_order, sb->insertion_order);
89}
90
91void grpc_channel_init_finalize(void) {
92 GPR_ASSERT(!g_finalized);
93 for (int i = 0; i < GRPC_NUM_CHANNEL_STACK_TYPES; i++) {
94 qsort(g_slots[i].slots, g_slots[i].num_slots, sizeof(*g_slots[i].slots),
95 compare_slots);
96 }
97 g_finalized = true;
98}
99
100void grpc_channel_init_shutdown(void) {
101 for (int i = 0; i < GRPC_NUM_CHANNEL_STACK_TYPES; i++) {
102 gpr_free(g_slots[i].slots);
Craig Tiller3d2686b2016-03-21 07:12:54 -0700103 g_slots[i].slots = (void *)(uintptr_t)0xdeadbeef;
Craig Tiller178edfa2016-02-17 20:54:46 -0800104 }
105}
106
Craig Tiller839bebe2016-04-06 08:07:11 -0700107bool grpc_channel_init_create_stack(grpc_exec_ctx *exec_ctx,
108 grpc_channel_stack_builder *builder,
109 grpc_channel_stack_type type) {
Craig Tiller178edfa2016-02-17 20:54:46 -0800110 GPR_ASSERT(g_finalized);
111
Craig Tiller4f89b0b2017-04-03 10:00:17 -0700112 grpc_channel_stack_builder_set_name(builder,
113 grpc_channel_stack_type_string(type));
Craig Tiller178edfa2016-02-17 20:54:46 -0800114
115 for (size_t i = 0; i < g_slots[type].num_slots; i++) {
116 const stage_slot *slot = &g_slots[type].slots[i];
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800117 if (!slot->fn(exec_ctx, builder, slot->arg)) {
Craig Tiller839bebe2016-04-06 08:07:11 -0700118 return false;
Craig Tiller178edfa2016-02-17 20:54:46 -0800119 }
120 }
121
Craig Tiller839bebe2016-04-06 08:07:11 -0700122 return true;
Craig Tiller178edfa2016-02-17 20:54:46 -0800123}