| 
					
				 | 
			
			
				@@ -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 
			 |