semaphore: signal safety

This commit is contained in:
Matheus
2024-05-08 20:13:12 -03:00
parent 0910232b56
commit bf841406d5
3 changed files with 23 additions and 7 deletions
+1 -1
View File
@@ -121,7 +121,7 @@ void sched_queue(thread_t *thread);
void sched_stopcurrentthread(); void sched_stopcurrentthread();
int sched_yield(); int sched_yield();
void sched_preparesleep(bool interruptible); void sched_preparesleep(bool interruptible);
void sched_wakeup(thread_t *thread, int reason); bool sched_wakeup(thread_t *thread, int reason);
int sched_sleep(); int sched_sleep();
proc_t *sched_newproc(); proc_t *sched_newproc();
vnode_t *sched_getcwd(); vnode_t *sched_getcwd();
+18 -4
View File
@@ -17,7 +17,8 @@ static void insert(semaphore_t *sem, thread_t *thread) {
static thread_t *get(semaphore_t *sem) { static thread_t *get(semaphore_t *sem) {
thread_t *thread = sem->tail; thread_t *thread = sem->tail;
__assert(thread); if (thread == NULL)
return NULL;
sem->tail = thread->sleepprev; sem->tail = thread->sleepprev;
@@ -44,6 +45,11 @@ int semaphore_wait(semaphore_t *sem, bool interruptible) {
sched_preparesleep(interruptible); sched_preparesleep(interruptible);
spinlock_release(&sem->lock); spinlock_release(&sem->lock);
ret = sched_yield(); ret = sched_yield();
if (ret) {
spinlock_acquire(&sem->lock);
++sem->i;
spinlock_release(&sem->lock);
}
goto leave; goto leave;
} }
@@ -57,9 +63,17 @@ void semaphore_signal(semaphore_t *sem) {
bool intstate = interrupt_set(false); bool intstate = interrupt_set(false);
spinlock_acquire(&sem->lock); spinlock_acquire(&sem->lock);
if (++sem->i <= 0) { if (++sem->i <= 0) {
thread_t *thread = get(sem); thread_t *thread;
// XXX the current method doesn't respect thread priorities do {
sched_wakeup(thread, 0); // wake SOMEONE up. this will *try* to wake up a thread
// it could wake up none though, as a thread could have been interrupted by a signal
thread = get(sem);
// XXX the current method doesn't respect thread priorities
if (thread) {
sched_wakeup(thread, 0);
break;
}
} while (thread);
} }
spinlock_release(&sem->lock); spinlock_release(&sem->lock);
interrupt_set(intstate); interrupt_set(intstate);
+4 -2
View File
@@ -417,14 +417,14 @@ void sched_preparesleep(bool interruptible) {
_cpu()->thread->flags |= SCHED_THREAD_FLAGS_SLEEP | (interruptible ? SCHED_THREAD_FLAGS_INTERRUPTIBLE : 0); _cpu()->thread->flags |= SCHED_THREAD_FLAGS_SLEEP | (interruptible ? SCHED_THREAD_FLAGS_INTERRUPTIBLE : 0);
} }
void sched_wakeup(thread_t *thread, int reason) { bool sched_wakeup(thread_t *thread, int reason) {
bool intstate = interrupt_set(false); bool intstate = interrupt_set(false);
spinlock_acquire(&thread->sleeplock); spinlock_acquire(&thread->sleeplock);
if ((thread->flags & SCHED_THREAD_FLAGS_SLEEP) == 0 || ((reason == SCHED_WAKEUP_REASON_INTERRUPTED) && (thread->flags & SCHED_THREAD_FLAGS_INTERRUPTIBLE) == 0)) { if ((thread->flags & SCHED_THREAD_FLAGS_SLEEP) == 0 || ((reason == SCHED_WAKEUP_REASON_INTERRUPTED) && (thread->flags & SCHED_THREAD_FLAGS_INTERRUPTIBLE) == 0)) {
spinlock_release(&thread->sleeplock); spinlock_release(&thread->sleeplock);
interrupt_set(intstate); interrupt_set(intstate);
return; return false;
} }
thread->flags &= ~(SCHED_THREAD_FLAGS_SLEEP | SCHED_THREAD_FLAGS_INTERRUPTIBLE); thread->flags &= ~(SCHED_THREAD_FLAGS_SLEEP | SCHED_THREAD_FLAGS_INTERRUPTIBLE);
@@ -433,6 +433,8 @@ void sched_wakeup(thread_t *thread, int reason) {
spinlock_release(&thread->sleeplock); spinlock_release(&thread->sleeplock);
sched_queue(thread); sched_queue(thread);
interrupt_set(intstate); interrupt_set(intstate);
return true;
} }
static vnode_t *getnodeslock(vnode_t **addr) { static vnode_t *getnodeslock(vnode_t **addr) {