resource_quota_test.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  1. /*
  2. *
  3. * Copyright 2016, 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/lib/iomgr/resource_quota.h"
  34. #include <grpc/support/alloc.h>
  35. #include <grpc/support/log.h>
  36. #include "src/core/lib/slice/slice_internal.h"
  37. #include "test/core/util/test_config.h"
  38. static void inc_int_cb(grpc_exec_ctx *exec_ctx, void *a, grpc_error *error) {
  39. ++*(int *)a;
  40. }
  41. static void set_bool_cb(grpc_exec_ctx *exec_ctx, void *a, grpc_error *error) {
  42. *(bool *)a = true;
  43. }
  44. grpc_closure *set_bool(bool *p) { return grpc_closure_create(set_bool_cb, p); }
  45. typedef struct {
  46. size_t size;
  47. grpc_resource_user *resource_user;
  48. grpc_closure *then;
  49. } reclaimer_args;
  50. static void reclaimer_cb(grpc_exec_ctx *exec_ctx, void *args,
  51. grpc_error *error) {
  52. GPR_ASSERT(error == GRPC_ERROR_NONE);
  53. reclaimer_args *a = args;
  54. grpc_resource_user_free(exec_ctx, a->resource_user, a->size);
  55. grpc_resource_user_finish_reclamation(exec_ctx, a->resource_user);
  56. grpc_closure_run(exec_ctx, a->then, GRPC_ERROR_NONE);
  57. gpr_free(a);
  58. }
  59. grpc_closure *make_reclaimer(grpc_resource_user *resource_user, size_t size,
  60. grpc_closure *then) {
  61. reclaimer_args *a = gpr_malloc(sizeof(*a));
  62. a->size = size;
  63. a->resource_user = resource_user;
  64. a->then = then;
  65. return grpc_closure_create(reclaimer_cb, a);
  66. }
  67. static void unused_reclaimer_cb(grpc_exec_ctx *exec_ctx, void *arg,
  68. grpc_error *error) {
  69. GPR_ASSERT(error == GRPC_ERROR_CANCELLED);
  70. grpc_closure_run(exec_ctx, arg, GRPC_ERROR_NONE);
  71. }
  72. grpc_closure *make_unused_reclaimer(grpc_closure *then) {
  73. return grpc_closure_create(unused_reclaimer_cb, then);
  74. }
  75. static void destroy_user(grpc_resource_user *usr) {
  76. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  77. grpc_resource_user_unref(&exec_ctx, usr);
  78. grpc_exec_ctx_finish(&exec_ctx);
  79. }
  80. static void test_no_op(void) {
  81. gpr_log(GPR_INFO, "** test_no_op **");
  82. grpc_resource_quota_unref(grpc_resource_quota_create("test_no_op"));
  83. }
  84. static void test_resize_then_destroy(void) {
  85. gpr_log(GPR_INFO, "** test_resize_then_destroy **");
  86. grpc_resource_quota *q =
  87. grpc_resource_quota_create("test_resize_then_destroy");
  88. grpc_resource_quota_resize(q, 1024 * 1024);
  89. grpc_resource_quota_unref(q);
  90. }
  91. static void test_resource_user_no_op(void) {
  92. gpr_log(GPR_INFO, "** test_resource_user_no_op **");
  93. grpc_resource_quota *q =
  94. grpc_resource_quota_create("test_resource_user_no_op");
  95. grpc_resource_user *usr = grpc_resource_user_create(q, "usr");
  96. grpc_resource_quota_unref(q);
  97. destroy_user(usr);
  98. }
  99. static void test_instant_alloc_then_free(void) {
  100. gpr_log(GPR_INFO, "** test_instant_alloc_then_free **");
  101. grpc_resource_quota *q =
  102. grpc_resource_quota_create("test_instant_alloc_then_free");
  103. grpc_resource_quota_resize(q, 1024 * 1024);
  104. grpc_resource_user *usr = grpc_resource_user_create(q, "usr");
  105. {
  106. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  107. grpc_resource_user_alloc(&exec_ctx, usr, 1024, NULL);
  108. grpc_exec_ctx_finish(&exec_ctx);
  109. }
  110. {
  111. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  112. grpc_resource_user_free(&exec_ctx, usr, 1024);
  113. grpc_exec_ctx_finish(&exec_ctx);
  114. }
  115. grpc_resource_quota_unref(q);
  116. destroy_user(usr);
  117. }
  118. static void test_instant_alloc_free_pair(void) {
  119. gpr_log(GPR_INFO, "** test_instant_alloc_free_pair **");
  120. grpc_resource_quota *q =
  121. grpc_resource_quota_create("test_instant_alloc_free_pair");
  122. grpc_resource_quota_resize(q, 1024 * 1024);
  123. grpc_resource_user *usr = grpc_resource_user_create(q, "usr");
  124. {
  125. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  126. grpc_resource_user_alloc(&exec_ctx, usr, 1024, NULL);
  127. grpc_resource_user_free(&exec_ctx, usr, 1024);
  128. grpc_exec_ctx_finish(&exec_ctx);
  129. }
  130. grpc_resource_quota_unref(q);
  131. destroy_user(usr);
  132. }
  133. static void test_simple_async_alloc(void) {
  134. gpr_log(GPR_INFO, "** test_simple_async_alloc **");
  135. grpc_resource_quota *q =
  136. grpc_resource_quota_create("test_simple_async_alloc");
  137. grpc_resource_quota_resize(q, 1024 * 1024);
  138. grpc_resource_user *usr = grpc_resource_user_create(q, "usr");
  139. {
  140. bool done = false;
  141. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  142. grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_bool(&done));
  143. grpc_exec_ctx_finish(&exec_ctx);
  144. GPR_ASSERT(done);
  145. }
  146. {
  147. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  148. grpc_resource_user_free(&exec_ctx, usr, 1024);
  149. grpc_exec_ctx_finish(&exec_ctx);
  150. }
  151. grpc_resource_quota_unref(q);
  152. destroy_user(usr);
  153. }
  154. static void test_async_alloc_blocked_by_size(void) {
  155. gpr_log(GPR_INFO, "** test_async_alloc_blocked_by_size **");
  156. grpc_resource_quota *q =
  157. grpc_resource_quota_create("test_async_alloc_blocked_by_size");
  158. grpc_resource_quota_resize(q, 1);
  159. grpc_resource_user *usr = grpc_resource_user_create(q, "usr");
  160. bool done = false;
  161. {
  162. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  163. grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_bool(&done));
  164. grpc_exec_ctx_finish(&exec_ctx);
  165. GPR_ASSERT(!done);
  166. }
  167. grpc_resource_quota_resize(q, 1024);
  168. GPR_ASSERT(done);
  169. {
  170. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  171. grpc_resource_user_free(&exec_ctx, usr, 1024);
  172. grpc_exec_ctx_finish(&exec_ctx);
  173. }
  174. grpc_resource_quota_unref(q);
  175. destroy_user(usr);
  176. }
  177. static void test_scavenge(void) {
  178. gpr_log(GPR_INFO, "** test_scavenge **");
  179. grpc_resource_quota *q = grpc_resource_quota_create("test_scavenge");
  180. grpc_resource_quota_resize(q, 1024);
  181. grpc_resource_user *usr1 = grpc_resource_user_create(q, "usr1");
  182. grpc_resource_user *usr2 = grpc_resource_user_create(q, "usr2");
  183. {
  184. bool done = false;
  185. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  186. grpc_resource_user_alloc(&exec_ctx, usr1, 1024, set_bool(&done));
  187. grpc_exec_ctx_finish(&exec_ctx);
  188. GPR_ASSERT(done);
  189. }
  190. {
  191. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  192. grpc_resource_user_free(&exec_ctx, usr1, 1024);
  193. grpc_exec_ctx_finish(&exec_ctx);
  194. }
  195. {
  196. bool done = false;
  197. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  198. grpc_resource_user_alloc(&exec_ctx, usr2, 1024, set_bool(&done));
  199. grpc_exec_ctx_finish(&exec_ctx);
  200. GPR_ASSERT(done);
  201. }
  202. {
  203. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  204. grpc_resource_user_free(&exec_ctx, usr2, 1024);
  205. grpc_exec_ctx_finish(&exec_ctx);
  206. }
  207. grpc_resource_quota_unref(q);
  208. destroy_user(usr1);
  209. destroy_user(usr2);
  210. }
  211. static void test_scavenge_blocked(void) {
  212. gpr_log(GPR_INFO, "** test_scavenge_blocked **");
  213. grpc_resource_quota *q = grpc_resource_quota_create("test_scavenge_blocked");
  214. grpc_resource_quota_resize(q, 1024);
  215. grpc_resource_user *usr1 = grpc_resource_user_create(q, "usr1");
  216. grpc_resource_user *usr2 = grpc_resource_user_create(q, "usr2");
  217. bool done;
  218. {
  219. done = false;
  220. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  221. grpc_resource_user_alloc(&exec_ctx, usr1, 1024, set_bool(&done));
  222. grpc_exec_ctx_finish(&exec_ctx);
  223. GPR_ASSERT(done);
  224. }
  225. {
  226. done = false;
  227. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  228. grpc_resource_user_alloc(&exec_ctx, usr2, 1024, set_bool(&done));
  229. grpc_exec_ctx_finish(&exec_ctx);
  230. GPR_ASSERT(!done);
  231. }
  232. {
  233. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  234. grpc_resource_user_free(&exec_ctx, usr1, 1024);
  235. grpc_exec_ctx_finish(&exec_ctx);
  236. GPR_ASSERT(done);
  237. }
  238. {
  239. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  240. grpc_resource_user_free(&exec_ctx, usr2, 1024);
  241. grpc_exec_ctx_finish(&exec_ctx);
  242. }
  243. grpc_resource_quota_unref(q);
  244. destroy_user(usr1);
  245. destroy_user(usr2);
  246. }
  247. static void test_blocked_until_scheduled_reclaim(void) {
  248. gpr_log(GPR_INFO, "** test_blocked_until_scheduled_reclaim **");
  249. grpc_resource_quota *q =
  250. grpc_resource_quota_create("test_blocked_until_scheduled_reclaim");
  251. grpc_resource_quota_resize(q, 1024);
  252. grpc_resource_user *usr = grpc_resource_user_create(q, "usr");
  253. {
  254. bool done = false;
  255. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  256. grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_bool(&done));
  257. grpc_exec_ctx_finish(&exec_ctx);
  258. GPR_ASSERT(done);
  259. }
  260. bool reclaim_done = false;
  261. {
  262. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  263. grpc_resource_user_post_reclaimer(
  264. &exec_ctx, usr, false,
  265. make_reclaimer(usr, 1024, set_bool(&reclaim_done)));
  266. grpc_exec_ctx_finish(&exec_ctx);
  267. }
  268. {
  269. bool done = false;
  270. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  271. grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_bool(&done));
  272. grpc_exec_ctx_finish(&exec_ctx);
  273. GPR_ASSERT(reclaim_done);
  274. GPR_ASSERT(done);
  275. }
  276. {
  277. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  278. grpc_resource_user_free(&exec_ctx, usr, 1024);
  279. grpc_exec_ctx_finish(&exec_ctx);
  280. }
  281. grpc_resource_quota_unref(q);
  282. destroy_user(usr);
  283. }
  284. static void test_blocked_until_scheduled_reclaim_and_scavenge(void) {
  285. gpr_log(GPR_INFO, "** test_blocked_until_scheduled_reclaim_and_scavenge **");
  286. grpc_resource_quota *q = grpc_resource_quota_create(
  287. "test_blocked_until_scheduled_reclaim_and_scavenge");
  288. grpc_resource_quota_resize(q, 1024);
  289. grpc_resource_user *usr1 = grpc_resource_user_create(q, "usr1");
  290. grpc_resource_user *usr2 = grpc_resource_user_create(q, "usr2");
  291. {
  292. bool done = false;
  293. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  294. grpc_resource_user_alloc(&exec_ctx, usr1, 1024, set_bool(&done));
  295. grpc_exec_ctx_finish(&exec_ctx);
  296. GPR_ASSERT(done);
  297. }
  298. bool reclaim_done = false;
  299. {
  300. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  301. grpc_resource_user_post_reclaimer(
  302. &exec_ctx, usr1, false,
  303. make_reclaimer(usr1, 1024, set_bool(&reclaim_done)));
  304. grpc_exec_ctx_finish(&exec_ctx);
  305. }
  306. {
  307. bool done = false;
  308. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  309. grpc_resource_user_alloc(&exec_ctx, usr2, 1024, set_bool(&done));
  310. grpc_exec_ctx_finish(&exec_ctx);
  311. GPR_ASSERT(reclaim_done);
  312. GPR_ASSERT(done);
  313. }
  314. {
  315. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  316. grpc_resource_user_free(&exec_ctx, usr2, 1024);
  317. grpc_exec_ctx_finish(&exec_ctx);
  318. }
  319. grpc_resource_quota_unref(q);
  320. destroy_user(usr1);
  321. destroy_user(usr2);
  322. }
  323. static void test_blocked_until_scheduled_destructive_reclaim(void) {
  324. gpr_log(GPR_INFO, "** test_blocked_until_scheduled_destructive_reclaim **");
  325. grpc_resource_quota *q = grpc_resource_quota_create(
  326. "test_blocked_until_scheduled_destructive_reclaim");
  327. grpc_resource_quota_resize(q, 1024);
  328. grpc_resource_user *usr = grpc_resource_user_create(q, "usr");
  329. {
  330. bool done = false;
  331. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  332. grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_bool(&done));
  333. grpc_exec_ctx_finish(&exec_ctx);
  334. GPR_ASSERT(done);
  335. }
  336. bool reclaim_done = false;
  337. {
  338. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  339. grpc_resource_user_post_reclaimer(
  340. &exec_ctx, usr, true,
  341. make_reclaimer(usr, 1024, set_bool(&reclaim_done)));
  342. grpc_exec_ctx_finish(&exec_ctx);
  343. }
  344. {
  345. bool done = false;
  346. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  347. grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_bool(&done));
  348. grpc_exec_ctx_finish(&exec_ctx);
  349. GPR_ASSERT(reclaim_done);
  350. GPR_ASSERT(done);
  351. }
  352. {
  353. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  354. grpc_resource_user_free(&exec_ctx, usr, 1024);
  355. grpc_exec_ctx_finish(&exec_ctx);
  356. }
  357. grpc_resource_quota_unref(q);
  358. destroy_user(usr);
  359. }
  360. static void test_unused_reclaim_is_cancelled(void) {
  361. gpr_log(GPR_INFO, "** test_unused_reclaim_is_cancelled **");
  362. grpc_resource_quota *q =
  363. grpc_resource_quota_create("test_unused_reclaim_is_cancelled");
  364. grpc_resource_quota_resize(q, 1024);
  365. grpc_resource_user *usr = grpc_resource_user_create(q, "usr");
  366. bool benign_done = false;
  367. bool destructive_done = false;
  368. {
  369. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  370. grpc_resource_user_post_reclaimer(
  371. &exec_ctx, usr, false, make_unused_reclaimer(set_bool(&benign_done)));
  372. grpc_resource_user_post_reclaimer(
  373. &exec_ctx, usr, true,
  374. make_unused_reclaimer(set_bool(&destructive_done)));
  375. grpc_exec_ctx_finish(&exec_ctx);
  376. GPR_ASSERT(!benign_done);
  377. GPR_ASSERT(!destructive_done);
  378. }
  379. grpc_resource_quota_unref(q);
  380. destroy_user(usr);
  381. GPR_ASSERT(benign_done);
  382. GPR_ASSERT(destructive_done);
  383. }
  384. static void test_benign_reclaim_is_preferred(void) {
  385. gpr_log(GPR_INFO, "** test_benign_reclaim_is_preferred **");
  386. grpc_resource_quota *q =
  387. grpc_resource_quota_create("test_benign_reclaim_is_preferred");
  388. grpc_resource_quota_resize(q, 1024);
  389. grpc_resource_user *usr = grpc_resource_user_create(q, "usr");
  390. bool benign_done = false;
  391. bool destructive_done = false;
  392. {
  393. bool done = false;
  394. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  395. grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_bool(&done));
  396. grpc_exec_ctx_finish(&exec_ctx);
  397. GPR_ASSERT(done);
  398. }
  399. {
  400. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  401. grpc_resource_user_post_reclaimer(
  402. &exec_ctx, usr, false,
  403. make_reclaimer(usr, 1024, set_bool(&benign_done)));
  404. grpc_resource_user_post_reclaimer(
  405. &exec_ctx, usr, true,
  406. make_unused_reclaimer(set_bool(&destructive_done)));
  407. grpc_exec_ctx_finish(&exec_ctx);
  408. GPR_ASSERT(!benign_done);
  409. GPR_ASSERT(!destructive_done);
  410. }
  411. {
  412. bool done = false;
  413. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  414. grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_bool(&done));
  415. grpc_exec_ctx_finish(&exec_ctx);
  416. GPR_ASSERT(benign_done);
  417. GPR_ASSERT(!destructive_done);
  418. GPR_ASSERT(done);
  419. }
  420. {
  421. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  422. grpc_resource_user_free(&exec_ctx, usr, 1024);
  423. grpc_exec_ctx_finish(&exec_ctx);
  424. }
  425. grpc_resource_quota_unref(q);
  426. destroy_user(usr);
  427. GPR_ASSERT(benign_done);
  428. GPR_ASSERT(destructive_done);
  429. }
  430. static void test_multiple_reclaims_can_be_triggered(void) {
  431. gpr_log(GPR_INFO, "** test_multiple_reclaims_can_be_triggered **");
  432. grpc_resource_quota *q =
  433. grpc_resource_quota_create("test_multiple_reclaims_can_be_triggered");
  434. grpc_resource_quota_resize(q, 1024);
  435. grpc_resource_user *usr = grpc_resource_user_create(q, "usr");
  436. bool benign_done = false;
  437. bool destructive_done = false;
  438. {
  439. bool done = false;
  440. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  441. grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_bool(&done));
  442. grpc_exec_ctx_finish(&exec_ctx);
  443. GPR_ASSERT(done);
  444. }
  445. {
  446. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  447. grpc_resource_user_post_reclaimer(
  448. &exec_ctx, usr, false,
  449. make_reclaimer(usr, 512, set_bool(&benign_done)));
  450. grpc_resource_user_post_reclaimer(
  451. &exec_ctx, usr, true,
  452. make_reclaimer(usr, 512, set_bool(&destructive_done)));
  453. grpc_exec_ctx_finish(&exec_ctx);
  454. GPR_ASSERT(!benign_done);
  455. GPR_ASSERT(!destructive_done);
  456. }
  457. {
  458. bool done = false;
  459. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  460. grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_bool(&done));
  461. grpc_exec_ctx_finish(&exec_ctx);
  462. GPR_ASSERT(benign_done);
  463. GPR_ASSERT(destructive_done);
  464. GPR_ASSERT(done);
  465. }
  466. {
  467. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  468. grpc_resource_user_free(&exec_ctx, usr, 1024);
  469. grpc_exec_ctx_finish(&exec_ctx);
  470. }
  471. grpc_resource_quota_unref(q);
  472. destroy_user(usr);
  473. GPR_ASSERT(benign_done);
  474. GPR_ASSERT(destructive_done);
  475. }
  476. static void test_resource_user_stays_allocated_until_memory_released(void) {
  477. gpr_log(GPR_INFO,
  478. "** test_resource_user_stays_allocated_until_memory_released **");
  479. grpc_resource_quota *q = grpc_resource_quota_create(
  480. "test_resource_user_stays_allocated_until_memory_released");
  481. grpc_resource_quota_resize(q, 1024 * 1024);
  482. grpc_resource_user *usr = grpc_resource_user_create(q, "usr");
  483. {
  484. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  485. grpc_resource_user_alloc(&exec_ctx, usr, 1024, NULL);
  486. grpc_exec_ctx_finish(&exec_ctx);
  487. }
  488. {
  489. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  490. grpc_resource_quota_unref(q);
  491. grpc_resource_user_unref(&exec_ctx, usr);
  492. grpc_exec_ctx_finish(&exec_ctx);
  493. }
  494. {
  495. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  496. grpc_resource_user_free(&exec_ctx, usr, 1024);
  497. grpc_exec_ctx_finish(&exec_ctx);
  498. }
  499. }
  500. static void
  501. test_resource_user_stays_allocated_and_reclaimers_unrun_until_memory_released(
  502. void) {
  503. gpr_log(GPR_INFO,
  504. "** "
  505. "test_resource_user_stays_allocated_and_reclaimers_unrun_until_"
  506. "memory_released **");
  507. grpc_resource_quota *q = grpc_resource_quota_create(
  508. "test_resource_user_stays_allocated_and_reclaimers_unrun_until_memory_"
  509. "released");
  510. grpc_resource_quota_resize(q, 1024);
  511. for (int i = 0; i < 10; i++) {
  512. grpc_resource_user *usr = grpc_resource_user_create(q, "usr");
  513. bool reclaimer_cancelled = false;
  514. {
  515. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  516. grpc_resource_user_post_reclaimer(
  517. &exec_ctx, usr, false,
  518. make_unused_reclaimer(set_bool(&reclaimer_cancelled)));
  519. grpc_exec_ctx_finish(&exec_ctx);
  520. GPR_ASSERT(!reclaimer_cancelled);
  521. }
  522. {
  523. bool allocated = false;
  524. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  525. grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_bool(&allocated));
  526. grpc_exec_ctx_finish(&exec_ctx);
  527. GPR_ASSERT(allocated);
  528. GPR_ASSERT(!reclaimer_cancelled);
  529. }
  530. {
  531. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  532. grpc_resource_user_unref(&exec_ctx, usr);
  533. grpc_exec_ctx_finish(&exec_ctx);
  534. GPR_ASSERT(!reclaimer_cancelled);
  535. }
  536. {
  537. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  538. grpc_resource_user_free(&exec_ctx, usr, 1024);
  539. grpc_exec_ctx_finish(&exec_ctx);
  540. GPR_ASSERT(reclaimer_cancelled);
  541. }
  542. }
  543. grpc_resource_quota_unref(q);
  544. }
  545. static void test_reclaimers_can_be_posted_repeatedly(void) {
  546. gpr_log(GPR_INFO, "** test_reclaimers_can_be_posted_repeatedly **");
  547. grpc_resource_quota *q =
  548. grpc_resource_quota_create("test_reclaimers_can_be_posted_repeatedly");
  549. grpc_resource_quota_resize(q, 1024);
  550. grpc_resource_user *usr = grpc_resource_user_create(q, "usr");
  551. {
  552. bool allocated = false;
  553. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  554. grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_bool(&allocated));
  555. grpc_exec_ctx_finish(&exec_ctx);
  556. GPR_ASSERT(allocated);
  557. }
  558. for (int i = 0; i < 10; i++) {
  559. bool reclaimer_done = false;
  560. {
  561. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  562. grpc_resource_user_post_reclaimer(
  563. &exec_ctx, usr, false,
  564. make_reclaimer(usr, 1024, set_bool(&reclaimer_done)));
  565. grpc_exec_ctx_finish(&exec_ctx);
  566. GPR_ASSERT(!reclaimer_done);
  567. }
  568. {
  569. bool allocated = false;
  570. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  571. grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_bool(&allocated));
  572. grpc_exec_ctx_finish(&exec_ctx);
  573. GPR_ASSERT(allocated);
  574. GPR_ASSERT(reclaimer_done);
  575. }
  576. }
  577. {
  578. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  579. grpc_resource_user_free(&exec_ctx, usr, 1024);
  580. grpc_exec_ctx_finish(&exec_ctx);
  581. }
  582. destroy_user(usr);
  583. grpc_resource_quota_unref(q);
  584. }
  585. static void test_one_slice(void) {
  586. gpr_log(GPR_INFO, "** test_one_slice **");
  587. grpc_resource_quota *q = grpc_resource_quota_create("test_one_slice");
  588. grpc_resource_quota_resize(q, 1024);
  589. grpc_resource_user *usr = grpc_resource_user_create(q, "usr");
  590. grpc_resource_user_slice_allocator alloc;
  591. int num_allocs = 0;
  592. grpc_resource_user_slice_allocator_init(&alloc, usr, inc_int_cb, &num_allocs);
  593. grpc_slice_buffer buffer;
  594. grpc_slice_buffer_init(&buffer);
  595. {
  596. const int start_allocs = num_allocs;
  597. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  598. grpc_resource_user_alloc_slices(&exec_ctx, &alloc, 1024, 1, &buffer);
  599. grpc_exec_ctx_finish(&exec_ctx);
  600. GPR_ASSERT(num_allocs == start_allocs + 1);
  601. }
  602. {
  603. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  604. grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer);
  605. grpc_exec_ctx_finish(&exec_ctx);
  606. }
  607. destroy_user(usr);
  608. grpc_resource_quota_unref(q);
  609. }
  610. static void test_one_slice_deleted_late(void) {
  611. gpr_log(GPR_INFO, "** test_one_slice_deleted_late **");
  612. grpc_resource_quota *q =
  613. grpc_resource_quota_create("test_one_slice_deleted_late");
  614. grpc_resource_quota_resize(q, 1024);
  615. grpc_resource_user *usr = grpc_resource_user_create(q, "usr");
  616. grpc_resource_user_slice_allocator alloc;
  617. int num_allocs = 0;
  618. grpc_resource_user_slice_allocator_init(&alloc, usr, inc_int_cb, &num_allocs);
  619. grpc_slice_buffer buffer;
  620. grpc_slice_buffer_init(&buffer);
  621. {
  622. const int start_allocs = num_allocs;
  623. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  624. grpc_resource_user_alloc_slices(&exec_ctx, &alloc, 1024, 1, &buffer);
  625. grpc_exec_ctx_finish(&exec_ctx);
  626. GPR_ASSERT(num_allocs == start_allocs + 1);
  627. }
  628. {
  629. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  630. grpc_resource_user_unref(&exec_ctx, usr);
  631. grpc_exec_ctx_finish(&exec_ctx);
  632. }
  633. grpc_resource_quota_unref(q);
  634. {
  635. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  636. grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer);
  637. grpc_exec_ctx_finish(&exec_ctx);
  638. }
  639. }
  640. int main(int argc, char **argv) {
  641. grpc_test_init(argc, argv);
  642. grpc_init();
  643. test_no_op();
  644. test_resize_then_destroy();
  645. test_resource_user_no_op();
  646. test_instant_alloc_then_free();
  647. test_instant_alloc_free_pair();
  648. test_simple_async_alloc();
  649. test_async_alloc_blocked_by_size();
  650. test_scavenge();
  651. test_scavenge_blocked();
  652. test_blocked_until_scheduled_reclaim();
  653. test_blocked_until_scheduled_reclaim_and_scavenge();
  654. test_blocked_until_scheduled_destructive_reclaim();
  655. test_unused_reclaim_is_cancelled();
  656. test_benign_reclaim_is_preferred();
  657. test_multiple_reclaims_can_be_triggered();
  658. test_resource_user_stays_allocated_until_memory_released();
  659. test_resource_user_stays_allocated_and_reclaimers_unrun_until_memory_released();
  660. test_reclaimers_can_be_posted_repeatedly();
  661. test_one_slice();
  662. test_one_slice_deleted_late();
  663. grpc_shutdown();
  664. return 0;
  665. }