xref: /NextBSD/lib/libosxsupport/si_data.c (revision 33da5adc555b3bc29986eeadca03829e4ad06b1e)
1 /*
2  * Copyright (c) 2008-2009 Apple 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 
25 #include <assert.h>
26 #include <errno.h>
27 #include <stdlib.h>
28 #ifdef __FreeBSD__
29 #include "atomic_compat.h"
30 #else
31 #include <libkern/OSAtomic.h>
32 #endif
33 
34 #include "si_data.h"
35 #include "si_module.h"
36 
37 
38 
39 si_list_t *
si_list_add(si_list_t * l,si_item_t * e)40 si_list_add(si_list_t *l, si_item_t *e)
41 {
42 	size_t size;
43 
44 	if (e == NULL) return l;
45 
46 	if (l == NULL)
47 	{
48 		l = (si_list_t *)calloc(1, sizeof(si_list_t));
49 		l->refcount = 1;
50 	}
51 
52 	if (l != NULL)
53 	{
54 		size = (l->count + 1) * sizeof(si_item_t *);
55 
56 		l->entry = (si_item_t **)reallocf(l->entry, size);
57 		if (l->entry != NULL)
58 		{
59 			l->entry[l->count++] = si_item_retain(e);
60 		}
61 	}
62 
63 	if ((l == NULL) || (l->entry == NULL))
64 	{
65 		free(l);
66 		l = NULL;
67 		errno = ENOMEM;
68 	}
69 
70 	return l;
71 }
72 
73 si_list_t *
si_list_concat(si_list_t * l,si_list_t * x)74 si_list_concat(si_list_t *l, si_list_t *x)
75 {
76 	si_item_t *item;
77 	uint32_t newcount;
78 	size_t size;
79 	uint32_t i;
80 
81 	if ((x == NULL) || (x->count == 0)) return l;
82 
83 	if (l == NULL)
84 	{
85 		l = (si_list_t *)calloc(1, sizeof(si_list_t));
86 		l->refcount = 1;
87 	}
88 
89 	if (l != NULL)
90 	{
91 		newcount = l->count + x->count;
92 		size = newcount * sizeof(si_item_t *);
93 
94 		l->entry = (si_item_t **)reallocf(l->entry, size);
95 		if (l->entry)
96 		{
97 			for (i = 0; i < x->count; ++i)
98 			{
99 				item = x->entry[i];
100 				si_item_retain(item);
101 				l->entry[l->count + i] = item;
102 			}
103 
104 			l->count += x->count;
105 		}
106 		else
107 		{
108 			l->count = 0;
109 			l = NULL;
110 		}
111 	}
112 
113 	if (l == NULL) errno = ENOMEM;
114 
115 	return l;
116 }
117 
118 si_item_t *
si_list_next(si_list_t * list)119 si_list_next(si_list_t *list)
120 {
121 	if (list == NULL) return NULL;
122 	if (list->curr >= list->count) return NULL;
123 
124 	return list->entry[list->curr++];
125 }
126 
127 void
si_list_reset(si_list_t * list)128 si_list_reset(si_list_t *list)
129 {
130 	if (list != NULL) list->curr = 0;
131 }
132 
133 si_list_t *
si_list_retain(si_list_t * list)134 si_list_retain(si_list_t *list)
135 {
136 	int32_t rc;
137 
138 	if (list == NULL) return NULL;
139 
140 	rc = OSAtomicIncrement32Barrier(&list->refcount);
141 	assert(rc >= 1);
142 
143 	return list;
144 }
145 
146 void
si_list_release(si_list_t * list)147 si_list_release(si_list_t *list)
148 {
149 	int32_t rc;
150 	uint32_t i;
151 
152 	if (list == NULL) return;
153 
154 	rc = OSAtomicDecrement32Barrier(&list->refcount);
155 	assert(rc >= 0);
156 
157 	if (rc == 0)
158 	{
159 		for (i = 0; i < list->count; i++)
160 		{
161 			si_item_release(list->entry[i]);
162 		}
163 
164 		free(list->entry);
165 		free(list);
166 	}
167 }
168 
169 si_item_t *
si_item_retain(si_item_t * item)170 si_item_retain(si_item_t *item)
171 {
172 	int32_t rc;
173 
174 	if (item == NULL) return NULL;
175 
176 	rc = OSAtomicIncrement32Barrier(&item->refcount);
177 	assert(rc >= 1);
178 
179 	return item;
180 }
181 
182 void
si_item_release(si_item_t * item)183 si_item_release(si_item_t *item)
184 {
185 	int32_t rc;
186 
187 	if (item == NULL) return;
188 
189 	rc = OSAtomicDecrement32Barrier(&item->refcount);
190 	assert(rc >= 0);
191 
192 	if (rc == 0) free(item);
193 }
194