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 2007 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 "thr_uberdata.h" 31 #include <pthread.h> 32 33 /* 34 * pthread_mutexattr_init: allocates the mutex attribute object and 35 * initializes it with the default values. 36 */ 37 #pragma weak pthread_mutexattr_init = _pthread_mutexattr_init 38 int 39 _pthread_mutexattr_init(pthread_mutexattr_t *attr) 40 { 41 mattr_t *ap; 42 43 if ((ap = lmalloc(sizeof (mattr_t))) == NULL) 44 return (ENOMEM); 45 ap->pshared = DEFAULT_TYPE; 46 ap->type = PTHREAD_MUTEX_DEFAULT; 47 ap->protocol = PTHREAD_PRIO_NONE; 48 ap->robustness = PTHREAD_MUTEX_STALL_NP; 49 attr->__pthread_mutexattrp = ap; 50 return (0); 51 } 52 53 /* 54 * pthread_mutexattr_destroy: frees the mutex attribute object and 55 * invalidates it with NULL value. 56 */ 57 #pragma weak pthread_mutexattr_destroy = _pthread_mutexattr_destroy 58 int 59 _pthread_mutexattr_destroy(pthread_mutexattr_t *attr) 60 { 61 if (attr == NULL || attr->__pthread_mutexattrp == NULL) 62 return (EINVAL); 63 lfree(attr->__pthread_mutexattrp, sizeof (mattr_t)); 64 attr->__pthread_mutexattrp = NULL; 65 return (0); 66 } 67 68 /* 69 * pthread_mutexattr_setpshared: sets the shared attribute 70 * to PTHREAD_PROCESS_PRIVATE or PTHREAD_PROCESS_SHARED. 71 * This is equivalent to setting the USYNC_THREAD/USYNC_PROCESS 72 * flag in mutex_init(). 73 */ 74 #pragma weak pthread_mutexattr_setpshared = _pthread_mutexattr_setpshared 75 int 76 _pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared) 77 { 78 mattr_t *ap; 79 80 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 81 (pshared != PTHREAD_PROCESS_PRIVATE && 82 pshared != PTHREAD_PROCESS_SHARED)) 83 return (EINVAL); 84 ap->pshared = pshared; 85 return (0); 86 } 87 88 /* 89 * pthread_mutexattr_getpshared: gets the shared attribute. 90 */ 91 #pragma weak pthread_mutexattr_getpshared = _pthread_mutexattr_getpshared 92 int 93 _pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, int *pshared) 94 { 95 mattr_t *ap; 96 97 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 98 pshared == NULL) 99 return (EINVAL); 100 *pshared = ap->pshared; 101 return (0); 102 } 103 104 /* 105 * pthread_mutexattr_setprioceiling: sets the prioceiling attribute. 106 */ 107 #pragma weak pthread_mutexattr_setprioceiling = \ 108 _pthread_mutexattr_setprioceiling 109 int 110 _pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int prioceiling) 111 { 112 mattr_t *ap; 113 114 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 115 _validate_rt_prio(SCHED_FIFO, prioceiling)) 116 return (EINVAL); 117 ap->prioceiling = prioceiling; 118 return (0); 119 } 120 121 /* 122 * pthread_mutexattr_getprioceiling: gets the prioceiling attribute. 123 */ 124 #pragma weak pthread_mutexattr_getprioceiling = \ 125 _pthread_mutexattr_getprioceiling 126 int 127 _pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr, int *ceiling) 128 { 129 mattr_t *ap; 130 131 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 132 ceiling == NULL) 133 return (EINVAL); 134 *ceiling = ap->prioceiling; 135 return (0); 136 } 137 138 /* 139 * pthread_mutexattr_setprotocol: sets the protocol attribute. 140 */ 141 #pragma weak pthread_mutexattr_setprotocol = _pthread_mutexattr_setprotocol 142 int 143 _pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol) 144 { 145 mattr_t *ap; 146 147 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL) 148 return (EINVAL); 149 if (protocol != PTHREAD_PRIO_NONE && 150 protocol != PTHREAD_PRIO_INHERIT && 151 protocol != PTHREAD_PRIO_PROTECT) 152 return (ENOTSUP); 153 ap->protocol = protocol; 154 return (0); 155 } 156 157 /* 158 * pthread_mutexattr_getprotocol: gets the protocol attribute. 159 */ 160 #pragma weak pthread_mutexattr_getprotocol = _pthread_mutexattr_getprotocol 161 int 162 _pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int *protocol) 163 { 164 mattr_t *ap; 165 166 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 167 protocol == NULL) 168 return (EINVAL); 169 *protocol = ap->protocol; 170 return (0); 171 } 172 173 /* 174 * pthread_mutexattr_setrobust_np: sets the robustness attribute 175 * to PTHREAD_MUTEX_ROBUST_NP or PTHREAD_MUTEX_STALL_NP. 176 */ 177 #pragma weak pthread_mutexattr_setrobust_np = \ 178 _pthread_mutexattr_setrobust_np 179 int 180 _pthread_mutexattr_setrobust_np(pthread_mutexattr_t *attr, int robust) 181 { 182 mattr_t *ap; 183 184 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 185 (robust != PTHREAD_MUTEX_ROBUST_NP && 186 robust != PTHREAD_MUTEX_STALL_NP)) 187 return (EINVAL); 188 ap->robustness = robust; 189 return (0); 190 } 191 192 /* 193 * pthread_mutexattr_getrobust_np: gets the robustness attribute. 194 */ 195 #pragma weak pthread_mutexattr_getrobust_np = \ 196 _pthread_mutexattr_getrobust_np 197 int 198 _pthread_mutexattr_getrobust_np(const pthread_mutexattr_t *attr, int *robust) 199 { 200 mattr_t *ap; 201 202 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 203 robust == NULL) 204 return (EINVAL); 205 *robust = ap->robustness; 206 return (0); 207 } 208 209 /* 210 * pthread_mutex_init: Initializes the mutex object. It copies the 211 * various attributes into one type argument and calls mutex_init(). 212 */ 213 #pragma weak pthread_mutex_init = _pthread_mutex_init 214 int 215 _pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr) 216 { 217 mattr_t *ap; 218 int type; 219 int prioceiling = 0; 220 221 /* 222 * All of the pshared, type, protocol, robust attributes 223 * translate to bits in the mutex_type field. 224 */ 225 if (attr != NULL) { 226 if ((ap = attr->__pthread_mutexattrp) == NULL) 227 return (EINVAL); 228 type = ap->pshared | ap->type | ap->protocol | ap->robustness; 229 if (ap->protocol == PTHREAD_PRIO_PROTECT) 230 prioceiling = ap->prioceiling; 231 } else { 232 type = DEFAULT_TYPE | PTHREAD_MUTEX_DEFAULT | 233 PTHREAD_PRIO_NONE | PTHREAD_MUTEX_STALL_NP; 234 } 235 236 return (_private_mutex_init((mutex_t *)mutex, type, &prioceiling)); 237 } 238 239 /* 240 * pthread_mutex_setprioceiling: sets the prioceiling. 241 */ 242 #pragma weak pthread_mutex_setprioceiling = _pthread_mutex_setprioceiling 243 int 244 _pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int ceil, int *oceil) 245 { 246 mutex_t *mp = (mutex_t *)mutex; 247 int error; 248 249 if (!(mp->mutex_type & PTHREAD_PRIO_PROTECT) || 250 _validate_rt_prio(SCHED_FIFO, ceil) != 0) 251 return (EINVAL); 252 error = _private_mutex_lock(mp); 253 if (error == 0) { 254 if (oceil) 255 *oceil = mp->mutex_ceiling; 256 mp->mutex_ceiling = (uint8_t)ceil; 257 error = _private_mutex_unlock(mp); 258 } 259 return (error); 260 } 261 262 /* 263 * pthread_mutex_getprioceiling: gets the prioceiling. 264 */ 265 #pragma weak pthread_mutex_getprioceiling = _pthread_mutex_getprioceiling 266 int 267 _pthread_mutex_getprioceiling(const pthread_mutex_t *mp, int *ceiling) 268 { 269 *ceiling = ((mutex_t *)mp)->mutex_ceiling; 270 return (0); 271 } 272 273 /* 274 * UNIX98 275 * pthread_mutexattr_settype: sets the type attribute 276 */ 277 #pragma weak pthread_mutexattr_settype = _pthread_mutexattr_settype 278 int 279 _pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) 280 { 281 mattr_t *ap; 282 283 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL) 284 return (EINVAL); 285 switch (type) { 286 case PTHREAD_MUTEX_NORMAL: 287 type = LOCK_NORMAL; 288 break; 289 case PTHREAD_MUTEX_ERRORCHECK: 290 type = LOCK_ERRORCHECK; 291 break; 292 case PTHREAD_MUTEX_RECURSIVE: 293 type = LOCK_RECURSIVE | LOCK_ERRORCHECK; 294 break; 295 default: 296 return (EINVAL); 297 } 298 ap->type = type; 299 return (0); 300 } 301 302 /* 303 * UNIX98 304 * pthread_mutexattr_gettype: gets the type attribute. 305 */ 306 #pragma weak pthread_mutexattr_gettype = _pthread_mutexattr_gettype 307 int 308 _pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *typep) 309 { 310 mattr_t *ap; 311 int type; 312 313 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 314 typep == NULL) 315 return (EINVAL); 316 switch (ap->type) { 317 case LOCK_NORMAL: 318 type = PTHREAD_MUTEX_NORMAL; 319 break; 320 case LOCK_ERRORCHECK: 321 type = PTHREAD_MUTEX_ERRORCHECK; 322 break; 323 case LOCK_RECURSIVE | LOCK_ERRORCHECK: 324 type = PTHREAD_MUTEX_RECURSIVE; 325 break; 326 default: 327 return (EINVAL); 328 } 329 *typep = type; 330 return (0); 331 } 332