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(!OSCompareAndSwap((UInt32)entry->next, (UInt32)entry, 77 (UInt32*)&list_head)); 78 79 return 0; 80} 81 82__private_extern__ void 83net_init_run(void) 84{ 85 struct init_list_entry *backward_head = 0; 86 struct init_list_entry *forward_head = 0; 87 struct init_list_entry *current = 0; 88 89 /* 90 * Grab the list, replacing the head with 0xffffffff to indicate 91 * that we've already run. 92 */ 93 do { 94 backward_head = list_head; 95 } while (!OSCompareAndSwap((UInt32)backward_head, (UInt32)LIST_RAN, 96 (UInt32*)&list_head)); 97 98 /* Reverse the order of the list */ 99 while (backward_head != 0) { 100 current = backward_head; 101 backward_head = current->next; 102 current->next = forward_head; 103 forward_head = current; 104 } 105 106 /* Call each function pointer registered */ 107 while (forward_head != 0) { 108 current = forward_head; 109 forward_head = current->next; 110 current->func(); 111 kfree(current, sizeof(*current)); 112 } 113} 114