static grpc_error *pollset_epoll(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, pollable *p, gpr_timespec now, gpr_timespec deadline) { int timeout = poll_deadline_to_millis_timeout(deadline, now); if (GRPC_TRACER_ON(grpc_polling_trace)) { gpr_log(GPR_DEBUG, "PS:%p poll %p for %dms", pollset, p, timeout); } if (timeout != 0) { GRPC_SCHEDULING_START_BLOCKING_REGION; } int r; do { r = epoll_wait(p->epfd, pollset->events, MAX_EPOLL_EVENTS, timeout); } while (r < 0 && errno == EINTR); if (timeout != 0) { GRPC_SCHEDULING_END_BLOCKING_REGION; } if (r < 0) return GRPC_OS_ERROR(errno, "epoll_wait"); if (GRPC_TRACER_ON(grpc_polling_trace)) { gpr_log(GPR_DEBUG, "PS:%p poll %p got %d events", pollset, p, r); } pollset->event_cursor = 0; pollset->event_count = r; return GRPC_ERROR_NONE; }
/* Return true if this thread should poll */ static bool begin_worker(grpc_pollset *pollset, grpc_pollset_worker *worker, grpc_pollset_worker **worker_hdl, gpr_timespec *now, gpr_timespec deadline) { bool do_poll = true; if (worker_hdl != NULL) *worker_hdl = worker; worker->initialized_cv = false; worker->kicked = false; worker->pollset = pollset; worker->pollable = pollset->current_pollable; if (pollset_is_pollable_fd(pollset, worker->pollable)) { REF_BY((grpc_fd *)worker->pollable, 2, "one_poll"); } worker_insert(&pollset->root_worker, PWL_POLLSET, worker); if (!worker_insert(&worker->pollable->root_worker, PWL_POLLABLE, worker)) { worker->initialized_cv = true; gpr_cv_init(&worker->cv); if (worker->pollable != &pollset->pollable) { gpr_mu_unlock(&pollset->pollable.po.mu); } if (GRPC_TRACER_ON(grpc_polling_trace) && worker->pollable->root_worker != worker) { gpr_log(GPR_DEBUG, "PS:%p wait %p w=%p for %dms", pollset, worker->pollable, worker, poll_deadline_to_millis_timeout(deadline, *now)); } while (do_poll && worker->pollable->root_worker != worker) { if (gpr_cv_wait(&worker->cv, &worker->pollable->po.mu, deadline)) { if (GRPC_TRACER_ON(grpc_polling_trace)) { gpr_log(GPR_DEBUG, "PS:%p timeout_wait %p w=%p", pollset, worker->pollable, worker); } do_poll = false; } else if (worker->kicked) { if (GRPC_TRACER_ON(grpc_polling_trace)) { gpr_log(GPR_DEBUG, "PS:%p wakeup %p w=%p", pollset, worker->pollable, worker); } do_poll = false; } else if (GRPC_TRACER_ON(grpc_polling_trace) && worker->pollable->root_worker != worker) { gpr_log(GPR_DEBUG, "PS:%p spurious_wakeup %p w=%p", pollset, worker->pollable, worker); } } if (worker->pollable != &pollset->pollable) { gpr_mu_unlock(&worker->pollable->po.mu); gpr_mu_lock(&pollset->pollable.po.mu); gpr_mu_lock(&worker->pollable->po.mu); } *now = gpr_now(now->clock_type); } return do_poll && pollset->shutdown_closure == NULL && pollset->current_pollable == worker->pollable; }
static grpc_error *init_frame_parser(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { if (t->is_first_frame && t->incoming_frame_type != GRPC_CHTTP2_FRAME_SETTINGS) { char *msg; gpr_asprintf( &msg, "Expected SETTINGS frame as the first frame, got frame type %d", t->incoming_frame_type); grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return err; } t->is_first_frame = false; if (t->expect_continuation_stream_id != 0) { if (t->incoming_frame_type != GRPC_CHTTP2_FRAME_CONTINUATION) { char *msg; gpr_asprintf(&msg, "Expected CONTINUATION frame, got frame type %02x", t->incoming_frame_type); grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return err; } if (t->expect_continuation_stream_id != t->incoming_stream_id) { char *msg; gpr_asprintf( &msg, "Expected CONTINUATION frame for grpc_chttp2_stream %08x, got " "grpc_chttp2_stream %08x", t->expect_continuation_stream_id, t->incoming_stream_id); grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return err; } return init_header_frame_parser(exec_ctx, t, 1); } switch (t->incoming_frame_type) { case GRPC_CHTTP2_FRAME_DATA: return init_data_frame_parser(exec_ctx, t); case GRPC_CHTTP2_FRAME_HEADER: return init_header_frame_parser(exec_ctx, t, 0); case GRPC_CHTTP2_FRAME_CONTINUATION: return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Unexpected CONTINUATION frame"); case GRPC_CHTTP2_FRAME_RST_STREAM: return init_rst_stream_parser(exec_ctx, t); case GRPC_CHTTP2_FRAME_SETTINGS: return init_settings_frame_parser(exec_ctx, t); case GRPC_CHTTP2_FRAME_WINDOW_UPDATE: return init_window_update_frame_parser(exec_ctx, t); case GRPC_CHTTP2_FRAME_PING: return init_ping_parser(exec_ctx, t); case GRPC_CHTTP2_FRAME_GOAWAY: return init_goaway_parser(exec_ctx, t); default: if (GRPC_TRACER_ON(grpc_http_trace)) { gpr_log(GPR_ERROR, "Unknown frame type %02x", t->incoming_frame_type); } return init_skip_frame_parser(exec_ctx, t, 0); } }
static grpc_error *parse_frame_slice(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_slice slice, int is_last) { grpc_chttp2_stream *s = t->incoming_stream; grpc_error *err = t->parser(exec_ctx, t->parser_data, t, s, slice, is_last); if (err == GRPC_ERROR_NONE) { return err; } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, NULL)) { if (GRPC_TRACER_ON(grpc_http_trace)) { const char *msg = grpc_error_string(err); gpr_log(GPR_ERROR, "%s", msg); } grpc_chttp2_parsing_become_skip_parser(exec_ctx, t); if (s) { s->forced_close_error = err; grpc_slice_buffer_add( &t->qbuf, grpc_chttp2_rst_stream_create(t->incoming_stream_id, GRPC_HTTP2_PROTOCOL_ERROR, &s->stats.outgoing)); } else { GRPC_ERROR_UNREF(err); } } return err; }
static grpc_error *fill_in_metadata(grpc_exec_ctx *exec_ctx, inproc_stream *s, const grpc_metadata_batch *metadata, uint32_t flags, grpc_metadata_batch *out_md, uint32_t *outflags, bool *markfilled) { if (GRPC_TRACER_ON(grpc_inproc_trace)) { log_metadata(metadata, s->t->is_client, outflags != NULL); } if (outflags != NULL) { *outflags = flags; } if (markfilled != NULL) { *markfilled = true; } grpc_error *error = GRPC_ERROR_NONE; for (grpc_linked_mdelem *elem = metadata->list.head; (elem != NULL) && (error == GRPC_ERROR_NONE); elem = elem->next) { grpc_linked_mdelem *nelem = gpr_arena_alloc(s->arena, sizeof(*nelem)); nelem->md = grpc_mdelem_from_slices( exec_ctx, grpc_slice_intern(GRPC_MDKEY(elem->md)), grpc_slice_intern(GRPC_MDVALUE(elem->md))); error = grpc_metadata_batch_link_tail(exec_ctx, out_md, nelem); } return error; }
void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker, grpc_connectivity_state state, grpc_error *error, const char *reason) { grpc_connectivity_state cur = (grpc_connectivity_state)gpr_atm_no_barrier_load( &tracker->current_state_atm); grpc_connectivity_state_watcher *w; if (GRPC_TRACER_ON(grpc_connectivity_state_trace)) { const char *error_string = grpc_error_string(error); gpr_log(GPR_DEBUG, "SET: %p %s: %s --> %s [%s] error=%p %s", tracker, tracker->name, grpc_connectivity_state_name(cur), grpc_connectivity_state_name(state), reason, error, error_string); } switch (state) { case GRPC_CHANNEL_INIT: case GRPC_CHANNEL_CONNECTING: case GRPC_CHANNEL_IDLE: case GRPC_CHANNEL_READY: GPR_ASSERT(error == GRPC_ERROR_NONE); break; case GRPC_CHANNEL_SHUTDOWN: case GRPC_CHANNEL_TRANSIENT_FAILURE: GPR_ASSERT(error != GRPC_ERROR_NONE); break; } GRPC_ERROR_UNREF(tracker->current_error); tracker->current_error = error; if (cur == state) { return; } GPR_ASSERT(cur != GRPC_CHANNEL_SHUTDOWN); gpr_atm_no_barrier_store(&tracker->current_state_atm, state); while ((w = tracker->watchers) != NULL) { *w->current = state; tracker->watchers = w->next; if (GRPC_TRACER_ON(grpc_connectivity_state_trace)) { gpr_log(GPR_DEBUG, "NOTIFY: %p %s: %p", tracker, tracker->name, w->notify); } GRPC_CLOSURE_SCHED(exec_ctx, w->notify, GRPC_ERROR_REF(tracker->current_error)); gpr_free(w); } }
static void finish_send_message(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { call_data *calld = elem->call_data; int did_compress; grpc_slice_buffer tmp; grpc_slice_buffer_init(&tmp); did_compress = grpc_msg_compress(exec_ctx, calld->compression_algorithm, &calld->slices, &tmp); if (did_compress) { if (GRPC_TRACER_ON(grpc_compression_trace)) { char *algo_name; const size_t before_size = calld->slices.length; const size_t after_size = tmp.length; const float savings_ratio = 1.0f - (float)after_size / (float)before_size; GPR_ASSERT(grpc_compression_algorithm_name(calld->compression_algorithm, &algo_name)); gpr_log(GPR_DEBUG, "Compressed[%s] %" PRIuPTR " bytes vs. %" PRIuPTR " bytes (%.2f%% savings)", algo_name, before_size, after_size, 100 * savings_ratio); } grpc_slice_buffer_swap(&calld->slices, &tmp); calld->send_flags |= GRPC_WRITE_INTERNAL_COMPRESS; } else { if (GRPC_TRACER_ON(grpc_compression_trace)) { char *algo_name; GPR_ASSERT(grpc_compression_algorithm_name(calld->compression_algorithm, &algo_name)); gpr_log(GPR_DEBUG, "Algorithm '%s' enabled but decided not to compress. Input size: " "%" PRIuPTR, algo_name, calld->slices.length); } } grpc_slice_buffer_destroy_internal(exec_ctx, &tmp); grpc_slice_buffer_stream_init(&calld->replacement_stream, &calld->slices, calld->send_flags); calld->send_op->payload->send_message.send_message = &calld->replacement_stream.base; calld->post_send = calld->send_op->on_complete; calld->send_op->on_complete = &calld->send_done; grpc_call_next_op(exec_ctx, elem, calld->send_op); }
static void on_trailing_header(grpc_exec_ctx *exec_ctx, void *tp, grpc_mdelem md) { grpc_chttp2_transport *t = (grpc_chttp2_transport *)tp; grpc_chttp2_stream *s = t->incoming_stream; GPR_TIMER_BEGIN("on_trailing_header", 0); GPR_ASSERT(s != NULL); if (GRPC_TRACER_ON(grpc_http_trace)) { char *key = grpc_slice_to_c_string(GRPC_MDKEY(md)); char *value = grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_INFO, "HTTP:%d:TRL:%s: %s: %s", s->id, t->is_client ? "CLI" : "SVR", key, value); gpr_free(key); gpr_free(value); } if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) && !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) { /* TODO(ctiller): check for a status like " 0" */ s->seen_error = true; } const size_t new_size = s->metadata_buffer[1].size + GRPC_MDELEM_LENGTH(md); const size_t metadata_size_limit = t->settings[GRPC_ACKED_SETTINGS] [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE]; if (new_size > metadata_size_limit) { gpr_log(GPR_DEBUG, "received trailing metadata size exceeds limit (%" PRIuPTR " vs. %" PRIuPTR ")", new_size, metadata_size_limit); grpc_chttp2_cancel_stream( exec_ctx, t, s, grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "received trailing metadata size exceeds limit"), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED)); grpc_chttp2_parsing_become_skip_parser(exec_ctx, t); s->seen_error = true; GRPC_MDELEM_UNREF(exec_ctx, md); } else { grpc_error *error = grpc_chttp2_incoming_metadata_buffer_add( exec_ctx, &s->metadata_buffer[1], md); if (error != GRPC_ERROR_NONE) { grpc_chttp2_cancel_stream(exec_ctx, t, s, error); grpc_chttp2_parsing_become_skip_parser(exec_ctx, t); s->seen_error = true; GRPC_MDELEM_UNREF(exec_ctx, md); } } GPR_TIMER_END("on_trailing_header", 0); }
static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file, int line) { if (GRPC_TRACER_ON(grpc_tcp_trace)) { gpr_atm val = gpr_atm_no_barrier_load(&tcp->refcount.count); gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP ref %p : %s %" PRIdPTR " -> %" PRIdPTR, tcp, reason, val, val + 1); } gpr_ref(&tcp->refcount); }
static void secure_endpoint_ref(secure_endpoint *ep, const char *reason, const char *file, int line) { if (GRPC_TRACER_ON(grpc_trace_secure_endpoint)) { gpr_atm val = gpr_atm_no_barrier_load(&ep->ref.count); gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP ref %p : %s %" PRIdPTR " -> %" PRIdPTR, ep, reason, val, val + 1); } gpr_ref(&ep->ref); }
/* pollset->po.mu lock must be held by the caller before calling this. The function pollset_work() may temporarily release the lock (pollset->po.mu) during the course of its execution but it will always re-acquire the lock and ensure that it is held by the time the function returns */ static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker **worker_hdl, gpr_timespec now, gpr_timespec deadline) { grpc_pollset_worker worker; if (0 && GRPC_TRACER_ON(grpc_polling_trace)) { gpr_log(GPR_DEBUG, "PS:%p work hdl=%p worker=%p now=%" PRId64 ".%09d deadline=%" PRId64 ".%09d kwp=%d root_worker=%p", pollset, worker_hdl, &worker, now.tv_sec, now.tv_nsec, deadline.tv_sec, deadline.tv_nsec, pollset->kicked_without_poller, pollset->root_worker); } grpc_error *error = GRPC_ERROR_NONE; static const char *err_desc = "pollset_work"; if (pollset->kicked_without_poller) { pollset->kicked_without_poller = false; return GRPC_ERROR_NONE; } if (pollset->current_pollable != &pollset->pollable) { gpr_mu_lock(&pollset->current_pollable->po.mu); } if (begin_worker(pollset, &worker, worker_hdl, &now, deadline)) { gpr_tls_set(&g_current_thread_pollset, (intptr_t)pollset); gpr_tls_set(&g_current_thread_worker, (intptr_t)&worker); GPR_ASSERT(!pollset->shutdown_closure); append_error(&error, pollable_materialize(worker.pollable), err_desc); if (worker.pollable != &pollset->pollable) { gpr_mu_unlock(&worker.pollable->po.mu); } gpr_mu_unlock(&pollset->pollable.po.mu); if (pollset->event_cursor == pollset->event_count) { append_error(&error, pollset_epoll(exec_ctx, pollset, worker.pollable, now, deadline), err_desc); } append_error(&error, pollset_process_events(exec_ctx, pollset, false), err_desc); gpr_mu_lock(&pollset->pollable.po.mu); if (worker.pollable != &pollset->pollable) { gpr_mu_lock(&worker.pollable->po.mu); } gpr_tls_set(&g_current_thread_pollset, 0); gpr_tls_set(&g_current_thread_worker, 0); pollset_maybe_finish_shutdown(exec_ctx, pollset); } end_worker(exec_ctx, pollset, &worker, worker_hdl); if (worker.pollable != &pollset->pollable) { gpr_mu_unlock(&worker.pollable->po.mu); } if (grpc_exec_ctx_has_work(exec_ctx)) { gpr_mu_unlock(&pollset->pollable.po.mu); grpc_exec_ctx_flush(exec_ctx); gpr_mu_lock(&pollset->pollable.po.mu); } return error; }
/* expects pollsets locked, flag whether fd is locked or not */ static grpc_error *pollset_add_fd_locked(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_fd *fd, bool fd_locked) { static const char *err_desc = "pollset_add_fd"; grpc_error *error = GRPC_ERROR_NONE; if (pollset->current_pollable == &g_empty_pollable) { if (GRPC_TRACER_ON(grpc_polling_trace)) gpr_log(GPR_DEBUG, "PS:%p add fd %p; transition pollable from empty to fd", pollset, fd); /* empty pollable --> single fd pollable */ pollset_kick_all(exec_ctx, pollset); pollset->current_pollable = &fd->pollable; if (!fd_locked) gpr_mu_lock(&fd->pollable.po.mu); append_error(&error, fd_become_pollable_locked(fd), err_desc); if (!fd_locked) gpr_mu_unlock(&fd->pollable.po.mu); REF_BY(fd, 2, "pollset_pollable"); } else if (pollset->current_pollable == &pollset->pollable) { if (GRPC_TRACER_ON(grpc_polling_trace)) gpr_log(GPR_DEBUG, "PS:%p add fd %p; already multipolling", pollset, fd); append_error(&error, pollable_add_fd(pollset->current_pollable, fd), err_desc); } else if (pollset->current_pollable != &fd->pollable) { grpc_fd *had_fd = (grpc_fd *)pollset->current_pollable; if (GRPC_TRACER_ON(grpc_polling_trace)) gpr_log(GPR_DEBUG, "PS:%p add fd %p; transition pollable from fd %p to multipoller", pollset, fd, had_fd); pollset_kick_all(exec_ctx, pollset); pollset->current_pollable = &pollset->pollable; if (append_error(&error, pollable_materialize(&pollset->pollable), err_desc)) { pollable_add_fd(&pollset->pollable, had_fd); pollable_add_fd(&pollset->pollable, fd); } GRPC_CLOSURE_SCHED(exec_ctx, GRPC_CLOSURE_CREATE(unref_fd_no_longer_poller, had_fd, grpc_schedule_on_exec_ctx), GRPC_ERROR_NONE); } return error; }
static void alarm_unref_dbg(grpc_alarm *alarm, const char *reason, const char *file, int line) { if (GRPC_TRACER_ON(grpc_trace_alarm_refcount)) { gpr_atm val = gpr_atm_no_barrier_load(&alarm->refs.count); gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "Alarm:%p Unref %" PRIdPTR " -> %" PRIdPTR " %s", alarm, val, val - 1, reason); } alarm_unref(alarm); }
static void partly_done(grpc_exec_ctx *exec_ctx, state_watcher *w, bool due_to_completion, grpc_error *error) { if (due_to_completion) { grpc_timer_cancel(exec_ctx, &w->alarm); } else { grpc_channel_element *client_channel_elem = grpc_channel_stack_last_element( grpc_channel_get_channel_stack(w->channel)); grpc_client_channel_watch_connectivity_state( exec_ctx, client_channel_elem, grpc_polling_entity_create_from_pollset(grpc_cq_pollset(w->cq)), NULL, &w->on_complete, NULL); } gpr_mu_lock(&w->mu); if (due_to_completion) { if (GRPC_TRACER_ON(grpc_trace_operation_failures)) { GRPC_LOG_IF_ERROR("watch_completion_error", GRPC_ERROR_REF(error)); } GRPC_ERROR_UNREF(error); error = GRPC_ERROR_NONE; } else { if (error == GRPC_ERROR_NONE) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Timed out waiting for connection state change"); } else if (error == GRPC_ERROR_CANCELLED) { error = GRPC_ERROR_NONE; } } switch (w->phase) { case WAITING: GRPC_ERROR_REF(error); w->error = error; w->phase = READY_TO_CALL_BACK; break; case READY_TO_CALL_BACK: if (error != GRPC_ERROR_NONE) { GPR_ASSERT(!due_to_completion); GRPC_ERROR_UNREF(w->error); GRPC_ERROR_REF(error); w->error = error; } w->phase = CALLING_BACK_AND_FINISHED; grpc_cq_end_op(exec_ctx, w->cq, w->tag, w->error, finished_completion, w, &w->completion_storage); break; case CALLING_BACK_AND_FINISHED: GPR_UNREACHABLE_CODE(return ); break; } gpr_mu_unlock(&w->mu); GRPC_ERROR_UNREF(error); }
grpc_connectivity_state grpc_connectivity_state_check( grpc_connectivity_state_tracker *tracker) { grpc_connectivity_state cur = (grpc_connectivity_state)gpr_atm_no_barrier_load( &tracker->current_state_atm); if (GRPC_TRACER_ON(grpc_connectivity_state_trace)) { gpr_log(GPR_DEBUG, "CONWATCH: %p %s: get %s", tracker, tracker->name, grpc_connectivity_state_name(cur)); } return cur; }
static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp, const char *reason, const char *file, int line) { if (GRPC_TRACER_ON(grpc_tcp_trace)) { gpr_atm val = gpr_atm_no_barrier_load(&tcp->refcount.count); gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %" PRIdPTR " -> %" PRIdPTR, tcp, reason, val, val - 1); } if (gpr_unref(&tcp->refcount)) { tcp_free(exec_ctx, tcp); } }
void grpc_stream_ref(grpc_stream_refcount *refcount, const char *reason) { if (GRPC_TRACER_ON(grpc_trace_stream_refcount)) { gpr_atm val = gpr_atm_no_barrier_load(&refcount->refs.count); gpr_log(GPR_DEBUG, "%s %p:%p REF %" PRIdPTR "->%" PRIdPTR " %s", refcount->object_type, refcount, refcount->destroy.cb_arg, val, val + 1, reason); } #else void grpc_stream_ref(grpc_stream_refcount *refcount) { #endif gpr_ref_non_zero(&refcount->refs); }
static void secure_endpoint_unref(grpc_exec_ctx *exec_ctx, secure_endpoint *ep, const char *reason, const char *file, int line) { if (GRPC_TRACER_ON(grpc_trace_secure_endpoint)) { gpr_atm val = gpr_atm_no_barrier_load(&ep->ref.count); gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP unref %p : %s %" PRIdPTR " -> %" PRIdPTR, ep, reason, val, val - 1); } if (gpr_unref(&ep->ref)) { destroy(exec_ctx, ep); } }
static gpr_atm ref_mutate(grpc_lb_policy *c, gpr_atm delta, int barrier REF_MUTATE_EXTRA_ARGS) { gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&c->ref_pair, delta) : gpr_atm_no_barrier_fetch_add(&c->ref_pair, delta); #ifndef NDEBUG if (GRPC_TRACER_ON(grpc_trace_lb_policy_refcount)) { gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "LB_POLICY: 0x%p %12s 0x%" PRIxPTR " -> 0x%" PRIxPTR " [%s]", c, purpose, old_val, old_val + delta, reason); } #endif return old_val; }
void grpc_cq_internal_ref(grpc_completion_queue *cq, const char *reason, const char *file, int line) { if (GRPC_TRACER_ON(grpc_trace_cq_refcount)) { gpr_atm val = gpr_atm_no_barrier_load(&cq->owning_refs.count); gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "CQ:%p ref %" PRIdPTR " -> %" PRIdPTR " %s", cq, val, val + 1, reason); } #else void grpc_cq_internal_ref(grpc_completion_queue *cq) { #endif gpr_ref(&cq->owning_refs); }
static grpc_error *pollset_process_events(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, bool drain) { static const char *err_desc = "pollset_process_events"; grpc_error *error = GRPC_ERROR_NONE; for (int i = 0; (drain || i < MAX_EPOLL_EVENTS_HANDLED_EACH_POLL_CALL) && pollset->event_cursor != pollset->event_count; i++) { int n = pollset->event_cursor++; struct epoll_event *ev = &pollset->events[n]; void *data_ptr = ev->data.ptr; if (1 & (intptr_t)data_ptr) { if (GRPC_TRACER_ON(grpc_polling_trace)) { gpr_log(GPR_DEBUG, "PS:%p got pollset_wakeup %p", pollset, data_ptr); } append_error(&error, grpc_wakeup_fd_consume_wakeup( (void *)((~(intptr_t)1) & (intptr_t)data_ptr)), err_desc); } else { grpc_fd *fd = (grpc_fd *)data_ptr; bool cancel = (ev->events & (EPOLLERR | EPOLLHUP)) != 0; bool read_ev = (ev->events & (EPOLLIN | EPOLLPRI)) != 0; bool write_ev = (ev->events & EPOLLOUT) != 0; if (GRPC_TRACER_ON(grpc_polling_trace)) { gpr_log(GPR_DEBUG, "PS:%p got fd %p: cancel=%d read=%d " "write=%d", pollset, fd, cancel, read_ev, write_ev); } if (read_ev || cancel) { fd_become_readable(exec_ctx, fd, pollset); } if (write_ev || cancel) { fd_become_writable(exec_ctx, fd); } } } return error; }
bool grpc_connectivity_state_notify_on_state_change( grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker, grpc_connectivity_state *current, grpc_closure *notify) { grpc_connectivity_state cur = (grpc_connectivity_state)gpr_atm_no_barrier_load( &tracker->current_state_atm); if (GRPC_TRACER_ON(grpc_connectivity_state_trace)) { if (current == NULL) { gpr_log(GPR_DEBUG, "CONWATCH: %p %s: unsubscribe notify=%p", tracker, tracker->name, notify); } else { gpr_log(GPR_DEBUG, "CONWATCH: %p %s: from %s [cur=%s] notify=%p", tracker, tracker->name, grpc_connectivity_state_name(*current), grpc_connectivity_state_name(cur), notify); } } if (current == NULL) { grpc_connectivity_state_watcher *w = tracker->watchers; if (w != NULL && w->notify == notify) { GRPC_CLOSURE_SCHED(exec_ctx, notify, GRPC_ERROR_CANCELLED); tracker->watchers = w->next; gpr_free(w); return false; } while (w != NULL) { grpc_connectivity_state_watcher *rm_candidate = w->next; if (rm_candidate != NULL && rm_candidate->notify == notify) { GRPC_CLOSURE_SCHED(exec_ctx, notify, GRPC_ERROR_CANCELLED); w->next = w->next->next; gpr_free(rm_candidate); return false; } w = w->next; } return false; } else { if (cur != *current) { *current = cur; GRPC_CLOSURE_SCHED(exec_ctx, notify, GRPC_ERROR_REF(tracker->current_error)); } else { grpc_connectivity_state_watcher *w = (grpc_connectivity_state_watcher *)gpr_malloc(sizeof(*w)); w->current = current; w->notify = notify; w->next = tracker->watchers; tracker->watchers = w; } return cur == GRPC_CHANNEL_IDLE; } }
grpc_connectivity_state grpc_connectivity_state_get( grpc_connectivity_state_tracker *tracker, grpc_error **error) { grpc_connectivity_state cur = (grpc_connectivity_state)gpr_atm_no_barrier_load( &tracker->current_state_atm); if (GRPC_TRACER_ON(grpc_connectivity_state_trace)) { gpr_log(GPR_DEBUG, "CONWATCH: %p %s: get %s", tracker, tracker->name, grpc_connectivity_state_name(cur)); } if (error != NULL) { *error = GRPC_ERROR_REF(tracker->current_error); } return cur; }
static void ref_by(grpc_fd *fd, int n, const char *reason, const char *file, int line) { if (GRPC_TRACER_ON(grpc_trace_fd_refcount)) { gpr_log(GPR_DEBUG, "FD %d %p ref %d %" PRIdPTR " -> %" PRIdPTR " [%s; %s:%d]", fd->fd, fd, n, gpr_atm_no_barrier_load(&fd->refst), gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line); } #else #define REF_BY(fd, n, reason) ref_by(fd, n) #define UNREF_BY(ec, fd, n, reason) unref_by(ec, fd, n) static void ref_by(grpc_fd *fd, int n) { #endif GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0); }
static void call_read_cb(grpc_exec_ctx *exec_ctx, secure_endpoint *ep, grpc_error *error) { if (GRPC_TRACER_ON(grpc_trace_secure_endpoint)) { size_t i; for (i = 0; i < ep->read_buffer->count; i++) { char *data = grpc_dump_slice(ep->read_buffer->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_DEBUG, "READ %p: %s", ep, data); gpr_free(data); } } ep->read_buffer = NULL; GRPC_CLOSURE_SCHED(exec_ctx, ep->read_cb, error); SECURE_ENDPOINT_UNREF(exec_ctx, ep, "read"); }
grpc_alarm *grpc_alarm_create(void *reserved) { grpc_alarm *alarm = (grpc_alarm *)gpr_malloc(sizeof(grpc_alarm)); #ifndef NDEBUG if (GRPC_TRACER_ON(grpc_trace_alarm_refcount)) { gpr_log(GPR_DEBUG, "Alarm:%p created (ref: 1)", alarm); } #endif gpr_ref_init(&alarm->refs, 1); grpc_timer_init_unset(&alarm->alarm); alarm->cq = NULL; GRPC_CLOSURE_INIT(&alarm->on_alarm, alarm_cb, alarm, grpc_schedule_on_exec_ctx); return alarm; }
/* pollable must be materialized */ static grpc_error *pollable_add_fd(pollable *p, grpc_fd *fd) { grpc_error *error = GRPC_ERROR_NONE; static const char *err_desc = "pollable_add_fd"; const int epfd = p->epfd; GPR_ASSERT(epfd != -1); if (GRPC_TRACER_ON(grpc_polling_trace)) { gpr_log(GPR_DEBUG, "add fd %p to pollable %p", fd, p); } gpr_mu_lock(&fd->orphaned_mu); if (fd->orphaned) { gpr_mu_unlock(&fd->orphaned_mu); return GRPC_ERROR_NONE; } struct epoll_event ev_fd = { .events = (uint32_t)(EPOLLET | EPOLLIN | EPOLLOUT | EPOLLEXCLUSIVE), .data.ptr = fd}; if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd->fd, &ev_fd) != 0) { switch (errno) { case EEXIST: break; default: append_error(&error, GRPC_OS_ERROR(errno, "epoll_ctl"), err_desc); } } gpr_mu_unlock(&fd->orphaned_mu); return error; } /******************************************************************************* * Pollset Definitions */ GPR_TLS_DECL(g_current_thread_pollset); GPR_TLS_DECL(g_current_thread_worker); /* Global state management */ static grpc_error *pollset_global_init(void) { gpr_tls_init(&g_current_thread_pollset); gpr_tls_init(&g_current_thread_worker); pollable_init(&g_empty_pollable, PO_EMPTY_POLLABLE); return GRPC_ERROR_NONE; }
static void stream_list_add_tail(grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_chttp2_stream_list_id id) { grpc_chttp2_stream *old_tail; GPR_ASSERT(!s->included[id]); old_tail = t->lists[id].tail; s->links[id].next = NULL; s->links[id].prev = old_tail; if (old_tail) { old_tail->links[id].next = s; } else { t->lists[id].head = s; } t->lists[id].tail = s; s->included[id] = 1; if (GRPC_TRACER_ON(grpc_trace_http2_stream_state)) { gpr_log(GPR_DEBUG, "%p[%d][%s]: add to %s", t, s->id, t->is_client ? "cli" : "svr", stream_list_id_string(id)); } }
static void unref_by(grpc_exec_ctx *exec_ctx, grpc_fd *fd, int n, const char *reason, const char *file, int line) { if (GRPC_TRACER_ON(grpc_trace_fd_refcount)) { gpr_log(GPR_DEBUG, "FD %d %p unref %d %" PRIdPTR " -> %" PRIdPTR " [%s; %s:%d]", fd->fd, fd, n, gpr_atm_no_barrier_load(&fd->refst), gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line); } #else static void unref_by(grpc_exec_ctx *exec_ctx, grpc_fd *fd, int n) { #endif gpr_atm old = gpr_atm_full_fetch_add(&fd->refst, -n); if (old == n) { GRPC_CLOSURE_SCHED(exec_ctx, GRPC_CLOSURE_CREATE(fd_destroy, fd, grpc_schedule_on_exec_ctx), GRPC_ERROR_NONE); } else { GPR_ASSERT(old > n); } }
static void stream_list_remove(grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_chttp2_stream_list_id id) { GPR_ASSERT(s->included[id]); s->included[id] = 0; if (s->links[id].prev) { s->links[id].prev->links[id].next = s->links[id].next; } else { GPR_ASSERT(t->lists[id].head == s); t->lists[id].head = s->links[id].next; } if (s->links[id].next) { s->links[id].next->links[id].prev = s->links[id].prev; } else { t->lists[id].tail = s->links[id].prev; } if (GRPC_TRACER_ON(grpc_trace_http2_stream_state)) { gpr_log(GPR_DEBUG, "%p[%d][%s]: remove from %s", t, s->id, t->is_client ? "cli" : "svr", stream_list_id_string(id)); } }