1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include "lint.h"
28 #include <stdlib.h>
29 #include <pthread.h>
30 #include <errno.h>
31 #include "mtlib.h"
32 #include "libc.h"
33 #include "tsd.h"
34
35 typedef void (*pfrv_t)(void *);
36
37 typedef struct {
38 void *buf;
39 size_t size;
40 pfrv_t destructor;
41 } tsdent_t;
42
43 static void
_free_tsdbuf(void * ptr)44 _free_tsdbuf(void *ptr)
45 {
46 tsdent_t *loc = ptr;
47 pfrv_t destructor;
48 void *p;
49 int i;
50
51 if (loc != NULL) {
52 for (i = 0; i < _T_NUM_ENTRIES; i++) {
53 if ((p = loc[i].buf) != NULL) {
54 destructor = loc[i].destructor;
55 if (destructor != NULL)
56 destructor(p);
57 lfree(p, loc[i].size);
58 }
59 }
60 lfree(loc, _T_NUM_ENTRIES * sizeof (tsdent_t));
61 }
62 }
63
64 void *
tsdalloc(__tsd_item_t n,size_t size,pfrv_t destructor)65 tsdalloc(__tsd_item_t n, size_t size, pfrv_t destructor)
66 {
67 static thread_key_t key = THR_ONCE_KEY;
68 tsdent_t *loc;
69 void *p;
70 int error;
71
72 if ((uint_t)n >= _T_NUM_ENTRIES) {
73 errno = ENOTSUP;
74 return (NULL);
75 }
76
77 if ((error = thr_keycreate_once(&key, _free_tsdbuf)) != 0) {
78 errno = error;
79 return (NULL);
80 }
81
82 if ((loc = pthread_getspecific(key)) != NULL) {
83 if ((p = loc[n].buf) != NULL)
84 return (p);
85 } else {
86 /* allocate our array of pointers */
87 loc = lmalloc(_T_NUM_ENTRIES * sizeof (tsdent_t));
88 if (loc == NULL)
89 return (NULL);
90 if ((error = thr_setspecific(key, loc)) != 0) {
91 lfree(loc, _T_NUM_ENTRIES * sizeof (tsdent_t));
92 errno = error;
93 return (NULL);
94 }
95 }
96
97 /* allocate item n */
98 loc[n].buf = p = lmalloc(size);
99 loc[n].size = size;
100 loc[n].destructor = destructor;
101 return (p);
102 }
103