From d7501532a41c437d4d99e85b56ff05569c754555 Mon Sep 17 00:00:00 2001
From: Bart Kuivenhoven <
bemkuiv...@gmail.com>
Date: Tue, 20 Aug 2013 16:25:01 +0200
Subject: [PATCH 2/2] atomic: Disable interrupts to prevent blocking
In my opinion this is kind of iffy, but hey, if it does the trick!
Before the other CPU's are excluded from the data, the interrupts on the
running CPU are disabled. Next the other CPU's are excluded, and the
operation is run. Next the other CPU's are allowed again, before the
interrupts are enabled if they were in fact enabled before the start of
the function.
Signed-off-by: Bart Kuivenhoven <
bemkuiv...@gmail.com>
---
src/andromeda/atomic.c | 70
++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 68 insertions(+), 2 deletions(-)
diff --git a/src/andromeda/atomic.c b/src/andromeda/atomic.c
index 7f26951..4b034b0 100644
--- a/src/andromeda/atomic.c
+++ b/src/andromeda/atomic.c
@@ -19,33 +19,59 @@
#include <stdio.h>
#include <stdlib.h>
#include <thread.h>
+#include <andromeda/system.h>
int64_t atomic_add(atomic_t* d, int cnt)
{
+ /* Make sure we can't be interrupted, (avoids interrupt
blocking issues) */
+ int intState = cpu_disable_interrupts(0);
+ /* Make sure no other CPU can access this code */
mutex_lock(&d->lock);
+ /* Do the actual arithmetic */
d->cnt += cnt;
int64_t ret = d->cnt;
+ /* Allow other CPU's */
mutex_unlock(&d->lock);
+ /* If interrupts were previously enabled, reenable */
+ if (intState)
+ cpu_enable_interrupts(0);
return ret;
}
uint64_t
atomic_set(atomic_t *atom)
{
+ /* Avoid blocking issues with other interrupts! */
+ int intState = cpu_disable_interrupts(0);
+ /* Forbid other CPU's to touch our data */
mutex_lock(&atom->lock);
+ /* Set the bits! */
uint64_t ret = atom->cnt;
atom->cnt = 1;
+ /* Allow touching of this memory again */
mutex_unlock(&atom->lock);
+ /* If interrupts were previously allowed, allow them again */
+ if (intState)
+ cpu_enable_interrupts(0);
return ret;
}
uint64_t
atomic_reset(atomic_t *atom)
{
+ /* Atomic services, can I have your interrupts please? */
+ int intState = cpu_disable_interrupts(0);
+ /* I'll lock the door for you, please relax */
mutex_lock(&atom->lock);
+ /* Let's massage your bits to the correct value */
uint64_t ret = atom->cnt;
atom->cnt = 0;
+ /* We may be disturbed again */
mutex_unlock(&atom->lock);
+ /* And here are your interrupts */
+ if (intState)
+ cpu_enable_interrupts(0);
+ /* We hope to see you soon! */
return ret;
}
@@ -70,45 +96,85 @@ atomic_dec(atomic_t* d)
int64_t
atomic_get(atomic_t* d)
{
+ /* Save and disable interrupt state */
+ int intState = cpu_disable_interrupts(0);
+ /* BLOCK!!! */
mutex_lock(&d->lock);
int64_t ret = d->cnt;
+ /* UNBLOCK!!! */
mutex_unlock(&d->lock);
+ /* Return to previous interrupt state */
+ if (intState)
+ cpu_enable_interrupts(0);
return ret;
}
+void
+atomic_init(atomic_t* d)
+{
+ if (d == NULL)
+ return;
+ d->cnt = 0;
+ d->lock = mutex_unlocked;
+ return;
+}
+
int64_t
semaphore_inc(semaphore_t* s)
{
int64_t ret = 0;
+ int intState;
+ /* While we didn't complete our action */
while (1)
{
+ /* Fetch lock, no interrupts please */
+ intState = cpu_disable_interrupts(0);
mutex_lock(&s->lock);
+ /* Try to do our job */
if (s->cnt < s->limit)
{
ret = s->cnt ++;
break;
}
+ /* Apparently doing our job wasn't possible. Allow
interrupts
+ * and try again.
+ */
mutex_unlock(&s->lock);
+ if (intState)
+ cpu_enable_interrupts(0);
+ /**
+ * \todo Add a scheduler yield here.
+ */
}
+ /* Apparently we were sucessful, let's make everything as it
was
+ * and return */
mutex_unlock(&s->lock);
+ if (intState)
+ cpu_enable_interrupts(0);
return ret;
}
int64_t
semaphore_dec(semaphore_t* s)
{
+ /* This code is similar to the above function, look there for
comments */
int64_t ret = 0;
+ int intState;
while (1)
{
+ intState = cpu_disable_interrupts(0);
mutex_lock(&s->lock);
-
if (s->cnt > 0)
{
ret = s->cnt --;
break;
}
mutex_unlock(&s->lock);
+ if (intState)
+ cpu_enable_interrupts(0);
}
mutex_unlock(&s->lock);
+ if (intState)
+ cpu_enable_interrupts(0);
return ret;
-}
\ No newline at end of file
+}
--
1.8.3.4