Fix ring reader ignoring signals and unqueuing threads twice
This commit is contained in:
@@ -18,6 +18,15 @@ amd64_exc_isr_\n:
|
||||
|
||||
.section .text
|
||||
amd64_exc_generic:
|
||||
// 0x18: cs
|
||||
// 0x10: rip
|
||||
// 0x08: error code
|
||||
// 0x00: error number
|
||||
cmpq $0x08, 0x18(%rip)
|
||||
jnz 1f
|
||||
swapgs
|
||||
1:
|
||||
|
||||
// Push full CPU context for dump
|
||||
pushq %rax
|
||||
pushq %rcx
|
||||
@@ -37,9 +46,6 @@ amd64_exc_generic:
|
||||
pushq %r14
|
||||
pushq %r15
|
||||
|
||||
pushq %fs
|
||||
pushq %gs
|
||||
|
||||
movq $AMD64_STACK_CTX_CANARY, %rax
|
||||
pushq %rax
|
||||
|
||||
@@ -53,9 +59,6 @@ amd64_exc_generic:
|
||||
1:
|
||||
addq $8, %rsp
|
||||
|
||||
popq %gs
|
||||
popq %fs
|
||||
|
||||
popq %r15
|
||||
popq %r14
|
||||
popq %r13
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include "arch/amd64/asm/asm_cpu.h"
|
||||
|
||||
.section .text
|
||||
.global spin_lock
|
||||
.global spin_release
|
||||
@@ -13,9 +15,12 @@ spin_lock_irqsave:
|
||||
cli
|
||||
|
||||
spin_lock:
|
||||
movq get_cpu(CPU_ID), %rax
|
||||
shlq $1, %rax
|
||||
// %rdi - spinlock
|
||||
lock bts $0, (%rdi)
|
||||
lock btsq $0, (%rdi)
|
||||
jc 1f
|
||||
orq %rax, (%rdi)
|
||||
retq
|
||||
|
||||
// Failed to obtain lock immediately, wait
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#define CPU_THREAD 0x08
|
||||
#define CPU_TSS 0x10
|
||||
#define CPU_SYSCALL_RSP 0x18
|
||||
#define CPU_ID 0x28
|
||||
|
||||
#define TSS_RSP0 0x04
|
||||
|
||||
@@ -37,9 +38,9 @@ struct cpu {
|
||||
struct thread *thread; // 0x08
|
||||
amd64_tss_t *tss; // 0x10
|
||||
uint64_t syscall_rsp; // 0x18
|
||||
uint64_t ticks;
|
||||
uint64_t ticks; // 0x20
|
||||
|
||||
uint64_t processor_id;
|
||||
uint64_t processor_id; // 0x28
|
||||
|
||||
// No need to define offsets for these: ther're not accessed
|
||||
// from assembly
|
||||
|
||||
@@ -34,7 +34,6 @@ extern struct cpu cpus[AMD64_MAX_SMP];
|
||||
|
||||
static inline struct cpu *get_cpu(void) {
|
||||
struct cpu *cpu;
|
||||
_assert(rdmsr(MSR_IA32_KERNEL_GS_BASE));
|
||||
asm volatile ("movq %%gs:0, %0":"=r"(cpu));
|
||||
return cpu;
|
||||
}
|
||||
|
||||
@@ -78,7 +78,11 @@ int ring_getc(struct thread *ctx, struct ring *ring, char *c, int err) {
|
||||
ctx->wait_next = ctx;
|
||||
ring->reader_head = ctx;
|
||||
|
||||
_assert(ctx->cpu >= 0);
|
||||
sched_unqueue(ctx, THREAD_WAITING_IO);
|
||||
|
||||
thread_check_signal(ctx, 0);
|
||||
_assert(ctx->cpu >= 0);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
+1
-1
@@ -91,7 +91,7 @@ void sched_unqueue(struct thread *thr, enum thread_state new_state) {
|
||||
|
||||
struct cpu *cpu = get_cpu();
|
||||
#if defined(AMD64_SMP)
|
||||
_assert(thr->cpu >= 0);
|
||||
assert(thr->cpu >= 0, "Tried to unqueue non-queued thread\n");
|
||||
if ((int) cpu->processor_id != thr->cpu) {
|
||||
// Need to ask another CPU to unqueue the task
|
||||
panic("TODO: implement cross-CPU unqueue\n");
|
||||
|
||||
+10
-10
@@ -662,28 +662,28 @@ void thread_signal(struct thread *thr, int signum) {
|
||||
if (thr->cpu == (int) get_cpu()->processor_id) {
|
||||
if (thr == thread_self) {
|
||||
kdebug("Signal will be handled now\n");
|
||||
thread_sigenter(signum);
|
||||
//thread_sigenter(signum);
|
||||
} else {
|
||||
kdebug("Signal will be handled later\n");
|
||||
thread_signal_set(thr, signum);
|
||||
|
||||
if (thr->state == THREAD_WAITING) {
|
||||
timer_remove_sleep(thr);
|
||||
}
|
||||
//if (thr->state == THREAD_WAITING) {
|
||||
// timer_remove_sleep(thr);
|
||||
//}
|
||||
|
||||
sched_queue(thr);
|
||||
//sched_queue(thr);
|
||||
}
|
||||
} else if (thr->cpu >= 0) {
|
||||
kdebug("Signal will be handled later (other cpu%d)\n", thr->cpu);
|
||||
thread_signal_set(thr, signum);
|
||||
|
||||
if (thr->state == THREAD_WAITING) {
|
||||
timer_remove_sleep(thr);
|
||||
}
|
||||
//if (thr->state == THREAD_WAITING) {
|
||||
// timer_remove_sleep(thr);
|
||||
//}
|
||||
|
||||
sched_queue(thr);
|
||||
//sched_queue(thr);
|
||||
} else {
|
||||
kdebug("Signal will be handled later\n");
|
||||
kdebug("Signal will be handled later (not running)\n");
|
||||
thread_signal_set(thr, signum);
|
||||
|
||||
if (thr->state == THREAD_WAITING) {
|
||||
|
||||
Reference in New Issue
Block a user