aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2013-06-13 21:24:14 -0400
committerKevin O'Connor <kevin@koconnor.net>2013-06-13 21:24:14 -0400
commit030a58a05e595694dccfa958563103d2f0644231 (patch)
tree3cb4e135ded7235f2edbbfc12db8764bd47221e7
parent7507ce28f436fe8b37bcd09a85c7289bf4c4284f (diff)
downloadseabios-030a58a05e595694dccfa958563103d2f0644231.tar.gz
Another fix for hlist_for_each_entry_safe.
Although the previous patch does fix hlist_for_each_entry_safe for the common case, it doesn't work correctly when deleting the current node. To fix this, introduce two macros - hlist_for_each_entry_safe for iterating through a list that can be modified, and hlist_for_each_entry_pprev for those users that only need access to the "pprev" pointer. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
-rw-r--r--src/boot.c2
-rw-r--r--src/list.h8
-rw-r--r--src/pciinit.c12
-rw-r--r--src/pmm.c2
4 files changed, 16 insertions, 8 deletions
diff --git a/src/boot.c b/src/boot.c
index 6286e3c..2fce315 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -324,7 +324,7 @@ bootentry_add(int type, int prio, u32 data, const char *desc)
// Add entry in sorted order.
struct hlist_node **pprev;
struct bootentry_s *pos;
- hlist_for_each_entry_safe(pos, pprev, &BootList, node) {
+ hlist_for_each_entry_pprev(pos, pprev, &BootList, node) {
if (be->priority < pos->priority)
break;
if (be->priority > pos->priority)
diff --git a/src/list.h b/src/list.h
index 0f0909b..de656b9 100644
--- a/src/list.h
+++ b/src/list.h
@@ -66,7 +66,13 @@ hlist_add_after(struct hlist_node *n, struct hlist_node *prev)
; pos != container_of(NULL, typeof(*pos), member) \
; pos = container_of(pos->member.next, typeof(*pos), member))
-#define hlist_for_each_entry_safe(pos, pprev, head, member) \
+#define hlist_for_each_entry_safe(pos, n, head, member) \
+ for (pos = container_of((head)->first, typeof(*pos), member) \
+ ; pos != container_of(NULL, typeof(*pos), member) \
+ && ({ n = pos->member.next; 1; }) \
+ ; pos = container_of(n, typeof(*pos), member))
+
+#define hlist_for_each_entry_pprev(pos, pprev, head, member) \
for (pprev = &(head)->first \
; *pprev && ({ pos=container_of(*pprev, typeof(*pos), member); 1; }) \
; pprev = &(*pprev)->next)
diff --git a/src/pciinit.c b/src/pciinit.c
index 446dddf..1943e64 100644
--- a/src/pciinit.c
+++ b/src/pciinit.c
@@ -571,9 +571,9 @@ static u64 pci_region_sum(struct pci_region *r)
static void pci_region_migrate_64bit_entries(struct pci_region *from,
struct pci_region *to)
{
- struct hlist_node **pprev, **last = &to->list.first;
+ struct hlist_node *n, **last = &to->list.first;
struct pci_region_entry *entry;
- hlist_for_each_entry_safe(entry, pprev, &from->list, node) {
+ hlist_for_each_entry_safe(entry, n, &from->list, node) {
if (!entry->is64)
continue;
// Move from source list to destination list.
@@ -601,11 +601,13 @@ pci_region_create_entry(struct pci_bus *bus, struct pci_device *dev,
// Insert into list in sorted order.
struct hlist_node **pprev;
struct pci_region_entry *pos;
- hlist_for_each_entry_safe(pos, pprev, &bus->r[type].list, node) {
+ hlist_for_each_entry_pprev(pos, pprev, &bus->r[type].list, node) {
if (pos->align < align || (pos->align == align && pos->size < size))
break;
}
hlist_add(&entry->node, pprev);
+ dprintf(1, "Add %p to %p (bus=%p dev=%p bar=%d size=%llx align=%lld type=%d is64=%d\n"
+ , entry, pprev, bus, dev, bar, size, align, type, is64);
return entry;
}
@@ -744,9 +746,9 @@ pci_region_map_one_entry(struct pci_region_entry *entry, u64 addr)
static void pci_region_map_entries(struct pci_bus *busses, struct pci_region *r)
{
- struct hlist_node **pprev;
+ struct hlist_node *n;
struct pci_region_entry *entry;
- hlist_for_each_entry_safe(entry, pprev, &r->list, node) {
+ hlist_for_each_entry_safe(entry, n, &r->list, node) {
u64 addr = r->base;
r->base += entry->size;
if (entry->bar == -1)
diff --git a/src/pmm.c b/src/pmm.c
index da97283..8f993fd 100644
--- a/src/pmm.c
+++ b/src/pmm.c
@@ -86,7 +86,7 @@ addSpace(struct zone_s *zone, void *start, void *end)
// Find position to add space
struct allocinfo_s *info;
struct hlist_node **pprev;
- hlist_for_each_entry_safe(info, pprev, &zone->head, node) {
+ hlist_for_each_entry_pprev(info, pprev, &zone->head, node) {
if (info->data < start)
break;
}