grpc 1.0.0.pre1 → 1.0.0.pre2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of grpc might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Makefile +1 -37
- data/include/grpc/impl/codegen/compression_types.h +16 -1
- data/include/grpc/impl/codegen/grpc_types.h +23 -15
- data/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c +4 -2
- data/src/core/ext/transport/chttp2/transport/chttp2_plugin.c +3 -0
- data/src/core/ext/transport/chttp2/transport/chttp2_transport.c +305 -64
- data/src/core/ext/transport/chttp2/transport/internal.h +46 -19
- data/src/core/ext/transport/chttp2/transport/parsing.c +6 -5
- data/src/core/ext/transport/chttp2/transport/stream_lists.c +11 -9
- data/src/core/ext/transport/chttp2/transport/writing.c +13 -3
- data/src/core/lib/iomgr/endpoint.c +4 -0
- data/src/core/lib/iomgr/endpoint.h +4 -0
- data/src/core/lib/iomgr/ev_epoll_linux.c +161 -116
- data/src/core/lib/iomgr/ev_poll_and_epoll_posix.c +3 -0
- data/src/core/lib/iomgr/ev_poll_posix.c +3 -0
- data/src/core/lib/iomgr/ev_posix.c +4 -0
- data/src/core/lib/iomgr/ev_posix.h +4 -0
- data/src/core/lib/iomgr/exec_ctx.c +7 -3
- data/src/core/lib/iomgr/exec_ctx.h +5 -1
- data/src/core/lib/iomgr/iomgr.c +3 -0
- data/src/core/lib/iomgr/network_status_tracker.c +9 -6
- data/src/core/lib/iomgr/network_status_tracker.h +4 -0
- data/src/core/lib/iomgr/tcp_posix.c +14 -4
- data/src/core/lib/iomgr/tcp_server_posix.c +2 -1
- data/src/core/lib/iomgr/tcp_windows.c +10 -3
- data/src/core/lib/iomgr/workqueue.h +25 -14
- data/src/core/lib/iomgr/workqueue_posix.c +1 -7
- data/src/core/lib/iomgr/workqueue_posix.h +5 -0
- data/src/core/lib/iomgr/workqueue_windows.c +22 -0
- data/src/core/lib/security/transport/secure_endpoint.c +13 -5
- data/src/core/lib/support/log.c +10 -9
- data/src/core/lib/surface/server.c +45 -31
- data/src/core/lib/surface/version.c +1 -1
- data/src/core/lib/transport/connectivity_state.c +3 -0
- data/src/ruby/bin/math_client.rb +1 -1
- data/src/ruby/bin/{math.rb → math_pb.rb} +0 -0
- data/src/ruby/bin/math_server.rb +1 -1
- data/src/ruby/bin/{math_services.rb → math_services_pb.rb} +4 -4
- data/src/ruby/lib/grpc/version.rb +1 -1
- data/src/ruby/pb/grpc/health/checker.rb +1 -1
- data/src/ruby/pb/grpc/health/v1/{health.rb → health_pb.rb} +0 -0
- data/src/ruby/pb/grpc/health/v1/{health_services.rb → health_services_pb.rb} +1 -1
- data/src/ruby/pb/grpc/testing/duplicate/{echo_duplicate_services.rb → echo_duplicate_services_pb.rb} +2 -2
- data/src/ruby/pb/grpc/testing/{metrics.rb → metrics_pb.rb} +1 -1
- data/src/ruby/pb/grpc/testing/{metrics_services.rb → metrics_services_pb.rb} +2 -2
- data/src/ruby/pb/src/proto/grpc/testing/{empty.rb → empty_pb.rb} +0 -0
- data/src/ruby/pb/src/proto/grpc/testing/{messages.rb → messages_pb.rb} +8 -10
- data/src/ruby/pb/src/proto/grpc/testing/{test.rb → test_pb.rb} +2 -2
- data/src/ruby/pb/src/proto/grpc/testing/{test_services.rb → test_services_pb.rb} +1 -1
- data/src/ruby/pb/test/client.rb +3 -3
- data/src/ruby/pb/test/server.rb +3 -3
- data/src/ruby/spec/pb/duplicate/codegen_spec.rb +2 -2
- data/src/ruby/spec/pb/health/checker_spec.rb +4 -4
- metadata +15 -19
- data/src/ruby/pb/test/proto/empty.rb +0 -15
- data/src/ruby/pb/test/proto/messages.rb +0 -80
- data/src/ruby/pb/test/proto/test.rb +0 -14
- data/src/ruby/pb/test/proto/test_services.rb +0 -64
@@ -305,6 +305,22 @@ typedef struct grpc_chttp2_executor_action_header {
|
|
305
305
|
void *arg;
|
306
306
|
} grpc_chttp2_executor_action_header;
|
307
307
|
|
308
|
+
typedef enum {
|
309
|
+
/** no writing activity */
|
310
|
+
GRPC_CHTTP2_WRITING_INACTIVE,
|
311
|
+
/** write has been requested, but not scheduled yet */
|
312
|
+
GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER,
|
313
|
+
GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER,
|
314
|
+
/** write has been requested and scheduled against the workqueue */
|
315
|
+
GRPC_CHTTP2_WRITE_SCHEDULED,
|
316
|
+
/** write has been initiated after being reaped from the workqueue */
|
317
|
+
GRPC_CHTTP2_WRITING,
|
318
|
+
/** write has been initiated, AND another write needs to be started once it's
|
319
|
+
done */
|
320
|
+
GRPC_CHTTP2_WRITING_STALE_WITH_POLLER,
|
321
|
+
GRPC_CHTTP2_WRITING_STALE_NO_POLLER,
|
322
|
+
} grpc_chttp2_write_state;
|
323
|
+
|
308
324
|
struct grpc_chttp2_transport {
|
309
325
|
grpc_transport base; /* must be first */
|
310
326
|
gpr_refcount refs;
|
@@ -319,10 +335,10 @@ struct grpc_chttp2_transport {
|
|
319
335
|
|
320
336
|
/** is a thread currently in the global lock */
|
321
337
|
bool global_active;
|
322
|
-
/** is a thread currently writing */
|
323
|
-
bool writing_active;
|
324
338
|
/** is a thread currently parsing */
|
325
339
|
bool parsing_active;
|
340
|
+
/** write execution state of the transport */
|
341
|
+
grpc_chttp2_write_state write_state;
|
326
342
|
|
327
343
|
grpc_chttp2_executor_action_header *pending_actions_head;
|
328
344
|
grpc_chttp2_executor_action_header *pending_actions_tail;
|
@@ -342,7 +358,8 @@ struct grpc_chttp2_transport {
|
|
342
358
|
/** global state for reading/writing */
|
343
359
|
grpc_chttp2_transport_global global;
|
344
360
|
/** state only accessible by the chain of execution that
|
345
|
-
set
|
361
|
+
set writing_state >= GRPC_WRITING, and only by the writing closure
|
362
|
+
chain. */
|
346
363
|
grpc_chttp2_transport_writing writing;
|
347
364
|
/** state only accessible by the chain of execution that
|
348
365
|
set parsing_active=1 */
|
@@ -363,6 +380,8 @@ struct grpc_chttp2_transport {
|
|
363
380
|
grpc_closure reading_action;
|
364
381
|
/** closure to actually do parsing */
|
365
382
|
grpc_closure parsing_action;
|
383
|
+
/** closure to initiate writing */
|
384
|
+
grpc_closure initiate_writing;
|
366
385
|
|
367
386
|
/** incoming read bytes */
|
368
387
|
gpr_slice_buffer read_buffer;
|
@@ -436,8 +455,10 @@ typedef struct {
|
|
436
455
|
bool seen_error;
|
437
456
|
bool exceeded_metadata_size;
|
438
457
|
|
439
|
-
/** the error that resulted in this stream being
|
440
|
-
grpc_error *
|
458
|
+
/** the error that resulted in this stream being read-closed */
|
459
|
+
grpc_error *read_closed_error;
|
460
|
+
/** the error that resulted in this stream being write-closed */
|
461
|
+
grpc_error *write_closed_error;
|
441
462
|
|
442
463
|
bool published_initial_metadata;
|
443
464
|
bool published_trailing_metadata;
|
@@ -514,15 +535,20 @@ struct grpc_chttp2_stream {
|
|
514
535
|
};
|
515
536
|
|
516
537
|
/** Transport writing call flow:
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
538
|
+
grpc_chttp2_initiate_write() is called anywhere that we know bytes need to
|
539
|
+
go out on the wire.
|
540
|
+
If no other write has been started, a task is enqueued onto our workqueue.
|
541
|
+
When that task executes, it obtains the global lock, and gathers the data
|
542
|
+
to write.
|
543
|
+
The global lock is dropped and we do the syscall to write.
|
544
|
+
After writing, a follow-up check is made to see if another round of writing
|
545
|
+
should be performed.
|
546
|
+
|
547
|
+
The actual call chain is documented in the implementation of this function.
|
548
|
+
*/
|
549
|
+
void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx,
|
550
|
+
grpc_chttp2_transport_global *transport_global,
|
551
|
+
bool covered_by_poller, const char *reason);
|
526
552
|
|
527
553
|
/** Someone is unlocking the transport mutex: check to see if writes
|
528
554
|
are required, and schedule them if so */
|
@@ -610,9 +636,8 @@ int grpc_chttp2_list_pop_check_read_ops(
|
|
610
636
|
void grpc_chttp2_list_add_writing_stalled_by_transport(
|
611
637
|
grpc_chttp2_transport_writing *transport_writing,
|
612
638
|
grpc_chttp2_stream_writing *stream_writing);
|
613
|
-
|
614
|
-
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing
|
615
|
-
bool is_window_available);
|
639
|
+
bool grpc_chttp2_list_flush_writing_stalled_by_transport(
|
640
|
+
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing);
|
616
641
|
|
617
642
|
void grpc_chttp2_list_add_stalled_by_transport(
|
618
643
|
grpc_chttp2_transport_writing *transport_writing,
|
@@ -822,7 +847,9 @@ void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx,
|
|
822
847
|
|
823
848
|
/** add a ref to the stream and add it to the writable list;
|
824
849
|
ref will be dropped in writing.c */
|
825
|
-
void grpc_chttp2_become_writable(
|
826
|
-
|
850
|
+
void grpc_chttp2_become_writable(grpc_exec_ctx *exec_ctx,
|
851
|
+
grpc_chttp2_transport_global *transport_global,
|
852
|
+
grpc_chttp2_stream_global *stream_global,
|
853
|
+
bool covered_by_poller, const char *reason);
|
827
854
|
|
828
855
|
#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_INTERNAL_H */
|
@@ -154,10 +154,8 @@ void grpc_chttp2_publish_reads(
|
|
154
154
|
transport_parsing, outgoing_window);
|
155
155
|
is_zero = transport_global->outgoing_window <= 0;
|
156
156
|
if (was_zero && !is_zero) {
|
157
|
-
|
158
|
-
|
159
|
-
grpc_chttp2_become_writable(transport_global, stream_global);
|
160
|
-
}
|
157
|
+
grpc_chttp2_initiate_write(exec_ctx, transport_global, false,
|
158
|
+
"new_global_flow_control");
|
161
159
|
}
|
162
160
|
|
163
161
|
if (transport_parsing->incoming_window <
|
@@ -168,6 +166,8 @@ void grpc_chttp2_publish_reads(
|
|
168
166
|
announce_incoming_window, announce_bytes);
|
169
167
|
GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", transport_parsing,
|
170
168
|
incoming_window, announce_bytes);
|
169
|
+
grpc_chttp2_initiate_write(exec_ctx, transport_global, false,
|
170
|
+
"global incoming window");
|
171
171
|
}
|
172
172
|
|
173
173
|
/* for each stream that saw an update, fixup global state */
|
@@ -190,7 +190,8 @@ void grpc_chttp2_publish_reads(
|
|
190
190
|
outgoing_window);
|
191
191
|
is_zero = stream_global->outgoing_window <= 0;
|
192
192
|
if (was_zero && !is_zero) {
|
193
|
-
grpc_chttp2_become_writable(transport_global, stream_global
|
193
|
+
grpc_chttp2_become_writable(exec_ctx, transport_global, stream_global,
|
194
|
+
false, "stream.read_flow_control");
|
194
195
|
}
|
195
196
|
|
196
197
|
stream_global->max_recv_bytes -= (uint32_t)GPR_MIN(
|
@@ -329,6 +329,7 @@ void grpc_chttp2_list_add_writing_stalled_by_transport(
|
|
329
329
|
grpc_chttp2_transport_writing *transport_writing,
|
330
330
|
grpc_chttp2_stream_writing *stream_writing) {
|
331
331
|
grpc_chttp2_stream *stream = STREAM_FROM_WRITING(stream_writing);
|
332
|
+
gpr_log(GPR_DEBUG, "writing stalled %d", stream->global.id);
|
332
333
|
if (!stream->included[GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT]) {
|
333
334
|
GRPC_CHTTP2_STREAM_REF(&stream->global, "chttp2_writing_stalled");
|
334
335
|
}
|
@@ -336,27 +337,28 @@ void grpc_chttp2_list_add_writing_stalled_by_transport(
|
|
336
337
|
GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT);
|
337
338
|
}
|
338
339
|
|
339
|
-
|
340
|
-
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing
|
341
|
-
bool is_window_available) {
|
340
|
+
bool grpc_chttp2_list_flush_writing_stalled_by_transport(
|
341
|
+
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing) {
|
342
342
|
grpc_chttp2_stream *stream;
|
343
|
+
bool out = false;
|
343
344
|
grpc_chttp2_transport *transport = TRANSPORT_FROM_WRITING(transport_writing);
|
344
345
|
while (stream_list_pop(transport, &stream,
|
345
346
|
GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT)) {
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
&stream->writing);
|
351
|
-
}
|
347
|
+
gpr_log(GPR_DEBUG, "move %d from writing stalled to just stalled",
|
348
|
+
stream->global.id);
|
349
|
+
grpc_chttp2_list_add_stalled_by_transport(transport_writing,
|
350
|
+
&stream->writing);
|
352
351
|
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, &stream->global,
|
353
352
|
"chttp2_writing_stalled");
|
353
|
+
out = true;
|
354
354
|
}
|
355
|
+
return out;
|
355
356
|
}
|
356
357
|
|
357
358
|
void grpc_chttp2_list_add_stalled_by_transport(
|
358
359
|
grpc_chttp2_transport_writing *transport_writing,
|
359
360
|
grpc_chttp2_stream_writing *stream_writing) {
|
361
|
+
gpr_log(GPR_DEBUG, "stalled %d", stream_writing->id);
|
360
362
|
stream_list_add(TRANSPORT_FROM_WRITING(transport_writing),
|
361
363
|
STREAM_FROM_WRITING(stream_writing),
|
362
364
|
GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
|
@@ -75,9 +75,13 @@ int grpc_chttp2_unlocking_check_writes(
|
|
75
75
|
|
76
76
|
GRPC_CHTTP2_FLOW_MOVE_TRANSPORT("write", transport_writing, outgoing_window,
|
77
77
|
transport_global, outgoing_window);
|
78
|
-
|
79
|
-
|
80
|
-
|
78
|
+
if (transport_writing->outgoing_window > 0) {
|
79
|
+
while (grpc_chttp2_list_pop_stalled_by_transport(transport_global,
|
80
|
+
&stream_global)) {
|
81
|
+
grpc_chttp2_become_writable(exec_ctx, transport_global, stream_global,
|
82
|
+
false, "transport.read_flow_control");
|
83
|
+
}
|
84
|
+
}
|
81
85
|
|
82
86
|
/* for each grpc_chttp2_stream that's become writable, frame it's data
|
83
87
|
(according to available window sizes) and add to the output buffer */
|
@@ -331,6 +335,12 @@ void grpc_chttp2_cleanup_writing(
|
|
331
335
|
grpc_chttp2_stream_writing *stream_writing;
|
332
336
|
grpc_chttp2_stream_global *stream_global;
|
333
337
|
|
338
|
+
if (grpc_chttp2_list_flush_writing_stalled_by_transport(exec_ctx,
|
339
|
+
transport_writing)) {
|
340
|
+
grpc_chttp2_initiate_write(exec_ctx, transport_global, false,
|
341
|
+
"resume_stalled_stream");
|
342
|
+
}
|
343
|
+
|
334
344
|
while (grpc_chttp2_list_pop_written_stream(
|
335
345
|
transport_global, transport_writing, &stream_global, &stream_writing)) {
|
336
346
|
if (stream_writing->sent_initial_metadata) {
|
@@ -65,3 +65,7 @@ void grpc_endpoint_destroy(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep) {
|
|
65
65
|
char* grpc_endpoint_get_peer(grpc_endpoint* ep) {
|
66
66
|
return ep->vtable->get_peer(ep);
|
67
67
|
}
|
68
|
+
|
69
|
+
grpc_workqueue* grpc_endpoint_get_workqueue(grpc_endpoint* ep) {
|
70
|
+
return ep->vtable->get_workqueue(ep);
|
71
|
+
}
|
@@ -51,6 +51,7 @@ struct grpc_endpoint_vtable {
|
|
51
51
|
gpr_slice_buffer *slices, grpc_closure *cb);
|
52
52
|
void (*write)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
|
53
53
|
gpr_slice_buffer *slices, grpc_closure *cb);
|
54
|
+
grpc_workqueue *(*get_workqueue)(grpc_endpoint *ep);
|
54
55
|
void (*add_to_pollset)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
|
55
56
|
grpc_pollset *pollset);
|
56
57
|
void (*add_to_pollset_set)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
|
@@ -69,6 +70,9 @@ void grpc_endpoint_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
|
|
69
70
|
|
70
71
|
char *grpc_endpoint_get_peer(grpc_endpoint *ep);
|
71
72
|
|
73
|
+
/* Retrieve a reference to the workqueue associated with this endpoint */
|
74
|
+
grpc_workqueue *grpc_endpoint_get_workqueue(grpc_endpoint *ep);
|
75
|
+
|
72
76
|
/* Write slices out to the socket.
|
73
77
|
|
74
78
|
If the connection is ready for more data after the end of the call, it
|
@@ -57,6 +57,7 @@
|
|
57
57
|
#include "src/core/lib/iomgr/ev_posix.h"
|
58
58
|
#include "src/core/lib/iomgr/iomgr_internal.h"
|
59
59
|
#include "src/core/lib/iomgr/wakeup_fd_posix.h"
|
60
|
+
#include "src/core/lib/iomgr/workqueue.h"
|
60
61
|
#include "src/core/lib/profiling/timers.h"
|
61
62
|
#include "src/core/lib/support/block_annotate.h"
|
62
63
|
|
@@ -113,9 +114,7 @@ struct grpc_fd {
|
|
113
114
|
grpc_closure *read_closure;
|
114
115
|
grpc_closure *write_closure;
|
115
116
|
|
116
|
-
/* The polling island to which this fd belongs to
|
117
|
-
the field */
|
118
|
-
gpr_mu pi_mu;
|
117
|
+
/* The polling island to which this fd belongs to (protected by mu) */
|
119
118
|
struct polling_island *polling_island;
|
120
119
|
|
121
120
|
struct grpc_fd *freelist_next;
|
@@ -152,16 +151,17 @@ static void fd_global_shutdown(void);
|
|
152
151
|
* Polling island Declarations
|
153
152
|
*/
|
154
153
|
|
155
|
-
|
154
|
+
//#define GRPC_PI_REF_COUNT_DEBUG
|
156
155
|
#ifdef GRPC_PI_REF_COUNT_DEBUG
|
157
156
|
|
158
157
|
#define PI_ADD_REF(p, r) pi_add_ref_dbg((p), (r), __FILE__, __LINE__)
|
159
|
-
#define PI_UNREF(
|
158
|
+
#define PI_UNREF(exec_ctx, p, r) \
|
159
|
+
pi_unref_dbg((exec_ctx), (p), (r), __FILE__, __LINE__)
|
160
160
|
|
161
161
|
#else /* defined(GRPC_PI_REF_COUNT_DEBUG) */
|
162
162
|
|
163
163
|
#define PI_ADD_REF(p, r) pi_add_ref((p))
|
164
|
-
#define PI_UNREF(p, r) pi_unref((p))
|
164
|
+
#define PI_UNREF(exec_ctx, p, r) pi_unref((exec_ctx), (p))
|
165
165
|
|
166
166
|
#endif /* !defined(GPRC_PI_REF_COUNT_DEBUG) */
|
167
167
|
|
@@ -172,7 +172,7 @@ typedef struct polling_island {
|
|
172
172
|
Once the ref count becomes zero, this structure is destroyed which means
|
173
173
|
we should ensure that there is never a scenario where a PI_ADD_REF() is
|
174
174
|
racing with a PI_UNREF() that just made the ref_count zero. */
|
175
|
-
|
175
|
+
gpr_atm ref_count;
|
176
176
|
|
177
177
|
/* Pointer to the polling_island this merged into.
|
178
178
|
* merged_to value is only set once in polling_island's lifetime (and that too
|
@@ -184,6 +184,9 @@ typedef struct polling_island {
|
|
184
184
|
* (except mu and ref_count) are invalid and must be ignored. */
|
185
185
|
gpr_atm merged_to;
|
186
186
|
|
187
|
+
/* The workqueue associated with this polling island */
|
188
|
+
grpc_workqueue *workqueue;
|
189
|
+
|
187
190
|
/* The fd of the underlying epoll set */
|
188
191
|
int epoll_fd;
|
189
192
|
|
@@ -191,11 +194,6 @@ typedef struct polling_island {
|
|
191
194
|
size_t fd_cnt;
|
192
195
|
size_t fd_capacity;
|
193
196
|
grpc_fd **fds;
|
194
|
-
|
195
|
-
/* Polling islands that are no longer needed are kept in a freelist so that
|
196
|
-
they can be reused. This field points to the next polling island in the
|
197
|
-
free list */
|
198
|
-
struct polling_island *next_free;
|
199
197
|
} polling_island;
|
200
198
|
|
201
199
|
/*******************************************************************************
|
@@ -253,13 +251,14 @@ struct grpc_pollset_set {
|
|
253
251
|
* Common helpers
|
254
252
|
*/
|
255
253
|
|
256
|
-
static
|
254
|
+
static bool append_error(grpc_error **composite, grpc_error *error,
|
257
255
|
const char *desc) {
|
258
|
-
if (error == GRPC_ERROR_NONE) return;
|
256
|
+
if (error == GRPC_ERROR_NONE) return true;
|
259
257
|
if (*composite == GRPC_ERROR_NONE) {
|
260
258
|
*composite = GRPC_ERROR_CREATE(desc);
|
261
259
|
}
|
262
260
|
*composite = grpc_error_add_child(*composite, error);
|
261
|
+
return false;
|
263
262
|
}
|
264
263
|
|
265
264
|
/*******************************************************************************
|
@@ -275,11 +274,8 @@ static void append_error(grpc_error **composite, grpc_error *error,
|
|
275
274
|
threads that woke up MUST NOT call grpc_wakeup_fd_consume_wakeup() */
|
276
275
|
static grpc_wakeup_fd polling_island_wakeup_fd;
|
277
276
|
|
278
|
-
/*
|
279
|
-
static
|
280
|
-
static polling_island *g_pi_freelist = NULL;
|
281
|
-
|
282
|
-
static void polling_island_delete(); /* Forward declaration */
|
277
|
+
/* Forward declaration */
|
278
|
+
static void polling_island_delete(grpc_exec_ctx *exec_ctx, polling_island *pi);
|
283
279
|
|
284
280
|
#ifdef GRPC_TSAN
|
285
281
|
/* Currently TSAN may incorrectly flag data races between epoll_ctl and
|
@@ -293,28 +289,35 @@ gpr_atm g_epoll_sync;
|
|
293
289
|
#endif /* defined(GRPC_TSAN) */
|
294
290
|
|
295
291
|
#ifdef GRPC_PI_REF_COUNT_DEBUG
|
296
|
-
void pi_add_ref(polling_island *pi);
|
297
|
-
void pi_unref(polling_island *pi);
|
292
|
+
static void pi_add_ref(polling_island *pi);
|
293
|
+
static void pi_unref(grpc_exec_ctx *exec_ctx, polling_island *pi);
|
298
294
|
|
299
|
-
void pi_add_ref_dbg(polling_island *pi, char *reason, char *file,
|
300
|
-
|
295
|
+
static void pi_add_ref_dbg(polling_island *pi, char *reason, char *file,
|
296
|
+
int line) {
|
297
|
+
long old_cnt = gpr_atm_acq_load(&pi->ref_count);
|
301
298
|
pi_add_ref(pi);
|
302
299
|
gpr_log(GPR_DEBUG, "Add ref pi: %p, old: %ld -> new:%ld (%s) - (%s, %d)",
|
303
300
|
(void *)pi, old_cnt, old_cnt + 1, reason, file, line);
|
304
301
|
}
|
305
302
|
|
306
|
-
void pi_unref_dbg(
|
307
|
-
|
308
|
-
|
303
|
+
static void pi_unref_dbg(grpc_exec_ctx *exec_ctx, polling_island *pi,
|
304
|
+
char *reason, char *file, int line) {
|
305
|
+
long old_cnt = gpr_atm_acq_load(&pi->ref_count);
|
306
|
+
pi_unref(exec_ctx, pi);
|
309
307
|
gpr_log(GPR_DEBUG, "Unref pi: %p, old:%ld -> new:%ld (%s) - (%s, %d)",
|
310
308
|
(void *)pi, old_cnt, (old_cnt - 1), reason, file, line);
|
311
309
|
}
|
312
310
|
#endif
|
313
311
|
|
314
|
-
void pi_add_ref(polling_island *pi) {
|
312
|
+
static void pi_add_ref(polling_island *pi) {
|
313
|
+
gpr_atm_no_barrier_fetch_add(&pi->ref_count, 1);
|
314
|
+
}
|
315
315
|
|
316
|
-
void pi_unref(polling_island *pi) {
|
317
|
-
/* If ref count went to
|
316
|
+
static void pi_unref(grpc_exec_ctx *exec_ctx, polling_island *pi) {
|
317
|
+
/* If ref count went to one, we're back to just the workqueue owning a ref.
|
318
|
+
Unref the workqueue to break the loop.
|
319
|
+
|
320
|
+
If ref count went to zero, delete the polling island.
|
318
321
|
Note that this deletion not be done under a lock. Once the ref count goes
|
319
322
|
to zero, we are guaranteed that no one else holds a reference to the
|
320
323
|
polling island (and that there is no racing pi_add_ref() call either).
|
@@ -322,12 +325,20 @@ void pi_unref(polling_island *pi) {
|
|
322
325
|
Also, if we are deleting the polling island and the merged_to field is
|
323
326
|
non-empty, we should remove a ref to the merged_to polling island
|
324
327
|
*/
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
328
|
+
switch (gpr_atm_full_fetch_add(&pi->ref_count, -1)) {
|
329
|
+
case 2: /* last external ref: the only one now owned is by the workqueue */
|
330
|
+
GRPC_WORKQUEUE_UNREF(exec_ctx, pi->workqueue, "polling_island");
|
331
|
+
break;
|
332
|
+
case 1: {
|
333
|
+
polling_island *next = (polling_island *)gpr_atm_acq_load(&pi->merged_to);
|
334
|
+
polling_island_delete(exec_ctx, pi);
|
335
|
+
if (next != NULL) {
|
336
|
+
PI_UNREF(exec_ctx, next, "pi_delete"); /* Recursive call */
|
337
|
+
}
|
338
|
+
break;
|
330
339
|
}
|
340
|
+
case 0:
|
341
|
+
GPR_UNREACHABLE_CODE(return );
|
331
342
|
}
|
332
343
|
}
|
333
344
|
|
@@ -462,69 +473,68 @@ static void polling_island_remove_fd_locked(polling_island *pi, grpc_fd *fd,
|
|
462
473
|
}
|
463
474
|
|
464
475
|
/* Might return NULL in case of an error */
|
465
|
-
static polling_island *polling_island_create(
|
476
|
+
static polling_island *polling_island_create(grpc_exec_ctx *exec_ctx,
|
477
|
+
grpc_fd *initial_fd,
|
466
478
|
grpc_error **error) {
|
467
479
|
polling_island *pi = NULL;
|
468
|
-
char *err_msg;
|
469
480
|
const char *err_desc = "polling_island_create";
|
470
481
|
|
471
|
-
|
472
|
-
gpr_mu_lock(&g_pi_freelist_mu);
|
473
|
-
if (g_pi_freelist != NULL) {
|
474
|
-
pi = g_pi_freelist;
|
475
|
-
g_pi_freelist = g_pi_freelist->next_free;
|
476
|
-
pi->next_free = NULL;
|
477
|
-
}
|
478
|
-
gpr_mu_unlock(&g_pi_freelist_mu);
|
482
|
+
*error = GRPC_ERROR_NONE;
|
479
483
|
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
}
|
484
|
+
pi = gpr_malloc(sizeof(*pi));
|
485
|
+
gpr_mu_init(&pi->mu);
|
486
|
+
pi->fd_cnt = 0;
|
487
|
+
pi->fd_capacity = 0;
|
488
|
+
pi->fds = NULL;
|
489
|
+
pi->epoll_fd = -1;
|
490
|
+
pi->workqueue = NULL;
|
488
491
|
|
489
|
-
|
492
|
+
gpr_atm_rel_store(&pi->ref_count, 0);
|
490
493
|
gpr_atm_rel_store(&pi->merged_to, (gpr_atm)NULL);
|
491
494
|
|
492
495
|
pi->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
|
493
496
|
|
494
497
|
if (pi->epoll_fd < 0) {
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
gpr_free(err_msg);
|
499
|
-
} else {
|
500
|
-
polling_island_add_wakeup_fd_locked(pi, &grpc_global_wakeup_fd, error);
|
501
|
-
pi->next_free = NULL;
|
498
|
+
append_error(error, GRPC_OS_ERROR(errno, "epoll_create1"), err_desc);
|
499
|
+
goto done;
|
500
|
+
}
|
502
501
|
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
502
|
+
polling_island_add_wakeup_fd_locked(pi, &grpc_global_wakeup_fd, error);
|
503
|
+
|
504
|
+
if (initial_fd != NULL) {
|
505
|
+
polling_island_add_fds_locked(pi, &initial_fd, 1, true, error);
|
506
|
+
}
|
507
|
+
|
508
|
+
if (append_error(error, grpc_workqueue_create(exec_ctx, &pi->workqueue),
|
509
|
+
err_desc) &&
|
510
|
+
*error == GRPC_ERROR_NONE) {
|
511
|
+
polling_island_add_fds_locked(pi, &pi->workqueue->wakeup_read_fd, 1, true,
|
512
|
+
error);
|
513
|
+
GPR_ASSERT(pi->workqueue->wakeup_read_fd->polling_island == NULL);
|
514
|
+
pi->workqueue->wakeup_read_fd->polling_island = pi;
|
515
|
+
PI_ADD_REF(pi, "fd");
|
511
516
|
}
|
512
517
|
|
518
|
+
done:
|
519
|
+
if (*error != GRPC_ERROR_NONE) {
|
520
|
+
if (pi->workqueue != NULL) {
|
521
|
+
GRPC_WORKQUEUE_UNREF(exec_ctx, pi->workqueue, "polling_island");
|
522
|
+
}
|
523
|
+
polling_island_delete(exec_ctx, pi);
|
524
|
+
pi = NULL;
|
525
|
+
}
|
513
526
|
return pi;
|
514
527
|
}
|
515
528
|
|
516
|
-
static void polling_island_delete(polling_island *pi) {
|
529
|
+
static void polling_island_delete(grpc_exec_ctx *exec_ctx, polling_island *pi) {
|
517
530
|
GPR_ASSERT(pi->fd_cnt == 0);
|
518
531
|
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
pi->
|
523
|
-
|
524
|
-
|
525
|
-
pi->next_free = g_pi_freelist;
|
526
|
-
g_pi_freelist = pi;
|
527
|
-
gpr_mu_unlock(&g_pi_freelist_mu);
|
532
|
+
if (pi->epoll_fd >= 0) {
|
533
|
+
close(pi->epoll_fd);
|
534
|
+
}
|
535
|
+
gpr_mu_destroy(&pi->mu);
|
536
|
+
gpr_free(pi->fds);
|
537
|
+
gpr_free(pi);
|
528
538
|
}
|
529
539
|
|
530
540
|
/* Attempts to gets the last polling island in the linked list (liked by the
|
@@ -704,9 +714,6 @@ static polling_island *polling_island_merge(polling_island *p,
|
|
704
714
|
static grpc_error *polling_island_global_init() {
|
705
715
|
grpc_error *error = GRPC_ERROR_NONE;
|
706
716
|
|
707
|
-
gpr_mu_init(&g_pi_freelist_mu);
|
708
|
-
g_pi_freelist = NULL;
|
709
|
-
|
710
717
|
error = grpc_wakeup_fd_init(&polling_island_wakeup_fd);
|
711
718
|
if (error == GRPC_ERROR_NONE) {
|
712
719
|
error = grpc_wakeup_fd_wakeup(&polling_island_wakeup_fd);
|
@@ -716,18 +723,6 @@ static grpc_error *polling_island_global_init() {
|
|
716
723
|
}
|
717
724
|
|
718
725
|
static void polling_island_global_shutdown() {
|
719
|
-
polling_island *next;
|
720
|
-
gpr_mu_lock(&g_pi_freelist_mu);
|
721
|
-
gpr_mu_unlock(&g_pi_freelist_mu);
|
722
|
-
while (g_pi_freelist != NULL) {
|
723
|
-
next = g_pi_freelist->next_free;
|
724
|
-
gpr_mu_destroy(&g_pi_freelist->mu);
|
725
|
-
gpr_free(g_pi_freelist->fds);
|
726
|
-
gpr_free(g_pi_freelist);
|
727
|
-
g_pi_freelist = next;
|
728
|
-
}
|
729
|
-
gpr_mu_destroy(&g_pi_freelist_mu);
|
730
|
-
|
731
726
|
grpc_wakeup_fd_destroy(&polling_island_wakeup_fd);
|
732
727
|
}
|
733
728
|
|
@@ -845,7 +840,6 @@ static grpc_fd *fd_create(int fd, const char *name) {
|
|
845
840
|
if (new_fd == NULL) {
|
846
841
|
new_fd = gpr_malloc(sizeof(grpc_fd));
|
847
842
|
gpr_mu_init(&new_fd->mu);
|
848
|
-
gpr_mu_init(&new_fd->pi_mu);
|
849
843
|
}
|
850
844
|
|
851
845
|
/* Note: It is not really needed to get the new_fd->mu lock here. If this is a
|
@@ -896,6 +890,7 @@ static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
|
|
896
890
|
const char *reason) {
|
897
891
|
bool is_fd_closed = false;
|
898
892
|
grpc_error *error = GRPC_ERROR_NONE;
|
893
|
+
polling_island *unref_pi = NULL;
|
899
894
|
|
900
895
|
gpr_mu_lock(&fd->mu);
|
901
896
|
fd->on_done_closure = on_done;
|
@@ -923,21 +918,26 @@ static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
|
|
923
918
|
- Unlock the latest polling island
|
924
919
|
- Set fd->polling_island to NULL (but remove the ref on the polling island
|
925
920
|
before doing this.) */
|
926
|
-
gpr_mu_lock(&fd->pi_mu);
|
927
921
|
if (fd->polling_island != NULL) {
|
928
922
|
polling_island *pi_latest = polling_island_lock(fd->polling_island);
|
929
923
|
polling_island_remove_fd_locked(pi_latest, fd, is_fd_closed, &error);
|
930
924
|
gpr_mu_unlock(&pi_latest->mu);
|
931
925
|
|
932
|
-
|
926
|
+
unref_pi = fd->polling_island;
|
933
927
|
fd->polling_island = NULL;
|
934
928
|
}
|
935
|
-
gpr_mu_unlock(&fd->pi_mu);
|
936
929
|
|
937
930
|
grpc_exec_ctx_sched(exec_ctx, fd->on_done_closure, error, NULL);
|
938
931
|
|
939
932
|
gpr_mu_unlock(&fd->mu);
|
940
933
|
UNREF_BY(fd, 2, reason); /* Drop the reference */
|
934
|
+
if (unref_pi != NULL) {
|
935
|
+
/* Unref stale polling island here, outside the fd lock above.
|
936
|
+
The polling island owns a workqueue which owns an fd, and unreffing
|
937
|
+
inside the lock can cause an eventual lock loop that makes TSAN very
|
938
|
+
unhappy. */
|
939
|
+
PI_UNREF(exec_ctx, unref_pi, "fd_orphan");
|
940
|
+
}
|
941
941
|
GRPC_LOG_IF_ERROR("fd_orphan", GRPC_ERROR_REF(error));
|
942
942
|
}
|
943
943
|
|
@@ -1037,6 +1037,17 @@ static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
|
|
1037
1037
|
gpr_mu_unlock(&fd->mu);
|
1038
1038
|
}
|
1039
1039
|
|
1040
|
+
static grpc_workqueue *fd_get_workqueue(grpc_fd *fd) {
|
1041
|
+
gpr_mu_lock(&fd->mu);
|
1042
|
+
grpc_workqueue *workqueue = NULL;
|
1043
|
+
if (fd->polling_island != NULL) {
|
1044
|
+
workqueue =
|
1045
|
+
GRPC_WORKQUEUE_REF(fd->polling_island->workqueue, "get_workqueue");
|
1046
|
+
}
|
1047
|
+
gpr_mu_unlock(&fd->mu);
|
1048
|
+
return workqueue;
|
1049
|
+
}
|
1050
|
+
|
1040
1051
|
/*******************************************************************************
|
1041
1052
|
* Pollset Definitions
|
1042
1053
|
*/
|
@@ -1227,9 +1238,10 @@ static void fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
|
|
1227
1238
|
gpr_mu_unlock(&fd->mu);
|
1228
1239
|
}
|
1229
1240
|
|
1230
|
-
static void pollset_release_polling_island(
|
1241
|
+
static void pollset_release_polling_island(grpc_exec_ctx *exec_ctx,
|
1242
|
+
grpc_pollset *ps, char *reason) {
|
1231
1243
|
if (ps->polling_island != NULL) {
|
1232
|
-
PI_UNREF(ps->polling_island, reason);
|
1244
|
+
PI_UNREF(exec_ctx, ps->polling_island, reason);
|
1233
1245
|
}
|
1234
1246
|
ps->polling_island = NULL;
|
1235
1247
|
}
|
@@ -1242,7 +1254,7 @@ static void finish_shutdown_locked(grpc_exec_ctx *exec_ctx,
|
|
1242
1254
|
pollset->finish_shutdown_called = true;
|
1243
1255
|
|
1244
1256
|
/* Release the ref and set pollset->polling_island to NULL */
|
1245
|
-
pollset_release_polling_island(pollset, "ps_shutdown");
|
1257
|
+
pollset_release_polling_island(exec_ctx, pollset, "ps_shutdown");
|
1246
1258
|
grpc_exec_ctx_sched(exec_ctx, pollset->shutdown_done, GRPC_ERROR_NONE, NULL);
|
1247
1259
|
}
|
1248
1260
|
|
@@ -1281,7 +1293,7 @@ static void pollset_reset(grpc_pollset *pollset) {
|
|
1281
1293
|
pollset->finish_shutdown_called = false;
|
1282
1294
|
pollset->kicked_without_pollers = false;
|
1283
1295
|
pollset->shutdown_done = NULL;
|
1284
|
-
|
1296
|
+
GPR_ASSERT(pollset->polling_island == NULL);
|
1285
1297
|
}
|
1286
1298
|
|
1287
1299
|
#define GRPC_EPOLL_MAX_EVENTS 1000
|
@@ -1309,7 +1321,7 @@ static void pollset_work_and_unlock(grpc_exec_ctx *exec_ctx,
|
|
1309
1321
|
this function (i.e pollset_work_and_unlock()) is called */
|
1310
1322
|
|
1311
1323
|
if (pollset->polling_island == NULL) {
|
1312
|
-
pollset->polling_island = polling_island_create(NULL, error);
|
1324
|
+
pollset->polling_island = polling_island_create(exec_ctx, NULL, error);
|
1313
1325
|
if (pollset->polling_island == NULL) {
|
1314
1326
|
GPR_TIMER_END("pollset_work_and_unlock", 0);
|
1315
1327
|
return; /* Fatal error. We cannot continue */
|
@@ -1329,7 +1341,7 @@ static void pollset_work_and_unlock(grpc_exec_ctx *exec_ctx,
|
|
1329
1341
|
/* Always do PI_ADD_REF before PI_UNREF because PI_UNREF may cause the
|
1330
1342
|
polling island to be deleted */
|
1331
1343
|
PI_ADD_REF(pi, "ps");
|
1332
|
-
PI_UNREF(pollset->polling_island, "ps");
|
1344
|
+
PI_UNREF(exec_ctx, pollset->polling_island, "ps");
|
1333
1345
|
pollset->polling_island = pi;
|
1334
1346
|
}
|
1335
1347
|
|
@@ -1400,7 +1412,7 @@ static void pollset_work_and_unlock(grpc_exec_ctx *exec_ctx,
|
|
1400
1412
|
that we got before releasing the polling island lock). This is because
|
1401
1413
|
pollset->polling_island pointer might get udpated in other parts of the
|
1402
1414
|
code when there is an island merge while we are doing epoll_wait() above */
|
1403
|
-
PI_UNREF(pi, "ps_work");
|
1415
|
+
PI_UNREF(exec_ctx, pi, "ps_work");
|
1404
1416
|
|
1405
1417
|
GPR_TIMER_END("pollset_work_and_unlock", 0);
|
1406
1418
|
}
|
@@ -1517,10 +1529,11 @@ static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
|
|
1517
1529
|
grpc_error *error = GRPC_ERROR_NONE;
|
1518
1530
|
|
1519
1531
|
gpr_mu_lock(&pollset->mu);
|
1520
|
-
gpr_mu_lock(&fd->
|
1532
|
+
gpr_mu_lock(&fd->mu);
|
1521
1533
|
|
1522
1534
|
polling_island *pi_new = NULL;
|
1523
1535
|
|
1536
|
+
retry:
|
1524
1537
|
/* 1) If fd->polling_island and pollset->polling_island are both non-NULL and
|
1525
1538
|
* equal, do nothing.
|
1526
1539
|
* 2) If fd->polling_island and pollset->polling_island are both NULL, create
|
@@ -1535,15 +1548,44 @@ static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
|
|
1535
1548
|
* polling_island fields in both fd and pollset to point to the merged
|
1536
1549
|
* polling island.
|
1537
1550
|
*/
|
1551
|
+
|
1552
|
+
if (fd->orphaned) {
|
1553
|
+
gpr_mu_unlock(&fd->mu);
|
1554
|
+
gpr_mu_unlock(&pollset->mu);
|
1555
|
+
/* early out */
|
1556
|
+
return;
|
1557
|
+
}
|
1558
|
+
|
1538
1559
|
if (fd->polling_island == pollset->polling_island) {
|
1539
1560
|
pi_new = fd->polling_island;
|
1540
1561
|
if (pi_new == NULL) {
|
1541
|
-
|
1542
|
-
|
1543
|
-
|
1544
|
-
|
1545
|
-
|
1546
|
-
|
1562
|
+
/* Unlock before creating a new polling island: the polling island will
|
1563
|
+
create a workqueue which creates a file descriptor, and holding an fd
|
1564
|
+
lock here can eventually cause a loop to appear to TSAN (making it
|
1565
|
+
unhappy). We don't think it's a real loop (there's an epoch point where
|
1566
|
+
that loop possibility disappears), but the advantages of keeping TSAN
|
1567
|
+
happy outweigh any performance advantage we might have by keeping the
|
1568
|
+
lock held. */
|
1569
|
+
gpr_mu_unlock(&fd->mu);
|
1570
|
+
pi_new = polling_island_create(exec_ctx, fd, &error);
|
1571
|
+
gpr_mu_lock(&fd->mu);
|
1572
|
+
/* Need to reverify any assumptions made between the initial lock and
|
1573
|
+
getting to this branch: if they've changed, we need to throw away our
|
1574
|
+
work and figure things out again. */
|
1575
|
+
if (fd->polling_island != NULL) {
|
1576
|
+
GRPC_POLLING_TRACE(
|
1577
|
+
"pollset_add_fd: Raced creating new polling island. pi_new: %p "
|
1578
|
+
"(fd: %d, pollset: %p)",
|
1579
|
+
(void *)pi_new, fd->fd, (void *)pollset);
|
1580
|
+
PI_ADD_REF(pi_new, "dance_of_destruction");
|
1581
|
+
PI_UNREF(exec_ctx, pi_new, "dance_of_destruction");
|
1582
|
+
goto retry;
|
1583
|
+
} else {
|
1584
|
+
GRPC_POLLING_TRACE(
|
1585
|
+
"pollset_add_fd: Created new polling island. pi_new: %p (fd: %d, "
|
1586
|
+
"pollset: %p)",
|
1587
|
+
(void *)pi_new, fd->fd, (void *)pollset);
|
1588
|
+
}
|
1547
1589
|
}
|
1548
1590
|
} else if (fd->polling_island == NULL) {
|
1549
1591
|
pi_new = polling_island_lock(pollset->polling_island);
|
@@ -1579,7 +1621,7 @@ static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
|
|
1579
1621
|
if (fd->polling_island != pi_new) {
|
1580
1622
|
PI_ADD_REF(pi_new, "fd");
|
1581
1623
|
if (fd->polling_island != NULL) {
|
1582
|
-
PI_UNREF(fd->polling_island, "fd");
|
1624
|
+
PI_UNREF(exec_ctx, fd->polling_island, "fd");
|
1583
1625
|
}
|
1584
1626
|
fd->polling_island = pi_new;
|
1585
1627
|
}
|
@@ -1587,13 +1629,15 @@ static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
|
|
1587
1629
|
if (pollset->polling_island != pi_new) {
|
1588
1630
|
PI_ADD_REF(pi_new, "ps");
|
1589
1631
|
if (pollset->polling_island != NULL) {
|
1590
|
-
PI_UNREF(pollset->polling_island, "ps");
|
1632
|
+
PI_UNREF(exec_ctx, pollset->polling_island, "ps");
|
1591
1633
|
}
|
1592
1634
|
pollset->polling_island = pi_new;
|
1593
1635
|
}
|
1594
1636
|
|
1595
|
-
gpr_mu_unlock(&fd->
|
1637
|
+
gpr_mu_unlock(&fd->mu);
|
1596
1638
|
gpr_mu_unlock(&pollset->mu);
|
1639
|
+
|
1640
|
+
GRPC_LOG_IF_ERROR("pollset_add_fd", error);
|
1597
1641
|
}
|
1598
1642
|
|
1599
1643
|
/*******************************************************************************
|
@@ -1744,9 +1788,9 @@ static void pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx,
|
|
1744
1788
|
void *grpc_fd_get_polling_island(grpc_fd *fd) {
|
1745
1789
|
polling_island *pi;
|
1746
1790
|
|
1747
|
-
gpr_mu_lock(&fd->
|
1791
|
+
gpr_mu_lock(&fd->mu);
|
1748
1792
|
pi = fd->polling_island;
|
1749
|
-
gpr_mu_unlock(&fd->
|
1793
|
+
gpr_mu_unlock(&fd->mu);
|
1750
1794
|
|
1751
1795
|
return pi;
|
1752
1796
|
}
|
@@ -1794,6 +1838,7 @@ static const grpc_event_engine_vtable vtable = {
|
|
1794
1838
|
.fd_notify_on_read = fd_notify_on_read,
|
1795
1839
|
.fd_notify_on_write = fd_notify_on_write,
|
1796
1840
|
.fd_get_read_notifier_pollset = fd_get_read_notifier_pollset,
|
1841
|
+
.fd_get_workqueue = fd_get_workqueue,
|
1797
1842
|
|
1798
1843
|
.pollset_init = pollset_init,
|
1799
1844
|
.pollset_shutdown = pollset_shutdown,
|