spinlock_test.cc
Go to the documentation of this file.
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 /* Test of gpr spin-lock support. */
20 
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 
26 #include <grpc/support/alloc.h>
27 #include <grpc/support/log.h>
28 #include <grpc/support/sync.h>
29 #include <grpc/support/time.h>
30 
31 #include "src/core/lib/gprpp/thd.h"
33 
34 /* ------------------------------------------------- */
35 /* Tests for gpr_spinlock. */
36 struct test {
37  int thread_count; /* number of threads */
39 
40  int64_t iterations; /* number of iterations per thread */
42  int incr_step; /* how much to increment/decrement refcount each time */
43 
44  gpr_spinlock mu; /* protects iterations, counter */
45 };
46 
47 /* Return pointer to a new struct test. */
48 static struct test* test_new(int threads, int64_t iterations, int incr_step) {
49  struct test* m = static_cast<struct test*>(gpr_malloc(sizeof(*m)));
50  m->thread_count = threads;
51  m->threads = static_cast<grpc_core::Thread*>(
52  gpr_malloc(sizeof(*m->threads) * static_cast<size_t>(threads)));
53  m->iterations = iterations;
54  m->counter = 0;
55  m->thread_count = 0;
56  m->incr_step = incr_step;
58  return m;
59 }
60 
61 /* Return pointer to a new struct test. */
62 static void test_destroy(struct test* m) {
63  gpr_free(m->threads);
64  gpr_free(m);
65 }
66 
67 /* Create m->threads threads, each running (*body)(m) */
68 static void test_create_threads(struct test* m, void (*body)(void* arg)) {
69  int i;
70  for (i = 0; i != m->thread_count; i++) {
71  m->threads[i] = grpc_core::Thread("grpc_create_threads", body, m);
72  m->threads[i].Start();
73  }
74 }
75 
76 /* Wait until all threads report done. */
77 static void test_wait(struct test* m) {
78  int i;
79  for (i = 0; i != m->thread_count; i++) {
80  m->threads[i].Join();
81  }
82 }
83 
84 /* Test several threads running (*body)(struct test *m) for increasing settings
85  of m->iterations, until about timeout_s to 2*timeout_s seconds have elapsed.
86  If extra!=NULL, run (*extra)(m) in an additional thread.
87  incr_step controls by how much m->refcount should be incremented/decremented
88  (if at all) each time in the tests.
89  */
90 static void test(const char* name, void (*body)(void* m), int timeout_s,
91  int incr_step) {
92  int64_t iterations = 1024;
93  struct test* m;
96  gpr_timespec deadline = gpr_time_add(
97  start, gpr_time_from_micros(static_cast<int64_t>(timeout_s) * 1000000,
98  GPR_TIMESPAN));
99  fprintf(stderr, "%s:", name);
100  fflush(stderr);
101  while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0) {
102  if (iterations < INT64_MAX / 2) iterations <<= 1;
103  fprintf(stderr, " %ld", static_cast<long>(iterations));
104  fflush(stderr);
105  m = test_new(10, iterations, incr_step);
106  test_create_threads(m, body);
107  test_wait(m);
108  if (m->counter != m->thread_count * m->iterations * m->incr_step) {
109  fprintf(stderr, "counter %ld threads %d iterations %ld\n",
110  static_cast<long>(m->counter), m->thread_count,
111  static_cast<long>(m->iterations));
112  fflush(stderr);
113  GPR_ASSERT(0);
114  }
115  test_destroy(m);
116  }
118  fprintf(stderr, " done %lld.%09d s\n",
119  static_cast<long long>(time_taken.tv_sec),
120  static_cast<int>(time_taken.tv_nsec));
121  fflush(stderr);
122 }
123 
124 /* Increment m->counter on each iteration; then mark thread as done. */
125 static void inc(void* v /*=m*/) {
126  struct test* m = static_cast<struct test*>(v);
127  int64_t i;
128  for (i = 0; i != m->iterations; i++) {
129  gpr_spinlock_lock(&m->mu);
130  m->counter++;
131  gpr_spinlock_unlock(&m->mu);
132  }
133 }
134 
135 /* Increment m->counter under lock acquired with trylock, m->iterations times;
136  then mark thread as done. */
137 static void inctry(void* v /*=m*/) {
138  struct test* m = static_cast<struct test*>(v);
139  int64_t i;
140  for (i = 0; i != m->iterations;) {
141  if (gpr_spinlock_trylock(&m->mu)) {
142  m->counter++;
143  gpr_spinlock_unlock(&m->mu);
144  i++;
145  }
146  }
147 }
148 
149 /* ------------------------------------------------- */
150 
151 int main(int argc, char* argv[]) {
152  grpc::testing::TestEnvironment env(&argc, argv);
153  test("spinlock", &inc, 1, 1);
154  test("spinlock try", &inctry, 1, 1);
155  return 0;
156 }
GPR_TIMESPAN
@ GPR_TIMESPAN
Definition: gpr_types.h:45
GPR_SPINLOCK_INITIALIZER
#define GPR_SPINLOCK_INITIALIZER
Definition: src/core/lib/gpr/spinlock.h:35
log.h
generate.env
env
Definition: generate.py:37
inc
static void inc(void *v)
Definition: spinlock_test.cc:125
gpr_spinlock
Definition: src/core/lib/gpr/spinlock.h:29
test
Definition: spinlock_test.cc:36
inctry
static void inctry(void *v)
Definition: spinlock_test.cc:137
INT64_MAX
#define INT64_MAX
Definition: stdint-msvc2008.h:139
test_destroy
static void test_destroy(struct test *m)
Definition: spinlock_test.cc:62
gpr_free
GPRAPI void gpr_free(void *ptr)
Definition: alloc.cc:51
gpr_malloc
GPRAPI void * gpr_malloc(size_t size)
Definition: alloc.cc:29
test::counter
int64_t counter
Definition: spinlock_test.cc:41
setup.name
name
Definition: setup.py:542
time.h
gpr_spinlock_lock
#define gpr_spinlock_lock(lock)
Definition: src/core/lib/gpr/spinlock.h:49
threads
static uv_thread_t * threads
Definition: threadpool.c:38
gen_build_yaml.struct
def struct(**kwargs)
Definition: test/core/end2end/gen_build_yaml.py:30
python_utils.port_server.stderr
stderr
Definition: port_server.py:51
start
static uint64_t start
Definition: benchmark-pound.c:74
test::iterations
int64_t iterations
Definition: spinlock_test.cc:40
GPR_ASSERT
#define GPR_ASSERT(x)
Definition: include/grpc/impl/codegen/log.h:94
int64_t
signed __int64 int64_t
Definition: stdint-msvc2008.h:89
gpr_time_cmp
GPRAPI int gpr_time_cmp(gpr_timespec a, gpr_timespec b)
Definition: src/core/lib/gpr/time.cc:30
profile_analyzer.time_taken
time_taken
Definition: profile_analyzer.py:176
gpr_time_sub
GPRAPI gpr_timespec gpr_time_sub(gpr_timespec a, gpr_timespec b)
Definition: src/core/lib/gpr/time.cc:168
test
static void test(const char *name, void(*body)(void *m), int timeout_s, int incr_step)
Definition: spinlock_test.cc:90
setup.v
v
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
test::mu
gpr_spinlock mu
Definition: spinlock_test.cc:44
test::incr_step
int incr_step
Definition: spinlock_test.cc:42
arg
Definition: cmdline.cc:40
gpr_spinlock_unlock
#define gpr_spinlock_unlock(lock)
Definition: src/core/lib/gpr/spinlock.h:41
gpr_now
GPRAPI gpr_timespec gpr_now(gpr_clock_type clock)
gpr_spinlock_trylock
#define gpr_spinlock_trylock(lock)
Definition: src/core/lib/gpr/spinlock.h:40
main
int main(int argc, char *argv[])
Definition: spinlock_test.cc:151
test_config.h
test_create_threads
static void test_create_threads(struct test *m, void(*body)(void *arg))
Definition: spinlock_test.cc:68
gpr_time_add
GPRAPI gpr_timespec gpr_time_add(gpr_timespec a, gpr_timespec b)
Definition: src/core/lib/gpr/time.cc:135
gpr_time_from_micros
GPRAPI gpr_timespec gpr_time_from_micros(int64_t us, gpr_clock_type clock_type)
Definition: src/core/lib/gpr/time.cc:115
alloc.h
grpc::testing::TestEnvironment
Definition: test/core/util/test_config.h:54
thd.h
grpc_core::Thread
Definition: thd.h:43
test::threads
grpc_core::Thread * threads
Definition: spinlock_test.cc:38
test::thread_count
int thread_count
Definition: spinlock_test.cc:37
spinlock.h
gpr_timespec
Definition: gpr_types.h:50
test_wait
static void test_wait(struct test *m)
Definition: spinlock_test.cc:77
GPR_CLOCK_REALTIME
@ GPR_CLOCK_REALTIME
Definition: gpr_types.h:39
regress.m
m
Definition: regress/regress.py:25
sync.h
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
test_new
static struct test * test_new(int threads, int64_t iterations, int incr_step)
Definition: spinlock_test.cc:48


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:01:20