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); }
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_init(&usr, q, "usr"); bool done = false; { 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_shutdown(&exec_ctx, &usr, 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); GPR_ASSERT(done); } { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_destroy(&exec_ctx, &usr); grpc_exec_ctx_finish(&exec_ctx); } }
static void ru_slice_unref(grpc_exec_ctx *exec_ctx, void *p) { ru_slice_refcount *rc = p; if (gpr_unref(&rc->refs)) { grpc_resource_user_free(exec_ctx, rc->resource_user, rc->size); gpr_free(rc); } }
static void reclaimer_cb(grpc_exec_ctx *exec_ctx, void *args, grpc_error *error) { GPR_ASSERT(error == GRPC_ERROR_NONE); reclaimer_args *a = args; grpc_resource_user_free(exec_ctx, a->resource_user, a->size); grpc_resource_user_finish_reclamation(exec_ctx, a->resource_user); grpc_closure_run(exec_ctx, a->then, GRPC_ERROR_NONE); gpr_free(a); }
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_init(&usr, q, "usr"); bool done = false; 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_shutdown(&exec_ctx, &usr, set_bool(&done)); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(!done); 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(done); GPR_ASSERT(reclaimer_cancelled); } { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_destroy(&exec_ctx, &usr); grpc_exec_ctx_finish(&exec_ctx); } } grpc_resource_quota_unref(q); }
static void test_scavenge_blocked(void) { gpr_log(GPR_INFO, "** test_scavenge_blocked **"); grpc_resource_quota *q = grpc_resource_quota_create("test_scavenge_blocked"); grpc_resource_quota_resize(q, 1024); grpc_resource_user usr1; grpc_resource_user usr2; grpc_resource_user_init(&usr1, q, "usr1"); grpc_resource_user_init(&usr2, q, "usr2"); bool done; { 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); } { 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, &usr1, 1024); 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); }
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_init(&usr, 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 ru_slice_unref(void *p) { ru_slice_refcount *rc = p; if (gpr_unref(&rc->refs)) { /* TODO(ctiller): this is dangerous, but I think safe for now: we have no guarantee here that we're at a safe point for creating an execution context, but we have no way of writing this code otherwise. In the future: consider lifting grpc_slice to grpc, and offering an internal_{ref,unref} pair that is execution context aware. Alternatively, make exec_ctx be thread local and 'do the right thing' (whatever that is) if NULL */ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_free(&exec_ctx, rc->resource_user, rc->size); grpc_exec_ctx_finish(&exec_ctx); gpr_free(rc); } }
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_init(&usr, 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_reclaim_and_scavenge(void) { gpr_log(GPR_INFO, "** test_blocked_until_scheduled_reclaim_and_scavenge **"); grpc_resource_quota *q = grpc_resource_quota_create( "test_blocked_until_scheduled_reclaim_and_scavenge"); grpc_resource_quota_resize(q, 1024); grpc_resource_user usr1; grpc_resource_user usr2; grpc_resource_user_init(&usr1, q, "usr1"); grpc_resource_user_init(&usr2, 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); } bool reclaim_done = false; { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_user_post_reclaimer( &exec_ctx, &usr1, false, make_reclaimer(&usr1, 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, &usr2, 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, &usr2, 1024); grpc_exec_ctx_finish(&exec_ctx); } grpc_resource_quota_unref(q); destroy_user(&usr1); destroy_user(&usr2); }
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 write_callback(uv_write_t *req, int status) { grpc_tcp *tcp = req->data; grpc_error *error; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_closure *cb = tcp->write_cb; tcp->write_cb = NULL; TCP_UNREF(&exec_ctx, tcp, "write"); if (status == 0) { error = GRPC_ERROR_NONE; } else { error = GRPC_ERROR_CREATE("TCP Write failed"); } if (grpc_tcp_trace) { const char *str = grpc_error_string(error); gpr_log(GPR_DEBUG, "write complete on %p: error=%s", tcp, str); } gpr_free(tcp->write_buffers); grpc_resource_user_free(&exec_ctx, tcp->resource_user, sizeof(uv_buf_t) * tcp->write_slices->count); grpc_closure_sched(&exec_ctx, cb, error); grpc_exec_ctx_finish(&exec_ctx); }
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_async_alloc_blocked_by_size(void) { gpr_log(GPR_INFO, "** test_async_alloc_blocked_by_size **"); grpc_resource_quota *q = grpc_resource_quota_create("test_async_alloc_blocked_by_size"); grpc_resource_quota_resize(q, 1); grpc_resource_user usr; grpc_resource_user_init(&usr, 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_resource_quota_resize(q, 1024); 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); } }