Initial sketch of async execution lock
diff --git a/src/core/lib/iomgr/async_execution_lock.c b/src/core/lib/iomgr/async_execution_lock.c
new file mode 100644
index 0000000..20bdf3f
--- /dev/null
+++ b/src/core/lib/iomgr/async_execution_lock.c
@@ -0,0 +1,71 @@
+#include "src/core/lib/iomgr/async_execution_lock.h"
+
+#define NO_CONSUMER ((gpr_atm)1)
+
+void grpc_aelock_init(grpc_aelock *lock, grpc_workqueue *optional_workqueue) {
+  lock->optional_workqueue = optional_workqueue;
+  gpr_atm_no_barrier_store(&lock->head, NO_CONSUMER);
+  lock->tail = &lock->stub;
+  gpr_atm_no_barrier_store(&lock->next, 0);
+}
+
+void grpc_aelock_destroy(grpc_aelock *lock) {
+  GPR_ASSERT(gpr_atm_no_barrier_load(&lock->head) == NO_CONSUMER);
+}
+
+static void finish(grpc_exec_ctx *exec_ctx, grpc_aelock *lock) {
+  for (;;) {
+    grpc_aelock_qnode *tail = lock->tail;
+    grpc_aelock_qnode *next =
+        (grpc_aelock_qnode *)gpr_atm_acq_load(&tail->next);
+    if (next == NULL) {
+      if (gpr_atm_rel_cas(&lock->head, (gpr_atm)&lock->stub, NO_CONSUMER)) {
+        return;
+      }
+    } else {
+      lock->tail = next;
+
+      next->action(exec_ctx, next->arg);
+      gpr_free(next);
+    }
+  }
+}
+
+void grpc_aelock_execute(grpc_exec_ctx *exec_ctx, grpc_aelock *lock,
+                         grpc_aelock_action action, void *arg,
+                         size_t sizeof_arg) {
+retry_top:
+  gpr_atm cur = gpr_atm_acq_load(&lock->head);
+  if (cur == NO_CONSUMER) {
+    if (!gpr_atm_rel_cas(&lock->head, NO_CONSUMER, (gpr_atm)&lock->stub)) {
+      goto retry_top;
+    }
+    action(exec_ctx, arg);
+    finish(exec_ctx, lock);
+    return;  // early out
+  }
+
+  grpc_aelock_qnode *n = gpr_malloc(sizeof(*n) + sizeof_arg);
+  n->action = action;
+  gpr_atm_no_barrier_store(&n->next, 0);
+  if (sizeof_arg > 0) {
+    memcpy(n + 1, arg, sizeof_arg);
+    n->arg = n + 1;
+  } else {
+    n->arg = arg;
+  }
+  while (!gpr_atm_rel_cas(&lock->head, cur, (gpr_atm)n)) {
+  retry_queue_load:
+    cur = gpr_atm_acq_load(&lock->head);
+    if (cur == NO_CONSUMER) {
+      if (!gpr_atm_rel_cas(&lock->head, NO_CONSUMER, (gpr_atm)&lock->stub)) {
+        goto retry_queue_load;
+      }
+      gpr_free(n);
+      action(exec_ctx, arg);
+      finish(exec_ctx, lock);
+      return;  // early out
+    }
+  }
+  gpr_atm_no_barrier_store(&((grpc_aelock_qnode *)cur)->next, (gpr_atm)n);
+}