espidf_thread.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #ifndef _GNU_SOURCE
  6. #define _GNU_SOURCE
  7. #endif
  8. #include "platform_api_vmcore.h"
  9. #include "platform_api_extension.h"
  10. typedef struct {
  11. thread_start_routine_t start;
  12. void *arg;
  13. } thread_wrapper_arg;
  14. static void *
  15. os_thread_wrapper(void *arg)
  16. {
  17. thread_wrapper_arg *targ = arg;
  18. thread_start_routine_t start_func = targ->start;
  19. void *thread_arg = targ->arg;
  20. #if 0
  21. os_printf("THREAD CREATED %jx\n", (uintmax_t)(uintptr_t)pthread_self());
  22. #endif
  23. BH_FREE(targ);
  24. start_func(thread_arg);
  25. return NULL;
  26. }
  27. korp_tid
  28. os_self_thread(void)
  29. {
  30. /* only allowed if this is a thread, xTaskCreate is not enough look at
  31. * product_mini for how to use this*/
  32. return pthread_self();
  33. }
  34. int
  35. os_mutex_init(korp_mutex *mutex)
  36. {
  37. return pthread_mutex_init(mutex, NULL);
  38. }
  39. int
  40. os_recursive_mutex_init(korp_mutex *mutex)
  41. {
  42. int ret;
  43. pthread_mutexattr_t mattr;
  44. assert(mutex);
  45. ret = pthread_mutexattr_init(&mattr);
  46. if (ret)
  47. return BHT_ERROR;
  48. pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);
  49. ret = pthread_mutex_init(mutex, &mattr);
  50. pthread_mutexattr_destroy(&mattr);
  51. return ret == 0 ? BHT_OK : BHT_ERROR;
  52. }
  53. int
  54. os_mutex_destroy(korp_mutex *mutex)
  55. {
  56. return pthread_mutex_destroy(mutex);
  57. }
  58. int
  59. os_mutex_lock(korp_mutex *mutex)
  60. {
  61. return pthread_mutex_lock(mutex);
  62. }
  63. int
  64. os_mutex_unlock(korp_mutex *mutex)
  65. {
  66. return pthread_mutex_unlock(mutex);
  67. }
  68. int
  69. os_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start,
  70. void *arg, unsigned int stack_size, int prio)
  71. {
  72. pthread_attr_t tattr;
  73. thread_wrapper_arg *targ;
  74. assert(stack_size > 0);
  75. assert(tid);
  76. assert(start);
  77. pthread_attr_init(&tattr);
  78. pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE);
  79. if (pthread_attr_setstacksize(&tattr, stack_size) != 0) {
  80. os_printf("Invalid thread stack size %u. Min stack size = %u",
  81. stack_size, PTHREAD_STACK_MIN);
  82. pthread_attr_destroy(&tattr);
  83. return BHT_ERROR;
  84. }
  85. targ = (thread_wrapper_arg *)BH_MALLOC(sizeof(*targ));
  86. if (!targ) {
  87. pthread_attr_destroy(&tattr);
  88. return BHT_ERROR;
  89. }
  90. targ->start = start;
  91. targ->arg = arg;
  92. #ifdef CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM
  93. esp_pthread_cfg_t default_config = esp_pthread_get_default_config();
  94. default_config.stack_alloc_caps = MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM;
  95. ESP_ERROR_CHECK(esp_pthread_set_cfg(&default_config));
  96. #endif
  97. if (pthread_create(tid, &tattr, os_thread_wrapper, targ) != 0) {
  98. pthread_attr_destroy(&tattr);
  99. os_free(targ);
  100. return BHT_ERROR;
  101. }
  102. pthread_attr_destroy(&tattr);
  103. return BHT_OK;
  104. }
  105. int
  106. os_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg,
  107. unsigned int stack_size)
  108. {
  109. return os_thread_create_with_prio(tid, start, arg, stack_size,
  110. BH_THREAD_DEFAULT_PRIORITY);
  111. }
  112. int
  113. os_thread_join(korp_tid thread, void **retval)
  114. {
  115. return pthread_join(thread, retval);
  116. }
  117. int
  118. os_thread_detach(korp_tid tid)
  119. {
  120. return pthread_detach(tid);
  121. }
  122. void
  123. os_thread_exit(void *retval)
  124. {
  125. pthread_exit(retval);
  126. }
  127. int
  128. os_cond_init(korp_cond *cond)
  129. {
  130. return pthread_cond_init(cond, NULL);
  131. }
  132. int
  133. os_cond_destroy(korp_cond *cond)
  134. {
  135. return pthread_cond_destroy(cond);
  136. }
  137. int
  138. os_cond_wait(korp_cond *cond, korp_mutex *mutex)
  139. {
  140. return pthread_cond_wait(cond, mutex);
  141. }
  142. static void
  143. msec_nsec_to_abstime(struct timespec *ts, uint64 usec)
  144. {
  145. struct timeval tv;
  146. time_t tv_sec_new;
  147. long int tv_nsec_new;
  148. gettimeofday(&tv, NULL);
  149. tv_sec_new = (time_t)(tv.tv_sec + usec / 1000000);
  150. if (tv_sec_new >= tv.tv_sec) {
  151. ts->tv_sec = tv_sec_new;
  152. }
  153. else {
  154. /* integer overflow */
  155. ts->tv_sec = BH_TIME_T_MAX;
  156. os_printf("Warning: os_cond_reltimedwait exceeds limit, "
  157. "set to max timeout instead\n");
  158. }
  159. tv_nsec_new = (long int)(tv.tv_usec * 1000 + (usec % 1000000) * 1000);
  160. if (tv.tv_usec * 1000 >= tv.tv_usec && tv_nsec_new >= tv.tv_usec * 1000) {
  161. ts->tv_nsec = tv_nsec_new;
  162. }
  163. else {
  164. /* integer overflow */
  165. ts->tv_nsec = LONG_MAX;
  166. os_printf("Warning: os_cond_reltimedwait exceeds limit, "
  167. "set to max timeout instead\n");
  168. }
  169. if (ts->tv_nsec >= 1000000000L && ts->tv_sec < BH_TIME_T_MAX) {
  170. ts->tv_sec++;
  171. ts->tv_nsec -= 1000000000L;
  172. }
  173. }
  174. int
  175. os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds)
  176. {
  177. int ret;
  178. struct timespec abstime;
  179. if (useconds == BHT_WAIT_FOREVER)
  180. ret = pthread_cond_wait(cond, mutex);
  181. else {
  182. msec_nsec_to_abstime(&abstime, useconds);
  183. ret = pthread_cond_timedwait(cond, mutex, &abstime);
  184. }
  185. if (ret != BHT_OK && ret != ETIMEDOUT)
  186. return BHT_ERROR;
  187. return ret;
  188. }
  189. int
  190. os_cond_signal(korp_cond *cond)
  191. {
  192. return pthread_cond_signal(cond);
  193. }
  194. int
  195. os_cond_broadcast(korp_cond *cond)
  196. {
  197. return pthread_cond_broadcast(cond);
  198. }
  199. int
  200. os_rwlock_init(korp_rwlock *lock)
  201. {
  202. assert(lock);
  203. if (pthread_rwlock_init(lock, NULL) != BHT_OK)
  204. return BHT_ERROR;
  205. return BHT_OK;
  206. }
  207. int
  208. os_rwlock_rdlock(korp_rwlock *lock)
  209. {
  210. assert(lock);
  211. if (pthread_rwlock_rdlock(lock) != BHT_OK)
  212. return BHT_ERROR;
  213. return BHT_OK;
  214. }
  215. int
  216. os_rwlock_wrlock(korp_rwlock *lock)
  217. {
  218. assert(lock);
  219. if (pthread_rwlock_wrlock(lock) != BHT_OK)
  220. return BHT_ERROR;
  221. return BHT_OK;
  222. }
  223. int
  224. os_rwlock_unlock(korp_rwlock *lock)
  225. {
  226. assert(lock);
  227. if (pthread_rwlock_unlock(lock) != BHT_OK)
  228. return BHT_ERROR;
  229. return BHT_OK;
  230. }
  231. int
  232. os_rwlock_destroy(korp_rwlock *lock)
  233. {
  234. assert(lock);
  235. if (pthread_rwlock_destroy(lock) != BHT_OK)
  236. return BHT_ERROR;
  237. return BHT_OK;
  238. }