completion_queue.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /*
  2. *
  3. * Copyright 2015, Google Inc.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are
  8. * met:
  9. *
  10. * * Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * * Redistributions in binary form must reproduce the above
  13. * copyright notice, this list of conditions and the following disclaimer
  14. * in the documentation and/or other materials provided with the
  15. * distribution.
  16. * * Neither the name of Google Inc. nor the names of its
  17. * contributors may be used to endorse or promote products derived from
  18. * this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. *
  32. */
  33. #include "src/core/surface/completion_queue.h"
  34. #include <stdio.h>
  35. #include <string.h>
  36. #include "src/core/iomgr/pollset.h"
  37. #include "src/core/support/string.h"
  38. #include "src/core/surface/call.h"
  39. #include "src/core/surface/event_string.h"
  40. #include "src/core/surface/surface_trace.h"
  41. #include <grpc/support/alloc.h>
  42. #include <grpc/support/atm.h>
  43. #include <grpc/support/log.h>
  44. typedef struct {
  45. grpc_pollset_worker *worker;
  46. void *tag;
  47. } plucker;
  48. /* Completion queue structure */
  49. struct grpc_completion_queue {
  50. /** completed events */
  51. grpc_cq_completion completed_head;
  52. grpc_cq_completion *completed_tail;
  53. /** Number of pending events (+1 if we're not shutdown) */
  54. gpr_refcount pending_events;
  55. /** Once owning_refs drops to zero, we will destroy the cq */
  56. gpr_refcount owning_refs;
  57. /** the set of low level i/o things that concern this cq */
  58. grpc_pollset pollset;
  59. /** 0 initially, 1 once we've begun shutting down */
  60. int shutdown;
  61. int shutdown_called;
  62. int is_server_cq;
  63. int num_pluckers;
  64. plucker pluckers[GRPC_MAX_COMPLETION_QUEUE_PLUCKERS];
  65. };
  66. grpc_completion_queue *grpc_completion_queue_create(void *reserved) {
  67. grpc_completion_queue *cc = gpr_malloc(sizeof(grpc_completion_queue));
  68. GPR_ASSERT(!reserved);
  69. memset(cc, 0, sizeof(*cc));
  70. /* Initial ref is dropped by grpc_completion_queue_shutdown */
  71. gpr_ref_init(&cc->pending_events, 1);
  72. /* One for destroy(), one for pollset_shutdown */
  73. gpr_ref_init(&cc->owning_refs, 2);
  74. grpc_pollset_init(&cc->pollset);
  75. cc->completed_tail = &cc->completed_head;
  76. cc->completed_head.next = (gpr_uintptr)cc->completed_tail;
  77. return cc;
  78. }
  79. #ifdef GRPC_CQ_REF_COUNT_DEBUG
  80. void grpc_cq_internal_ref(grpc_completion_queue *cc, const char *reason,
  81. const char *file, int line) {
  82. gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "CQ:%p ref %d -> %d %s", cc,
  83. (int)cc->owning_refs.count, (int)cc->owning_refs.count + 1, reason);
  84. #else
  85. void grpc_cq_internal_ref(grpc_completion_queue *cc) {
  86. #endif
  87. gpr_ref(&cc->owning_refs);
  88. }
  89. static void on_pollset_destroy_done(void *arg) {
  90. grpc_completion_queue *cc = arg;
  91. GRPC_CQ_INTERNAL_UNREF(cc, "pollset_destroy");
  92. }
  93. #ifdef GRPC_CQ_REF_COUNT_DEBUG
  94. void grpc_cq_internal_unref(grpc_completion_queue *cc, const char *reason,
  95. const char *file, int line) {
  96. gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "CQ:%p unref %d -> %d %s", cc,
  97. (int)cc->owning_refs.count, (int)cc->owning_refs.count - 1, reason);
  98. #else
  99. void grpc_cq_internal_unref(grpc_completion_queue *cc) {
  100. #endif
  101. if (gpr_unref(&cc->owning_refs)) {
  102. GPR_ASSERT(cc->completed_head.next == (gpr_uintptr)&cc->completed_head);
  103. grpc_pollset_destroy(&cc->pollset);
  104. gpr_free(cc);
  105. }
  106. }
  107. void grpc_cq_begin_op(grpc_completion_queue *cc) {
  108. #ifndef NDEBUG
  109. gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
  110. GPR_ASSERT(!cc->shutdown_called);
  111. gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
  112. #endif
  113. gpr_ref(&cc->pending_events);
  114. }
  115. /* Signal the end of an operation - if this is the last waiting-to-be-queued
  116. event, then enter shutdown mode */
  117. /* Queue a GRPC_OP_COMPLETED operation */
  118. void grpc_cq_end_op(grpc_completion_queue *cc, void *tag, int success,
  119. void (*done)(void *done_arg, grpc_cq_completion *storage),
  120. void *done_arg, grpc_cq_completion *storage) {
  121. int shutdown;
  122. int i;
  123. grpc_pollset_worker *pluck_worker;
  124. storage->tag = tag;
  125. storage->done = done;
  126. storage->done_arg = done_arg;
  127. storage->next =
  128. ((gpr_uintptr)&cc->completed_head) | ((gpr_uintptr)(success != 0));
  129. gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
  130. shutdown = gpr_unref(&cc->pending_events);
  131. if (!shutdown) {
  132. cc->completed_tail->next =
  133. ((gpr_uintptr)storage) | (1u & (gpr_uintptr)cc->completed_tail->next);
  134. cc->completed_tail = storage;
  135. pluck_worker = NULL;
  136. for (i = 0; i < cc->num_pluckers; i++) {
  137. if (cc->pluckers[i].tag == tag) {
  138. pluck_worker = cc->pluckers[i].worker;
  139. break;
  140. }
  141. }
  142. grpc_pollset_kick(&cc->pollset, pluck_worker);
  143. gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
  144. } else {
  145. cc->completed_tail->next =
  146. ((gpr_uintptr)storage) | (1u & (gpr_uintptr)cc->completed_tail->next);
  147. cc->completed_tail = storage;
  148. GPR_ASSERT(!cc->shutdown);
  149. GPR_ASSERT(cc->shutdown_called);
  150. cc->shutdown = 1;
  151. gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
  152. grpc_pollset_shutdown(&cc->pollset, on_pollset_destroy_done, cc);
  153. }
  154. }
  155. grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
  156. gpr_timespec deadline, void *reserved) {
  157. grpc_event ret;
  158. grpc_pollset_worker worker;
  159. int first_loop = 1;
  160. gpr_timespec now;
  161. GPR_ASSERT(!reserved);
  162. deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC);
  163. GRPC_CQ_INTERNAL_REF(cc, "next");
  164. gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
  165. for (;;) {
  166. if (cc->completed_tail != &cc->completed_head) {
  167. grpc_cq_completion *c = (grpc_cq_completion *)cc->completed_head.next;
  168. cc->completed_head.next = c->next & ~(gpr_uintptr)1;
  169. if (c == cc->completed_tail) {
  170. cc->completed_tail = &cc->completed_head;
  171. }
  172. gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
  173. ret.type = GRPC_OP_COMPLETE;
  174. ret.success = c->next & 1u;
  175. ret.tag = c->tag;
  176. c->done(c->done_arg, c);
  177. break;
  178. }
  179. if (cc->shutdown) {
  180. gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
  181. memset(&ret, 0, sizeof(ret));
  182. ret.type = GRPC_QUEUE_SHUTDOWN;
  183. break;
  184. }
  185. now = gpr_now(GPR_CLOCK_MONOTONIC);
  186. if (!first_loop && gpr_time_cmp(now, deadline) >= 0) {
  187. gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
  188. memset(&ret, 0, sizeof(ret));
  189. ret.type = GRPC_QUEUE_TIMEOUT;
  190. break;
  191. }
  192. first_loop = 0;
  193. grpc_pollset_work(&cc->pollset, &worker, now, deadline);
  194. }
  195. GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret);
  196. GRPC_CQ_INTERNAL_UNREF(cc, "next");
  197. return ret;
  198. }
  199. static int add_plucker(grpc_completion_queue *cc, void *tag,
  200. grpc_pollset_worker *worker) {
  201. if (cc->num_pluckers == GRPC_MAX_COMPLETION_QUEUE_PLUCKERS) {
  202. return 0;
  203. }
  204. cc->pluckers[cc->num_pluckers].tag = tag;
  205. cc->pluckers[cc->num_pluckers].worker = worker;
  206. cc->num_pluckers++;
  207. return 1;
  208. }
  209. static void del_plucker(grpc_completion_queue *cc, void *tag,
  210. grpc_pollset_worker *worker) {
  211. int i;
  212. for (i = 0; i < cc->num_pluckers; i++) {
  213. if (cc->pluckers[i].tag == tag && cc->pluckers[i].worker == worker) {
  214. cc->num_pluckers--;
  215. GPR_SWAP(plucker, cc->pluckers[i], cc->pluckers[cc->num_pluckers]);
  216. return;
  217. }
  218. }
  219. gpr_log(GPR_ERROR, "should never reach here");
  220. abort();
  221. }
  222. grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
  223. gpr_timespec deadline, void *reserved) {
  224. grpc_event ret;
  225. grpc_cq_completion *c;
  226. grpc_cq_completion *prev;
  227. grpc_pollset_worker worker;
  228. gpr_timespec now;
  229. int first_loop = 1;
  230. GPR_ASSERT(!reserved);
  231. deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC);
  232. GRPC_CQ_INTERNAL_REF(cc, "pluck");
  233. gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
  234. for (;;) {
  235. prev = &cc->completed_head;
  236. while ((c = (grpc_cq_completion *)(prev->next & ~(gpr_uintptr)1)) !=
  237. &cc->completed_head) {
  238. if (c->tag == tag) {
  239. prev->next =
  240. (prev->next & (gpr_uintptr)1) | (c->next & ~(gpr_uintptr)1);
  241. if (c == cc->completed_tail) {
  242. cc->completed_tail = prev;
  243. }
  244. gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
  245. ret.type = GRPC_OP_COMPLETE;
  246. ret.success = c->next & 1u;
  247. ret.tag = c->tag;
  248. c->done(c->done_arg, c);
  249. goto done;
  250. }
  251. prev = c;
  252. }
  253. if (cc->shutdown) {
  254. gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
  255. memset(&ret, 0, sizeof(ret));
  256. ret.type = GRPC_QUEUE_SHUTDOWN;
  257. break;
  258. }
  259. if (!add_plucker(cc, tag, &worker)) {
  260. gpr_log(GPR_DEBUG,
  261. "Too many outstanding grpc_completion_queue_pluck calls: maximum "
  262. "is %d",
  263. GRPC_MAX_COMPLETION_QUEUE_PLUCKERS);
  264. gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
  265. memset(&ret, 0, sizeof(ret));
  266. /* TODO(ctiller): should we use a different result here */
  267. ret.type = GRPC_QUEUE_TIMEOUT;
  268. break;
  269. }
  270. now = gpr_now(GPR_CLOCK_MONOTONIC);
  271. if (!first_loop && gpr_time_cmp(now, deadline) >= 0) {
  272. del_plucker(cc, tag, &worker);
  273. gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
  274. memset(&ret, 0, sizeof(ret));
  275. ret.type = GRPC_QUEUE_TIMEOUT;
  276. break;
  277. }
  278. first_loop = 0;
  279. grpc_pollset_work(&cc->pollset, &worker, now, deadline);
  280. del_plucker(cc, tag, &worker);
  281. }
  282. done:
  283. GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret);
  284. GRPC_CQ_INTERNAL_UNREF(cc, "pluck");
  285. return ret;
  286. }
  287. /* Shutdown simply drops a ref that we reserved at creation time; if we drop
  288. to zero here, then enter shutdown mode and wake up any waiters */
  289. void grpc_completion_queue_shutdown(grpc_completion_queue *cc) {
  290. gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
  291. if (cc->shutdown_called) {
  292. gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
  293. return;
  294. }
  295. cc->shutdown_called = 1;
  296. gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
  297. if (gpr_unref(&cc->pending_events)) {
  298. gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
  299. GPR_ASSERT(!cc->shutdown);
  300. cc->shutdown = 1;
  301. gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
  302. grpc_pollset_shutdown(&cc->pollset, on_pollset_destroy_done, cc);
  303. }
  304. }
  305. void grpc_completion_queue_destroy(grpc_completion_queue *cc) {
  306. grpc_completion_queue_shutdown(cc);
  307. GRPC_CQ_INTERNAL_UNREF(cc, "destroy");
  308. }
  309. grpc_pollset *grpc_cq_pollset(grpc_completion_queue *cc) {
  310. return &cc->pollset;
  311. }
  312. void grpc_cq_mark_server_cq(grpc_completion_queue *cc) { cc->is_server_cq = 1; }
  313. int grpc_cq_is_server_cq(grpc_completion_queue *cc) { return cc->is_server_cq; }