#include <kern/kalloc.h>
#include <libkern/OSAtomic.h>
#include <sys/errno.h>
#include <net/init.h>
#include <libkern/libkern.h>
#include <string.h>
struct init_list_entry {
struct init_list_entry *next;
net_init_func_ptr func;
};
#define LIST_RAN ((struct init_list_entry*)0xffffffff)
static struct init_list_entry *list_head = 0;
errno_t
net_init_add(
net_init_func_ptr init_func)
{
struct init_list_entry *entry;
if (init_func == 0) {
return EINVAL;
}
if (list_head == LIST_RAN) {
return EALREADY;
}
entry = kalloc(sizeof(*entry));
if (entry == 0) {
printf("net_init_add: no memory\n");
return ENOMEM;
}
bzero(entry, sizeof(*entry));
entry->func = init_func;
do {
entry->next = list_head;
if (entry->next == LIST_RAN) {
kfree(entry, sizeof(*entry));
return EALREADY;
}
} while(!OSCompareAndSwap((UInt32)entry->next, (UInt32)entry,
(UInt32*)&list_head));
return 0;
}
__private_extern__ void
net_init_run(void)
{
struct init_list_entry *backward_head = 0;
struct init_list_entry *forward_head = 0;
struct init_list_entry *current = 0;
do {
backward_head = list_head;
} while (!OSCompareAndSwap((UInt32)backward_head, (UInt32)LIST_RAN,
(UInt32*)&list_head));
while (backward_head != 0) {
current = backward_head;
backward_head = current->next;
current->next = forward_head;
forward_head = current;
}
while (forward_head != 0) {
current = forward_head;
forward_head = current->next;
current->func();
kfree(current, sizeof(*current));
}
}