Kaynağa Gözat

cancel GIL yiled between bc to avoid data race

pikastech 2 yıl önce
ebeveyn
işleme
c487912fc5

+ 1 - 1
examples/_thread/test1.py

@@ -27,6 +27,6 @@ _thread.start_new_thread(task1, ())
 _thread.start_new_thread(task2, (0.05, 10))
 
 while not task1_finished or not task2_finished:
-    pass
+    time.sleep(0.1)
 
 time.sleep(0.5)  # wait for threads to exit

+ 7 - 12
package/_thread/_thread.c

@@ -12,18 +12,6 @@ typedef struct pika_thread_info {
 } pika_thread_info;
 
 static void _thread_func(void* arg) {
-    pika_debug("waiting for first lock");
-    while (1) {
-        if (_VM_is_first_lock()) {
-            break;
-        }
-        //! This May break the thread
-        // if (_VMEvent_getVMCnt() <= 0) {
-        //     break;
-        // }
-        pika_debug("VM num %d", _VMEvent_getVMCnt());
-        pika_platform_thread_delay();
-    }
     pika_debug("thread start");
     pika_GIL_ENTER();
     PikaObj* ctx = New_TinyObj(NULL);
@@ -100,6 +88,13 @@ void _thread_start_new_thread(PikaObj* self, Arg* function, Arg* args_) {
     }
 
     _VM_lock_init();
+
+    if (!_VM_is_first_lock()) {
+        pika_debug("first lock for main thread");
+        pika_GIL_ENTER();
+        pika_debug("VM num %d", _VMEvent_getVMCnt());
+    }
+
     info->stack_size = g_thread_stack_size;
     info->thread = pika_platform_thread_init("pika_thread", _thread_func, info,
                                              info->stack_size, PIKA_THREAD_PRIO,

+ 2 - 2
port/linux/.vscode/launch.json

@@ -16,8 +16,8 @@
                 // "--gtest_filter=packtool.*"
                 // "--gtest_filter=os.path"
                 // "--gtest_filter=packtool.packread"
-                // "--gtest_filter=parser.char_issue1"
-                "--gtest_filter=eventloop.test1"
+                "--gtest_filter=thread.test1"
+                // "--gtest_filter=eventloop.test1"
             ],
             "stopAtEntry": false,
             "cwd": "${workspaceFolder}",

+ 7 - 12
port/linux/package/pikascript/pikascript-lib/_thread/_thread.c

@@ -12,18 +12,6 @@ typedef struct pika_thread_info {
 } pika_thread_info;
 
 static void _thread_func(void* arg) {
-    pika_debug("waiting for first lock");
-    while (1) {
-        if (_VM_is_first_lock()) {
-            break;
-        }
-        //! This May break the thread
-        // if (_VMEvent_getVMCnt() <= 0) {
-        //     break;
-        // }
-        pika_debug("VM num %d", _VMEvent_getVMCnt());
-        pika_platform_thread_delay();
-    }
     pika_debug("thread start");
     pika_GIL_ENTER();
     PikaObj* ctx = New_TinyObj(NULL);
@@ -100,6 +88,13 @@ void _thread_start_new_thread(PikaObj* self, Arg* function, Arg* args_) {
     }
 
     _VM_lock_init();
+
+    if (!_VM_is_first_lock()) {
+        pika_debug("first lock for main thread");
+        pika_GIL_ENTER();
+        pika_debug("VM num %d", _VMEvent_getVMCnt());
+    }
+
     info->stack_size = g_thread_stack_size;
     info->thread = pika_platform_thread_init("pika_thread", _thread_func, info,
                                              info->stack_size, PIKA_THREAD_PRIO,

+ 5 - 5
src/PikaObj.c

@@ -55,9 +55,9 @@ PikaObj* New_PikaStdData_Dict(Args* args);
 PikaObj* New_PikaStdData_dict_keys(Args* args);
 PikaObj* New_PikaStdData_List(Args* args);
 PikaObj* New_PikaStdData_Tuple(Args* args);
-void PikaStdData_Tuple___init__(PikaObj* self);
-void PikaStdData_List___init__(PikaObj* self);
-void PikaStdData_List_append(PikaObj* self, Arg* arg);
+void PikaStdData_Tuple___init__(PikaObj *self);
+void PikaStdData_List___init__(PikaObj *self);
+void PikaStdData_List_append(PikaObj *self, Arg* arg);
 void _mem_cache_deinit(void);
 void _VMEvent_deinit(void);
 void pikaGC_markObj(PikaGC* gc, PikaObj* self);
@@ -2471,8 +2471,8 @@ void pks_printVersion(void) {
 }
 
 void pks_getVersion(char* buff) {
-    pika_sprintf(buff, "%d.%d.%d", PIKA_VERSION_MAJOR, PIKA_VERSION_MINOR,
-                 PIKA_VERSION_MICRO);
+    pika_sprintf(buff, "%d.%d.%d", PIKA_VERSION_MAJOR,
+                          PIKA_VERSION_MINOR, PIKA_VERSION_MICRO);
 }
 
 void* obj_getStruct(PikaObj* self, char* name) {

+ 4 - 0
src/PikaPlatform.c

@@ -674,3 +674,7 @@ PIKA_WEAK void pika_platform_reboot(void) {
 PIKA_WEAK void pika_platform_clear(void) {
     WEAK_FUNCTION_NEED_OVERRIDE_ERROR();
 }
+
+PIKA_WEAK void pika_platform_abort_handler(void){
+    return;
+}

+ 2 - 0
src/PikaPlatform.h

@@ -48,6 +48,7 @@ extern "C" {
     #define pika_assert(expr) \
     if(!(expr)) { \
         pika_platform_printf((char*)"Assertion \"%s\" failed, in function: %s(). \r\n  (at %s:%d)\n", #expr, __FUNCTION__, __FILE__, __LINE__); \
+        pika_platform_abort_handler(); \
         abort(); \
     }
 #else
@@ -133,6 +134,7 @@ typedef enum {
 /* interrupt config */
 void pika_platform_enable_irq_handle(void);
 void pika_platform_disable_irq_handle(void);
+void pika_platform_abort_handler(void);
 
 /* printf family config */
 #ifndef pika_platform_printf

+ 6 - 2
src/PikaVM.c

@@ -4151,6 +4151,10 @@ void _pikaVM_yield(void) {
         _VMEvent_pickupEvent();
     }
 #endif
-    pika_GIL_EXIT();
-    pika_GIL_ENTER();
+    /*
+     * [Warning!] Can not use pika_GIL_ENTER() and pika_GIL_EXIT() here, because
+     * yield() is called not atomically, and it will cause data race.
+     */
+    // pika_GIL_EXIT();
+    // pika_GIL_ENTER();
 }

+ 1 - 1
test/python/_thread/test1.py

@@ -27,6 +27,6 @@ _thread.start_new_thread(task1, ())
 _thread.start_new_thread(task2, (0.05, 10))
 
 while not task1_finished or not task2_finished:
-    pass
+    time.sleep(0.1)
 
 time.sleep(0.5)  # wait for threads to exit