1 /* 2 * 3 * Copyright 2017 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 #include "src/core/lib/gpr/arena.h" 20 21 #include <inttypes.h> 22 #include <string.h> 23 24 #include <grpc/support/alloc.h> 25 #include <grpc/support/log.h> 26 #include <grpc/support/string_util.h> 27 #include <grpc/support/sync.h> 28 29 #include "src/core/lib/gpr/string.h" 30 #include "src/core/lib/gpr/useful.h" 31 #include "src/core/lib/gprpp/thd.h" 32 #include "test/core/util/test_config.h" 33 34 static void test_noop(void) { gpr_arena_destroy(gpr_arena_create(1)); } 35 36 static void test(const char* name, size_t init_size, const size_t* allocs, 37 size_t nallocs) { 38 gpr_strvec v; 39 char* s; 40 gpr_strvec_init(&v); 41 gpr_asprintf(&s, "test '%s': %" PRIdPTR " <- {", name, init_size); 42 gpr_strvec_add(&v, s); 43 for (size_t i = 0; i < nallocs; i++) { 44 gpr_asprintf(&s, "%" PRIdPTR ",", allocs[i]); 45 gpr_strvec_add(&v, s); 46 } 47 gpr_strvec_add(&v, gpr_strdup("}")); 48 s = gpr_strvec_flatten(&v, nullptr); 49 gpr_strvec_destroy(&v); 50 gpr_log(GPR_INFO, "%s", s); 51 gpr_free(s); 52 53 gpr_arena* a = gpr_arena_create(init_size); 54 void** ps = static_cast<void**>(gpr_zalloc(sizeof(*ps) * nallocs)); 55 for (size_t i = 0; i < nallocs; i++) { 56 ps[i] = gpr_arena_alloc(a, allocs[i]); 57 // ensure the returned address is aligned 58 GPR_ASSERT(((intptr_t)ps[i] & 0xf) == 0); 59 // ensure no duplicate results 60 for (size_t j = 0; j < i; j++) { 61 GPR_ASSERT(ps[i] != ps[j]); 62 } 63 // ensure writable 64 memset(ps[i], 1, allocs[i]); 65 } 66 gpr_arena_destroy(a); 67 gpr_free(ps); 68 } 69 70 #define TEST(name, init_size, ...) \ 71 static const size_t allocs_##name[] = {__VA_ARGS__}; \ 72 test(#name, init_size, allocs_##name, GPR_ARRAY_SIZE(allocs_##name)) 73 74 #define CONCURRENT_TEST_THREADS 10 75 76 size_t concurrent_test_iterations() { 77 if (sizeof(void*) < 8) return 1000; 78 return 100000; 79 } 80 81 typedef struct { 82 gpr_event ev_start; 83 gpr_arena* arena; 84 } concurrent_test_args; 85 86 static void concurrent_test_body(void* arg) { 87 concurrent_test_args* a = static_cast<concurrent_test_args*>(arg); 88 gpr_event_wait(&a->ev_start, gpr_inf_future(GPR_CLOCK_REALTIME)); 89 for (size_t i = 0; i < concurrent_test_iterations(); i++) { 90 *static_cast<char*>(gpr_arena_alloc(a->arena, 1)) = static_cast<char>(i); 91 } 92 } 93 94 static void concurrent_test(void) { 95 gpr_log(GPR_DEBUG, "concurrent_test"); 96 97 concurrent_test_args args; 98 gpr_event_init(&args.ev_start); 99 args.arena = gpr_arena_create(1024); 100 101 grpc_core::Thread thds[CONCURRENT_TEST_THREADS]; 102 103 for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) { 104 thds[i] = 105 grpc_core::Thread("grpc_concurrent_test", concurrent_test_body, &args); 106 thds[i].Start(); 107 } 108 109 gpr_event_set(&args.ev_start, (void*)1); 110 111 for (auto& th : thds) { 112 th.Join(); 113 } 114 115 gpr_arena_destroy(args.arena); 116 } 117 118 int main(int argc, char* argv[]) { 119 grpc_test_init(argc, argv); 120 121 test_noop(); 122 TEST(0_1, 0, 1); 123 TEST(1_1, 1, 1); 124 TEST(1_2, 1, 2); 125 TEST(1_3, 1, 3); 126 TEST(1_inc, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); 127 TEST(6_123, 6, 1, 2, 3); 128 concurrent_test(); 129 130 return 0; 131 } 132