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 int 58 pthread_mutexattr_destroy(pthread_mutexattr_t *attr) 59 { 60 if (attr == NULL || attr->__pthread_mutexattrp == NULL) 61 return (EINVAL); 62 lfree(attr->__pthread_mutexattrp, sizeof (mattr_t)); 63 attr->__pthread_mutexattrp = NULL; 64 return (0); 65 } 66 67 /* 68 * pthread_mutexattr_setpshared: sets the shared attribute 69 * to PTHREAD_PROCESS_PRIVATE or PTHREAD_PROCESS_SHARED. 70 * This is equivalent to setting the USYNC_THREAD/USYNC_PROCESS 71 * flag in mutex_init(). 72 */ 73 int 74 pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared) 75 { 76 mattr_t *ap; 77 78 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 79 (pshared != PTHREAD_PROCESS_PRIVATE && 80 pshared != PTHREAD_PROCESS_SHARED)) 81 return (EINVAL); 82 ap->pshared = pshared; 83 return (0); 84 } 85 86 /* 87 * pthread_mutexattr_getpshared: gets the shared attribute. 88 */ 89 #pragma weak _pthread_mutexattr_getpshared = pthread_mutexattr_getpshared 90 int 91 pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, int *pshared) 92 { 93 mattr_t *ap; 94 95 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 96 pshared == NULL) 97 return (EINVAL); 98 *pshared = ap->pshared; 99 return (0); 100 } 101 102 /* 103 * pthread_mutexattr_setprioceiling: sets the prioceiling attribute. 104 */ 105 int 106 pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int prioceiling) 107 { 108 const pcclass_t *pccp = get_info_by_policy(SCHED_FIFO); 109 mattr_t *ap; 110 111 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 112 prioceiling < pccp->pcc_primin || prioceiling > pccp->pcc_primax) 113 return (EINVAL); 114 ap->prioceiling = prioceiling; 115 return (0); 116 } 117 118 /* 119 * pthread_mutexattr_getprioceiling: gets the prioceiling attribute. 120 */ 121 #pragma weak _pthread_mutexattr_getprioceiling = \ 122 pthread_mutexattr_getprioceiling 123 int 124 pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr, int *ceiling) 125 { 126 mattr_t *ap; 127 128 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 129 ceiling == NULL) 130 return (EINVAL); 131 *ceiling = ap->prioceiling; 132 return (0); 133 } 134 135 /* 136 * pthread_mutexattr_setprotocol: sets the protocol attribute. 137 */ 138 int 139 pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol) 140 { 141 mattr_t *ap; 142 143 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL) 144 return (EINVAL); 145 if (protocol != PTHREAD_PRIO_NONE && 146 protocol != PTHREAD_PRIO_INHERIT && 147 protocol != PTHREAD_PRIO_PROTECT) 148 return (ENOTSUP); 149 ap->protocol = protocol; 150 return (0); 151 } 152 153 /* 154 * pthread_mutexattr_getprotocol: gets the protocol attribute. 155 */ 156 #pragma weak _pthread_mutexattr_getprotocol = pthread_mutexattr_getprotocol 157 int 158 pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int *protocol) 159 { 160 mattr_t *ap; 161 162 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 163 protocol == NULL) 164 return (EINVAL); 165 *protocol = ap->protocol; 166 return (0); 167 } 168 169 /* 170 * pthread_mutexattr_setrobust_np: sets the robustness attribute 171 * to PTHREAD_MUTEX_ROBUST_NP or PTHREAD_MUTEX_STALL_NP. 172 */ 173 int 174 pthread_mutexattr_setrobust_np(pthread_mutexattr_t *attr, int robust) 175 { 176 mattr_t *ap; 177 178 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL || 179 (robust != PTHREAD_MUTEX_ROBUST_NP && 180 robust != PTHREAD_MUTEX_STALL_NP)) 181 return (EINVAL); 182 ap->robustness = robust; 183 return (0); 184 } 185 186 /* 187 * pthread_mutexattr_getrobust_np: gets the robustness attribute. 188 */ 189 int 190 pthread_mutexattr_getrobust_np(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_STALL_NP; 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) { 252 if (oceil) 253 *oceil = mp->mutex_ceiling; 254 mp->mutex_ceiling = ceil; 255 error = mutex_unlock_internal(mp, 0); 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