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