2 * Copyright (c) 2008-2018 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 "libinfo_common.h"
26 #include <thread_data.h>
31 static pthread_key_t _info_key
= 0;
32 static int _info_key_ok
= 0;
33 static pthread_once_t _info_key_initialized
= PTHREAD_ONCE_INIT
;
44 si_item_t
*thread_item
;
45 si_list_t
*thread_list
;
49 _LI_thread_info_free(void *x
)
51 li_thread_data_t
*tdata
;
53 if (x
== NULL
) return;
55 tdata
= (li_thread_data_t
*)x
;
56 si_item_release(tdata
->thread_item
);
57 si_list_release(tdata
->thread_list
);
63 _LI_data_free(void *x
)
68 if (x
== NULL
) return;
70 t
= (struct _li_data_s
*)x
;
72 for (i
= 0; i
< t
->icount
; i
++)
74 _LI_thread_info_free(t
->idata
[i
]);
78 if (t
->ikey
!= NULL
) free(t
->ikey
);
81 if (t
->idata
!= NULL
) free(t
->idata
);
90 /* _info_key_ok is set to 1 if pthread_key_create succeeded */
91 if (pthread_key_create(&_info_key
, _LI_data_free
) == 0) _info_key_ok
= 1;
95 static struct _li_data_s
*
98 struct _li_data_s
*libinfo_data
;
100 /* only one thread should create the _info_key */
101 pthread_once(&_info_key_initialized
, _LI_data_init
);
103 /* no thread-specific data if pthread_key_create failed */
104 if (_info_key_ok
== 0) return NULL
;
106 /* Check if this thread already created libinfo_data */
107 libinfo_data
= pthread_getspecific(_info_key
);
108 if (libinfo_data
!= NULL
) return libinfo_data
;
110 libinfo_data
= (struct _li_data_s
*)calloc(1, sizeof(struct _li_data_s
));
111 if (libinfo_data
== NULL
) return NULL
;
113 pthread_setspecific(_info_key
, libinfo_data
);
117 static li_thread_data_t
*
118 LI_get_thread_info(uint32_t key
)
120 struct _li_data_s
*libinfo_data
;
121 li_thread_data_t
*tdata
;
124 libinfo_data
= _LI_data_get();
125 if (libinfo_data
== NULL
) return NULL
;
127 for (i
= 0; i
< libinfo_data
->icount
; i
++)
129 if (libinfo_data
->ikey
[i
] == key
) return libinfo_data
->idata
[i
];
132 i
= libinfo_data
->icount
;
137 libinfo_data
->ikey
= (uint32_t *)malloc(sizeof(uint32_t));
138 libinfo_data
->idata
= (void **)malloc(sizeof(void *));
142 libinfo_data
->ikey
= (uint32_t *)reallocf(libinfo_data
->ikey
, n
* sizeof(uint32_t));
143 libinfo_data
->idata
= (void **)reallocf(libinfo_data
->idata
, n
* sizeof(void *));
146 if ((libinfo_data
->ikey
== NULL
) || (libinfo_data
->idata
== NULL
))
148 if (libinfo_data
->ikey
!= NULL
) free(libinfo_data
->ikey
);
149 libinfo_data
->ikey
= NULL
;
151 if (libinfo_data
->idata
!= NULL
) free(libinfo_data
->idata
);
152 libinfo_data
->idata
= NULL
;
157 tdata
= (li_thread_data_t
*)calloc(1, sizeof(li_thread_data_t
));
158 if (tdata
== NULL
) return NULL
;
160 libinfo_data
->ikey
[i
] = key
;
161 libinfo_data
->idata
[i
] = tdata
;
162 libinfo_data
->icount
++;
169 LI_get_thread_item(uint32_t key
)
171 li_thread_data_t
*tdata
;
173 tdata
= LI_get_thread_info(key
);
174 if (tdata
== NULL
) return NULL
;
176 return tdata
->thread_item
;
181 LI_get_thread_list(uint32_t key
)
183 li_thread_data_t
*tdata
;
185 tdata
= LI_get_thread_info(key
);
186 if (tdata
== NULL
) return NULL
;
188 return tdata
->thread_list
;
193 LI_set_thread_item(uint32_t key
, si_item_t
*item
)
195 li_thread_data_t
*tdata
;
197 tdata
= LI_get_thread_info(key
);
198 if (tdata
== NULL
) return;
200 si_item_release(tdata
->thread_item
);
201 tdata
->thread_item
= item
;
206 LI_set_thread_list(uint32_t key
, si_list_t
*list
)
208 li_thread_data_t
*tdata
;
210 tdata
= LI_get_thread_info(key
);
211 if (tdata
== NULL
) return;
213 si_list_release(tdata
->thread_list
);
216 tdata
->thread_list
= list
;