2 * Copyright (c) 2008 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <thread_data.h>
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
;
42 si_item_t
*thread_item
;
43 si_list_t
*thread_list
;
47 _LI_thread_info_free(void *x
)
49 li_thread_data_t
*tdata
;
51 if (x
== NULL
) return;
53 tdata
= (li_thread_data_t
*)x
;
54 si_item_release(tdata
->thread_item
);
55 si_list_release(tdata
->thread_list
);
61 _LI_data_free(void *x
)
66 if (x
== NULL
) return;
68 t
= (struct _li_data_s
*)x
;
70 for (i
= 0; i
< t
->icount
; i
++)
72 _LI_thread_info_free(t
->idata
[i
]);
76 if (t
->ikey
!= NULL
) free(t
->ikey
);
79 if (t
->idata
!= NULL
) free(t
->idata
);
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;
93 static struct _li_data_s
*
96 struct _li_data_s
*libinfo_data
;
98 /* only one thread should create the _info_key */
99 pthread_once(&_info_key_initialized
, _LI_data_init
);
101 /* no thread-specific data if pthread_key_create failed */
102 if (_info_key_ok
== 0) return NULL
;
104 /* Check if this thread already created libinfo_data */
105 libinfo_data
= pthread_getspecific(_info_key
);
106 if (libinfo_data
!= NULL
) return libinfo_data
;
108 libinfo_data
= (struct _li_data_s
*)calloc(1, sizeof(struct _li_data_s
));
109 if (libinfo_data
== NULL
) return NULL
;
111 pthread_setspecific(_info_key
, libinfo_data
);
115 static li_thread_data_t
*
116 LI_get_thread_info(uint32_t key
)
118 struct _li_data_s
*libinfo_data
;
119 li_thread_data_t
*tdata
;
122 libinfo_data
= _LI_data_get();
123 if (libinfo_data
== NULL
) return NULL
;
125 for (i
= 0; i
< libinfo_data
->icount
; i
++)
127 if (libinfo_data
->ikey
[i
] == key
) return libinfo_data
->idata
[i
];
130 i
= libinfo_data
->icount
;
135 libinfo_data
->ikey
= (uint32_t *)malloc(sizeof(uint32_t));
136 libinfo_data
->idata
= (void **)malloc(sizeof(void *));
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 *));
144 if ((libinfo_data
->ikey
== NULL
) || (libinfo_data
->idata
== NULL
))
146 if (libinfo_data
->ikey
!= NULL
) free(libinfo_data
->ikey
);
147 libinfo_data
->ikey
= NULL
;
149 if (libinfo_data
->idata
!= NULL
) free(libinfo_data
->idata
);
150 libinfo_data
->idata
= NULL
;
155 tdata
= (li_thread_data_t
*)calloc(1, sizeof(li_thread_data_t
));
156 if (tdata
== NULL
) return NULL
;
158 libinfo_data
->ikey
[i
] = key
;
159 libinfo_data
->idata
[i
] = tdata
;
160 libinfo_data
->icount
++;
165 __private_extern__ si_item_t
*
166 LI_get_thread_item(uint32_t key
)
168 li_thread_data_t
*tdata
;
170 tdata
= LI_get_thread_info(key
);
171 if (tdata
== NULL
) return NULL
;
173 return tdata
->thread_item
;
176 __private_extern__ si_list_t
*
177 LI_get_thread_list(uint32_t key
)
179 li_thread_data_t
*tdata
;
181 tdata
= LI_get_thread_info(key
);
182 if (tdata
== NULL
) return NULL
;
184 return tdata
->thread_list
;
187 __private_extern__
void
188 LI_set_thread_item(uint32_t key
, si_item_t
*item
)
190 li_thread_data_t
*tdata
;
192 tdata
= LI_get_thread_info(key
);
193 if (tdata
== NULL
) return;
195 si_item_release(tdata
->thread_item
);
196 tdata
->thread_item
= item
;
199 __private_extern__
void
200 LI_set_thread_list(uint32_t key
, si_list_t
*list
)
202 li_thread_data_t
*tdata
;
204 tdata
= LI_get_thread_info(key
);
205 if (tdata
== NULL
) return;
207 si_list_release(tdata
->thread_list
);
210 tdata
->thread_list
= list
;