Return TMP, or a thread-specific struct tm * selected by WHICH. */
| 2171 | |
| 2172 | /* Return TMP, or a thread-specific struct tm * selected by WHICH. */ |
| 2173 | static struct tm * |
| 2174 | tm_multi(struct tm *tmp, ATTRIBUTE_MAYBE_UNUSED enum tm_multi which) |
| 2175 | { |
| 2176 | # if THREAD_SAFE && THREAD_TM_MULTI |
| 2177 | /* It is OK to check is_threaded() separately here; even if it |
| 2178 | returns a different value in other places in the caller, |
| 2179 | this function's behavior is still valid. */ |
| 2180 | if (is_threaded()) { |
| 2181 | /* Try to get a thread-specific struct tm *. |
| 2182 | Fall back on TMP if this fails. */ |
| 2183 | static pthread_once_t tm_multi_once = PTHREAD_ONCE_INIT; |
| 2184 | pthread_once(&tm_multi_once, tm_multi_key_init); |
| 2185 | if (!tm_multi_key_err) { |
| 2186 | struct tm *p = pthread_getspecific(tm_multi_key); |
| 2187 | if (!p) { |
| 2188 | p = malloc(N_TM_MULTI * sizeof *p); |
| 2189 | if (p && pthread_setspecific(tm_multi_key, p) != 0) { |
| 2190 | free(p); |
| 2191 | p = NULL; |
| 2192 | } |
| 2193 | } |
| 2194 | if (p) |
| 2195 | return &p[which]; |
| 2196 | } |
| 2197 | } |
| 2198 | # endif |
| 2199 | return tmp; |
| 2200 | } |
| 2201 | |
| 2202 | # if NETBSD_INSPIRED |
| 2203 | struct tm * |
no test coverage detected