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 "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 const pcclass_t *pccp = get_info_by_policy(SCHED_FIFO); 113 mattr_t *ap; 114 115 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 116 prioceiling < pccp->pcc_primin || prioceiling > pccp->pcc_primax) 117 return (EINVAL); 118 ap->prioceiling = prioceiling; 119 return (0); 120 } 121 122 /* 123 * pthread_mutexattr_getprioceiling: gets the prioceiling attribute. 124 */ 125 #pragma weak pthread_mutexattr_getprioceiling = \ 126 _pthread_mutexattr_getprioceiling 127 int 128 _pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr, int *ceiling) 129 { 130 mattr_t *ap; 131 132 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 133 ceiling == NULL) 134 return (EINVAL); 135 *ceiling = ap->prioceiling; 136 return (0); 137 } 138 139 /* 140 * pthread_mutexattr_setprotocol: sets the protocol attribute. 141 */ 142 #pragma weak pthread_mutexattr_setprotocol = _pthread_mutexattr_setprotocol 143 int 144 _pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol) 145 { 146 mattr_t *ap; 147 148 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL) 149 return (EINVAL); 150 if (protocol != PTHREAD_PRIO_NONE && 151 protocol != PTHREAD_PRIO_INHERIT && 152 protocol != PTHREAD_PRIO_PROTECT) 153 return (ENOTSUP); 154 ap->protocol = protocol; 155 return (0); 156 } 157 158 /* 159 * pthread_mutexattr_getprotocol: gets the protocol attribute. 160 */ 161 #pragma weak pthread_mutexattr_getprotocol = _pthread_mutexattr_getprotocol 162 int 163 _pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int *protocol) 164 { 165 mattr_t *ap; 166 167 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 168 protocol == NULL) 169 return (EINVAL); 170 *protocol = ap->protocol; 171 return (0); 172 } 173 174 /* 175 * pthread_mutexattr_setrobust_np: sets the robustness attribute 176 * to PTHREAD_MUTEX_ROBUST_NP or PTHREAD_MUTEX_STALL_NP. 177 */ 178 #pragma weak pthread_mutexattr_setrobust_np = \ 179 _pthread_mutexattr_setrobust_np 180 int 181 _pthread_mutexattr_setrobust_np(pthread_mutexattr_t *attr, int robust) 182 { 183 mattr_t *ap; 184 185 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 186 (robust != PTHREAD_MUTEX_ROBUST_NP && 187 robust != PTHREAD_MUTEX_STALL_NP)) 188 return (EINVAL); 189 ap->robustness = robust; 190 return (0); 191 } 192 193 /* 194 * pthread_mutexattr_getrobust_np: gets the robustness attribute. 195 */ 196 #pragma weak pthread_mutexattr_getrobust_np = \ 197 _pthread_mutexattr_getrobust_np 198 int 199 _pthread_mutexattr_getrobust_np(const pthread_mutexattr_t *attr, int *robust) 200 { 201 mattr_t *ap; 202 203 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 204 robust == NULL) 205 return (EINVAL); 206 *robust = ap->robustness; 207 return (0); 208 } 209 210 /* 211 * pthread_mutex_init: Initializes the mutex object. It copies the 212 * various attributes into one type argument and calls mutex_init(). 213 */ 214 #pragma weak pthread_mutex_init = _pthread_mutex_init 215 int 216 _pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr) 217 { 218 mattr_t *ap; 219 int type; 220 int prioceiling = 0; 221 222 /* 223 * All of the pshared, type, protocol, robust attributes 224 * translate to bits in the mutex_type field. 225 */ 226 if (attr != NULL) { 227 if ((ap = attr->__pthread_mutexattrp) == NULL) 228 return (EINVAL); 229 type = ap->pshared | ap->type | ap->protocol | ap->robustness; 230 if (ap->protocol == PTHREAD_PRIO_PROTECT) 231 prioceiling = ap->prioceiling; 232 } else { 233 type = DEFAULT_TYPE | PTHREAD_MUTEX_DEFAULT | 234 PTHREAD_PRIO_NONE | PTHREAD_MUTEX_STALL_NP; 235 } 236 237 return (_private_mutex_init((mutex_t *)mutex, type, &prioceiling)); 238 } 239 240 /* 241 * pthread_mutex_setprioceiling: sets the prioceiling. 242 * From the SUSv3 (POSIX) specification for pthread_mutex_setprioceiling(): 243 * The process of locking the mutex need not 244 * adhere to the priority protect protocol. 245 * We pass the MUTEX_NOCEIL flag to mutex_lock_internal() so that 246 * a non-realtime thread can successfully execute this operation. 247 */ 248 #pragma weak pthread_mutex_setprioceiling = _pthread_mutex_setprioceiling 249 int 250 _pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int ceil, int *oceil) 251 { 252 mutex_t *mp = (mutex_t *)mutex; 253 const pcclass_t *pccp = get_info_by_policy(SCHED_FIFO); 254 int error; 255 256 if (!(mp->mutex_type & PTHREAD_PRIO_PROTECT) || 257 ceil < pccp->pcc_primin || ceil > pccp->pcc_primax) 258 return (EINVAL); 259 error = mutex_lock_internal(mp, NULL, MUTEX_LOCK | MUTEX_NOCEIL); 260 if (error == 0) { 261 if (oceil) 262 *oceil = mp->mutex_ceiling; 263 mp->mutex_ceiling = ceil; 264 error = mutex_unlock_internal(mp, 0); 265 } 266 return (error); 267 } 268 269 /* 270 * pthread_mutex_getprioceiling: gets the prioceiling. 271 */ 272 #pragma weak pthread_mutex_getprioceiling = _pthread_mutex_getprioceiling 273 int 274 _pthread_mutex_getprioceiling(const pthread_mutex_t *mp, int *ceiling) 275 { 276 *ceiling = ((mutex_t *)mp)->mutex_ceiling; 277 return (0); 278 } 279 280 /* 281 * UNIX98 282 * pthread_mutexattr_settype: sets the type attribute 283 */ 284 #pragma weak pthread_mutexattr_settype = _pthread_mutexattr_settype 285 int 286 _pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) 287 { 288 mattr_t *ap; 289 290 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL) 291 return (EINVAL); 292 switch (type) { 293 case PTHREAD_MUTEX_NORMAL: 294 type = LOCK_NORMAL; 295 break; 296 case PTHREAD_MUTEX_ERRORCHECK: 297 type = LOCK_ERRORCHECK; 298 break; 299 case PTHREAD_MUTEX_RECURSIVE: 300 type = LOCK_RECURSIVE | LOCK_ERRORCHECK; 301 break; 302 default: 303 return (EINVAL); 304 } 305 ap->type = type; 306 return (0); 307 } 308 309 /* 310 * UNIX98 311 * pthread_mutexattr_gettype: gets the type attribute. 312 */ 313 #pragma weak pthread_mutexattr_gettype = _pthread_mutexattr_gettype 314 int 315 _pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *typep) 316 { 317 mattr_t *ap; 318 int type; 319 320 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 321 typep == NULL) 322 return (EINVAL); 323 switch (ap->type) { 324 case LOCK_NORMAL: 325 type = PTHREAD_MUTEX_NORMAL; 326 break; 327 case LOCK_ERRORCHECK: 328 type = PTHREAD_MUTEX_ERRORCHECK; 329 break; 330 case LOCK_RECURSIVE | LOCK_ERRORCHECK: 331 type = PTHREAD_MUTEX_RECURSIVE; 332 break; 333 default: 334 return (EINVAL); 335 } 336 *typep = type; 337 return (0); 338 } 339