Fix ring reader ignoring signals and unqueuing threads twice

This commit is contained in:
Mark
2020-02-05 13:28:11 +02:00
parent 533bc8567a
commit 41ae3d7aab
7 changed files with 33 additions and 21 deletions
+9 -6
View File
@@ -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
+6 -1
View File
@@ -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
+3 -2
View File
@@ -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
-1
View File
@@ -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;
}
+4
View File
@@ -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
View File
@@ -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
View File
@@ -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) {