aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2010-03-20 18:17:19 -0400
committerKevin O'Connor <kevin@koconnor.net>2010-03-20 18:17:19 -0400
commitd7eb27efa3f9265dca8357cfa05d9e0560fd4534 (patch)
treee47ab5db226465cf2a87276d161f861e626ccef5
parent7415270ed16175e443ac1b10205ccabbc964a309 (diff)
downloadseabios-hppa-d7eb27efa3f9265dca8357cfa05d9e0560fd4534.zip
seabios-hppa-d7eb27efa3f9265dca8357cfa05d9e0560fd4534.tar.gz
seabios-hppa-d7eb27efa3f9265dca8357cfa05d9e0560fd4534.tar.bz2
Don't move EBDA while an optionrom is running (CONFIG_THREAD_OPTIONROMS).
Moving the ebda while an optionrom is running could confuse it. So, avoid doing that.
-rw-r--r--src/pmm.c18
-rw-r--r--src/stacks.c12
-rw-r--r--src/types.h3
-rw-r--r--src/util.h1
4 files changed, 28 insertions, 6 deletions
diff --git a/src/pmm.c b/src/pmm.c
index 0461e41..1b90f21 100644
--- a/src/pmm.c
+++ b/src/pmm.c
@@ -74,12 +74,18 @@ relocate_ebda(u32 newebda, u32 oldebda, u8 ebda_size)
static void
zonelow_expand(u32 size, u32 align)
{
- u32 oldpos = GET_PMMVAR(ZoneLow.cur);
- u32 newpos = ALIGN_DOWN(oldpos - size, align);
- u32 bottom = GET_PMMVAR(ZoneLow.bottom);
- if (newpos >= bottom && newpos <= oldpos)
- // Space already present.
- return;
+ u32 oldpos, newpos, bottom;
+ for (;;) {
+ oldpos = GET_PMMVAR(ZoneLow.cur);
+ newpos = ALIGN_DOWN(oldpos - size, align);
+ bottom = GET_PMMVAR(ZoneLow.bottom);
+ if (newpos >= bottom && newpos <= oldpos)
+ // Space already present.
+ return;
+ // Make sure to not move ebda while an optionrom is running.
+ if (likely(!wait_preempt()))
+ break;
+ }
u16 ebda_seg = get_ebda_seg();
u32 ebda_pos = (u32)MAKE_FLATPTR(ebda_seg, 0);
u8 ebda_size = GET_EBDA2(ebda_seg, size);
diff --git a/src/stacks.c b/src/stacks.c
index c783967..4a30b3d 100644
--- a/src/stacks.c
+++ b/src/stacks.c
@@ -297,6 +297,18 @@ finish_preempt(void)
dprintf(1, "Done preempt - %d checks\n", PreemptCount);
}
+// Check if preemption is on, and wait for it to complete if so.
+int
+wait_preempt(void)
+{
+ if (MODESEGMENT || !CONFIG_THREADS || !CONFIG_THREAD_OPTIONROMS
+ || !CanPreempt)
+ return 0;
+ while (CanPreempt)
+ yield();
+ return 1;
+}
+
extern void yield_preempt(void);
#if MODESEGMENT == 0
// Try to execute 32bit threads.
diff --git a/src/types.h b/src/types.h
index 5da299d..e013358 100644
--- a/src/types.h
+++ b/src/types.h
@@ -114,6 +114,9 @@ extern void __force_link_error__only_in_16bit(void) __noreturn;
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
+#define likely(x) __builtin_expect(!!(x), 1)
+#define unlikely(x) __builtin_expect(!!(x), 0)
+
#define NULL ((void*)0)
#define __weak __attribute__((weak))
diff --git a/src/util.h b/src/util.h
index 7c7c698..d2ac08a 100644
--- a/src/util.h
+++ b/src/util.h
@@ -216,6 +216,7 @@ void mutex_lock(struct mutex_s *mutex);
void mutex_unlock(struct mutex_s *mutex);
void start_preempt(void);
void finish_preempt(void);
+int wait_preempt(void);
void check_preempt(void);
// output.c