mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-26 15:03:53 +01:00
Merge pull request #1966 from Kijewski/semaphore-fix-irq
posix: Fix missing `restoreIRQ()` in `sem_post()`
This commit is contained in:
commit
263dbd7e2f
@ -47,7 +47,8 @@ int sem_init(sem_t *sem, int pshared, unsigned int value)
|
||||
int sem_destroy(sem_t *sem)
|
||||
{
|
||||
if (sem->queue.first) {
|
||||
DEBUG("%s: tried to destroy active semaphore.\n", sched_active_thread->name);
|
||||
DEBUG("sem_destroy: %" PRIkernel_pid ": tried to destroy active semaphore.\n",
|
||||
sched_active_thread->pid);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@ -72,44 +73,35 @@ int sem_unlink(const char *name)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void sem_thread_blocked(sem_t *sem)
|
||||
{
|
||||
/* I'm going blocked */
|
||||
sched_set_status((tcb_t*) sched_active_thread, STATUS_MUTEX_BLOCKED);
|
||||
|
||||
priority_queue_node_t n;
|
||||
n.priority = (uint32_t) sched_active_thread->priority;
|
||||
n.data = (size_t) sched_active_thread;
|
||||
n.next = NULL;
|
||||
|
||||
DEBUG("%s: Adding node to mutex queue: prio: %" PRIu32 "\n",
|
||||
sched_active_thread->name, n.priority);
|
||||
|
||||
/* add myself to the waiters queue */
|
||||
priority_queue_add(&sem->queue, &n);
|
||||
|
||||
/* scheduler should schedule an other thread, that unlocks the
|
||||
* mutex in the future, when this happens I get scheduled again
|
||||
*/
|
||||
thread_yield_higher();
|
||||
}
|
||||
|
||||
int sem_wait(sem_t *sem)
|
||||
{
|
||||
unsigned old_state = disableIRQ();
|
||||
while (1) {
|
||||
unsigned old_state = disableIRQ();
|
||||
|
||||
unsigned value = sem->value;
|
||||
if (value == 0) {
|
||||
sem_thread_blocked(sem);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
if (value != 0) {
|
||||
sem->value = value - 1;
|
||||
break;
|
||||
restoreIRQ(old_state);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* I'm going blocked */
|
||||
priority_queue_node_t n;
|
||||
n.priority = (uint32_t) sched_active_thread->priority;
|
||||
n.data = (uintptr_t) sched_active_thread;
|
||||
n.next = NULL;
|
||||
priority_queue_add(&sem->queue, &n);
|
||||
|
||||
DEBUG("sem_wait: %" PRIkernel_pid ": Adding node to mutex queue: prio: %" PRIu32 "\n",
|
||||
sched_active_thread->pid, sched_active_thread->priority);
|
||||
|
||||
/* scheduler should schedule an other thread, that unlocks the
|
||||
* mutex in the future, when this happens I get scheduled again
|
||||
*/
|
||||
sched_set_status((tcb_t*) sched_active_thread, STATUS_MUTEX_BLOCKED);
|
||||
restoreIRQ(old_state);
|
||||
thread_yield_higher();
|
||||
}
|
||||
restoreIRQ(old_state);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sem_timedwait(sem_t *sem, const struct timespec *abstime)
|
||||
@ -145,12 +137,18 @@ int sem_post(sem_t *sem)
|
||||
priority_queue_node_t *next = priority_queue_remove_head(&sem->queue);
|
||||
if (next) {
|
||||
tcb_t *next_process = (tcb_t*) next->data;
|
||||
DEBUG("%s: waking up %s\n", sched_active_thread->name, next_process->name);
|
||||
DEBUG("sem_post: %" PRIkernel_pid ": waking up %" PRIkernel_pid "\n",
|
||||
sched_active_thread->pid, next_process->pid);
|
||||
sched_set_status(next_process, STATUS_PENDING);
|
||||
sched_switch(next_process->priority);
|
||||
|
||||
uint16_t prio = next_process->priority;
|
||||
restoreIRQ(old_state);
|
||||
sched_switch(prio);
|
||||
}
|
||||
else {
|
||||
restoreIRQ(old_state);
|
||||
}
|
||||
|
||||
restoreIRQ(old_state);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
#include "thread.h"
|
||||
#include "semaphore.h"
|
||||
|
||||
#define SEMAPHORE_TEST_THREADS 10
|
||||
#define SEMAPHORE_TEST_THREADS 5
|
||||
char test1_thread_stack[KERNEL_CONF_STACKSIZE_MAIN];
|
||||
char test2_thread_stack[SEMAPHORE_TEST_THREADS][KERNEL_CONF_STACKSIZE_MAIN];
|
||||
|
||||
@ -70,18 +70,16 @@ static void test1(void)
|
||||
test1_second_thread,
|
||||
NULL,
|
||||
"second");
|
||||
|
||||
if (pid == KERNEL_PID_UNDEF) {
|
||||
puts("first: thread create failed");
|
||||
}
|
||||
|
||||
puts("first: thread created");
|
||||
|
||||
puts("first: sem_getvalue");
|
||||
int val;
|
||||
|
||||
if (sem_getvalue(&s, &val) != 0 || val != 0) {
|
||||
puts("first: sem_getvalue failed");
|
||||
puts("first: sem_getvalue FAILED");
|
||||
}
|
||||
|
||||
puts("first: sem_getvalue != 0");
|
||||
@ -95,7 +93,7 @@ static void test1(void)
|
||||
puts("first: sem_trywait");
|
||||
|
||||
if (sem_trywait(&s) != -1) {
|
||||
puts("first: sem_trywait failed");
|
||||
puts("first: sem_trywait FAILED");
|
||||
}
|
||||
|
||||
puts("first: sem_trywait done");
|
||||
@ -103,7 +101,7 @@ static void test1(void)
|
||||
puts("first: sem_post");
|
||||
|
||||
if (sem_post(&s) != 1) {
|
||||
puts("first: sem_post failed");
|
||||
puts("first: sem_post FAILED");
|
||||
}
|
||||
|
||||
puts("first: sem_post done");
|
||||
@ -113,21 +111,16 @@ static void test1(void)
|
||||
puts("first: sem_destroy");
|
||||
|
||||
if (sem_destroy(&s) != 0) {
|
||||
puts("first: sem_destroy failed");
|
||||
puts("first: sem_destroy FAILED");
|
||||
}
|
||||
|
||||
puts("first: end");
|
||||
}
|
||||
|
||||
static void *priority_sema_thread(void *arg)
|
||||
static void *priority_sema_thread(void *name)
|
||||
{
|
||||
(void) arg;
|
||||
sem_wait(&s);
|
||||
#ifdef DEVELHELP
|
||||
printf("Thread '%s' woke up.\n", thread_getname(thread_getpid()));
|
||||
#else
|
||||
printf("Thread with PID '%" PRIkernel_pid "' woke up.\n", thread_getpid());
|
||||
#endif
|
||||
printf("Thread '%s' woke up.\n", (const char *) name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -137,7 +130,7 @@ void test2(void)
|
||||
puts("first: sem_init");
|
||||
|
||||
if (sem_init(&s, 0, 0) != 0) {
|
||||
puts("first: sem_init failed");
|
||||
puts("first: sem_init FAILED");
|
||||
}
|
||||
|
||||
for (int i = 0; i < SEMAPHORE_TEST_THREADS; i++) {
|
||||
@ -150,11 +143,11 @@ void test2(void)
|
||||
priority,
|
||||
CREATE_STACKTEST,
|
||||
priority_sema_thread,
|
||||
NULL,
|
||||
names[i],
|
||||
names[i]);
|
||||
|
||||
if (pid == KERNEL_PID_UNDEF) {
|
||||
puts("first: thread create failed");
|
||||
puts("first: thread create FAILED");
|
||||
}
|
||||
|
||||
printf("first: thread created: %s (%d/%d)\n", names[i], i + 1, SEMAPHORE_TEST_THREADS);
|
||||
@ -171,10 +164,10 @@ void test2(void)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
puts("#########################");
|
||||
puts("######################### TEST1:");
|
||||
test1();
|
||||
puts("#########################");
|
||||
puts("######################### TEST2:");
|
||||
test2();
|
||||
puts("#########################");
|
||||
puts("######################### DONE");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user