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 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include "lint.h"
30 #include <stdlib.h>
31 #include <pthread.h>
32 #include <errno.h>
33 #include "mtlib.h"
34 #include "libc.h"
35 #include "tsd.h"
36
37 typedef void (*pfrv_t)(void *);
38
39 typedef struct {
40 void *buf;
41 size_t size;
42 pfrv_t destructor;
43 } tsdent_t;
44
45 static void
_free_tsdbuf(void * ptr)46 _free_tsdbuf(void *ptr)
47 {
48 tsdent_t *loc = ptr;
49 pfrv_t destructor;
50 void *p;
51 int i;
52
53 if (loc != NULL) {
54 for (i = 0; i < _T_NUM_ENTRIES; i++) {
55 if ((p = loc[i].buf) != NULL) {
56 destructor = loc[i].destructor;
57 if (destructor != NULL)
58 destructor(p);
59 lfree(p, loc[i].size);
60 }
61 }
62 lfree(loc, _T_NUM_ENTRIES * sizeof (tsdent_t));
63 }
64 }
65
66 void *
tsdalloc(__tsd_item_t n,size_t size,pfrv_t destructor)67 tsdalloc(__tsd_item_t n, size_t size, pfrv_t destructor)
68 {
69 static thread_key_t key = THR_ONCE_KEY;
70 tsdent_t *loc;
71 void *p;
72 int error;
73
74 if ((uint_t)n >= _T_NUM_ENTRIES) {
75 errno = ENOTSUP;
76 return (NULL);
77 }
78
79 if ((error = thr_keycreate_once(&key, _free_tsdbuf)) != 0) {
80 errno = error;
81 return (NULL);
82 }
83
84 if ((loc = pthread_getspecific(key)) != NULL) {
85 if ((p = loc[n].buf) != NULL)
86 return (p);
87 } else {
88 /* allocate our array of pointers */
89 loc = lmalloc(_T_NUM_ENTRIES * sizeof (tsdent_t));
90 if (loc == NULL)
91 return (NULL);
92 if ((error = thr_setspecific(key, loc)) != 0) {
93 lfree(loc, _T_NUM_ENTRIES * sizeof (tsdent_t));
94 errno = error;
95 return (NULL);
96 }
97 }
98
99 /* allocate item n */
100 loc[n].buf = p = lmalloc(size);
101 loc[n].size = size;
102 loc[n].destructor = destructor;
103 return (p);
104 }
105