1 /* $NetBSD: pthread_attr.c,v 1.16 2012/03/02 18:06:05 joerg Exp $ */ 2 3 /*- 4 * Copyright (c) 2001, 2002, 2003, 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Nathan J. Williams. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __RCSID("$NetBSD: pthread_attr.c,v 1.16 2012/03/02 18:06:05 joerg Exp $"); 34 35 #include <errno.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <unistd.h> 40 41 #ifndef __lint__ 42 #define pthread_attr_get_np _pthread_attr_get_np 43 #endif 44 45 #include "pthread.h" 46 #include "pthread_int.h" 47 48 __weak_alias(pthread_attr_get_np, _pthread_attr_get_np) 49 50 static struct pthread_attr_private *pthread__attr_init_private( 51 pthread_attr_t *); 52 53 static struct pthread_attr_private * 54 pthread__attr_init_private(pthread_attr_t *attr) 55 { 56 struct pthread_attr_private *p; 57 58 if ((p = attr->pta_private) != NULL) 59 return p; 60 61 p = malloc(sizeof(*p)); 62 if (p != NULL) { 63 memset(p, 0, sizeof(*p)); 64 attr->pta_private = p; 65 p->ptap_policy = SCHED_OTHER; 66 } 67 return p; 68 } 69 70 71 int 72 pthread_attr_init(pthread_attr_t *attr) 73 { 74 75 attr->pta_magic = PT_ATTR_MAGIC; 76 attr->pta_flags = 0; 77 attr->pta_private = NULL; 78 79 return 0; 80 } 81 82 83 int 84 pthread_attr_destroy(pthread_attr_t *attr) 85 { 86 struct pthread_attr_private *p; 87 88 if ((p = attr->pta_private) != NULL) 89 free(p); 90 91 return 0; 92 } 93 94 95 int 96 pthread_attr_get_np(pthread_t thread, pthread_attr_t *attr) 97 { 98 struct pthread_attr_private *p; 99 100 p = pthread__attr_init_private(attr); 101 if (p == NULL) 102 return ENOMEM; 103 104 attr->pta_flags = thread->pt_flags & 105 (PT_FLAG_DETACHED | PT_FLAG_SCOPE_SYSTEM | PT_FLAG_EXPLICIT_SCHED); 106 107 p->ptap_namearg = thread->pt_name; 108 p->ptap_stackaddr = thread->pt_stack.ss_sp; 109 p->ptap_stacksize = thread->pt_stack.ss_size; 110 p->ptap_guardsize = pthread__pagesize; 111 return pthread_getschedparam(thread, &p->ptap_policy, &p->ptap_sp); 112 } 113 114 115 int 116 pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) 117 { 118 119 if (attr->pta_flags & PT_FLAG_DETACHED) 120 *detachstate = PTHREAD_CREATE_DETACHED; 121 else 122 *detachstate = PTHREAD_CREATE_JOINABLE; 123 124 return 0; 125 } 126 127 128 int 129 pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) 130 { 131 132 switch (detachstate) { 133 case PTHREAD_CREATE_JOINABLE: 134 attr->pta_flags &= ~PT_FLAG_DETACHED; 135 break; 136 case PTHREAD_CREATE_DETACHED: 137 attr->pta_flags |= PT_FLAG_DETACHED; 138 break; 139 default: 140 return EINVAL; 141 } 142 143 return 0; 144 } 145 146 147 int 148 pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guard) 149 { 150 struct pthread_attr_private *p; 151 152 if ((p = attr->pta_private) == NULL) 153 *guard = (size_t)sysconf(_SC_PAGESIZE); 154 else 155 *guard = p->ptap_guardsize; 156 157 return 0; 158 } 159 160 161 int 162 pthread_attr_setguardsize(pthread_attr_t *attr, size_t guard) 163 { 164 struct pthread_attr_private *p; 165 166 p = pthread__attr_init_private(attr); 167 if (p == NULL) 168 return ENOMEM; 169 170 p->ptap_guardsize = guard; 171 172 return 0; 173 } 174 175 176 int 177 pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit) 178 { 179 180 if (attr->pta_flags & PT_FLAG_EXPLICIT_SCHED) 181 *inherit = PTHREAD_EXPLICIT_SCHED; 182 else 183 *inherit = PTHREAD_INHERIT_SCHED; 184 185 return 0; 186 } 187 188 189 int 190 pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit) 191 { 192 193 switch (inherit) { 194 case PTHREAD_INHERIT_SCHED: 195 attr->pta_flags &= ~PT_FLAG_EXPLICIT_SCHED; 196 break; 197 case PTHREAD_EXPLICIT_SCHED: 198 attr->pta_flags |= PT_FLAG_EXPLICIT_SCHED; 199 break; 200 default: 201 return EINVAL; 202 } 203 204 return 0; 205 } 206 207 208 int 209 pthread_attr_getscope(const pthread_attr_t *attr, int *scope) 210 { 211 212 if (attr->pta_flags & PT_FLAG_SCOPE_SYSTEM) 213 *scope = PTHREAD_SCOPE_SYSTEM; 214 else 215 *scope = PTHREAD_SCOPE_PROCESS; 216 217 return 0; 218 } 219 220 221 int 222 pthread_attr_setscope(pthread_attr_t *attr, int scope) 223 { 224 225 switch (scope) { 226 case PTHREAD_SCOPE_PROCESS: 227 attr->pta_flags &= ~PT_FLAG_SCOPE_SYSTEM; 228 break; 229 case PTHREAD_SCOPE_SYSTEM: 230 attr->pta_flags |= PT_FLAG_SCOPE_SYSTEM; 231 break; 232 default: 233 return EINVAL; 234 } 235 236 return 0; 237 } 238 239 240 int 241 pthread_attr_setschedparam(pthread_attr_t *attr, 242 const struct sched_param *param) 243 { 244 struct pthread_attr_private *p; 245 int error; 246 247 if (param == NULL) 248 return EINVAL; 249 p = pthread__attr_init_private(attr); 250 if (p == NULL) 251 return ENOMEM; 252 error = pthread__checkpri(param->sched_priority); 253 if (error == 0) 254 p->ptap_sp = *param; 255 return error; 256 } 257 258 259 int 260 pthread_attr_getschedparam(const pthread_attr_t *attr, 261 struct sched_param *param) 262 { 263 struct pthread_attr_private *p; 264 265 if (param == NULL) 266 return EINVAL; 267 p = attr->pta_private; 268 if (p == NULL) 269 memset(param, 0, sizeof(*param)); 270 else 271 *param = p->ptap_sp; 272 return 0; 273 } 274 275 276 int 277 pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) 278 { 279 struct pthread_attr_private *p; 280 281 282 switch (policy) { 283 case SCHED_OTHER: 284 case SCHED_FIFO: 285 case SCHED_RR: 286 p = pthread__attr_init_private(attr); 287 if (p == NULL) 288 return ENOMEM; 289 p->ptap_policy = policy; 290 return 0; 291 default: 292 return ENOTSUP; 293 } 294 } 295 296 297 int 298 pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) 299 { 300 struct pthread_attr_private *p; 301 302 p = attr->pta_private; 303 if (p == NULL) { 304 *policy = SCHED_OTHER; 305 return 0; 306 } 307 *policy = p->ptap_policy; 308 return 0; 309 } 310 311 312 int 313 pthread_attr_getstack(const pthread_attr_t *attr, void **addr, size_t *size) 314 { 315 struct pthread_attr_private *p; 316 317 if ((p = attr->pta_private) == NULL) { 318 *addr = NULL; 319 *size = pthread__stacksize; 320 } else { 321 *addr = p->ptap_stackaddr; 322 *size = p->ptap_stacksize; 323 } 324 325 return 0; 326 } 327 328 329 int 330 pthread_attr_setstack(pthread_attr_t *attr, void *addr, size_t size) 331 { 332 struct pthread_attr_private *p; 333 334 p = pthread__attr_init_private(attr); 335 if (p == NULL) 336 return ENOMEM; 337 338 p->ptap_stackaddr = addr; 339 p->ptap_stacksize = size; 340 341 return 0; 342 } 343 344 345 int 346 pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *size) 347 { 348 struct pthread_attr_private *p; 349 350 if ((p = attr->pta_private) == NULL) 351 *size = pthread__stacksize; 352 else 353 *size = p->ptap_stacksize; 354 355 return 0; 356 } 357 358 359 int 360 pthread_attr_setstacksize(pthread_attr_t *attr, size_t size) 361 { 362 struct pthread_attr_private *p; 363 364 if (size < (size_t)sysconf(_SC_THREAD_STACK_MIN)) 365 return EINVAL; 366 367 p = pthread__attr_init_private(attr); 368 if (p == NULL) 369 return ENOMEM; 370 371 p->ptap_stacksize = size; 372 373 return 0; 374 } 375 376 377 int 378 pthread_attr_getstackaddr(const pthread_attr_t *attr, void **addr) 379 { 380 struct pthread_attr_private *p; 381 382 if ((p = attr->pta_private) == NULL) 383 *addr = NULL; 384 else 385 *addr = p->ptap_stackaddr; 386 387 return 0; 388 } 389 390 391 int 392 pthread_attr_setstackaddr(pthread_attr_t *attr, void *addr) 393 { 394 struct pthread_attr_private *p; 395 396 p = pthread__attr_init_private(attr); 397 if (p == NULL) 398 return ENOMEM; 399 400 p->ptap_stackaddr = addr; 401 402 return 0; 403 } 404 405 406 int 407 pthread_attr_getname_np(const pthread_attr_t *attr, char *name, size_t len, 408 void **argp) 409 { 410 struct pthread_attr_private *p; 411 412 if ((p = attr->pta_private) == NULL) { 413 name[0] = '\0'; 414 if (argp != NULL) 415 *argp = NULL; 416 } else { 417 strlcpy(name, p->ptap_name, len); 418 if (argp != NULL) 419 *argp = p->ptap_namearg; 420 } 421 422 return 0; 423 } 424 425 426 int 427 pthread_attr_setname_np(pthread_attr_t *attr, const char *name, void *arg) 428 { 429 struct pthread_attr_private *p; 430 int namelen; 431 432 p = pthread__attr_init_private(attr); 433 if (p == NULL) 434 return ENOMEM; 435 436 namelen = snprintf(p->ptap_name, PTHREAD_MAX_NAMELEN_NP, name, arg); 437 if (namelen >= PTHREAD_MAX_NAMELEN_NP) { 438 p->ptap_name[0] = '\0'; 439 return EINVAL; 440 } 441 p->ptap_namearg = arg; 442 443 return 0; 444 } 445 446 int 447 pthread_attr_setcreatesuspend_np(pthread_attr_t *attr) 448 { 449 attr->pta_flags |= PT_FLAG_SUSPENDED; 450 return 0; 451 } 452 453 int 454 pthread_getattr_np(pthread_t thread, pthread_attr_t *attr) 455 { 456 int error; 457 if ((error = pthread_attr_init(attr)) != 0) 458 return error; 459 if ((error = pthread_attr_get_np(thread, attr)) != 0) { 460 (void)pthread_attr_destroy(attr); 461 return error; 462 } 463 return 0; 464 } 465