1/* 2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29#include <kern/kalloc.h> 30#include <libkern/OSAtomic.h> 31#include <sys/errno.h> 32#include <net/init.h> 33#include <libkern/libkern.h> 34#include <string.h> 35 36struct init_list_entry { 37 struct init_list_entry *next; 38 net_init_func_ptr func; 39}; 40 41#define LIST_RAN ((struct init_list_entry*)0xffffffff) 42static struct init_list_entry *list_head = 0; 43 44errno_t 45net_init_add( 46 net_init_func_ptr init_func) 47{ 48 struct init_list_entry *entry; 49 50 if (init_func == 0) { 51 return EINVAL; 52 } 53 54 /* Check if we've already started */ 55 if (list_head == LIST_RAN) { 56 return EALREADY; 57 } 58 59 entry = kalloc(sizeof(*entry)); 60 if (entry == 0) { 61 printf("net_init_add: no memory\n"); 62 return ENOMEM; 63 } 64 65 bzero(entry, sizeof(*entry)); 66 entry->func = init_func; 67 68 do { 69 entry->next = list_head; 70 71 if (entry->next == LIST_RAN) { 72 /* List already ran, cleanup and call the function */ 73 kfree(entry, sizeof(*entry)); 74 return EALREADY; 75 } 76 } while(!OSCompareAndSwapPtr(entry->next, entry, &list_head)); 77 78 return 0; 79} 80 81__private_extern__ void 82net_init_run(void) 83{ 84 struct init_list_entry *backward_head = 0; 85 struct init_list_entry *forward_head = 0; 86 struct init_list_entry *current = 0; 87 88 /* 89 * Grab the list, replacing the head with 0xffffffff to indicate 90 * that we've already run. 91 */ 92 do { 93 backward_head = list_head; 94 } while (!OSCompareAndSwapPtr(backward_head, LIST_RAN, &list_head)); 95 96 /* Reverse the order of the list */ 97 while (backward_head != 0) { 98 current = backward_head; 99 backward_head = current->next; 100 current->next = forward_head; 101 forward_head = current; 102 } 103 104 /* Call each function pointer registered */ 105 while (forward_head != 0) { 106 current = forward_head; 107 forward_head = current->next; 108 current->func(); 109 kfree(current, sizeof(*current)); 110 } 111} 112