|  | @@ -81,7 +81,6 @@ typedef struct requested_call {
 | 
	
		
			
				|  |  |    void *tag;
 | 
	
		
			
				|  |  |    grpc_server *server;
 | 
	
		
			
				|  |  |    grpc_completion_queue *cq_bound_to_call;
 | 
	
		
			
				|  |  | -  grpc_completion_queue *cq_for_notification;
 | 
	
		
			
				|  |  |    grpc_call **call;
 | 
	
		
			
				|  |  |    grpc_cq_completion completion;
 | 
	
		
			
				|  |  |    grpc_metadata_array *initial_metadata;
 | 
	
	
		
			
				|  | @@ -171,6 +170,7 @@ struct call_data {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  struct request_matcher {
 | 
	
		
			
				|  |  |    grpc_server *server;
 | 
	
		
			
				|  |  | +  size_t cq_idx;
 | 
	
		
			
				|  |  |    call_data *pending_head;
 | 
	
		
			
				|  |  |    call_data *pending_tail;
 | 
	
		
			
				|  |  |    gpr_stack_lockfree *requests;
 | 
	
	
		
			
				|  | @@ -237,7 +237,7 @@ struct grpc_server {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void publish_new_rpc(grpc_exec_ctx *exec_ctx, void *calld, bool success);
 | 
	
		
			
				|  |  |  static void fail_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
 | 
	
		
			
				|  |  | -                      requested_call *rc);
 | 
	
		
			
				|  |  | +                      size_t cq_idx, requested_call *rc);
 | 
	
		
			
				|  |  |  /* Before calling maybe_finish_shutdown, we must hold mu_global and not
 | 
	
		
			
				|  |  |     hold mu_call */
 | 
	
		
			
				|  |  |  static void maybe_finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_server *server);
 | 
	
	
		
			
				|  | @@ -312,9 +312,10 @@ static void channel_broadcaster_shutdown(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void request_matcher_init(request_matcher *rm, size_t entries,
 | 
	
		
			
				|  |  | -                                 grpc_server *server) {
 | 
	
		
			
				|  |  | +                                 size_t cq_idx, grpc_server *server) {
 | 
	
		
			
				|  |  |    memset(rm, 0, sizeof(*rm));
 | 
	
		
			
				|  |  |    rm->server = server;
 | 
	
		
			
				|  |  | +  rm->cq_idx = cq_idx;
 | 
	
		
			
				|  |  |    rm->requests = gpr_stack_lockfree_create(entries);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -347,7 +348,8 @@ static void request_matcher_kill_requests(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  |                                            request_matcher *rm) {
 | 
	
		
			
				|  |  |    int request_id;
 | 
	
		
			
				|  |  |    while ((request_id = gpr_stack_lockfree_pop(rm->requests)) != -1) {
 | 
	
		
			
				|  |  | -    fail_call(exec_ctx, server, &server->requested_calls[request_id]);
 | 
	
		
			
				|  |  | +    fail_call(exec_ctx, server, rm->cq_idx,
 | 
	
		
			
				|  |  | +              &server->requested_calls[request_id]);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -458,11 +460,11 @@ static void done_request_event(grpc_exec_ctx *exec_ctx, void *req,
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void publish_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
 | 
	
		
			
				|  |  | -                         call_data *calld, requested_call *rc) {
 | 
	
		
			
				|  |  | +                         call_data *calld, size_t cq_idx, requested_call *rc) {
 | 
	
		
			
				|  |  |    grpc_call_set_completion_queue(exec_ctx, calld->call, rc->cq_bound_to_call);
 | 
	
		
			
				|  |  |    grpc_call *call = calld->call;
 | 
	
		
			
				|  |  |    *rc->call = call;
 | 
	
		
			
				|  |  | -  calld->cq_new = rc->cq_for_notification;
 | 
	
		
			
				|  |  | +  calld->cq_new = server->cqs[cq_idx];
 | 
	
		
			
				|  |  |    GPR_SWAP(grpc_metadata_array, *rc->initial_metadata, calld->initial_metadata);
 | 
	
		
			
				|  |  |    switch (rc->type) {
 | 
	
		
			
				|  |  |      case BATCH_CALL:
 | 
	
	
		
			
				|  | @@ -530,7 +532,8 @@ static void publish_new_rpc(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
 | 
	
		
			
				|  |  |      gpr_mu_lock(&calld->mu_state);
 | 
	
		
			
				|  |  |      calld->state = ACTIVATED;
 | 
	
		
			
				|  |  |      gpr_mu_unlock(&calld->mu_state);
 | 
	
		
			
				|  |  | -    publish_call(exec_ctx, server, calld, &server->requested_calls[request_id]);
 | 
	
		
			
				|  |  | +    publish_call(exec_ctx, server, calld, rm->cq_idx,
 | 
	
		
			
				|  |  | +                 &server->requested_calls[request_id]);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -972,8 +975,6 @@ grpc_server *grpc_server_create(const grpc_channel_args *args, void *reserved) {
 | 
	
		
			
				|  |  |    for (i = 0; i < (size_t)server->max_requested_calls; i++) {
 | 
	
		
			
				|  |  |      gpr_stack_lockfree_push(server->request_freelist, (int)i);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  request_matcher_init(&server->unregistered_request_matcher,
 | 
	
		
			
				|  |  | -                       server->max_requested_calls, server);
 | 
	
		
			
				|  |  |    server->requested_calls = gpr_malloc(server->max_requested_calls *
 | 
	
		
			
				|  |  |                                         sizeof(*server->requested_calls));
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -1017,8 +1018,6 @@ void *grpc_server_register_method(
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    m = gpr_malloc(sizeof(registered_method));
 | 
	
		
			
				|  |  |    memset(m, 0, sizeof(*m));
 | 
	
		
			
				|  |  | -  request_matcher_init(&m->request_matcher, server->max_requested_calls,
 | 
	
		
			
				|  |  | -                       server);
 | 
	
		
			
				|  |  |    m->method = gpr_strdup(method);
 | 
	
		
			
				|  |  |    m->host = gpr_strdup(host);
 | 
	
		
			
				|  |  |    m->next = server->registered_methods;
 | 
	
	
		
			
				|  | @@ -1036,8 +1035,21 @@ void grpc_server_start(grpc_server *server) {
 | 
	
		
			
				|  |  |    GRPC_API_TRACE("grpc_server_start(server=%p)", 1, (server));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    server->pollsets = gpr_malloc(sizeof(grpc_pollset *) * server->cq_count);
 | 
	
		
			
				|  |  | +  server->unregistered_request_matchers = gpr_malloc(
 | 
	
		
			
				|  |  | +      sizeof(*server->unregistered_request_matchers) * server->cq_count);
 | 
	
		
			
				|  |  |    for (i = 0; i < server->cq_count; i++) {
 | 
	
		
			
				|  |  |      server->pollsets[i] = grpc_cq_pollset(server->cqs[i]);
 | 
	
		
			
				|  |  | +    request_matcher_init(&server->unregistered_request_matchers[i],
 | 
	
		
			
				|  |  | +                         server->max_requested_calls, i, server);
 | 
	
		
			
				|  |  | +    for (registered_method *rm = server->registered_methods; rm;
 | 
	
		
			
				|  |  | +         rm = rm->next) {
 | 
	
		
			
				|  |  | +      if (i == 0) {
 | 
	
		
			
				|  |  | +        rm->request_matchers =
 | 
	
		
			
				|  |  | +            gpr_malloc(sizeof(*rm->request_matchers) * server->cq_count);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      request_matcher_init(&rm->request_matchers[i],
 | 
	
		
			
				|  |  | +                           server->max_requested_calls, i, server);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    for (l = server->listeners; l; l = l->next) {
 | 
	
	
		
			
				|  | @@ -1074,6 +1086,17 @@ void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s,
 | 
	
		
			
				|  |  |    server_ref(s);
 | 
	
		
			
				|  |  |    chand->channel = channel;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  size_t cq_idx;
 | 
	
		
			
				|  |  | +  grpc_completion_queue *accepting_cq = grpc_cq_from_pollset(accepting_pollset);
 | 
	
		
			
				|  |  | +  for (cq_idx = 0; cq_idx < s->cq_count; cq_idx++) {
 | 
	
		
			
				|  |  | +    if (s->cqs[cq_idx] == accepting_cq) break;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  if (cq_idx == s->cq_count) {
 | 
	
		
			
				|  |  | +    /* completion queue not found: pick a random one to publish new calls to */
 | 
	
		
			
				|  |  | +    cq_idx = (size_t)rand() % s->cq_count;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  chand->cq_idx = cq_idx;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    num_registered_methods = 0;
 | 
	
		
			
				|  |  |    for (rm = s->registered_methods; rm; rm = rm->next) {
 | 
	
		
			
				|  |  |      num_registered_methods++;
 | 
	
	
		
			
				|  | @@ -1244,27 +1267,27 @@ void grpc_server_add_listener(
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static grpc_call_error queue_call_request(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | -                                          grpc_server *server,
 | 
	
		
			
				|  |  | +                                          grpc_server *server, size_t cq_idx,
 | 
	
		
			
				|  |  |                                            requested_call *rc) {
 | 
	
		
			
				|  |  |    call_data *calld = NULL;
 | 
	
		
			
				|  |  |    request_matcher *rm = NULL;
 | 
	
		
			
				|  |  |    int request_id;
 | 
	
		
			
				|  |  |    if (gpr_atm_acq_load(&server->shutdown_flag)) {
 | 
	
		
			
				|  |  | -    fail_call(exec_ctx, server, rc);
 | 
	
		
			
				|  |  | +    fail_call(exec_ctx, server, cq_idx, rc);
 | 
	
		
			
				|  |  |      return GRPC_CALL_OK;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    request_id = gpr_stack_lockfree_pop(server->request_freelist);
 | 
	
		
			
				|  |  |    if (request_id == -1) {
 | 
	
		
			
				|  |  |      /* out of request ids: just fail this one */
 | 
	
		
			
				|  |  | -    fail_call(exec_ctx, server, rc);
 | 
	
		
			
				|  |  | +    fail_call(exec_ctx, server, cq_idx, rc);
 | 
	
		
			
				|  |  |      return GRPC_CALL_OK;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    switch (rc->type) {
 | 
	
		
			
				|  |  |      case BATCH_CALL:
 | 
	
		
			
				|  |  | -      rm = &server->unregistered_request_matcher;
 | 
	
		
			
				|  |  | +      rm = &server->unregistered_request_matchers[cq_idx];
 | 
	
		
			
				|  |  |        break;
 | 
	
		
			
				|  |  |      case REGISTERED_CALL:
 | 
	
		
			
				|  |  | -      rm = &rc->data.registered.registered_method->request_matcher;
 | 
	
		
			
				|  |  | +      rm = &rc->data.registered.registered_method->request_matchers[cq_idx];
 | 
	
		
			
				|  |  |        break;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    server->requested_calls[request_id] = *rc;
 | 
	
	
		
			
				|  | @@ -1290,7 +1313,7 @@ static grpc_call_error queue_call_request(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  |          GPR_ASSERT(calld->state == PENDING);
 | 
	
		
			
				|  |  |          calld->state = ACTIVATED;
 | 
	
		
			
				|  |  |          gpr_mu_unlock(&calld->mu_state);
 | 
	
		
			
				|  |  | -        publish_call(exec_ctx, server, calld,
 | 
	
		
			
				|  |  | +        publish_call(exec_ctx, server, calld, cq_idx,
 | 
	
		
			
				|  |  |                       &server->requested_calls[request_id]);
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |        gpr_mu_lock(&server->mu_call);
 | 
	
	
		
			
				|  | @@ -1314,7 +1337,13 @@ grpc_call_error grpc_server_request_call(
 | 
	
		
			
				|  |  |        "cq_bound_to_call=%p, cq_for_notification=%p, tag=%p)",
 | 
	
		
			
				|  |  |        7, (server, call, details, initial_metadata, cq_bound_to_call,
 | 
	
		
			
				|  |  |            cq_for_notification, tag));
 | 
	
		
			
				|  |  | -  if (!grpc_cq_is_server_cq(cq_for_notification)) {
 | 
	
		
			
				|  |  | +  size_t cq_idx;
 | 
	
		
			
				|  |  | +  for (cq_idx = 0; cq_idx < server->cq_count; cq_idx++) {
 | 
	
		
			
				|  |  | +    if (server->cqs[cq_idx] == cq_for_notification) {
 | 
	
		
			
				|  |  | +      break;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  if (cq_idx == server->cq_count) {
 | 
	
		
			
				|  |  |      gpr_free(rc);
 | 
	
		
			
				|  |  |      error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
 | 
	
		
			
				|  |  |      goto done;
 | 
	
	
		
			
				|  | @@ -1325,11 +1354,10 @@ grpc_call_error grpc_server_request_call(
 | 
	
		
			
				|  |  |    rc->server = server;
 | 
	
		
			
				|  |  |    rc->tag = tag;
 | 
	
		
			
				|  |  |    rc->cq_bound_to_call = cq_bound_to_call;
 | 
	
		
			
				|  |  | -  rc->cq_for_notification = cq_for_notification;
 | 
	
		
			
				|  |  |    rc->call = call;
 | 
	
		
			
				|  |  |    rc->data.batch.details = details;
 | 
	
		
			
				|  |  |    rc->initial_metadata = initial_metadata;
 | 
	
		
			
				|  |  | -  error = queue_call_request(&exec_ctx, server, rc);
 | 
	
		
			
				|  |  | +  error = queue_call_request(&exec_ctx, server, cq_idx, rc);
 | 
	
		
			
				|  |  |  done:
 | 
	
		
			
				|  |  |    grpc_exec_ctx_finish(&exec_ctx);
 | 
	
		
			
				|  |  |    return error;
 | 
	
	
		
			
				|  | @@ -1351,7 +1379,14 @@ grpc_call_error grpc_server_request_registered_call(
 | 
	
		
			
				|  |  |        "tag=%p)",
 | 
	
		
			
				|  |  |        9, (server, rmp, call, deadline, initial_metadata, optional_payload,
 | 
	
		
			
				|  |  |            cq_bound_to_call, cq_for_notification, tag));
 | 
	
		
			
				|  |  | -  if (!grpc_cq_is_server_cq(cq_for_notification)) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  size_t cq_idx;
 | 
	
		
			
				|  |  | +  for (cq_idx = 0; cq_idx < server->cq_count; cq_idx++) {
 | 
	
		
			
				|  |  | +    if (server->cqs[cq_idx] == cq_for_notification) {
 | 
	
		
			
				|  |  | +      break;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  if (cq_idx == server->cq_count) {
 | 
	
		
			
				|  |  |      gpr_free(rc);
 | 
	
		
			
				|  |  |      error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
 | 
	
		
			
				|  |  |      goto done;
 | 
	
	
		
			
				|  | @@ -1367,26 +1402,25 @@ grpc_call_error grpc_server_request_registered_call(
 | 
	
		
			
				|  |  |    rc->server = server;
 | 
	
		
			
				|  |  |    rc->tag = tag;
 | 
	
		
			
				|  |  |    rc->cq_bound_to_call = cq_bound_to_call;
 | 
	
		
			
				|  |  | -  rc->cq_for_notification = cq_for_notification;
 | 
	
		
			
				|  |  |    rc->call = call;
 | 
	
		
			
				|  |  |    rc->data.registered.registered_method = rm;
 | 
	
		
			
				|  |  |    rc->data.registered.deadline = deadline;
 | 
	
		
			
				|  |  |    rc->initial_metadata = initial_metadata;
 | 
	
		
			
				|  |  |    rc->data.registered.optional_payload = optional_payload;
 | 
	
		
			
				|  |  | -  error = queue_call_request(&exec_ctx, server, rc);
 | 
	
		
			
				|  |  | +  error = queue_call_request(&exec_ctx, server, cq_idx, rc);
 | 
	
		
			
				|  |  |  done:
 | 
	
		
			
				|  |  |    grpc_exec_ctx_finish(&exec_ctx);
 | 
	
		
			
				|  |  |    return error;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void fail_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
 | 
	
		
			
				|  |  | -                      requested_call *rc) {
 | 
	
		
			
				|  |  | +                      size_t cq_idx, requested_call *rc) {
 | 
	
		
			
				|  |  |    *rc->call = NULL;
 | 
	
		
			
				|  |  |    rc->initial_metadata->count = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    server_ref(server);
 | 
	
		
			
				|  |  | -  grpc_cq_end_op(exec_ctx, rc->cq_for_notification, rc->tag, 0,
 | 
	
		
			
				|  |  | -                 done_request_event, rc, &rc->completion);
 | 
	
		
			
				|  |  | +  grpc_cq_end_op(exec_ctx, server->cqs[cq_idx], rc->tag, 0, done_request_event,
 | 
	
		
			
				|  |  | +                 rc, &rc->completion);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) {
 |