mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
systrap: handler interrupted contexts in __export_start
contexts with pending interrupts should not be executed. PiperOrigin-RevId: 521835904
This commit is contained in:
@@ -160,6 +160,7 @@ static void set_fsbase(uint64_t fsbase) {
|
||||
struct thread_context *switch_context_amd64(
|
||||
struct sysmsg *sysmsg, struct thread_context *ctx,
|
||||
enum thread_state new_thread_state, enum context_state new_context_state) {
|
||||
struct thread_context *old_ctx = sysmsg->context;
|
||||
|
||||
for (;;) {
|
||||
// TODO(b/271631387): Once stub code globals can be used between objects
|
||||
@@ -189,6 +190,9 @@ struct thread_context *switch_context_amd64(
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (old_ctx != ctx || ctx->last_thread_id != sysmsg->thread_id) {
|
||||
ctx->fpstate_changed = 1;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
@@ -366,6 +370,20 @@ void __syshandler() {
|
||||
}
|
||||
}
|
||||
|
||||
void __export_start(struct sysmsg *sysmsg, void *_ucontext) {
|
||||
#if defined(__x86_64__)
|
||||
asm volatile("movq %%gs:0, %0\n" : "=r"(sysmsg) : :);
|
||||
if (sysmsg->self != sysmsg) {
|
||||
panic(0xdeaddead);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct thread_context *ctx = switch_context_amd64(
|
||||
sysmsg, NULL, THREAD_STATE_EVENT, CONTEXT_STATE_INVALID);
|
||||
|
||||
restore_state(sysmsg, ctx, _ucontext);
|
||||
}
|
||||
|
||||
// asm_restore_state is implemented in syshandler_amd64.S
|
||||
void asm_restore_state();
|
||||
|
||||
|
||||
@@ -91,6 +91,10 @@ static void ptregs_to_gregs(ucontext_t *ucontext,
|
||||
ucontext->uc_mcontext.pstate = ptregs->pstate;
|
||||
}
|
||||
|
||||
void __export_start(struct sysmsg *sysmsg, void *_ucontext) {
|
||||
panic(0x11111111);
|
||||
}
|
||||
|
||||
void __export_sighandler(int signo, siginfo_t *siginfo, void *_ucontext) {
|
||||
ucontext_t *ucontext = _ucontext;
|
||||
void *sp = sysmsg_sp();
|
||||
@@ -98,16 +102,18 @@ void __export_sighandler(int signo, siginfo_t *siginfo, void *_ucontext) {
|
||||
|
||||
if (sysmsg != sysmsg->self) panic(0xdeaddead);
|
||||
int32_t thread_state = __atomic_load_n(&sysmsg->state, __ATOMIC_ACQUIRE);
|
||||
|
||||
uint32_t ctx_state = CONTEXT_STATE_INVALID;
|
||||
struct thread_context *ctx = NULL, *old_ctx = NULL;
|
||||
if (__export_context_decoupling_exp &&
|
||||
thread_state == THREAD_STATE_INITIALIZING) {
|
||||
// Find a new context and exit to restore it.
|
||||
__export_start(sysmsg, _ucontext);
|
||||
return;
|
||||
goto init;
|
||||
}
|
||||
|
||||
struct thread_context *ctx = sysmsg->context;
|
||||
ctx = sysmsg->context;
|
||||
old_ctx = sysmsg->context;
|
||||
|
||||
uint32_t ctx_state = CONTEXT_STATE_INVALID;
|
||||
ctx->signo = signo;
|
||||
|
||||
gregs_to_ptregs(ucontext, &ctx->ptregs);
|
||||
@@ -154,6 +160,7 @@ void __export_sighandler(int signo, siginfo_t *siginfo, void *_ucontext) {
|
||||
return;
|
||||
}
|
||||
|
||||
init:
|
||||
for (;;) {
|
||||
if (__export_context_decoupling_exp) {
|
||||
ctx = switch_context(sysmsg, ctx, ctx_state);
|
||||
@@ -174,6 +181,10 @@ void __export_sighandler(int signo, siginfo_t *siginfo, void *_ucontext) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (old_ctx != ctx || ctx->last_thread_id != sysmsg->thread_id) {
|
||||
ctx->fpstate_changed = 1;
|
||||
}
|
||||
restore_state(sysmsg, ctx, _ucontext);
|
||||
}
|
||||
|
||||
|
||||
@@ -259,41 +259,20 @@ struct thread_context *switch_context(struct sysmsg *sysmsg,
|
||||
enum context_state new_context_state) {
|
||||
struct context_queue *queue = __export_context_queue_addr;
|
||||
|
||||
__atomic_sub_fetch(&queue->num_active_contexts, 1, __ATOMIC_ACQ_REL);
|
||||
__atomic_store_n(&ctx->thread_id, INVALID_THREAD_ID, __ATOMIC_RELEASE);
|
||||
__atomic_store_n(&ctx->last_thread_id, sysmsg->thread_id, __ATOMIC_RELEASE);
|
||||
__atomic_store_n(&ctx->state, new_context_state, __ATOMIC_RELEASE);
|
||||
if (__atomic_load_n(&ctx->sentry_fast_path, __ATOMIC_ACQUIRE) == 0) {
|
||||
int ret = sys_futex(&ctx->state, FUTEX_WAKE, 1, NULL, NULL, 0);
|
||||
if (ret < 0) {
|
||||
panic(ret);
|
||||
if (ctx) {
|
||||
__atomic_sub_fetch(&queue->num_active_contexts, 1, __ATOMIC_ACQ_REL);
|
||||
__atomic_store_n(&ctx->thread_id, INVALID_THREAD_ID, __ATOMIC_RELEASE);
|
||||
__atomic_store_n(&ctx->last_thread_id, sysmsg->thread_id, __ATOMIC_RELEASE);
|
||||
__atomic_store_n(&ctx->state, new_context_state, __ATOMIC_RELEASE);
|
||||
if (__atomic_load_n(&ctx->sentry_fast_path, __ATOMIC_ACQUIRE) == 0) {
|
||||
int ret = sys_futex(&ctx->state, FUTEX_WAKE, 1, NULL, NULL, 0);
|
||||
if (ret < 0) {
|
||||
panic(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct thread_context *old_ctx = sysmsg->context;
|
||||
|
||||
ctx = get_context(sysmsg);
|
||||
|
||||
if (old_ctx != ctx || ctx->last_thread_id != sysmsg->thread_id) {
|
||||
ctx->fpstate_changed = 1;
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void __export_start(struct sysmsg *sysmsg, void *_ucontext) {
|
||||
#if defined(__x86_64__)
|
||||
asm volatile("movq %%gs:0, %0\n" : "=r"(sysmsg) : :);
|
||||
if (sysmsg->self != sysmsg) {
|
||||
panic(0xdeaddead);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct thread_context *ctx = get_context(sysmsg);
|
||||
__atomic_store_n(&ctx->fpstate_changed, 1, __ATOMIC_RELEASE);
|
||||
__atomic_store_n(&ctx->thread_id, sysmsg->thread_id, __ATOMIC_RELEASE);
|
||||
|
||||
restore_state(sysmsg, ctx, _ucontext);
|
||||
return get_context(sysmsg);
|
||||
}
|
||||
|
||||
int wait_state(struct sysmsg *sysmsg, enum thread_state new_thread_state) {
|
||||
|
||||
Reference in New Issue
Block a user