PikaPlatformEx.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. #include "PikaPlatformEx.h"
  2. //----------------------------- mutex -------------------------------
  3. // 带超时的互斥锁加锁
  4. int pika_platform_thread_mutex_timedlock(pika_platform_thread_mutex_t* m,
  5. pika_bool block,
  6. Arg* timeout) {
  7. #if defined(__linux) || (PIKA_WIN_PTHREAD_ENABLE)
  8. ArgType timout_type = arg_getType(timeout);
  9. pika_float timeout_f;
  10. int result;
  11. if (!(timout_type == ARG_TYPE_FLOAT || timout_type == ARG_TYPE_INT ||
  12. timout_type == ARG_TYPE_NONE)) {
  13. return PIKA_RES_ERR_INVALID_PARAM;
  14. }
  15. if (timout_type == ARG_TYPE_FLOAT || timout_type == ARG_TYPE_INT) {
  16. // printf("==== #01\n");
  17. if (timout_type == ARG_TYPE_FLOAT) {
  18. timeout_f = arg_getFloat(timeout);
  19. }
  20. if (timout_type == ARG_TYPE_INT) {
  21. int timeout_d = arg_getInt(timeout);
  22. timeout_f = (pika_float)timeout_d;
  23. // printf("==== #04 %lf\n", timeout_f);
  24. }
  25. if (timeout_f < 0.0f) {
  26. return PIKA_RES_ERR_INVALID_PARAM;
  27. }
  28. struct timespec ts;
  29. clock_gettime(CLOCK_REALTIME, &ts); // 获取当前时间
  30. // 将浮点数秒转换为秒和纳秒
  31. long sec = (long)timeout_f;
  32. long nsec = (long)((timeout_f - (pika_float)sec) * 1000000000.0);
  33. ts.tv_sec += sec;
  34. ts.tv_nsec += nsec;
  35. // 如果纳秒数超过 1 秒,则需要调整秒数和纳秒数
  36. if (ts.tv_nsec >= 1000000000) {
  37. ts.tv_nsec -= 1000000000; // 减去 1 秒的纳秒数
  38. ts.tv_sec += 1; // 增加 1 秒
  39. }
  40. pika_GIL_EXIT();
  41. result = pthread_mutex_timedlock(&m->mutex, &ts);
  42. pika_GIL_ENTER();
  43. return result == 0 ? 0 : -1;
  44. } else if (timout_type == ARG_TYPE_NONE) {
  45. if (block) {
  46. // printf("==== #02\n");
  47. pika_GIL_EXIT();
  48. result = pthread_mutex_lock(&m->mutex);
  49. pika_GIL_ENTER();
  50. return result == 0 ? 0 : -1;
  51. } else {
  52. // printf("==== #03\n");
  53. pika_GIL_EXIT();
  54. result = pthread_mutex_trylock(&m->mutex);
  55. pika_GIL_ENTER();
  56. return result == 0 ? 0 : -1;
  57. }
  58. } else {
  59. return PIKA_RES_ERR_INVALID_PARAM;
  60. }
  61. #elif PIKA_FREERTOS_ENABLE
  62. if (pdTRUE == xSemaphoreTake(m->mutex, (TickType_t)(timeout * 1000.0f))) {
  63. return 0;
  64. }
  65. return -1;
  66. #elif PIKA_RTTHREAD_ENABLE
  67. return rt_mutex_take((m->mutex), (rt_tick_t)(timeout * RT_TICK_PER_SECOND));
  68. #elif PIKA_ZEUSOS_ENABLE
  69. return zos_mutex_lock(m->mutex, (uint32_t)(timeout * 1000.0f));
  70. #else
  71. WEAK_FUNCTION_NEED_OVERRIDE_ERROR(_);
  72. return -1;
  73. #endif
  74. }
  75. //----------------------------- rtmutex -------------------------------
  76. // 初始化递归互斥锁
  77. void pika_platform_thread_rtmutex_init(pika_platform_thread_rtmutex_t* rtm) {
  78. #if defined(__linux) || (PIKA_WIN_PTHREAD_ENABLE)
  79. pthread_mutexattr_t attr;
  80. if (pthread_mutexattr_init(&attr) != 0) {
  81. perror("pthread_mutexattr_init");
  82. exit(EXIT_FAILURE);
  83. }
  84. // 设置互斥锁类型为递归互斥锁
  85. if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0) {
  86. perror("pthread_mutexattr_settype");
  87. pthread_mutexattr_destroy(&attr);
  88. exit(EXIT_FAILURE);
  89. }
  90. pthread_mutex_init(&rtm->mutex, &attr);
  91. pthread_cond_init(&rtm->cond, NULL);
  92. rtm->owner = (pthread_t)0;
  93. rtm->count = 0;
  94. #elif PIKA_FREERTOS_ENABLE
  95. #elif PIKA_RTTHREAD_ENABLE
  96. #elif PIKA_ZEUSOS_ENABLE
  97. #else
  98. WEAK_FUNCTION_NEED_OVERRIDE_ERROR(_);
  99. #endif
  100. }
  101. // 销毁递归互斥锁
  102. void pika_platform_thread_rtmutex_destroy(pika_platform_thread_rtmutex_t* rtm) {
  103. #if defined(__linux) || (PIKA_WIN_PTHREAD_ENABLE)
  104. pthread_cond_destroy(&rtm->cond);
  105. pthread_mutex_destroy(&rtm->mutex);
  106. #elif PIKA_FREERTOS_ENABLE
  107. #elif PIKA_RTTHREAD_ENABLE
  108. #elif PIKA_ZEUSOS_ENABLE
  109. #else
  110. WEAK_FUNCTION_NEED_OVERRIDE_ERROR(_);
  111. #endif
  112. }
  113. // 带超时的递归互斥锁加锁
  114. int pika_platform_thread_rtmutex_lock(pika_platform_thread_rtmutex_t* rtm,
  115. pika_bool block,
  116. Arg* timeout) {
  117. #if defined(__linux) || (PIKA_WIN_PTHREAD_ENABLE)
  118. ArgType timout_type = arg_getType(timeout);
  119. pika_float timeout_f;
  120. int result;
  121. if (!(timout_type == ARG_TYPE_FLOAT || timout_type == ARG_TYPE_INT ||
  122. timout_type == ARG_TYPE_NONE)) {
  123. return PIKA_RES_ERR_INVALID_PARAM;
  124. }
  125. pika_GIL_EXIT();
  126. pthread_mutex_lock(&rtm->mutex);
  127. pika_GIL_ENTER();
  128. if (rtm->owner == pthread_self()) {
  129. // 如果当前线程已经持有锁,则递归深度加1
  130. rtm->count++;
  131. // printf("rtm->count = %d\n", rtm->count);
  132. pthread_mutex_unlock(&rtm->mutex);
  133. // printf("succ\n");
  134. return 0;
  135. }
  136. if (timout_type == ARG_TYPE_FLOAT || timout_type == ARG_TYPE_INT) {
  137. // printf("==== #01\n");
  138. if (timout_type == ARG_TYPE_FLOAT) {
  139. timeout_f = arg_getFloat(timeout);
  140. }
  141. if (timout_type == ARG_TYPE_INT) {
  142. int timeout_d = arg_getInt(timeout);
  143. timeout_f = (pika_float)timeout_d;
  144. // printf("==== #04 %lf\n", timeout_f);
  145. }
  146. if (timeout_f < 0.0f) {
  147. return PIKA_RES_ERR_INVALID_PARAM;
  148. }
  149. struct timespec ts;
  150. clock_gettime(CLOCK_REALTIME, &ts); // 获取当前时间
  151. // 将浮点数秒转换为秒和纳秒
  152. long sec = (long)timeout_f;
  153. long nsec = (long)((timeout_f - (pika_float)sec) * 1000000000.0);
  154. ts.tv_sec += sec;
  155. ts.tv_nsec += nsec;
  156. // 如果纳秒数超过 1 秒,则需要调整秒数和纳秒数
  157. if (ts.tv_nsec >= 1000000000) {
  158. ts.tv_nsec -= 1000000000; // 减去 1 秒的纳秒数
  159. ts.tv_sec += 1; // 增加 1 秒
  160. }
  161. // 等待直到获得锁或超时
  162. while (rtm->owner != (pthread_t)0) {
  163. pika_GIL_EXIT();
  164. result = pthread_cond_timedwait(&rtm->cond, &rtm->mutex, &ts);
  165. pika_GIL_ENTER();
  166. if (result != 0) {
  167. pthread_mutex_unlock(&rtm->mutex);
  168. return -1;
  169. }
  170. }
  171. // 设置当前线程为锁的持有者
  172. rtm->owner = pthread_self();
  173. rtm->count = 1;
  174. pthread_mutex_unlock(&rtm->mutex);
  175. return 0;
  176. } else if (timout_type == ARG_TYPE_NONE) {
  177. if (block) {
  178. // 永久等待
  179. while (rtm->owner != (pthread_t)0) {
  180. pika_GIL_EXIT();
  181. result = pthread_cond_wait(&rtm->cond, &rtm->mutex);
  182. pika_GIL_ENTER();
  183. if (result != 0) {
  184. pthread_mutex_unlock(&rtm->mutex);
  185. return -1;
  186. }
  187. }
  188. // 设置当前线程为锁的持有者
  189. rtm->owner = pthread_self();
  190. rtm->count = 1;
  191. pthread_mutex_unlock(&rtm->mutex);
  192. return 0;
  193. } else {
  194. // 非阻塞模式
  195. if (rtm->owner == (pthread_t)0) {
  196. // 如果没有其他线程持有锁,获取锁
  197. rtm->owner = pthread_self();
  198. rtm->count = 1;
  199. pthread_mutex_unlock(&rtm->mutex);
  200. return 0;
  201. } else {
  202. // 如果已经有其他线程持有锁,立即返回 -1
  203. pthread_mutex_unlock(&rtm->mutex);
  204. return -1;
  205. }
  206. }
  207. } else {
  208. return PIKA_RES_ERR_INVALID_PARAM;
  209. }
  210. #elif PIKA_FREERTOS_ENABLE
  211. #elif PIKA_RTTHREAD_ENABLE
  212. #elif PIKA_ZEUSOS_ENABLE
  213. #else
  214. WEAK_FUNCTION_NEED_OVERRIDE_ERROR(_);
  215. #endif
  216. }
  217. #if 1
  218. // 释放递归互斥锁
  219. int pika_platform_thread_rtmutex_unlock(pika_platform_thread_rtmutex_t* rtm) {
  220. #if defined(__linux) || (PIKA_WIN_PTHREAD_ENABLE)
  221. pthread_t self = pthread_self();
  222. pika_GIL_EXIT();
  223. pthread_mutex_lock(&rtm->mutex);
  224. pika_GIL_ENTER();
  225. // printf("rtm->owner = %lu\n", rtm->owner);
  226. if (rtm->owner != self) {
  227. perror("Attempt to unlock a mutex not owned by the current thread");
  228. pthread_mutex_unlock(&rtm->mutex);
  229. return -1;
  230. }
  231. rtm->count--;
  232. if (rtm->count == 0) {
  233. rtm->owner = (pthread_t)0;
  234. pthread_cond_signal(&rtm->cond);
  235. // printf("rtm->owner = %lu\n", rtm->owner);
  236. }
  237. pthread_mutex_unlock(&rtm->mutex);
  238. return 0;
  239. #elif PIKA_FREERTOS_ENABLE
  240. #elif PIKA_RTTHREAD_ENABLE
  241. #elif PIKA_ZEUSOS_ENABLE
  242. #else
  243. WEAK_FUNCTION_NEED_OVERRIDE_ERROR(_);
  244. #endif
  245. }
  246. #endif
  247. // 检查递归互斥锁是否已被当前线程获取
  248. int pika_platform_thread_rtmutex_locked(pika_platform_thread_rtmutex_t* rtm) {
  249. #if defined(__linux) || (PIKA_WIN_PTHREAD_ENABLE)
  250. pthread_t self = pthread_self();
  251. pika_GIL_EXIT();
  252. pthread_mutex_lock(&rtm->mutex);
  253. pika_GIL_ENTER();
  254. int is_locked = (rtm->owner == self && rtm->count > 0);
  255. pthread_mutex_unlock(&rtm->mutex);
  256. return is_locked;
  257. #elif PIKA_FREERTOS_ENABLE
  258. #elif PIKA_RTTHREAD_ENABLE
  259. #elif PIKA_ZEUSOS_ENABLE
  260. #else
  261. WEAK_FUNCTION_NEED_OVERRIDE_ERROR(_);
  262. #endif
  263. }
  264. //----------------------------- cond -------------------------------
  265. void pika_platform_thread_cond_init(pika_platform_thread_cond_t* cond) {
  266. #if defined(__linux) || (PIKA_WIN_PTHREAD_ENABLE)
  267. pika_platform_thread_rtmutex_init(&cond->rtmutex);
  268. pthread_cond_init(&cond->cond, NULL);
  269. cond->owner = (pthread_t)0;
  270. #elif PIKA_FREERTOS_ENABLE
  271. #elif PIKA_RTTHREAD_ENABLE
  272. #elif PIKA_ZEUSOS_ENABLE
  273. #else
  274. WEAK_FUNCTION_NEED_OVERRIDE_ERROR(_);
  275. #endif
  276. }
  277. void pika_platform_thread_cond_destroy(pika_platform_thread_cond_t* cond) {
  278. #if defined(__linux) || (PIKA_WIN_PTHREAD_ENABLE)
  279. pthread_cond_destroy(&cond->cond);
  280. pika_platform_thread_rtmutex_destroy(&cond->rtmutex);
  281. cond->owner = (pthread_t)0; // 释放资源后重置 owner
  282. #elif PIKA_FREERTOS_ENABLE
  283. #elif PIKA_RTTHREAD_ENABLE
  284. #elif PIKA_ZEUSOS_ENABLE
  285. #else
  286. WEAK_FUNCTION_NEED_OVERRIDE_ERROR(_);
  287. #endif
  288. }
  289. // 检查当前线程是否持有互斥锁
  290. static int is_mutex_owned(pika_platform_thread_cond_t* cond) {
  291. // pthread_t current_thread = pthread_self();
  292. // 使用 pthread_mutex_trylock 来检查是否已经持有锁
  293. if (pthread_mutex_trylock(&cond->rtmutex.mutex) == EBUSY) {
  294. // 如果锁已经被持有,尝试解锁并检查是否是当前线程持有的
  295. if (pthread_mutex_unlock(&cond->rtmutex.mutex) == 0) {
  296. return 1; // 当前线程持有锁
  297. }
  298. }
  299. return 0;
  300. }
  301. // 带阻塞和超时功能的条件变量等待
  302. int pika_platform_thread_cond_timedwait(pika_platform_thread_cond_t* cond,
  303. Arg* timeout) {
  304. #if defined(__linux) || (PIKA_WIN_PTHREAD_ENABLE)
  305. ArgType timout_type = arg_getType(timeout);
  306. pika_float timeout_f;
  307. int result;
  308. // 检查是否已经获得了互斥锁
  309. if (!is_mutex_owned(cond)) {
  310. return -1;
  311. }
  312. if (!(timout_type == ARG_TYPE_FLOAT || timout_type == ARG_TYPE_INT ||
  313. timout_type == ARG_TYPE_NONE)) {
  314. return PIKA_RES_ERR_INVALID_PARAM;
  315. }
  316. if (timout_type == ARG_TYPE_FLOAT || timout_type == ARG_TYPE_INT) {
  317. if (timout_type == ARG_TYPE_FLOAT) {
  318. timeout_f = arg_getFloat(timeout);
  319. } else {
  320. int timeout_d = arg_getInt(timeout);
  321. timeout_f = (pika_float)timeout_d;
  322. }
  323. if (timeout_f < 0.0f) {
  324. return PIKA_RES_ERR_INVALID_PARAM;
  325. }
  326. struct timespec ts;
  327. clock_gettime(CLOCK_REALTIME, &ts); // 获取当前时间
  328. // 将浮点数秒转换为秒和纳秒
  329. long sec = (long)timeout_f;
  330. long nsec = (long)((timeout_f - (pika_float)sec) * 1000000000.0);
  331. ts.tv_sec += sec;
  332. ts.tv_nsec += nsec;
  333. // 如果纳秒数超过 1 秒,则需要调整秒数和纳秒数
  334. if (ts.tv_nsec >= 1000000000) {
  335. ts.tv_nsec -= 1000000000; // 减去 1 秒的纳秒数
  336. ts.tv_sec += 1; // 增加 1 秒
  337. }
  338. // 等待直到被通知或超时
  339. pika_GIL_EXIT();
  340. result = pthread_cond_timedwait(&cond->cond, &cond->rtmutex.mutex, &ts);
  341. pika_GIL_ENTER();
  342. if (result != 0) {
  343. if (result == ETIMEDOUT) {
  344. return -1; // 超时
  345. }
  346. perror("pthread_cond_timedwait");
  347. return -1; // 其他错误
  348. }
  349. } else if (timout_type == ARG_TYPE_NONE) {
  350. // 永久等待
  351. pika_GIL_EXIT();
  352. result = pthread_cond_wait(&cond->cond, &cond->rtmutex.mutex);
  353. pika_GIL_ENTER();
  354. if (result != 0) {
  355. perror("pthread_cond_wait");
  356. return -1;
  357. }
  358. } else {
  359. return PIKA_RES_ERR_INVALID_PARAM;
  360. }
  361. return 0;
  362. #elif PIKA_FREERTOS_ENABLE
  363. #elif PIKA_RTTHREAD_ENABLE
  364. #elif PIKA_ZEUSOS_ENABLE
  365. #else
  366. WEAK_FUNCTION_NEED_OVERRIDE_ERROR(_);
  367. #endif
  368. }
  369. // 信号量通知
  370. int pika_platform_thread_cond_signal(pika_platform_thread_cond_t* cond) {
  371. #if defined(__linux) || (PIKA_WIN_PTHREAD_ENABLE)
  372. int result;
  373. result = pthread_cond_signal(&cond->cond);
  374. cond->owner = (pthread_t)0; // 通知后重置 owner
  375. return result == 0 ? 0 : -1;
  376. #elif PIKA_FREERTOS_ENABLE
  377. #elif PIKA_RTTHREAD_ENABLE
  378. #elif PIKA_ZEUSOS_ENABLE
  379. #else
  380. WEAK_FUNCTION_NEED_OVERRIDE_ERROR(_);
  381. #endif
  382. }
  383. // 信号量广播
  384. int pika_platform_thread_cond_broadcast(pika_platform_thread_cond_t* cond) {
  385. #if defined(__linux) || (PIKA_WIN_PTHREAD_ENABLE)
  386. int result;
  387. result = pthread_cond_broadcast(&cond->cond);
  388. cond->owner = (pthread_t)0; // 广播后重置 owner
  389. return result == 0 ? 0 : -1;
  390. #elif PIKA_FREERTOS_ENABLE
  391. #elif PIKA_RTTHREAD_ENABLE
  392. #elif PIKA_ZEUSOS_ENABLE
  393. #else
  394. WEAK_FUNCTION_NEED_OVERRIDE_ERROR(_);
  395. #endif
  396. }