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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1999-2003 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 attr to PRIVATE or SHARED. 70 * This is equivalent to setting USYNC_PROCESS/USYNC_THREAD flag in 71 * mutex_init(). 72 */ 73 #pragma weak pthread_mutexattr_setpshared = _pthread_mutexattr_setpshared 74 int 75 _pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared) 76 { 77 mattr_t *ap; 78 79 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 80 (pshared != PTHREAD_PROCESS_PRIVATE && 81 pshared != PTHREAD_PROCESS_SHARED)) 82 return (EINVAL); 83 ap->pshared = pshared; 84 return (0); 85 } 86 87 /* 88 * pthread_mutexattr_getpshared: gets the shared attr. 89 */ 90 #pragma weak pthread_mutexattr_getpshared = _pthread_mutexattr_getpshared 91 int 92 _pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, int *pshared) 93 { 94 mattr_t *ap; 95 96 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 97 pshared == NULL) 98 return (EINVAL); 99 *pshared = ap->pshared; 100 return (0); 101 } 102 103 /* 104 * pthread_mutexattr_setprioceiling: sets the prioceiling attr. 105 */ 106 #pragma weak pthread_mutexattr_setprioceiling = \ 107 _pthread_mutexattr_setprioceiling 108 int 109 _pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int prioceiling) 110 { 111 mattr_t *ap; 112 113 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 114 _validate_rt_prio(SCHED_FIFO, prioceiling)) 115 return (EINVAL); 116 ap->prioceiling = prioceiling; 117 return (0); 118 } 119 120 /* 121 * pthread_mutexattr_getprioceiling: gets the prioceiling attr. 122 * Currently unsupported. 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 * Currently unsupported. 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 * Currently unsupported. 161 */ 162 #pragma weak pthread_mutexattr_getprotocol = _pthread_mutexattr_getprotocol 163 int 164 _pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int *protocol) 165 { 166 mattr_t *ap; 167 168 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 169 protocol == NULL) 170 return (EINVAL); 171 *protocol = ap->protocol; 172 return (0); 173 } 174 175 /* 176 * pthread_mutexattr_setrobust_np: sets the robustness attr to ROBUST or STALL. 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 attr. 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_consistent_np: make an inconsistent mutex consistent. 212 * The mutex must have been made inconsistent due to the last owner of it 213 * having died. Currently, no validation is done to check if: 214 * - the caller owns the mutex 215 * Since this function is supported only for PI/robust locks, to check 216 * if the caller owns the mutex, one needs to call the kernel. For now, 217 * such extra validation does not seem necessary. 218 */ 219 #pragma weak pthread_mutex_consistent_np = _pthread_mutex_consistent_np 220 int 221 _pthread_mutex_consistent_np(pthread_mutex_t *pmp) 222 { 223 mutex_t *mp = (mutex_t *)pmp; 224 225 /* 226 * Do this only for an inconsistent, initialized, PI, Robust lock. 227 * For all other cases, return EINVAL. 228 */ 229 if ((mp->mutex_type & PTHREAD_PRIO_INHERIT) && 230 (mp->mutex_type & PTHREAD_MUTEX_ROBUST_NP) && 231 (mp->mutex_flag & LOCK_INITED) && 232 (mp->mutex_flag & LOCK_OWNERDEAD)) { 233 mp->mutex_flag &= ~LOCK_OWNERDEAD; 234 return (0); 235 } 236 return (EINVAL); 237 } 238 239 /* 240 * pthread_mutex_init: Initializes the mutex object. It copies the 241 * pshared attr into type argument and calls mutex_init(). 242 */ 243 #pragma weak pthread_mutex_init = _pthread_mutex_init 244 int 245 _pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr) 246 { 247 mutex_t *mp = (mutex_t *)mutex; 248 int type; 249 int pshared; 250 int protocol; 251 int prioceiling = 0; 252 int robust; 253 int error; 254 mattr_t *ap; 255 256 if (attr != NULL) { 257 if ((ap = attr->__pthread_mutexattrp) == NULL) 258 return (EINVAL); 259 pshared = ap->pshared; 260 type = ap->type; 261 protocol = ap->protocol; 262 if (protocol == PTHREAD_PRIO_PROTECT) 263 prioceiling = ap->prioceiling; 264 robust = ap->robustness; 265 /* 266 * Support robust mutexes only for PI locks. 267 */ 268 if (robust == PTHREAD_MUTEX_ROBUST_NP && 269 protocol != PTHREAD_PRIO_INHERIT) 270 return (EINVAL); 271 } else { 272 pshared = DEFAULT_TYPE; 273 type = PTHREAD_MUTEX_DEFAULT; 274 protocol = PTHREAD_PRIO_NONE; 275 robust = PTHREAD_MUTEX_STALL_NP; 276 } 277 278 error = _private_mutex_init(mp, pshared, NULL); 279 if (error == 0) { 280 /* 281 * Use the same routine to set the protocol, and robustness 282 * attributes, as that used to set the type attribute, since 283 * all of these attributes translate to bits in the mutex_type 284 * field. 285 * 286 * Note that robustness is a new bit, not the Solaris robust 287 * bit - the latter implies USYNC_PROCESS_ROBUST, or 288 * SHARED,ROBUST together. For POSIX, since robustness is an 289 * orthogonal attribute, both SHARED,ROBUST and PRIVATE,ROBUST 290 * should be valid combinations for the future. Hence, 291 * introduce a new bit in the mutex type field. See 292 * sys/synch.h or pthread.h. In the future, if we ever 293 * introduce a USYNC_THREAD_ROBUST, the latter could use this 294 * new bit... 295 */ 296 _mutex_set_typeattr(mp, type|protocol|robust); 297 mp->mutex_ceiling = (uint8_t)prioceiling; 298 } 299 return (error); 300 } 301 302 /* 303 * pthread_mutex_setprioceiling: sets the prioceiling. 304 */ 305 #pragma weak pthread_mutex_setprioceiling = _pthread_mutex_setprioceiling 306 int 307 _pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int ceil, int *oceil) 308 { 309 mutex_t *mp = (mutex_t *)mutex; 310 int error; 311 312 if (!(mp->mutex_type & PTHREAD_PRIO_PROTECT) || 313 _validate_rt_prio(SCHED_FIFO, ceil) != 0) 314 return (EINVAL); 315 error = _private_mutex_lock(mp); 316 if (error == 0) { 317 if (oceil) 318 *oceil = mp->mutex_ceiling; 319 mp->mutex_ceiling = (uint8_t)ceil; 320 error = _private_mutex_unlock(mp); 321 } 322 return (error); 323 } 324 325 /* 326 * pthread_mutex_getprioceiling: gets the prioceiling. 327 */ 328 #pragma weak pthread_mutex_getprioceiling = _pthread_mutex_getprioceiling 329 int 330 _pthread_mutex_getprioceiling(const pthread_mutex_t *mp, int *ceiling) 331 { 332 *ceiling = ((mutex_t *)mp)->mutex_ceiling; 333 return (0); 334 } 335 336 /* 337 * UNIX98 338 * pthread_mutexattr_settype: sets the type attribute 339 */ 340 #pragma weak pthread_mutexattr_settype = _pthread_mutexattr_settype 341 int 342 _pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) 343 { 344 mattr_t *ap; 345 346 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL) 347 return (EINVAL); 348 switch (type) { 349 case PTHREAD_MUTEX_NORMAL: 350 type = LOCK_NORMAL; 351 break; 352 case PTHREAD_MUTEX_ERRORCHECK: 353 type = LOCK_ERRORCHECK; 354 break; 355 case PTHREAD_MUTEX_RECURSIVE: 356 type = LOCK_RECURSIVE|LOCK_ERRORCHECK; 357 break; 358 default: 359 return (EINVAL); 360 } 361 ap->type = type; 362 return (0); 363 } 364 365 /* 366 * UNIX98 367 * pthread_mutexattr_gettype: gets the type attr. 368 */ 369 #pragma weak pthread_mutexattr_gettype = _pthread_mutexattr_gettype 370 int 371 _pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *typep) 372 { 373 mattr_t *ap; 374 int type; 375 376 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 377 typep == NULL) 378 return (EINVAL); 379 switch (ap->type) { 380 case LOCK_NORMAL: 381 type = PTHREAD_MUTEX_NORMAL; 382 break; 383 case LOCK_ERRORCHECK: 384 type = PTHREAD_MUTEX_ERRORCHECK; 385 break; 386 case LOCK_RECURSIVE|LOCK_ERRORCHECK: 387 type = PTHREAD_MUTEX_RECURSIVE; 388 break; 389 default: 390 return (EINVAL); 391 } 392 *typep = type; 393 return (0); 394 } 395