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 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 * 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