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 #include "lint.h" 28 #include "thr_uberdata.h" 29 #include <pthread.h> 30 31 /* 32 * pthread_mutexattr_init: allocates the mutex attribute object and 33 * initializes it with the default values. 34 */ 35 #pragma weak _pthread_mutexattr_init = pthread_mutexattr_init 36 int 37 pthread_mutexattr_init(pthread_mutexattr_t *attr) 38 { 39 mattr_t *ap; 40 41 if ((ap = lmalloc(sizeof (mattr_t))) == NULL) 42 return (ENOMEM); 43 ap->pshared = PTHREAD_PROCESS_PRIVATE; 44 ap->type = PTHREAD_MUTEX_DEFAULT; 45 ap->protocol = PTHREAD_PRIO_NONE; 46 ap->robustness = PTHREAD_MUTEX_STALLED; 47 attr->__pthread_mutexattrp = ap; 48 return (0); 49 } 50 51 /* 52 * pthread_mutexattr_destroy: frees the mutex attribute object and 53 * invalidates it with NULL value. 54 */ 55 int 56 pthread_mutexattr_destroy(pthread_mutexattr_t *attr) 57 { 58 if (attr == NULL || attr->__pthread_mutexattrp == NULL) 59 return (EINVAL); 60 lfree(attr->__pthread_mutexattrp, sizeof (mattr_t)); 61 attr->__pthread_mutexattrp = NULL; 62 return (0); 63 } 64 65 /* 66 * pthread_mutexattr_setpshared: sets the shared attribute 67 * to PTHREAD_PROCESS_PRIVATE or PTHREAD_PROCESS_SHARED. 68 * This is equivalent to setting the USYNC_THREAD/USYNC_PROCESS 69 * flag in mutex_init(). 70 */ 71 int 72 pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared) 73 { 74 mattr_t *ap; 75 76 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 77 (pshared != PTHREAD_PROCESS_PRIVATE && 78 pshared != PTHREAD_PROCESS_SHARED)) 79 return (EINVAL); 80 ap->pshared = pshared; 81 return (0); 82 } 83 84 /* 85 * pthread_mutexattr_getpshared: gets the shared attribute. 86 */ 87 #pragma weak _pthread_mutexattr_getpshared = pthread_mutexattr_getpshared 88 int 89 pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, int *pshared) 90 { 91 mattr_t *ap; 92 93 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 94 pshared == NULL) 95 return (EINVAL); 96 *pshared = ap->pshared; 97 return (0); 98 } 99 100 /* 101 * pthread_mutexattr_setprioceiling: sets the prioceiling attribute. 102 */ 103 int 104 pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int prioceiling) 105 { 106 const pcclass_t *pccp = get_info_by_policy(SCHED_FIFO); 107 mattr_t *ap; 108 109 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 110 prioceiling < pccp->pcc_primin || prioceiling > pccp->pcc_primax) 111 return (EINVAL); 112 ap->prioceiling = prioceiling; 113 return (0); 114 } 115 116 /* 117 * pthread_mutexattr_getprioceiling: gets the prioceiling attribute. 118 */ 119 #pragma weak _pthread_mutexattr_getprioceiling = \ 120 pthread_mutexattr_getprioceiling 121 int 122 pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr, int *ceiling) 123 { 124 mattr_t *ap; 125 126 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 127 ceiling == NULL) 128 return (EINVAL); 129 *ceiling = ap->prioceiling; 130 return (0); 131 } 132 133 /* 134 * pthread_mutexattr_setprotocol: sets the protocol attribute. 135 */ 136 int 137 pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol) 138 { 139 mattr_t *ap; 140 141 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL) 142 return (EINVAL); 143 if (protocol != PTHREAD_PRIO_NONE && 144 protocol != PTHREAD_PRIO_INHERIT && 145 protocol != PTHREAD_PRIO_PROTECT) 146 return (ENOTSUP); 147 ap->protocol = protocol; 148 return (0); 149 } 150 151 /* 152 * pthread_mutexattr_getprotocol: gets the protocol attribute. 153 */ 154 #pragma weak _pthread_mutexattr_getprotocol = pthread_mutexattr_getprotocol 155 int 156 pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int *protocol) 157 { 158 mattr_t *ap; 159 160 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 161 protocol == NULL) 162 return (EINVAL); 163 *protocol = ap->protocol; 164 return (0); 165 } 166 167 /* 168 * pthread_mutexattr_setrobust: set the mutex robust attribute. 169 * pthread_mutexattr_setrobust_np: the historical name. 170 */ 171 #pragma weak pthread_mutexattr_setrobust_np = pthread_mutexattr_setrobust 172 int 173 pthread_mutexattr_setrobust(pthread_mutexattr_t *attr, int robust) 174 { 175 mattr_t *ap; 176 177 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 178 (robust != PTHREAD_MUTEX_ROBUST && robust != PTHREAD_MUTEX_STALLED)) 179 return (EINVAL); 180 ap->robustness = robust; 181 return (0); 182 } 183 184 /* 185 * pthread_mutexattr_getrobust: get the mutex robust attribute. 186 * pthread_mutexattr_getrobust_np: the historical name. 187 */ 188 #pragma weak pthread_mutexattr_getrobust_np = pthread_mutexattr_getrobust 189 int 190 pthread_mutexattr_getrobust(const pthread_mutexattr_t *attr, int *robust) 191 { 192 mattr_t *ap; 193 194 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 195 robust == NULL) 196 return (EINVAL); 197 *robust = ap->robustness; 198 return (0); 199 } 200 201 /* 202 * pthread_mutex_init: Initializes the mutex object. It copies the various 203 * attributes into one type argument and calls mutex_init(). Unlike other 204 * values, the types that are used in the mutex attributes are not 1:1 mapped to 205 * our underlying lock types at this time so we can properly honor the semantics 206 * of someone asking for a PTHREAD_MUTEX_NORMAL lock that must deadlock. The 207 * underlying threads implementation does not do this by default for 208 * USYNC_THREAD and so we don't do this unless explicitly asked for it. 209 */ 210 #pragma weak _pthread_mutex_init = pthread_mutex_init 211 int 212 pthread_mutex_init(pthread_mutex_t *_RESTRICT_KYWD mutex, 213 const pthread_mutexattr_t *_RESTRICT_KYWD attr) 214 { 215 mattr_t *ap; 216 int type, ret; 217 int prioceiling = 0; 218 uint16_t flags = 0; 219 220 /* 221 * All of the pshared, type, protocol, robust attributes 222 * translate to bits in the mutex_type field. 223 */ 224 if (attr != NULL) { 225 if ((ap = attr->__pthread_mutexattrp) == NULL) 226 return (EINVAL); 227 switch (ap->type) { 228 case PTHREAD_MUTEX_NORMAL: 229 type = LOCK_NORMAL; 230 flags = LOCK_DEADLOCK; 231 break; 232 case PTHREAD_MUTEX_ERRORCHECK: 233 type = LOCK_ERRORCHECK; 234 break; 235 case PTHREAD_MUTEX_RECURSIVE: 236 type = LOCK_RECURSIVE; 237 break; 238 default: 239 /* 240 * This covers PTHREAD_MUTEX_DEFAULT, which should be 241 * the only remaining valid value. 242 */ 243 type = LOCK_NORMAL; 244 break; 245 } 246 247 type |= ap->pshared | ap->protocol | ap->robustness; 248 if (ap->protocol == PTHREAD_PRIO_PROTECT) 249 prioceiling = ap->prioceiling; 250 } else { 251 type = PTHREAD_PROCESS_PRIVATE | LOCK_NORMAL | 252 PTHREAD_PRIO_NONE | PTHREAD_MUTEX_STALLED; 253 } 254 255 /* 256 * POSIX mutexes (this interface) make no guarantee about the state of 257 * the mutex before pthread_mutex_init(3C) is called. Sun mutexes, upon 258 * which these are built and which mutex_init(3C) below represents 259 * require that a robust mutex be initialized to all 0s _prior_ to 260 * mutex_init() being called, and that mutex_init() of an initialized 261 * mutex return EBUSY. 262 * 263 * We respect both these behaviors by zeroing the mutex here in the 264 * POSIX implementation if and only if the mutex magic is incorrect, 265 * and the mutex is robust. 266 */ 267 if (((type & PTHREAD_MUTEX_ROBUST) != 0) && 268 (((mutex_t *)mutex)->mutex_magic != MUTEX_MAGIC)) { 269 (void) memset(mutex, 0, sizeof (*mutex)); 270 } 271 272 ret = mutex_init((mutex_t *)mutex, type, &prioceiling); 273 274 /* 275 * If we have a normal mutex, we need to set that deadlock behavior is 276 * required. 277 */ 278 if (ret == 0 && flags != 0) { 279 mutex_t *mp = (mutex_t *)mutex; 280 mp->mutex_flag |= flags; 281 } 282 283 return (ret); 284 } 285 286 /* 287 * pthread_mutex_setprioceiling: sets the prioceiling. 288 * From the SUSv3 (POSIX) specification for pthread_mutex_setprioceiling(): 289 * The process of locking the mutex need not 290 * adhere to the priority protect protocol. 291 * We pass the MUTEX_NOCEIL flag to mutex_lock_internal() so that 292 * a non-realtime thread can successfully execute this operation. 293 */ 294 int 295 pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int ceil, int *oceil) 296 { 297 mutex_t *mp = (mutex_t *)mutex; 298 const pcclass_t *pccp = get_info_by_policy(SCHED_FIFO); 299 int error; 300 301 if (!(mp->mutex_type & PTHREAD_PRIO_PROTECT) || 302 ceil < pccp->pcc_primin || ceil > pccp->pcc_primax) 303 return (EINVAL); 304 error = mutex_lock_internal(mp, NULL, MUTEX_LOCK | MUTEX_NOCEIL); 305 if (error == 0 || error == EOWNERDEAD || error == ELOCKUNMAPPED) { 306 if (oceil) 307 *oceil = mp->mutex_ceiling; 308 mp->mutex_ceiling = ceil; 309 error = mutex_unlock_internal(mp, 1); 310 } 311 return (error); 312 } 313 314 /* 315 * pthread_mutex_getprioceiling: gets the prioceiling. 316 */ 317 #pragma weak _pthread_mutex_getprioceiling = pthread_mutex_getprioceiling 318 int 319 pthread_mutex_getprioceiling(const pthread_mutex_t *mp, int *ceiling) 320 { 321 *ceiling = ((mutex_t *)mp)->mutex_ceiling; 322 return (0); 323 } 324 325 /* 326 * UNIX98 327 * pthread_mutexattr_settype: sets the type attribute 328 * 329 * Type attributes are kept in terms of POSIX mutex types until the mutex is 330 * initialized, after which it is translated into the corresponding underlying 331 * lock type. 332 */ 333 int 334 pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) 335 { 336 mattr_t *ap; 337 338 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL) 339 return (EINVAL); 340 switch (type) { 341 case PTHREAD_MUTEX_NORMAL: 342 case PTHREAD_MUTEX_ERRORCHECK: 343 case PTHREAD_MUTEX_RECURSIVE: 344 case PTHREAD_MUTEX_DEFAULT: 345 break; 346 default: 347 return (EINVAL); 348 } 349 ap->type = type; 350 return (0); 351 } 352 353 /* 354 * UNIX98 355 * pthread_mutexattr_gettype: gets the type attribute. 356 */ 357 int 358 pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *typep) 359 { 360 mattr_t *ap; 361 int type; 362 363 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 364 typep == NULL) 365 return (EINVAL); 366 *typep = type; 367 return (0); 368 } 369