thd_windows.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2015 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 /* Windows implementation for gpr threads. */
20 
22 
23 #ifdef GPR_WINDOWS
24 
25 #include <string.h>
26 
27 #include <grpc/support/alloc.h>
28 #include <grpc/support/log.h>
29 #include <grpc/support/sync.h>
30 #include <grpc/support/thd_id.h>
31 #include <grpc/support/time.h>
32 
33 #include "src/core/lib/gpr/tls.h"
35 #include "src/core/lib/gprpp/thd.h"
36 
37 namespace {
38 class ThreadInternalsWindows;
39 struct thd_info {
40  ThreadInternalsWindows* thread;
41  void (*body)(void* arg); /* body of a thread */
42  void* arg; /* argument to a thread */
43  HANDLE join_event; /* the join event */
44  bool joinable; /* whether it is joinable */
45 };
46 
47 GPR_THREAD_LOCAL(struct thd_info*) g_thd_info;
48 
49 class ThreadInternalsWindows
51  public:
52  ThreadInternalsWindows(void (*thd_body)(void* arg), void* arg, bool* success,
54  : started_(false) {
55  gpr_mu_init(&mu_);
56  gpr_cv_init(&ready_);
57 
58  HANDLE handle;
59  info_ = (struct thd_info*)gpr_malloc(sizeof(*info_));
60  info_->thread = this;
61  info_->body = thd_body;
62  info_->arg = arg;
63  info_->join_event = nullptr;
64  info_->joinable = options.joinable();
65  if (info_->joinable) {
66  info_->join_event = CreateEvent(nullptr, FALSE, FALSE, nullptr);
67  if (info_->join_event == nullptr) {
68  gpr_free(info_);
69  *success = false;
70  return;
71  }
72  }
73 
74  if (options.stack_size() != 0) {
75  // Windows will round up the given stack_size value to nearest page.
76  handle = CreateThread(nullptr, options.stack_size(), thread_body, info_,
77  0, nullptr);
78  } else {
79  handle = CreateThread(nullptr, 64 * 1024, thread_body, info_, 0, nullptr);
80  }
81 
82  if (handle == nullptr) {
83  destroy_thread();
84  *success = false;
85  } else {
86  CloseHandle(handle);
87  *success = true;
88  }
89  }
90 
91  ~ThreadInternalsWindows() override {
93  gpr_cv_destroy(&ready_);
94  }
95 
96  void Start() override {
97  gpr_mu_lock(&mu_);
98  started_ = true;
99  gpr_cv_signal(&ready_);
100  gpr_mu_unlock(&mu_);
101  }
102 
103  void Join() override {
104  DWORD ret = WaitForSingleObject(info_->join_event, INFINITE);
105  GPR_ASSERT(ret == WAIT_OBJECT_0);
106  destroy_thread();
107  }
108 
109  private:
110  static DWORD WINAPI thread_body(void* v) {
111  g_thd_info = static_cast<thd_info*>(v);
112  gpr_mu_lock(&g_thd_info->thread->mu_);
113  while (!g_thd_info->thread->started_) {
114  gpr_cv_wait(&g_thd_info->thread->ready_, &g_thd_info->thread->mu_,
116  }
117  gpr_mu_unlock(&g_thd_info->thread->mu_);
118  if (!g_thd_info->joinable) {
119  delete g_thd_info->thread;
120  g_thd_info->thread = nullptr;
121  }
122  g_thd_info->body(g_thd_info->arg);
123  if (g_thd_info->joinable) {
124  BOOL ret = SetEvent(g_thd_info->join_event);
125  GPR_ASSERT(ret);
126  } else {
127  gpr_free(g_thd_info);
128  }
129  return 0;
130  }
131 
132  void destroy_thread() {
133  if (info_ != nullptr && info_->joinable) {
134  CloseHandle(info_->join_event);
135  }
136  gpr_free(info_);
137  }
138 
139  gpr_mu mu_;
140  gpr_cv ready_;
141  bool started_;
142  thd_info* info_;
143 };
144 
145 } // namespace
146 
147 namespace grpc_core {
148 
149 Thread::Thread(const char* thd_name, void (*thd_body)(void* arg), void* arg,
150  bool* success, const Options& options)
151  : options_(options) {
152  bool outcome = false;
153  impl_ = new ThreadInternalsWindows(thd_body, arg, &outcome, options);
154  if (outcome) {
155  state_ = ALIVE;
156  } else {
157  state_ = FAILED;
158  delete impl_;
159  impl_ = nullptr;
160  }
161 
162  if (success != nullptr) {
163  *success = outcome;
164  }
165 }
166 
167 } // namespace grpc_core
168 
170  return reinterpret_cast<gpr_thd_id>(g_thd_info);
171 }
172 
173 #endif /* GPR_WINDOWS */
gpr_cv_signal
GPRAPI void gpr_cv_signal(gpr_cv *cv)
gpr_mu_unlock
GPRAPI void gpr_mu_unlock(gpr_mu *mu)
log.h
false
#define false
Definition: setup_once.h:323
grpc_core
Definition: call_metric_recorder.h:31
gpr_cv
pthread_cond_t gpr_cv
Definition: impl/codegen/sync_posix.h:48
string.h
options
double_dict options[]
Definition: capstone_test.c:55
grpc_core::internal::ThreadInternalsInterface
Base class for platform-specific thread-state.
Definition: thd.h:34
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
gpr_inf_future
GPRAPI gpr_timespec gpr_inf_future(gpr_clock_type type)
Definition: src/core/lib/gpr/time.cc:55
FAILED
@ FAILED
Definition: alts_tsi_handshaker_test.cc:85
thd_id.h
time.h
BOOL
int BOOL
Definition: undname.c:46
mu_
Mutex mu_
Definition: oob_backend_metric.cc:115
info_
experimental::ClientRpcInfo * info_
Definition: client_interceptors_end2end_test.cc:169
memory.h
gpr_thd_id
uintptr_t gpr_thd_id
Definition: thd_id.h:35
gpr_mu_destroy
GPRAPI void gpr_mu_destroy(gpr_mu *mu)
gpr_thd_currentid
GPRAPI gpr_thd_id gpr_thd_currentid(void)
GPR_ASSERT
#define GPR_ASSERT(x)
Definition: include/grpc/impl/codegen/log.h:94
gpr_cv_destroy
GPRAPI void gpr_cv_destroy(gpr_cv *cv)
impl_
std::shared_ptr< ExternalConnectionAcceptorImpl > impl_
Definition: external_connection_acceptor_impl.cc:43
gpr_mu_init
GPRAPI void gpr_mu_init(gpr_mu *mu)
setup.v
v
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
started_
bool started_
Definition: xds_cluster_impl.cc:357
arg
Definition: cmdline.cc:40
gpr_cv_wait
GPRAPI int gpr_cv_wait(gpr_cv *cv, gpr_mu *mu, gpr_timespec abs_deadline)
grpc_core::Thread::Thread
Thread()
Definition: thd.h:78
GPR_CLOCK_MONOTONIC
@ GPR_CLOCK_MONOTONIC
Definition: gpr_types.h:36
gpr_mu_lock
GPRAPI void gpr_mu_lock(gpr_mu *mu)
grpc_core::promise_detail::Join
BasicJoin< JoinTraits, Promises... > Join
Definition: join.h:42
GPR_THREAD_LOCAL
#define GPR_THREAD_LOCAL(type)
Definition: tls.h:151
grpc_core::Thread::Options
Definition: thd.h:45
FALSE
const BOOL FALSE
Definition: undname.c:47
options_
DebugStringOptions options_
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.cc:2390
gpr_mu
pthread_mutex_t gpr_mu
Definition: impl/codegen/sync_posix.h:47
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
alloc.h
thd.h
arg
struct arg arg
tls.h
state_
grpc_connectivity_state state_
Definition: channel_connectivity.cc:213
handle
static csh handle
Definition: test_arm_regression.c:16
sync.h
thread
static uv_thread_t thread
Definition: test-async-null-cb.c:29
gpr_cv_init
GPRAPI void gpr_cv_init(gpr_cv *cv)
port_platform.h


grpc
Author(s):
autogenerated on Fri May 16 2025 03:00:35