Libinfo-391.tar.gz
[apple/libinfo.git] / lookup.subproj / thread_data.c
1 /*
2 * Copyright (c) 2008 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 #include <thread_data.h>
25 #include <pthread.h>
26 #include <string.h>
27 #include <stdlib.h>
28
29 static pthread_key_t _info_key = 0;
30 static int _info_key_ok = 0;
31 static pthread_once_t _info_key_initialized = PTHREAD_ONCE_INIT;
32
33 struct _li_data_s
34 {
35 uint32_t icount;
36 uint32_t *ikey;
37 void **idata;
38 };
39
40 typedef struct
41 {
42 si_item_t *thread_item;
43 si_list_t *thread_list;
44 } li_thread_data_t;
45
46 static void
47 _LI_thread_info_free(void *x)
48 {
49 li_thread_data_t *tdata;
50
51 if (x == NULL) return;
52
53 tdata = (li_thread_data_t *)x;
54 si_item_release(tdata->thread_item);
55 si_list_release(tdata->thread_list);
56
57 free(tdata);
58 }
59
60 static void
61 _LI_data_free(void *x)
62 {
63 struct _li_data_s *t;
64 int i;
65
66 if (x == NULL) return;
67
68 t = (struct _li_data_s *)x;
69
70 for (i = 0; i < t->icount; i++)
71 {
72 _LI_thread_info_free(t->idata[i]);
73 t->idata[i] = NULL;
74 }
75
76 if (t->ikey != NULL) free(t->ikey);
77 t->ikey = NULL;
78
79 if (t->idata != NULL) free(t->idata);
80 t->idata = NULL;
81
82 free(t);
83 }
84
85 static void
86 _LI_data_init()
87 {
88 /* _info_key_ok is set to 1 if pthread_key_create succeeded */
89 if (pthread_key_create(&_info_key, _LI_data_free) == 0) _info_key_ok = 1;
90 return;
91 }
92
93 static struct _li_data_s *
94 _LI_data_get()
95 {
96 struct _li_data_s *libinfo_data;
97
98 /* only one thread should create the _info_key */
99 pthread_once(&_info_key_initialized, _LI_data_init);
100
101 /* no thread-specific data if pthread_key_create failed */
102 if (_info_key_ok == 0) return NULL;
103
104 /* Check if this thread already created libinfo_data */
105 libinfo_data = pthread_getspecific(_info_key);
106 if (libinfo_data != NULL) return libinfo_data;
107
108 libinfo_data = (struct _li_data_s *)calloc(1, sizeof(struct _li_data_s));
109 if (libinfo_data == NULL) return NULL;
110
111 pthread_setspecific(_info_key, libinfo_data);
112 return libinfo_data;
113 }
114
115 static li_thread_data_t *
116 LI_get_thread_info(uint32_t key)
117 {
118 struct _li_data_s *libinfo_data;
119 li_thread_data_t *tdata;
120 uint32_t i, n;
121
122 libinfo_data = _LI_data_get();
123 if (libinfo_data == NULL) return NULL;
124
125 for (i = 0; i < libinfo_data->icount; i++)
126 {
127 if (libinfo_data->ikey[i] == key) return libinfo_data->idata[i];
128 }
129
130 i = libinfo_data->icount;
131 n = i + 1;
132
133 if (i == 0)
134 {
135 libinfo_data->ikey = (uint32_t *)malloc(sizeof(uint32_t));
136 libinfo_data->idata = (void **)malloc(sizeof(void *));
137 }
138 else
139 {
140 libinfo_data->ikey = (uint32_t *)reallocf(libinfo_data->ikey, n * sizeof(uint32_t));
141 libinfo_data->idata = (void **)reallocf(libinfo_data->idata, n * sizeof(void *));
142 }
143
144 if ((libinfo_data->ikey == NULL) || (libinfo_data->idata == NULL))
145 {
146 if (libinfo_data->ikey != NULL) free(libinfo_data->ikey);
147 libinfo_data->ikey = NULL;
148
149 if (libinfo_data->idata != NULL) free(libinfo_data->idata);
150 libinfo_data->idata = NULL;
151
152 return NULL;
153 }
154
155 tdata = (li_thread_data_t *)calloc(1, sizeof(li_thread_data_t));
156 if (tdata == NULL) return NULL;
157
158 libinfo_data->ikey[i] = key;
159 libinfo_data->idata[i] = tdata;
160 libinfo_data->icount++;
161
162 return tdata;
163 }
164
165 si_item_t *
166 LI_get_thread_item(uint32_t key)
167 {
168 li_thread_data_t *tdata;
169
170 tdata = LI_get_thread_info(key);
171 if (tdata == NULL) return NULL;
172
173 return tdata->thread_item;
174 }
175
176 si_list_t *
177 LI_get_thread_list(uint32_t key)
178 {
179 li_thread_data_t *tdata;
180
181 tdata = LI_get_thread_info(key);
182 if (tdata == NULL) return NULL;
183
184 return tdata->thread_list;
185 }
186
187 void
188 LI_set_thread_item(uint32_t key, si_item_t *item)
189 {
190 li_thread_data_t *tdata;
191
192 tdata = LI_get_thread_info(key);
193 if (tdata == NULL) return;
194
195 si_item_release(tdata->thread_item);
196 tdata->thread_item = item;
197 }
198
199 void
200 LI_set_thread_list(uint32_t key, si_list_t *list)
201 {
202 li_thread_data_t *tdata;
203
204 tdata = LI_get_thread_info(key);
205 if (tdata == NULL) return;
206
207 si_list_release(tdata->thread_list);
208
209 si_list_reset(list);
210 tdata->thread_list = list;
211 }