@@ -51,28 +51,29 @@ LUAMOD_API int luaopen_ltask_root(lua_State *L);
5151#define MAINTHREAD_STATUS_INVALID 4
5252
5353struct mainthread_session {
54- service_id srv ;
54+ atomic_int srv ;
5555 struct cond ev ;
5656 int status ;
5757};
5858
5959static void
6060mainthread_init (struct mainthread_session * mt ) {
61- mt -> srv . id = 0 ;
61+ atomic_int_init ( & mt -> srv , 0 ) ;
6262 mt -> status = MAINTHREAD_STATUS_NONE ;
6363 cond_create (& mt -> ev );
6464}
6565
6666static void
6767mainthread_deinit (struct mainthread_session * mt ) {
6868 assert (mt -> status == MAINTHREAD_STATUS_NONE || mt -> status == MAINTHREAD_STATUS_YIELD );
69+ atomic_int_store (& mt -> srv , 0 );
6970 mt -> status = MAINTHREAD_STATUS_INVALID ;
7071 cond_release (& mt -> ev );
7172}
7273
7374static inline int
7475mainthread_current (struct mainthread_session * mt , service_id id ) {
75- return mt -> srv . id == id . id && mt -> status == MAINTHREAD_STATUS_READY ;
76+ return mt -> status == MAINTHREAD_STATUS_READY && atomic_int_load ( & mt -> srv ) == id . id ;
7677}
7778
7879static inline void
@@ -208,7 +209,7 @@ collect_done_job(struct ltask *task, service_id done_job[]) {
208209 for (i = 0 ;i < worker_n ;i ++ ) {
209210 struct worker_thread * w = & task -> workers [i ];
210211 service_id job = worker_done_job (w );
211- if (job .id && ! mainthread_current ( & task -> mt , job ) ) {
212+ if (job .id ) {
212213 debug_printf (task -> logger , "Service %x is done" , job .id );
213214 done_job [done_job_n ++ ] = job ;
214215 }
@@ -695,6 +696,7 @@ thread_worker(void *ud) {
695696 } else if (mainthread_current (& w -> task -> mt , id )) {
696697 service_status_set (P , id , SERVICE_STATUS_MAINTHREAD );
697698 mainthread_trigger (& w -> task -> mt );
699+ w -> running .id = 0 ;
698700 } else {
699701 service_status_set (P , id , SERVICE_STATUS_DONE );
700702 }
@@ -712,17 +714,19 @@ thread_worker(void *ud) {
712714 w -> binding = id ;
713715 }
714716
715- while (worker_complete_job (w )) {
716- // Can't complete (running -> done)
717- if (!acquire_scheduler (w )) {
718- if (worker_complete_job (w )) {
719- // Do it self
720- schedule_dispatch (w -> task );
721- while (worker_complete_job (w )) {} // CAS may fail spuriously
717+ if (w -> running .id ) {
718+ while (worker_complete_job (w )) {
719+ // Can't complete (running -> done)
720+ if (!acquire_scheduler (w )) {
721+ if (worker_complete_job (w )) {
722+ // Do it self
723+ schedule_dispatch (w -> task );
724+ while (worker_complete_job (w )) {} // CAS may fail spuriously
725+ }
726+ schedule_dispatch_worker (w );
727+ release_scheduler (w );
728+ break ;
722729 }
723- schedule_dispatch_worker (w );
724- release_scheduler (w );
725- break ;
726730 }
727731 }
728732 } else {
@@ -1157,14 +1161,18 @@ lmainthread_wait(lua_State *L) {
11571161 if (mt -> status != MAINTHREAD_STATUS_READY )
11581162 luaL_error (L , "mainthread not ready" );
11591163
1160- service_id id = mt -> srv ;
1164+ service_id id = { atomic_int_load (& mt -> srv ) };
1165+ atomic_int_store (& mt -> srv , 0 );
11611166
11621167 debug_printf (task -> logger , "service %x run in mainthread" , id .id );
11631168 assert (service_status_get (P , id ) == SERVICE_STATUS_MAINTHREAD );
11641169 if (service_resume (P , id )) {
11651170 // dead
11661171 debug_printf (task -> logger , "service %x is dead in mainthread" , id .id );
11671172 service_status_set (P , id , SERVICE_STATUS_DEAD );
1173+ if (id .id != SERVICE_ID_ROOT ) {
1174+ service_send_signal (P , id );
1175+ }
11681176 } else {
11691177 service_status_set (P , id , SERVICE_STATUS_SCHEDULE );
11701178 switch (mt -> status ) {
@@ -1178,14 +1186,17 @@ lmainthread_wait(lua_State *L) {
11781186 default :
11791187 debug_printf (task -> logger , "service %x is dead in mainthread" , id .id );
11801188 service_status_set (P , id , SERVICE_STATUS_DEAD );
1189+ if (id .id != SERVICE_ID_ROOT ) {
1190+ service_send_signal (P , id );
1191+ }
11811192 schedule_back (task , id );
11821193 return luaL_error (L , "Can't yield in mainthread (status = %d), kill service (%d)" , mt -> status , id .id );
11831194 }
1184- schedule_back (task , id );
11851195 }
1196+ schedule_back (task , id );
11861197 mt -> status = MAINTHREAD_STATUS_NONE ;
11871198 } while (!finish );
1188- return 0 ;
1199+ atomic_int_store ( & mt -> srv , 0 ); return 0 ;
11891200}
11901201
11911202LUAMOD_API int
@@ -1660,9 +1671,12 @@ static int
16601671mainthread_change_status (lua_State * L , int status ) {
16611672 const struct service_ud * S = getS (L );
16621673 struct ltask * task = S -> task ;
1663- task -> mt .srv = S -> id ;
1664- task -> mt .status = status ;
1665- return 0 ;
1674+ if (atomic_int_cas (& task -> mt .srv , 0 , S -> id .id )) {
1675+ task -> mt .status = status ;
1676+ return 0 ;
1677+ } else {
1678+ return luaL_error (L , "Change mainthread status fail" );
1679+ }
16661680}
16671681
16681682static int
0 commit comments