mutex_tc.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. /*
  2. * Copyright (c) 2006-2019, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-09.01 luckyzjq the first version
  9. * 2023-09-15 xqyjlj change stack size in cpu64
  10. */
  11. #define __RT_IPC_SOURCE__
  12. #include <rtthread.h>
  13. #include <stdlib.h>
  14. #include "utest.h"
  15. #ifdef ARCH_CPU_64BIT
  16. #define THREAD_STACKSIZE 8192
  17. #else
  18. #define THREAD_STACKSIZE 4096
  19. #endif
  20. static struct rt_mutex static_mutex;
  21. #ifdef RT_USING_HEAP
  22. static rt_mutex_t dynamic_mutex;
  23. #endif /* RT_USING_HEAP */
  24. /* init test */
  25. static void test_static_mutex_init(void)
  26. {
  27. rt_err_t result = -RT_ERROR;
  28. result = rt_mutex_init(&static_mutex, "static_mutex", RT_IPC_FLAG_PRIO);
  29. if (RT_EOK != result)
  30. {
  31. uassert_true(RT_FALSE);
  32. }
  33. result = rt_mutex_detach(&static_mutex);
  34. if (RT_EOK != result)
  35. {
  36. uassert_true(RT_FALSE);
  37. }
  38. result = rt_mutex_init(&static_mutex, "static_mutex", RT_IPC_FLAG_PRIO);
  39. if (RT_EOK != result)
  40. {
  41. uassert_true(RT_FALSE);
  42. }
  43. result = rt_mutex_detach(&static_mutex);
  44. if (RT_EOK != result)
  45. {
  46. uassert_true(RT_FALSE);
  47. }
  48. uassert_true(RT_TRUE);
  49. }
  50. /* static take test */
  51. static void static_mutex_take_entry(void *param)
  52. {
  53. rt_err_t result;
  54. rt_mutex_t mutex;
  55. int rand_num = rand() % 0x1000;
  56. mutex = (rt_mutex_t)param;
  57. result = rt_mutex_take(mutex, rand_num);
  58. if (RT_EOK == result)
  59. {
  60. uassert_true(RT_FALSE);
  61. }
  62. }
  63. static void test_static_mutex_take(void)
  64. {
  65. rt_err_t result;
  66. result = rt_mutex_init(&static_mutex, "static_mutex", RT_IPC_FLAG_PRIO);
  67. if (RT_EOK != result)
  68. {
  69. uassert_true(RT_FALSE);
  70. return;
  71. }
  72. /* take mutex and not release */
  73. result = rt_mutex_take(&static_mutex, RT_WAITING_FOREVER);
  74. if (RT_EOK != result)
  75. uassert_true(RT_FALSE);
  76. rt_thread_t tid = rt_thread_create("mutex_th",
  77. static_mutex_take_entry,
  78. &static_mutex,
  79. THREAD_STACKSIZE,
  80. 10,
  81. 10);
  82. if (RT_NULL == tid)
  83. {
  84. uassert_true(RT_FALSE);
  85. return;
  86. }
  87. /* startup thread take second */
  88. rt_thread_startup(tid);
  89. /* let system schedule */
  90. rt_thread_mdelay(5);
  91. result = rt_mutex_detach(&static_mutex);
  92. if (RT_EOK != result)
  93. uassert_true(RT_FALSE);
  94. uassert_true(RT_TRUE);
  95. }
  96. /* static release test */
  97. static void static_mutex_release_entry(void *param)
  98. {
  99. rt_err_t result;
  100. rt_mutex_t mutex;
  101. int rand_num = rand() % 0x1000;
  102. mutex = (rt_mutex_t)param;
  103. result = rt_mutex_take(mutex, rand_num);
  104. if (RT_EOK != result)
  105. {
  106. uassert_true(RT_FALSE);
  107. }
  108. }
  109. static void test_static_mutex_release(void)
  110. {
  111. rt_err_t result;
  112. result = rt_mutex_init(&static_mutex, "static_mutex", RT_IPC_FLAG_PRIO);
  113. if (RT_EOK != result)
  114. {
  115. uassert_true(RT_FALSE);
  116. return;
  117. }
  118. /* take mutex */
  119. result = rt_mutex_take(&static_mutex, RT_WAITING_FOREVER);
  120. if (RT_EOK != result)
  121. uassert_true(RT_FALSE);
  122. /* release mutex */
  123. result = rt_mutex_release(&static_mutex);
  124. if (RT_EOK != result)
  125. uassert_true(RT_FALSE);
  126. rt_thread_t tid = rt_thread_create("mutex_th",
  127. static_mutex_release_entry,
  128. &static_mutex,
  129. THREAD_STACKSIZE,
  130. 10,
  131. 10);
  132. if (RT_NULL == tid)
  133. {
  134. uassert_true(RT_FALSE);
  135. return;
  136. }
  137. /* startup thread and take mutex second */
  138. rt_thread_startup(tid);
  139. /* let system schedule */
  140. rt_thread_mdelay(5);
  141. result = rt_mutex_detach(&static_mutex);
  142. if (RT_EOK != result)
  143. uassert_true(RT_FALSE);
  144. uassert_true(RT_TRUE);
  145. }
  146. /* static trytake test */
  147. static void static_mutex_trytake_entry(void *param)
  148. {
  149. rt_err_t result;
  150. rt_mutex_t mutex;
  151. mutex = (rt_mutex_t)param;
  152. result = rt_mutex_trytake(mutex);
  153. if (RT_EOK == result)
  154. {
  155. uassert_true(RT_FALSE);
  156. }
  157. }
  158. static void test_static_mutex_trytake(void)
  159. {
  160. rt_err_t result;
  161. result = rt_mutex_init(&static_mutex, "static_mutex", RT_IPC_FLAG_PRIO);
  162. if (RT_EOK != result)
  163. {
  164. uassert_true(RT_FALSE);
  165. return;
  166. }
  167. /* take mutex and not release */
  168. result = rt_mutex_take(&static_mutex, RT_WAITING_FOREVER);
  169. if (RT_EOK != result)
  170. uassert_true(RT_FALSE);
  171. rt_thread_t tid = rt_thread_create("mutex_th",
  172. static_mutex_trytake_entry,
  173. &static_mutex,
  174. THREAD_STACKSIZE,
  175. 10,
  176. 10);
  177. if (RT_NULL == tid)
  178. {
  179. uassert_true(RT_FALSE);
  180. return;
  181. }
  182. /* startup thread and trytake mutex second */
  183. rt_thread_startup(tid);
  184. /* let system schedule */
  185. rt_thread_mdelay(5);
  186. result = rt_mutex_detach(&static_mutex);
  187. if (RT_EOK != result)
  188. uassert_true(RT_FALSE);
  189. uassert_true(RT_TRUE);
  190. }
  191. static rt_thread_t tid1 = RT_NULL;
  192. static rt_thread_t tid2 = RT_NULL;
  193. static rt_thread_t tid3 = RT_NULL;
  194. /* static mutex priority reverse test */
  195. static void static_thread1_entry(void *param)
  196. {
  197. /* let system schedule */
  198. rt_thread_mdelay(100);
  199. /* thread3 hode mutex thread2 take mutex */
  200. /* check thread2 and thread3 priority */
  201. if (RT_SCHED_PRIV(tid2).current_priority != RT_SCHED_PRIV(tid3).current_priority)
  202. {
  203. uassert_true(RT_FALSE);
  204. }
  205. else
  206. {
  207. uassert_true(RT_TRUE);
  208. }
  209. }
  210. static void static_thread2_entry(void *param)
  211. {
  212. rt_err_t result;
  213. rt_mutex_t mutex = (rt_mutex_t)param;
  214. /* let system schedule */
  215. rt_thread_mdelay(50);
  216. result = rt_mutex_take(mutex, RT_WAITING_FOREVER);
  217. if (result == RT_EOK)
  218. {
  219. rt_mutex_release(mutex);
  220. }
  221. }
  222. static void static_thread3_entry(void *param)
  223. {
  224. rt_tick_t tick;
  225. rt_err_t result;
  226. rt_mutex_t mutex = (rt_mutex_t)param;
  227. result = rt_mutex_take(mutex, RT_WAITING_FOREVER);
  228. if (result != RT_EOK)
  229. {
  230. uassert_true(RT_FALSE);
  231. }
  232. tick = rt_tick_get();
  233. while (rt_tick_get() - tick < (RT_TICK_PER_SECOND / 2));
  234. rt_mutex_release(mutex);
  235. }
  236. static void test_static_pri_reverse(void)
  237. {
  238. rt_err_t result;
  239. tid1 = RT_NULL;
  240. tid2 = RT_NULL;
  241. tid3 = RT_NULL;
  242. result = rt_mutex_init(&static_mutex, "static_mutex", RT_IPC_FLAG_PRIO);
  243. if (RT_EOK != result)
  244. {
  245. uassert_true(RT_FALSE);
  246. return;
  247. }
  248. /* thread1 */
  249. tid1 = rt_thread_create("thread1",
  250. static_thread1_entry,
  251. &static_mutex,
  252. UTEST_THR_STACK_SIZE,
  253. 10 - 1,
  254. 10);
  255. if (tid1 != RT_NULL)
  256. rt_thread_startup(tid1);
  257. /* thread2 */
  258. tid2 = rt_thread_create("thread2",
  259. static_thread2_entry,
  260. &static_mutex,
  261. UTEST_THR_STACK_SIZE,
  262. 10,
  263. 10);
  264. if (tid2 != RT_NULL)
  265. rt_thread_startup(tid2);
  266. /* thread3 */
  267. tid3 = rt_thread_create("thread3",
  268. static_thread3_entry,
  269. &static_mutex,
  270. UTEST_THR_STACK_SIZE,
  271. 10 + 1,
  272. 10);
  273. if (tid3 != RT_NULL)
  274. rt_thread_startup(tid3);
  275. rt_thread_mdelay(1000);
  276. result = rt_mutex_detach(&static_mutex);
  277. if (RT_EOK != result)
  278. uassert_true(RT_FALSE);
  279. uassert_true(RT_TRUE);
  280. }
  281. /* create test */
  282. static void test_dynamic_mutex_create(void)
  283. {
  284. rt_err_t result = -RT_ERROR;
  285. /* PRIO mode */
  286. dynamic_mutex = rt_mutex_create("dynamic_mutex", RT_IPC_FLAG_PRIO);
  287. if (RT_NULL == dynamic_mutex)
  288. {
  289. uassert_true(RT_FALSE);
  290. }
  291. result = rt_mutex_delete(dynamic_mutex);
  292. if (RT_EOK != result)
  293. {
  294. uassert_true(RT_FALSE);
  295. }
  296. /* FIFO mode */
  297. dynamic_mutex = rt_mutex_create("dynamic_mutex", RT_IPC_FLAG_PRIO);
  298. if (RT_NULL == dynamic_mutex)
  299. {
  300. uassert_true(RT_FALSE);
  301. }
  302. result = rt_mutex_delete(dynamic_mutex);
  303. if (RT_EOK != result)
  304. {
  305. uassert_true(RT_FALSE);
  306. }
  307. uassert_true(RT_TRUE);
  308. }
  309. /* dynamic take test */
  310. static void dynamic_mutex_take_entry(void *param)
  311. {
  312. rt_err_t result;
  313. rt_mutex_t mutex;
  314. int rand_num = rand() % 0x1000;
  315. mutex = (rt_mutex_t)param;
  316. result = rt_mutex_take(mutex, rand_num);
  317. if (RT_EOK == result)
  318. {
  319. uassert_true(RT_FALSE);
  320. }
  321. }
  322. static void test_dynamic_mutex_take(void)
  323. {
  324. rt_err_t result;
  325. dynamic_mutex = rt_mutex_create("dynamic_mutex", RT_IPC_FLAG_PRIO);
  326. if (RT_NULL == dynamic_mutex)
  327. {
  328. uassert_true(RT_FALSE);
  329. return;
  330. }
  331. /* take mutex and not release */
  332. result = rt_mutex_take(dynamic_mutex, RT_WAITING_FOREVER);
  333. if (RT_EOK != result)
  334. uassert_true(RT_FALSE);
  335. rt_thread_t tid = rt_thread_create("mutex_th",
  336. dynamic_mutex_take_entry,
  337. dynamic_mutex,
  338. THREAD_STACKSIZE,
  339. 10,
  340. 10);
  341. if (RT_NULL == tid)
  342. {
  343. uassert_true(RT_FALSE);
  344. return;
  345. }
  346. /* startup thread take second */
  347. rt_thread_startup(tid);
  348. /* let system schedule */
  349. rt_thread_mdelay(5);
  350. result = rt_mutex_delete(dynamic_mutex);
  351. if (RT_EOK != result)
  352. uassert_true(RT_FALSE);
  353. uassert_true(RT_TRUE);
  354. }
  355. /* dynamic release test */
  356. static void dynamic_mutex_release_entry(void *param)
  357. {
  358. rt_err_t result;
  359. rt_mutex_t mutex;
  360. int rand_num = rand() % 0x1000;
  361. mutex = (rt_mutex_t)param;
  362. result = rt_mutex_take(mutex, rand_num);
  363. if (RT_EOK != result)
  364. {
  365. uassert_true(RT_FALSE);
  366. }
  367. }
  368. static void test_dynamic_mutex_release(void)
  369. {
  370. rt_err_t result;
  371. dynamic_mutex = rt_mutex_create("dynamic_mutex", RT_IPC_FLAG_PRIO);
  372. if (RT_NULL == dynamic_mutex)
  373. {
  374. uassert_true(RT_FALSE);
  375. return;
  376. }
  377. /* take mutex */
  378. result = rt_mutex_take(dynamic_mutex, RT_WAITING_FOREVER);
  379. if (RT_EOK != result)
  380. uassert_true(RT_FALSE);
  381. /* release mutex */
  382. result = rt_mutex_release(dynamic_mutex);
  383. if (RT_EOK != result)
  384. uassert_true(RT_FALSE);
  385. rt_thread_t tid = rt_thread_create("mutex_th",
  386. dynamic_mutex_release_entry,
  387. dynamic_mutex,
  388. THREAD_STACKSIZE,
  389. 10,
  390. 10);
  391. if (RT_NULL == tid)
  392. {
  393. uassert_true(RT_FALSE);
  394. return;
  395. }
  396. /* startup thread and take mutex second */
  397. rt_thread_startup(tid);
  398. /* let system schedule */
  399. rt_thread_mdelay(5);
  400. result = rt_mutex_delete(dynamic_mutex);
  401. if (RT_EOK != result)
  402. uassert_true(RT_FALSE);
  403. uassert_true(RT_TRUE);
  404. }
  405. /* dynamic trytake test */
  406. static void dynamic_mutex_trytake_entry(void *param)
  407. {
  408. rt_err_t result;
  409. rt_mutex_t mutex;
  410. mutex = (rt_mutex_t)param;
  411. result = rt_mutex_trytake(mutex);
  412. if (RT_EOK == result)
  413. {
  414. uassert_true(RT_FALSE);
  415. }
  416. }
  417. static void test_dynamic_mutex_trytake(void)
  418. {
  419. rt_err_t result;
  420. dynamic_mutex = rt_mutex_create("dynamic_mutex", RT_IPC_FLAG_PRIO);
  421. if (RT_NULL == dynamic_mutex)
  422. {
  423. uassert_true(RT_FALSE);
  424. return;
  425. }
  426. /* take mutex and not release */
  427. result = rt_mutex_take(dynamic_mutex, RT_WAITING_FOREVER);
  428. if (RT_EOK != result)
  429. uassert_true(RT_FALSE);
  430. rt_thread_t tid = rt_thread_create("mutex_th",
  431. dynamic_mutex_trytake_entry,
  432. dynamic_mutex,
  433. THREAD_STACKSIZE,
  434. 10,
  435. 10);
  436. if (RT_NULL == tid)
  437. {
  438. uassert_true(RT_FALSE);
  439. return;
  440. }
  441. /* startup thread and trytake mutex second */
  442. rt_thread_startup(tid);
  443. /* let system schedule */
  444. rt_thread_mdelay(5);
  445. result = rt_mutex_delete(dynamic_mutex);
  446. if (RT_EOK != result)
  447. uassert_true(RT_FALSE);
  448. uassert_true(RT_TRUE);
  449. }
  450. /* dynamic mutex priority reverse test */
  451. static void dynamic_thread1_entry(void *param)
  452. {
  453. /* let system schedule */
  454. rt_thread_mdelay(100);
  455. /* thread3 hode mutex thread2 take mutex */
  456. /* check thread2 and thread3 priority */
  457. if (RT_SCHED_PRIV(tid2).current_priority != RT_SCHED_PRIV(tid3).current_priority)
  458. {
  459. uassert_true(RT_FALSE);
  460. }
  461. else
  462. {
  463. uassert_true(RT_TRUE);
  464. }
  465. }
  466. static void dynamic_thread2_entry(void *param)
  467. {
  468. rt_err_t result;
  469. rt_mutex_t mutex = (rt_mutex_t)param;
  470. /* let system schedule */
  471. rt_thread_mdelay(50);
  472. result = rt_mutex_take(mutex, RT_WAITING_FOREVER);
  473. if (result == RT_EOK)
  474. {
  475. rt_mutex_release(mutex);
  476. }
  477. }
  478. static void dynamic_thread3_entry(void *param)
  479. {
  480. rt_tick_t tick;
  481. rt_err_t result;
  482. rt_mutex_t mutex = (rt_mutex_t)param;
  483. result = rt_mutex_take(mutex, RT_WAITING_FOREVER);
  484. if (result != RT_EOK)
  485. {
  486. uassert_true(RT_FALSE);
  487. }
  488. tick = rt_tick_get();
  489. while (rt_tick_get() - tick < (RT_TICK_PER_SECOND / 2));
  490. rt_mutex_release(mutex);
  491. }
  492. static void test_dynamic_pri_reverse(void)
  493. {
  494. rt_err_t result;
  495. tid1 = RT_NULL;
  496. tid2 = RT_NULL;
  497. tid3 = RT_NULL;
  498. dynamic_mutex = rt_mutex_create("dynamic_mutex", RT_IPC_FLAG_PRIO);
  499. if (RT_NULL == dynamic_mutex)
  500. {
  501. uassert_true(RT_FALSE);
  502. return;
  503. }
  504. /* thread1 */
  505. tid1 = rt_thread_create("thread1",
  506. dynamic_thread1_entry,
  507. dynamic_mutex,
  508. UTEST_THR_STACK_SIZE,
  509. 10 - 1,
  510. 10);
  511. if (tid1 != RT_NULL)
  512. rt_thread_startup(tid1);
  513. /* thread2 */
  514. tid2 = rt_thread_create("thread2",
  515. dynamic_thread2_entry,
  516. dynamic_mutex,
  517. UTEST_THR_STACK_SIZE,
  518. 10,
  519. 10);
  520. if (tid2 != RT_NULL)
  521. rt_thread_startup(tid2);
  522. /* thread3 */
  523. tid3 = rt_thread_create("thread3",
  524. dynamic_thread3_entry,
  525. dynamic_mutex,
  526. UTEST_THR_STACK_SIZE,
  527. 10 + 1,
  528. 10);
  529. if (tid3 != RT_NULL)
  530. rt_thread_startup(tid3);
  531. rt_thread_mdelay(1000);
  532. result = rt_mutex_delete(dynamic_mutex);
  533. if (RT_EOK != result)
  534. uassert_true(RT_FALSE);
  535. uassert_true(RT_TRUE);
  536. }
  537. static rt_err_t utest_tc_init(void)
  538. {
  539. #ifdef RT_USING_HEAP
  540. dynamic_mutex = RT_NULL;
  541. #endif /* RT_USING_HEAP */
  542. return RT_EOK;
  543. }
  544. static rt_err_t utest_tc_cleanup(void)
  545. {
  546. #ifdef RT_USING_HEAP
  547. dynamic_mutex = RT_NULL;
  548. #endif /* RT_USING_HEAP */
  549. return RT_EOK;
  550. }
  551. static void testcase(void)
  552. {
  553. UTEST_UNIT_RUN(test_static_mutex_init);
  554. UTEST_UNIT_RUN(test_static_mutex_take);
  555. UTEST_UNIT_RUN(test_static_mutex_release);
  556. UTEST_UNIT_RUN(test_static_mutex_trytake);
  557. UTEST_UNIT_RUN(test_static_pri_reverse);
  558. #ifdef RT_USING_HEAP
  559. UTEST_UNIT_RUN(test_dynamic_mutex_create);
  560. UTEST_UNIT_RUN(test_dynamic_mutex_take);
  561. UTEST_UNIT_RUN(test_dynamic_mutex_release);
  562. UTEST_UNIT_RUN(test_dynamic_mutex_trytake);
  563. UTEST_UNIT_RUN(test_dynamic_pri_reverse);
  564. #endif
  565. }
  566. UTEST_TC_EXPORT(testcase, "testcases.kernel.mutex_tc", utest_tc_init, utest_tc_cleanup, 1000);
  567. /********************* end of file ************************/