static void win_maybe_shutdown_resource_user(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) { if (gpr_atm_full_fetch_add(&tcp->resource_user_shutdown_count, 1) == 0) { grpc_resource_user_shutdown(exec_ctx, &tcp->resource_user, grpc_closure_create(win_unref_closure, tcp)); } }
static void do_iocp_work() { BOOL success; DWORD bytes = 0; DWORD flags = 0; ULONG_PTR completion_key; LPOVERLAPPED overlapped; gpr_timespec wait_time = gpr_inf_future; grpc_winsocket *socket; grpc_winsocket_callback_info *info; void(*f)(void *, int) = NULL; void *opaque = NULL; success = GetQueuedCompletionStatus(g_iocp, &bytes, &completion_key, &overlapped, gpr_time_to_millis(wait_time)); if (!success && !overlapped) { /* The deadline got attained. */ return; } GPR_ASSERT(completion_key && overlapped); if (overlapped == &g_iocp_custom_overlap) { if (completion_key == (ULONG_PTR) &g_iocp_kick_token) { /* We were awoken from a kick. */ return; } gpr_log(GPR_ERROR, "Unknown custom completion key."); abort(); } socket = (grpc_winsocket*) completion_key; if (overlapped == &socket->write_info.overlapped) { info = &socket->write_info; } else if (overlapped == &socket->read_info.overlapped) { info = &socket->read_info; } else { gpr_log(GPR_ERROR, "Unknown IOCP operation"); abort(); } success = WSAGetOverlappedResult(socket->socket, &info->overlapped, &bytes, FALSE, &flags); if (socket->orphan) { grpc_winsocket_destroy(socket); gpr_atm_full_fetch_add(&g_orphans, -1); return; } info->bytes_transfered = bytes; info->wsa_error = success ? 0 : WSAGetLastError(); GPR_ASSERT(overlapped == &info->overlapped); gpr_mu_lock(&socket->state_mu); GPR_ASSERT(!info->has_pending_iocp); if (info->cb) { f = info->cb; opaque = info->opaque; info->cb = NULL; } else { info->has_pending_iocp = 1; } gpr_mu_unlock(&socket->state_mu); if (f) f(opaque, 1); }
void grpc_resource_user_shutdown(grpc_exec_ctx *exec_ctx, grpc_resource_user *resource_user) { if (gpr_atm_full_fetch_add(&resource_user->shutdown, 1) == 0) { grpc_combiner_execute(exec_ctx, resource_user->resource_quota->combiner, grpc_closure_create(ru_shutdown, resource_user), GRPC_ERROR_NONE, false); } }
static void start_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { gpr_atm old_state = gpr_atm_full_fetch_add(&lock->state, -STATE_UNORPHANED); GRPC_COMBINER_TRACE(gpr_log( GPR_DEBUG, "C:%p really_destroy old_state=%" PRIdPTR, lock, old_state)); if (old_state == 1) { really_destroy(exec_ctx, lock); } }
void grpc_iocp_kick(void) { BOOL success; gpr_atm_full_fetch_add(&g_custom_events, 1); success = PostQueuedCompletionStatus(g_iocp, 0, (ULONG_PTR)&g_iocp_kick_token, &g_iocp_custom_overlap); GPR_ASSERT(success); }
static void ru_unref_by(grpc_exec_ctx *exec_ctx, grpc_resource_user *resource_user, gpr_atm amount) { GPR_ASSERT(amount > 0); gpr_atm old = gpr_atm_full_fetch_add(&resource_user->refs, -amount); GPR_ASSERT(old >= amount); if (old == amount) { grpc_closure_sched(exec_ctx, &resource_user->destroy_closure, GRPC_ERROR_NONE); } }
static void unref_by(grpc_fd *fd, int n) { gpr_atm old = gpr_atm_full_fetch_add(&fd->refst, -n); if (old == n) { grpc_iomgr_add_callback(&fd->on_done_closure); freelist_fd(fd); grpc_iomgr_unregister_object(&fd->iomgr_object); } else { GPR_ASSERT(old > n); } }
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); #ifdef GRPC_LB_POLICY_REFCOUNT_DEBUG gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "LB_POLICY: %p % 12s 0x%08x -> 0x%08x [%s]", c, purpose, old_val, old_val + delta, reason); #endif return old_val; }
static void ru_unref_by(grpc_exec_ctx *exec_ctx, grpc_resource_user *resource_user, gpr_atm amount) { GPR_ASSERT(amount > 0); gpr_atm old = gpr_atm_full_fetch_add(&resource_user->refs, -amount); GPR_ASSERT(old >= amount); if (old == amount) { grpc_combiner_execute(exec_ctx, resource_user->resource_quota->combiner, &resource_user->destroy_closure, GRPC_ERROR_NONE, false); } }
/* Signal the end of an operation - if this is the last waiting-to-be-queued event, then enter shutdown mode */ static void end_op_locked(grpc_completion_queue *cc, grpc_completion_type type) { #ifndef NDEBUG GPR_ASSERT(gpr_atm_full_fetch_add(&cc->pending_op_count[type], -1) > 0); #endif if (gpr_unref(&cc->refs)) { GPR_ASSERT(!cc->shutdown); GPR_ASSERT(cc->shutdown_called); cc->shutdown = 1; gpr_cv_broadcast(GRPC_POLLSET_CV(&cc->pollset)); } }
void grpc_workqueue_enqueue(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, grpc_closure *closure, grpc_error *error) { GPR_TIMER_BEGIN("workqueue.enqueue", 0); gpr_atm last = gpr_atm_full_fetch_add(&workqueue->state, 2); GPR_ASSERT(last & 1); closure->error = error; gpr_mpscq_push(&workqueue->queue, &closure->next_data.atm_next); if (last == 1) { wakeup(exec_ctx, workqueue); } GPR_TIMER_END("workqueue.enqueue", 0); }
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_iocp_work(grpc_exec_ctx *exec_ctx, gpr_timespec deadline) { BOOL success; DWORD bytes = 0; DWORD flags = 0; ULONG_PTR completion_key; LPOVERLAPPED overlapped; grpc_winsocket *socket; grpc_winsocket_callback_info *info; grpc_closure *closure = NULL; success = GetQueuedCompletionStatus( g_iocp, &bytes, &completion_key, &overlapped, deadline_to_millis_timeout(deadline, gpr_now(deadline.clock_type))); if (success == 0 && overlapped == NULL) { return; } GPR_ASSERT(completion_key && overlapped); if (overlapped == &g_iocp_custom_overlap) { gpr_atm_full_fetch_add(&g_custom_events, -1); if (completion_key == (ULONG_PTR)&g_iocp_kick_token) { /* We were awoken from a kick. */ return; } gpr_log(GPR_ERROR, "Unknown custom completion key."); abort(); } socket = (grpc_winsocket *)completion_key; if (overlapped == &socket->write_info.overlapped) { info = &socket->write_info; } else if (overlapped == &socket->read_info.overlapped) { info = &socket->read_info; } else { gpr_log(GPR_ERROR, "Unknown IOCP operation"); abort(); } success = WSAGetOverlappedResult(socket->socket, &info->overlapped, &bytes, FALSE, &flags); info->bytes_transfered = bytes; info->wsa_error = success ? 0 : WSAGetLastError(); GPR_ASSERT(overlapped == &info->overlapped); GPR_ASSERT(!info->has_pending_iocp); gpr_mu_lock(&socket->state_mu); if (info->closure) { closure = info->closure; info->closure = NULL; } else { info->has_pending_iocp = 1; } gpr_mu_unlock(&socket->state_mu); grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL); }
static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { GPR_TIMER_BEGIN("workqueue.on_readable", 0); grpc_workqueue *workqueue = arg; if (error != GRPC_ERROR_NONE) { /* HACK: let wakeup_fd code know that we stole the fd */ workqueue->wakeup_fd.read_fd = 0; grpc_wakeup_fd_destroy(&workqueue->wakeup_fd); grpc_fd_orphan(exec_ctx, workqueue->wakeup_read_fd, NULL, NULL, "destroy"); GPR_ASSERT(gpr_atm_no_barrier_load(&workqueue->state) == 0); gpr_free(workqueue); } else { error = grpc_wakeup_fd_consume_wakeup(&workqueue->wakeup_fd); gpr_mpscq_node *n = gpr_mpscq_pop(&workqueue->queue); if (error == GRPC_ERROR_NONE) { grpc_fd_notify_on_read(exec_ctx, workqueue->wakeup_read_fd, &workqueue->read_closure); } else { /* recurse to get error handling */ on_readable(exec_ctx, arg, error); } if (n == NULL) { /* try again - queue in an inconsistant state */ wakeup(exec_ctx, workqueue); } else { switch (gpr_atm_full_fetch_add(&workqueue->state, -2)) { case 3: // had one count, one unorphaned --> done, unorphaned break; case 2: // had one count, one orphaned --> done, orphaned workqueue_destroy(exec_ctx, workqueue); break; case 1: case 0: // these values are illegal - representing an already done or // deleted workqueue GPR_UNREACHABLE_CODE(break); default: // schedule a wakeup since there's more to do wakeup(exec_ctx, workqueue); } grpc_closure *cl = (grpc_closure *)n; grpc_error *clerr = cl->error; cl->cb(exec_ctx, cl->cb_arg, clerr); GRPC_ERROR_UNREF(clerr); } } GPR_TIMER_END("workqueue.on_readable", 0); }
static void unref_by(grpc_fd *fd, int n, const char *reason, const char *file, int line) { gpr_atm old; gpr_log(GPR_DEBUG, "FD %d %p unref %d %d -> %d [%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_fd *fd, int n) { gpr_atm old; #endif old = gpr_atm_full_fetch_add(&fd->refst, -n); if (old == n) { freelist_fd(fd); } else { GPR_ASSERT(old > n); } }
static void destroy_server(grpc_rb_server* server, gpr_timespec deadline) { grpc_event ev; // This can be started by app or implicitly by GC. Avoid a race between these. if (gpr_atm_full_fetch_add(&server->shutdown_started, (gpr_atm)1) == 0) { if (server->wrapped != NULL) { grpc_server_shutdown_and_notify(server->wrapped, server->queue, NULL); ev = rb_completion_queue_pluck(server->queue, NULL, deadline, NULL); if (ev.type == GRPC_QUEUE_TIMEOUT) { grpc_server_cancel_all_calls(server->wrapped); rb_completion_queue_pluck(server->queue, NULL, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); } grpc_server_destroy(server->wrapped); grpc_rb_completion_queue_destroy(server->queue); server->wrapped = NULL; server->queue = NULL; } } }
grpc_iocp_work_status grpc_iocp_work(grpc_exec_ctx *exec_ctx, gpr_timespec deadline) { BOOL success; DWORD bytes = 0; DWORD flags = 0; ULONG_PTR completion_key; LPOVERLAPPED overlapped; grpc_winsocket *socket; grpc_winsocket_callback_info *info; success = GetQueuedCompletionStatus( g_iocp, &bytes, &completion_key, &overlapped, deadline_to_millis_timeout(deadline, gpr_now(deadline.clock_type))); if (success == 0 && overlapped == NULL) { return GRPC_IOCP_WORK_TIMEOUT; } GPR_ASSERT(completion_key && overlapped); if (overlapped == &g_iocp_custom_overlap) { gpr_atm_full_fetch_add(&g_custom_events, -1); if (completion_key == (ULONG_PTR)&g_iocp_kick_token) { /* We were awoken from a kick. */ return GRPC_IOCP_WORK_KICK; } gpr_log(GPR_ERROR, "Unknown custom completion key."); abort(); } socket = (grpc_winsocket *)completion_key; if (overlapped == &socket->write_info.overlapped) { info = &socket->write_info; } else if (overlapped == &socket->read_info.overlapped) { info = &socket->read_info; } else { abort(); } success = WSAGetOverlappedResult(socket->socket, &info->overlapped, &bytes, FALSE, &flags); info->bytes_transfered = bytes; info->wsa_error = success ? 0 : WSAGetLastError(); GPR_ASSERT(overlapped == &info->overlapped); grpc_socket_become_ready(exec_ctx, socket, info); return GRPC_IOCP_WORK_WORK; }
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 unref_by(grpc_fd *fd, int n, const char *reason, const char *file, int line) { gpr_atm old; gpr_log(GPR_DEBUG, "FD %d %p unref %d %d -> %d [%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_fd *fd, int n) { gpr_atm old; #endif old = gpr_atm_full_fetch_add(&fd->refst, -n); if (old == n) { if (fd->on_done_closure) { grpc_iomgr_add_callback(fd->on_done_closure); } grpc_iomgr_unregister_object(&fd->iomgr_object); freelist_fd(fd); } else { GPR_ASSERT(old > n); } }
void grpc_iocp_socket_orphan(grpc_winsocket *socket) { GPR_ASSERT(!socket->orphan); gpr_atm_full_fetch_add(&g_orphans, 1); socket->orphan = 1; }
static void interned_slice_unref(grpc_exec_ctx *exec_ctx, void *p) { interned_slice_refcount *s = (interned_slice_refcount *)p; if (1 == gpr_atm_full_fetch_add(&s->refcnt, -1)) { interned_slice_destroy(s); } }
int gpr_unref(gpr_refcount *r) { gpr_atm prior = gpr_atm_full_fetch_add(&r->count, -1); GPR_ASSERT(prior > 0); return prior == 1; }
static void workqueue_orphan(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { if (gpr_atm_full_fetch_add(&workqueue->state, -1) == 1) { workqueue_destroy(exec_ctx, workqueue); } }