static void test_scavenge(void) { gpr_log(GPR_INFO, "** test_scavenge **"); grpc_resource_quota *q = grpc_resource_quota_create("test_scavenge"); grpc_resource_quota_resize(q, 1024); grpc_resource_user *usr1 = grpc_resource_user_create(q, "usr1"); grpc_resource_user *usr2 = grpc_resource_user_create(q, "usr2"); { bool done = false; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_alloc(&exec_ctx, usr1, 1024, set_bool(&done)); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(done); } { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_free(&exec_ctx, usr1, 1024); grpc_exec_ctx_finish(&exec_ctx); } { bool done = false; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_alloc(&exec_ctx, usr2, 1024, set_bool(&done)); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(done); } { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_free(&exec_ctx, usr2, 1024); grpc_exec_ctx_finish(&exec_ctx); } grpc_resource_quota_unref(q); destroy_user(usr1); destroy_user(usr2); }
grpc_endpoint *grpc_tcp_create(uv_tcp_t *handle, grpc_resource_quota *resource_quota, char *peer_string) { grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp)); if (grpc_tcp_trace) { gpr_log(GPR_DEBUG, "Creating TCP endpoint %p", tcp); } /* Disable Nagle's Algorithm */ uv_tcp_nodelay(handle, 1); memset(tcp, 0, sizeof(grpc_tcp)); tcp->base.vtable = &vtable; tcp->handle = handle; handle->data = tcp; gpr_ref_init(&tcp->refcount, 1); tcp->peer_string = gpr_strdup(peer_string); tcp->shutting_down = false; tcp->resource_user = grpc_resource_user_create(resource_quota, peer_string); /* Tell network status tracking code about the new endpoint */ grpc_network_status_register_endpoint(&tcp->base); #ifndef GRPC_UV_TCP_HOLD_LOOP uv_unref((uv_handle_t *)handle); #endif return &tcp->base; }
grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, grpc_resource_quota *resource_quota, size_t slice_size, const char *peer_string) { grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp)); tcp->base.vtable = &vtable; tcp->peer_string = gpr_strdup(peer_string); tcp->fd = grpc_fd_wrapped_fd(em_fd); tcp->read_cb = NULL; tcp->write_cb = NULL; tcp->release_fd_cb = NULL; tcp->release_fd = NULL; tcp->incoming_buffer = NULL; tcp->slice_size = slice_size; tcp->iov_size = 1; tcp->finished_edge = true; /* paired with unref in grpc_tcp_destroy */ gpr_ref_init(&tcp->refcount, 1); gpr_atm_no_barrier_store(&tcp->shutdown_count, 0); tcp->em_fd = em_fd; tcp->read_closure.cb = tcp_handle_read; tcp->read_closure.cb_arg = tcp; tcp->write_closure.cb = tcp_handle_write; tcp->write_closure.cb_arg = tcp; grpc_slice_buffer_init(&tcp->last_read_buffer); tcp->resource_user = grpc_resource_user_create(resource_quota, peer_string); grpc_resource_user_slice_allocator_init( &tcp->slice_allocator, tcp->resource_user, tcp_read_allocation_done, tcp); /* Tell network status tracker about new endpoint */ grpc_network_status_register_endpoint(&tcp->base); return &tcp->base; }
static void test_one_slice(void) { gpr_log(GPR_INFO, "** test_one_slice **"); grpc_resource_quota *q = grpc_resource_quota_create("test_one_slice"); grpc_resource_quota_resize(q, 1024); grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); grpc_resource_user_slice_allocator alloc; int num_allocs = 0; grpc_resource_user_slice_allocator_init(&alloc, usr, inc_int_cb, &num_allocs); grpc_slice_buffer buffer; grpc_slice_buffer_init(&buffer); { const int start_allocs = num_allocs; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_alloc_slices(&exec_ctx, &alloc, 1024, 1, &buffer); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(num_allocs == start_allocs + 1); } { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer); grpc_exec_ctx_finish(&exec_ctx); } destroy_user(usr); grpc_resource_quota_unref(q); }
grpc_endpoint *grpc_tcp_create(grpc_exec_ctx *exec_ctx, grpc_winsocket *socket, grpc_channel_args *channel_args, char *peer_string) { grpc_resource_quota *resource_quota = grpc_resource_quota_create(NULL); if (channel_args != NULL) { for (size_t i = 0; i < channel_args->num_args; i++) { if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_RESOURCE_QUOTA)) { grpc_resource_quota_unref_internal(exec_ctx, resource_quota); resource_quota = grpc_resource_quota_ref_internal( channel_args->args[i].value.pointer.p); } } } grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp)); memset(tcp, 0, sizeof(grpc_tcp)); tcp->base.vtable = &vtable; tcp->socket = socket; gpr_mu_init(&tcp->mu); gpr_ref_init(&tcp->refcount, 1); GRPC_CLOSURE_INIT(&tcp->on_read, on_read, tcp, grpc_schedule_on_exec_ctx); GRPC_CLOSURE_INIT(&tcp->on_write, on_write, tcp, grpc_schedule_on_exec_ctx); tcp->peer_string = gpr_strdup(peer_string); tcp->resource_user = grpc_resource_user_create(resource_quota, peer_string); /* Tell network status tracking code about the new endpoint */ grpc_network_status_register_endpoint(&tcp->base); return &tcp->base; }
static void test_resource_user_no_op(void) { gpr_log(GPR_INFO, "** test_resource_user_no_op **"); grpc_resource_quota *q = grpc_resource_quota_create("test_resource_user_no_op"); grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); grpc_resource_quota_unref(q); destroy_user(usr); }
static void half_init(half *m, passthru_endpoint *parent, grpc_resource_quota *resource_quota, const char *half_name) { m->base.vtable = &vtable; m->parent = parent; grpc_slice_buffer_init(&m->read_buffer); m->on_read = NULL; char *name; gpr_asprintf(&name, "passthru_endpoint_%s_%" PRIxPTR, half_name, (intptr_t)parent); m->resource_user = grpc_resource_user_create(resource_quota, name); gpr_free(name); }
grpc_endpoint *grpc_mock_endpoint_create(void (*on_write)(grpc_slice slice), grpc_resource_quota *resource_quota) { grpc_mock_endpoint *m = gpr_malloc(sizeof(*m)); m->base.vtable = &vtable; char *name; gpr_asprintf(&name, "mock_endpoint_%" PRIxPTR, (intptr_t)m); m->resource_user = grpc_resource_user_create(resource_quota, name); gpr_free(name); grpc_slice_buffer_init(&m->read_buffer); gpr_mu_init(&m->mu); m->on_write = on_write; m->on_read = NULL; return &m->base; }
static void test_instant_alloc_free_pair(void) { gpr_log(GPR_INFO, "** test_instant_alloc_free_pair **"); grpc_resource_quota *q = grpc_resource_quota_create("test_instant_alloc_free_pair"); grpc_resource_quota_resize(q, 1024 * 1024); grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_alloc(&exec_ctx, usr, 1024, NULL); grpc_resource_user_free(&exec_ctx, usr, 1024); grpc_exec_ctx_finish(&exec_ctx); } grpc_resource_quota_unref(q); destroy_user(usr); }
static void test_multiple_reclaims_can_be_triggered(void) { gpr_log(GPR_INFO, "** test_multiple_reclaims_can_be_triggered **"); grpc_resource_quota *q = grpc_resource_quota_create("test_multiple_reclaims_can_be_triggered"); grpc_resource_quota_resize(q, 1024); grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); bool benign_done = false; bool destructive_done = false; { bool done = false; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_bool(&done)); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(done); } { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_post_reclaimer( &exec_ctx, usr, false, make_reclaimer(usr, 512, set_bool(&benign_done))); grpc_resource_user_post_reclaimer( &exec_ctx, usr, true, make_reclaimer(usr, 512, set_bool(&destructive_done))); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(!benign_done); GPR_ASSERT(!destructive_done); } { bool done = false; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_bool(&done)); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(benign_done); GPR_ASSERT(destructive_done); GPR_ASSERT(done); } { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_free(&exec_ctx, usr, 1024); grpc_exec_ctx_finish(&exec_ctx); } grpc_resource_quota_unref(q); destroy_user(usr); GPR_ASSERT(benign_done); GPR_ASSERT(destructive_done); }
static void test_resource_user_stays_allocated_and_reclaimers_unrun_until_memory_released( void) { gpr_log(GPR_INFO, "** " "test_resource_user_stays_allocated_and_reclaimers_unrun_until_" "memory_released **"); grpc_resource_quota *q = grpc_resource_quota_create( "test_resource_user_stays_allocated_and_reclaimers_unrun_until_memory_" "released"); grpc_resource_quota_resize(q, 1024); for (int i = 0; i < 10; i++) { grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); bool reclaimer_cancelled = false; { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_post_reclaimer( &exec_ctx, usr, false, make_unused_reclaimer(set_bool(&reclaimer_cancelled))); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(!reclaimer_cancelled); } { bool allocated = false; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_bool(&allocated)); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(allocated); GPR_ASSERT(!reclaimer_cancelled); } { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_unref(&exec_ctx, usr); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(!reclaimer_cancelled); } { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_free(&exec_ctx, usr, 1024); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(reclaimer_cancelled); } } grpc_resource_quota_unref(q); }
grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket, grpc_resource_quota *resource_quota, char *peer_string) { grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp)); memset(tcp, 0, sizeof(grpc_tcp)); tcp->base.vtable = &vtable; tcp->socket = socket; gpr_mu_init(&tcp->mu); gpr_ref_init(&tcp->refcount, 1); grpc_closure_init(&tcp->on_read, on_read, tcp); grpc_closure_init(&tcp->on_write, on_write, tcp); tcp->peer_string = gpr_strdup(peer_string); tcp->resource_user = grpc_resource_user_create(resource_quota, peer_string); /* Tell network status tracking code about the new endpoint */ grpc_network_status_register_endpoint(&tcp->base); return &tcp->base; }
static void test_negative_rq_free_pool(void) { gpr_log(GPR_INFO, "** test_negative_rq_free_pool **"); grpc_resource_quota *q = grpc_resource_quota_create("test_negative_rq_free_pool"); grpc_resource_quota_resize(q, 1024); grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); grpc_resource_user_slice_allocator alloc; int num_allocs = 0; grpc_resource_user_slice_allocator_init(&alloc, usr, inc_int_cb, &num_allocs); grpc_slice_buffer buffer; grpc_slice_buffer_init(&buffer); { const int start_allocs = num_allocs; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_alloc_slices(&exec_ctx, &alloc, 1024, 1, &buffer); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(num_allocs == start_allocs + 1); } grpc_resource_quota_resize(q, 512); double eps = 0.0001; GPR_ASSERT(grpc_resource_quota_get_memory_pressure(q) < 1 + eps); GPR_ASSERT(grpc_resource_quota_get_memory_pressure(q) > 1 - eps); { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_unref(&exec_ctx, usr); grpc_exec_ctx_finish(&exec_ctx); } grpc_resource_quota_unref(q); { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer); grpc_exec_ctx_finish(&exec_ctx); } }
static void test_simple_async_alloc(void) { gpr_log(GPR_INFO, "** test_simple_async_alloc **"); grpc_resource_quota *q = grpc_resource_quota_create("test_simple_async_alloc"); grpc_resource_quota_resize(q, 1024 * 1024); grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); { bool done = false; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_bool(&done)); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(done); } { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_free(&exec_ctx, usr, 1024); grpc_exec_ctx_finish(&exec_ctx); } grpc_resource_quota_unref(q); destroy_user(usr); }
static void test_reclaimers_can_be_posted_repeatedly(void) { gpr_log(GPR_INFO, "** test_reclaimers_can_be_posted_repeatedly **"); grpc_resource_quota *q = grpc_resource_quota_create("test_reclaimers_can_be_posted_repeatedly"); grpc_resource_quota_resize(q, 1024); grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); { bool allocated = false; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_bool(&allocated)); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(allocated); } for (int i = 0; i < 10; i++) { bool reclaimer_done = false; { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_post_reclaimer( &exec_ctx, usr, false, make_reclaimer(usr, 1024, set_bool(&reclaimer_done))); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(!reclaimer_done); } { bool allocated = false; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_bool(&allocated)); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(allocated); GPR_ASSERT(reclaimer_done); } } { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_free(&exec_ctx, usr, 1024); grpc_exec_ctx_finish(&exec_ctx); } destroy_user(usr); grpc_resource_quota_unref(q); }
static void test_blocked_until_scheduled_destructive_reclaim(void) { gpr_log(GPR_INFO, "** test_blocked_until_scheduled_destructive_reclaim **"); grpc_resource_quota *q = grpc_resource_quota_create( "test_blocked_until_scheduled_destructive_reclaim"); grpc_resource_quota_resize(q, 1024); grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); { bool done = false; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_bool(&done)); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(done); } bool reclaim_done = false; { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_post_reclaimer( &exec_ctx, usr, true, make_reclaimer(usr, 1024, set_bool(&reclaim_done))); grpc_exec_ctx_finish(&exec_ctx); } { bool done = false; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_bool(&done)); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(reclaim_done); GPR_ASSERT(done); } { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_free(&exec_ctx, usr, 1024); grpc_exec_ctx_finish(&exec_ctx); } grpc_resource_quota_unref(q); destroy_user(usr); }
static void test_resource_user_stays_allocated_until_memory_released(void) { gpr_log(GPR_INFO, "** test_resource_user_stays_allocated_until_memory_released **"); grpc_resource_quota *q = grpc_resource_quota_create( "test_resource_user_stays_allocated_until_memory_released"); grpc_resource_quota_resize(q, 1024 * 1024); grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_alloc(&exec_ctx, usr, 1024, NULL); grpc_exec_ctx_finish(&exec_ctx); } { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_quota_unref(q); grpc_resource_user_unref(&exec_ctx, usr); grpc_exec_ctx_finish(&exec_ctx); } { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_free(&exec_ctx, usr, 1024); grpc_exec_ctx_finish(&exec_ctx); } }
static void test_unused_reclaim_is_cancelled(void) { gpr_log(GPR_INFO, "** test_unused_reclaim_is_cancelled **"); grpc_resource_quota *q = grpc_resource_quota_create("test_unused_reclaim_is_cancelled"); grpc_resource_quota_resize(q, 1024); grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); bool benign_done = false; bool destructive_done = false; { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_post_reclaimer( &exec_ctx, usr, false, make_unused_reclaimer(set_bool(&benign_done))); grpc_resource_user_post_reclaimer( &exec_ctx, usr, true, make_unused_reclaimer(set_bool(&destructive_done))); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(!benign_done); GPR_ASSERT(!destructive_done); } grpc_resource_quota_unref(q); destroy_user(usr); GPR_ASSERT(benign_done); GPR_ASSERT(destructive_done); }