_thread.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #include "_thread.h"
  2. #include "PikaVM.h"
  3. #include "TinyObj.h"
  4. #include "dataMemory.h"
  5. #if !PIKASCRIPT_VERSION_REQUIRE_MINIMUN(1, 13, 4)
  6. #error "pikapython version must be greater than 1.13.4"
  7. #endif
  8. static volatile int g_thread_stack_size = PIKA_THREAD_STACK_SIZE;
  9. #if !PIKA_THREAD_MALLOC_STACK_ENABLE
  10. extern volatile PikaMemInfo g_PikaMemInfo;
  11. #endif
  12. #if PIKA_FREERTOS_ENABLE
  13. static pika_platform_thread_t* g_thread_to_free = NULL;
  14. static pika_platform_thread_mutex_t g_thread_idle_hook_mutex = {0};
  15. static int g_thread_idle_hook_mutex_inited = 0;
  16. #if PIKA_THREAD_MALLOC_STACK_ENABLE
  17. void pika_thread_idle_hook(void) {
  18. if (0 == g_thread_idle_hook_mutex_inited) {
  19. pika_platform_thread_mutex_init(&g_thread_idle_hook_mutex);
  20. g_thread_idle_hook_mutex_inited = 1;
  21. }
  22. pika_platform_thread_mutex_lock(&g_thread_idle_hook_mutex);
  23. if (NULL != g_thread_to_free) {
  24. pika_platform_thread_exit(g_thread_to_free);
  25. pikaFree(g_thread_to_free->thread_stack,
  26. g_thread_to_free->thread_stack_size);
  27. pikaFree(g_thread_to_free, sizeof(pika_platform_thread_t));
  28. g_thread_to_free = NULL;
  29. }
  30. pika_platform_thread_mutex_unlock(&g_thread_idle_hook_mutex);
  31. return;
  32. }
  33. #endif
  34. #endif
  35. typedef struct pika_thread_info {
  36. Arg* function;
  37. Arg* args;
  38. pika_platform_thread_t* thread;
  39. int stack_size;
  40. } pika_thread_info;
  41. static void _thread_func(void* arg) {
  42. pika_debug("thread start");
  43. pika_GIL_ENTER();
  44. PikaVMThread* vmThread = pikaVMThread_require();
  45. vmThread->is_sub_thread = 1;
  46. PikaObj* ctx = New_TinyObj(NULL);
  47. pika_thread_info* info = (pika_thread_info*)arg;
  48. if (NULL != info->args) {
  49. obj_setArg(ctx, "args", info->args);
  50. }
  51. obj_setArg(ctx, "thread", info->function);
  52. if (NULL == info->args) {
  53. /* clang-format off */
  54. PIKA_PYTHON(
  55. thread()
  56. )
  57. /* clang-format on */
  58. const uint8_t bytes[] = {
  59. 0x04, 0x00, 0x00, 0x00, /* instruct array size */
  60. 0x00, 0x82, 0x01, 0x00, /* instruct array */
  61. 0x08, 0x00, 0x00, 0x00, /* const pool size */
  62. 0x00, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x00, /* const pool */
  63. };
  64. pikaVM_runByteCode(ctx, (uint8_t*)bytes);
  65. } else {
  66. /* clang-format off */
  67. PIKA_PYTHON(
  68. thread(*args)
  69. )
  70. /* clang-format on */
  71. const uint8_t bytes[] = {
  72. 0x0c, 0x00, 0x00, 0x00, /* instruct array size */
  73. 0x20, 0x81, 0x01, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x02, 0x08,
  74. 0x00,
  75. /* instruct array */
  76. 0x0f, 0x00, 0x00, 0x00, /* const pool size */
  77. 0x00, 0x61, 0x72, 0x67, 0x73, 0x00, 0x2a, 0x00, 0x74, 0x68, 0x72,
  78. 0x65, 0x61, 0x64, 0x00, /* const pool */
  79. };
  80. pikaVM_runByteCode(ctx, (uint8_t*)bytes);
  81. }
  82. obj_deinit(ctx);
  83. arg_deinit(info->function);
  84. if (NULL != info->args) {
  85. arg_deinit(info->args);
  86. }
  87. #if !PIKA_THREAD_MALLOC_STACK_ENABLE
  88. g_PikaMemInfo.heapUsed -= info->stack_size;
  89. #endif
  90. pika_debug("thread exiting");
  91. pika_platform_thread_t* thread = info->thread;
  92. pikaFree(info, sizeof(pika_thread_info));
  93. pika_GIL_EXIT();
  94. #if PIKA_FREERTOS_ENABLE
  95. #if PIKA_THREAD_MALLOC_STACK_ENABLE
  96. if (0 == g_thread_idle_hook_mutex_inited) {
  97. pika_platform_thread_mutex_init(&g_thread_idle_hook_mutex);
  98. g_thread_idle_hook_mutex_inited = 1;
  99. }
  100. pika_platform_thread_mutex_lock(&g_thread_idle_hook_mutex);
  101. while (NULL != g_thread_to_free) {
  102. pika_platform_thread_mutex_unlock(&g_thread_idle_hook_mutex);
  103. vTaskDelay(10);
  104. pika_platform_thread_mutex_lock(&g_thread_idle_hook_mutex);
  105. }
  106. g_thread_to_free = thread;
  107. pika_platform_thread_mutex_unlock(&g_thread_idle_hook_mutex);
  108. while (1) {
  109. vTaskDelay(1);
  110. }
  111. #else
  112. pikaFree(thread, sizeof(pika_platform_thread_t));
  113. pika_platform_thread_exit(NULL);
  114. #endif
  115. #else
  116. pika_platform_thread_exit(thread);
  117. #endif
  118. }
  119. void _thread_start_new_thread(PikaObj* self, Arg* function, Arg* args_) {
  120. pika_thread_info* info =
  121. (pika_thread_info*)pikaMalloc(sizeof(pika_thread_info));
  122. pika_platform_memset(info, 0, sizeof(pika_thread_info));
  123. info->function = arg_copy(function);
  124. if (arg_isObject(args_)) {
  125. PikaObj* tuple = arg_getPtr(args_);
  126. size_t tuple_size = pikaTuple_getSize(tuple);
  127. pika_debug("type of args is %d", arg_getType(args_));
  128. pika_debug("new_thread: args tuple size %d", tuple_size);
  129. if (tuple_size > 0) {
  130. info->args = arg_copy(args_);
  131. }
  132. } else {
  133. info->args = arg_copy(args_);
  134. }
  135. _VM_lock_init();
  136. if (!_VM_is_first_lock()) {
  137. pika_debug("first lock for main thread");
  138. pika_GIL_ENTER();
  139. pika_debug("VM num %d", _VMEvent_getVMCnt());
  140. }
  141. info->stack_size = g_thread_stack_size;
  142. pika_debug("thread stack size %d", info->stack_size);
  143. info->thread = pika_platform_thread_init("pika_thread", _thread_func, info,
  144. info->stack_size, PIKA_THREAD_PRIO,
  145. PIKA_THREAD_TICK);
  146. if (NULL == info->thread) {
  147. pikaFree(info, sizeof(pika_thread_info));
  148. obj_setErrorCode(self, PIKA_RES_ERR_RUNTIME_ERROR);
  149. obj_setSysOut(self, "thread create failed");
  150. return;
  151. }
  152. pika_platform_thread_startup(info->thread);
  153. #if !PIKA_THREAD_MALLOC_STACK_ENABLE
  154. g_PikaMemInfo.heapUsed += info->stack_size;
  155. #endif
  156. }
  157. int _thread_stack_size(PikaObj* self, PikaTuple* size) {
  158. if (pikaTuple_getSize(size) == 1) {
  159. int stack_size = pikaTuple_getInt(size, 0);
  160. if (stack_size == 0) {
  161. stack_size = PIKA_THREAD_STACK_SIZE;
  162. }
  163. g_thread_stack_size = stack_size;
  164. }
  165. return g_thread_stack_size;
  166. }