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 203 * various attributes into one type argument and calls mutex_init(). 204 */ 205 #pragma weak _pthread_mutex_init = pthread_mutex_init 206 int 207 pthread_mutex_init(pthread_mutex_t *_RESTRICT_KYWD mutex, 208 const pthread_mutexattr_t *_RESTRICT_KYWD attr) 209 { 210 mattr_t *ap; 211 int type; 212 int prioceiling = 0; 213 214 /* 215 * All of the pshared, type, protocol, robust attributes 216 * translate to bits in the mutex_type field. 217 */ 218 if (attr != NULL) { 219 if ((ap = attr->__pthread_mutexattrp) == NULL) 220 return (EINVAL); 221 type = ap->pshared | ap->type | ap->protocol | ap->robustness; 222 if (ap->protocol == PTHREAD_PRIO_PROTECT) 223 prioceiling = ap->prioceiling; 224 } else { 225 type = PTHREAD_PROCESS_PRIVATE | PTHREAD_MUTEX_DEFAULT | 226 PTHREAD_PRIO_NONE | PTHREAD_MUTEX_STALLED; 227 } 228 229 /* 230 * POSIX mutexes (this interface) make no guarantee about the state of 231 * the mutex before pthread_mutex_init(3C) is called. Sun mutexes, upon 232 * which these are built and which mutex_init(3C) below represents 233 * require that a robust mutex be initialized to all 0s _prior_ to 234 * mutex_init() being called, and that mutex_init() of an initialized 235 * mutex return EBUSY. 236 * 237 * We respect both these behaviors by zeroing the mutex here in the 238 * POSIX implementation if and only if the mutex magic is incorrect, 239 * and the mutex is robust. 240 */ 241 if (((type & PTHREAD_MUTEX_ROBUST) != 0) && 242 (((mutex_t *)mutex)->mutex_magic != MUTEX_MAGIC)) { 243 (void) memset(mutex, 0, sizeof (*mutex)); 244 } 245 246 return (mutex_init((mutex_t *)mutex, type, &prioceiling)); 247 } 248 249 /* 250 * pthread_mutex_setprioceiling: sets the prioceiling. 251 * From the SUSv3 (POSIX) specification for pthread_mutex_setprioceiling(): 252 * The process of locking the mutex need not 253 * adhere to the priority protect protocol. 254 * We pass the MUTEX_NOCEIL flag to mutex_lock_internal() so that 255 * a non-realtime thread can successfully execute this operation. 256 */ 257 int 258 pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int ceil, int *oceil) 259 { 260 mutex_t *mp = (mutex_t *)mutex; 261 const pcclass_t *pccp = get_info_by_policy(SCHED_FIFO); 262 int error; 263 264 if (!(mp->mutex_type & PTHREAD_PRIO_PROTECT) || 265 ceil < pccp->pcc_primin || ceil > pccp->pcc_primax) 266 return (EINVAL); 267 error = mutex_lock_internal(mp, NULL, MUTEX_LOCK | MUTEX_NOCEIL); 268 if (error == 0 || error == EOWNERDEAD || error == ELOCKUNMAPPED) { 269 if (oceil) 270 *oceil = mp->mutex_ceiling; 271 mp->mutex_ceiling = ceil; 272 error = mutex_unlock_internal(mp, 1); 273 } 274 return (error); 275 } 276 277 /* 278 * pthread_mutex_getprioceiling: gets the prioceiling. 279 */ 280 #pragma weak _pthread_mutex_getprioceiling = pthread_mutex_getprioceiling 281 int 282 pthread_mutex_getprioceiling(const pthread_mutex_t *mp, int *ceiling) 283 { 284 *ceiling = ((mutex_t *)mp)->mutex_ceiling; 285 return (0); 286 } 287 288 /* 289 * UNIX98 290 * pthread_mutexattr_settype: sets the type attribute 291 */ 292 int 293 pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) 294 { 295 mattr_t *ap; 296 297 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL) 298 return (EINVAL); 299 switch (type) { 300 case PTHREAD_MUTEX_NORMAL: 301 type = LOCK_NORMAL; 302 break; 303 case PTHREAD_MUTEX_ERRORCHECK: 304 type = LOCK_ERRORCHECK; 305 break; 306 case PTHREAD_MUTEX_RECURSIVE: 307 type = LOCK_RECURSIVE | LOCK_ERRORCHECK; 308 break; 309 default: 310 return (EINVAL); 311 } 312 ap->type = type; 313 return (0); 314 } 315 316 /* 317 * UNIX98 318 * pthread_mutexattr_gettype: gets the type attribute. 319 */ 320 int 321 pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *typep) 322 { 323 mattr_t *ap; 324 int type; 325 326 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 327 typep == NULL) 328 return (EINVAL); 329 switch (ap->type) { 330 case LOCK_NORMAL: 331 type = PTHREAD_MUTEX_NORMAL; 332 break; 333 case LOCK_ERRORCHECK: 334 type = PTHREAD_MUTEX_ERRORCHECK; 335 break; 336 case LOCK_RECURSIVE | LOCK_ERRORCHECK: 337 type = PTHREAD_MUTEX_RECURSIVE; 338 break; 339 default: 340 return (EINVAL); 341 } 342 *typep = type; 343 return (0); 344 } 345