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 = DEFAULT_TYPE; 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 = DEFAULT_TYPE | PTHREAD_MUTEX_DEFAULT | 226 PTHREAD_PRIO_NONE | PTHREAD_MUTEX_STALLED; 227 } 228 229 return (mutex_init((mutex_t *)mutex, type, &prioceiling)); 230 } 231 232 /* 233 * pthread_mutex_setprioceiling: sets the prioceiling. 234 * From the SUSv3 (POSIX) specification for pthread_mutex_setprioceiling(): 235 * The process of locking the mutex need not 236 * adhere to the priority protect protocol. 237 * We pass the MUTEX_NOCEIL flag to mutex_lock_internal() so that 238 * a non-realtime thread can successfully execute this operation. 239 */ 240 int 241 pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int ceil, int *oceil) 242 { 243 mutex_t *mp = (mutex_t *)mutex; 244 const pcclass_t *pccp = get_info_by_policy(SCHED_FIFO); 245 int error; 246 247 if (!(mp->mutex_type & PTHREAD_PRIO_PROTECT) || 248 ceil < pccp->pcc_primin || ceil > pccp->pcc_primax) 249 return (EINVAL); 250 error = mutex_lock_internal(mp, NULL, MUTEX_LOCK | MUTEX_NOCEIL); 251 if (error == 0 || error == EOWNERDEAD || error == ELOCKUNMAPPED) { 252 if (oceil) 253 *oceil = mp->mutex_ceiling; 254 mp->mutex_ceiling = ceil; 255 error = mutex_unlock_internal(mp, 1); 256 } 257 return (error); 258 } 259 260 /* 261 * pthread_mutex_getprioceiling: gets the prioceiling. 262 */ 263 #pragma weak _pthread_mutex_getprioceiling = pthread_mutex_getprioceiling 264 int 265 pthread_mutex_getprioceiling(const pthread_mutex_t *mp, int *ceiling) 266 { 267 *ceiling = ((mutex_t *)mp)->mutex_ceiling; 268 return (0); 269 } 270 271 /* 272 * UNIX98 273 * pthread_mutexattr_settype: sets the type attribute 274 */ 275 int 276 pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) 277 { 278 mattr_t *ap; 279 280 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL) 281 return (EINVAL); 282 switch (type) { 283 case PTHREAD_MUTEX_NORMAL: 284 type = LOCK_NORMAL; 285 break; 286 case PTHREAD_MUTEX_ERRORCHECK: 287 type = LOCK_ERRORCHECK; 288 break; 289 case PTHREAD_MUTEX_RECURSIVE: 290 type = LOCK_RECURSIVE | LOCK_ERRORCHECK; 291 break; 292 default: 293 return (EINVAL); 294 } 295 ap->type = type; 296 return (0); 297 } 298 299 /* 300 * UNIX98 301 * pthread_mutexattr_gettype: gets the type attribute. 302 */ 303 int 304 pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *typep) 305 { 306 mattr_t *ap; 307 int type; 308 309 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 310 typep == NULL) 311 return (EINVAL); 312 switch (ap->type) { 313 case LOCK_NORMAL: 314 type = PTHREAD_MUTEX_NORMAL; 315 break; 316 case LOCK_ERRORCHECK: 317 type = PTHREAD_MUTEX_ERRORCHECK; 318 break; 319 case LOCK_RECURSIVE | LOCK_ERRORCHECK: 320 type = PTHREAD_MUTEX_RECURSIVE; 321 break; 322 default: 323 return (EINVAL); 324 } 325 *typep = type; 326 return (0); 327 } 328