|  | @@ -34,9 +34,12 @@
 | 
	
		
			
				|  |  |  #include "src/core/iomgr/exec_ctx.h"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #include <grpc/support/log.h>
 | 
	
		
			
				|  |  | +#include <grpc/support/sync.h>
 | 
	
		
			
				|  |  | +#include <grpc/support/thd.h>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #include "src/core/profiling/timers.h"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +#ifndef GRPC_EXECUTION_CONTEXT_SANITIZER
 | 
	
		
			
				|  |  |  bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) {
 | 
	
		
			
				|  |  |    bool did_something = 0;
 | 
	
		
			
				|  |  |    GPR_TIMER_BEGIN("grpc_exec_ctx_flush", 0);
 | 
	
	
		
			
				|  | @@ -74,3 +77,76 @@ void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  |    GPR_ASSERT(offload_target_or_null == NULL);
 | 
	
		
			
				|  |  |    grpc_closure_list_move(list, &exec_ctx->closure_list);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void grpc_exec_ctx_global_init(void) {}
 | 
	
		
			
				|  |  | +void grpc_exec_ctx_global_shutdown(void) {}
 | 
	
		
			
				|  |  | +#else
 | 
	
		
			
				|  |  | +static gpr_mu g_mu;
 | 
	
		
			
				|  |  | +static gpr_cv g_cv;
 | 
	
		
			
				|  |  | +static int g_threads = 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void run_closure(void *arg) {
 | 
	
		
			
				|  |  | +  grpc_closure *closure = arg;
 | 
	
		
			
				|  |  | +  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
 | 
	
		
			
				|  |  | +  closure->cb(&exec_ctx, closure->cb_arg, (closure->final_data & 1) != 0);
 | 
	
		
			
				|  |  | +  grpc_exec_ctx_finish(&exec_ctx);
 | 
	
		
			
				|  |  | +  gpr_mu_lock(&g_mu);
 | 
	
		
			
				|  |  | +  if (--g_threads == 0) {
 | 
	
		
			
				|  |  | +    gpr_cv_signal(&g_cv);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  gpr_mu_unlock(&g_mu);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void start_closure(grpc_closure *closure) {
 | 
	
		
			
				|  |  | +  gpr_thd_id id;
 | 
	
		
			
				|  |  | +  gpr_mu_lock(&g_mu);
 | 
	
		
			
				|  |  | +  g_threads++;
 | 
	
		
			
				|  |  | +  gpr_mu_unlock(&g_mu);
 | 
	
		
			
				|  |  | +  gpr_thd_new(&id, run_closure, closure, NULL);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) {
 | 
	
		
			
				|  |  | +  return false;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx) {
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void grpc_exec_ctx_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
 | 
	
		
			
				|  |  | +                           bool success,
 | 
	
		
			
				|  |  | +                           grpc_workqueue *offload_target_or_null) {
 | 
	
		
			
				|  |  | +  GPR_ASSERT(offload_target_or_null == NULL);
 | 
	
		
			
				|  |  | +  closure->final_data = success;
 | 
	
		
			
				|  |  | +  start_closure(closure);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                                grpc_closure_list *list,
 | 
	
		
			
				|  |  | +                                grpc_workqueue *offload_target_or_null) {
 | 
	
		
			
				|  |  | +                                  GPR_ASSERT(offload_target_or_null == NULL);
 | 
	
		
			
				|  |  | +  grpc_closure *p = list->head;
 | 
	
		
			
				|  |  | +  while (p) {
 | 
	
		
			
				|  |  | +    grpc_closure *start = p;
 | 
	
		
			
				|  |  | +    p = grpc_closure_next(start);
 | 
	
		
			
				|  |  | +    start_closure(start);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  grpc_closure_list r = GRPC_CLOSURE_LIST_INIT;
 | 
	
		
			
				|  |  | +  *list = r;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void grpc_exec_ctx_global_init(void) {
 | 
	
		
			
				|  |  | +  gpr_mu_init(&g_mu);
 | 
	
		
			
				|  |  | +  gpr_cv_init(&g_cv);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void grpc_exec_ctx_global_shutdown(void) {
 | 
	
		
			
				|  |  | +  gpr_mu_lock(&g_mu);
 | 
	
		
			
				|  |  | +  while (g_threads != 0) {
 | 
	
		
			
				|  |  | +    gpr_cv_wait(&g_cv, &g_mu, gpr_inf_future(GPR_CLOCK_REALTIME));
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  gpr_mu_unlock(&g_mu);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  gpr_mu_destroy(&g_mu);
 | 
	
		
			
				|  |  | +  gpr_cv_destroy(&g_cv);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +#endif
 |