Skip to content

Commit 7ff66e3

Browse files
committed
There can only be one mainthread run at a time
1 parent 085073e commit 7ff66e3

1 file changed

Lines changed: 34 additions & 20 deletions

File tree

src/ltask.c

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -51,28 +51,29 @@ LUAMOD_API int luaopen_ltask_root(lua_State *L);
5151
#define MAINTHREAD_STATUS_INVALID 4
5252

5353
struct mainthread_session {
54-
service_id srv;
54+
atomic_int srv;
5555
struct cond ev;
5656
int status;
5757
};
5858

5959
static void
6060
mainthread_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

6666
static void
6767
mainthread_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

7374
static inline int
7475
mainthread_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

7879
static 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

11911202
LUAMOD_API int
@@ -1660,9 +1671,12 @@ static int
16601671
mainthread_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

16681682
static int

0 commit comments

Comments
 (0)