1 /* 2 * Copyright (c) 2003 Craig Rodrigues <rodrigc@attbi.com>. 3 * Copyright (c) 2002,2003 Alexey Zelkin <phantom@FreeBSD.org> 4 * Copyright (C) 2001 Jason Evans <jasone@freebsd.org>. 5 * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. 6 * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice(s), this list of conditions and the following disclaimer 14 * unmodified other than the allowable addition of one or more 15 * copyright notices. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice(s), this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY 22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE 25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 30 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 31 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 * $DragonFly: src/lib/libthread_xu/thread/thr_attr.c,v 1.9 2008/07/15 01:18:53 dillon Exp $ 34 */ 35 36 #include "namespace.h" 37 #include <machine/tls.h> 38 39 #include <errno.h> 40 #include <pthread.h> 41 #include <stdlib.h> 42 #include <string.h> 43 #include <pthread_np.h> 44 #include "un-namespace.h" 45 46 #include "thr_private.h" 47 48 /* Default thread attributes. */ 49 struct pthread_attr _pthread_attr_default = { 50 .sched_policy = SCHED_OTHER, 51 .sched_inherit = 0, 52 .prio = THR_DEFAULT_PRIORITY, 53 .suspend = THR_CREATE_RUNNING, 54 .flags = 0, 55 .stackaddr_attr = NULL, 56 .stacksize_attr = THR_STACK_DEFAULT, 57 .guardsize_attr = 0 58 }; 59 60 int 61 _pthread_attr_destroy(pthread_attr_t *attr) 62 { 63 int ret; 64 65 /* Check for invalid arguments: */ 66 if (attr == NULL || *attr == NULL) 67 /* Invalid argument: */ 68 ret = EINVAL; 69 else { 70 /* Free the memory allocated to the attribute object: */ 71 free(*attr); 72 73 /* 74 * Leave the attribute pointer NULL now that the memory 75 * has been freed: 76 */ 77 *attr = NULL; 78 ret = 0; 79 } 80 return(ret); 81 } 82 83 __strong_reference(_pthread_attr_destroy, pthread_attr_destroy); 84 85 int 86 _pthread_attr_get_np(pthread_t pid, pthread_attr_t *dst) 87 { 88 struct pthread *curthread; 89 struct pthread_attr attr; 90 int ret; 91 92 if (pid == NULL || dst == NULL || *dst == NULL) 93 return (EINVAL); 94 95 curthread = tls_get_curthread(); 96 if ((ret = _thr_ref_add(curthread, pid, /*include dead*/0)) != 0) 97 return (ret); 98 attr = pid->attr; 99 if (pid->tlflags & TLFLAGS_DETACHED) 100 attr.flags |= PTHREAD_DETACHED; 101 _thr_ref_delete(curthread, pid); 102 memcpy(*dst, &attr, sizeof(struct pthread_attr)); 103 104 return (0); 105 } 106 107 __strong_reference(_pthread_attr_get_np, pthread_attr_get_np); 108 109 int 110 _pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) 111 { 112 int ret; 113 114 /* Check for invalid arguments: */ 115 if (attr == NULL || *attr == NULL || detachstate == NULL) 116 ret = EINVAL; 117 else { 118 /* Check if the detached flag is set: */ 119 if ((*attr)->flags & PTHREAD_DETACHED) 120 /* Return detached: */ 121 *detachstate = PTHREAD_CREATE_DETACHED; 122 else 123 /* Return joinable: */ 124 *detachstate = PTHREAD_CREATE_JOINABLE; 125 ret = 0; 126 } 127 return(ret); 128 } 129 130 __strong_reference(_pthread_attr_getdetachstate, pthread_attr_getdetachstate); 131 132 int 133 _pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize) 134 { 135 int ret; 136 137 /* Check for invalid arguments: */ 138 if (attr == NULL || *attr == NULL || guardsize == NULL) 139 ret = EINVAL; 140 else { 141 /* Return the guard size: */ 142 *guardsize = (*attr)->guardsize_attr; 143 ret = 0; 144 } 145 return(ret); 146 } 147 148 __strong_reference(_pthread_attr_getguardsize, pthread_attr_getguardsize); 149 150 int 151 _pthread_attr_getinheritsched(const pthread_attr_t *attr, int *sched_inherit) 152 { 153 int ret = 0; 154 155 if ((attr == NULL) || (*attr == NULL)) 156 ret = EINVAL; 157 else 158 *sched_inherit = (*attr)->sched_inherit; 159 160 return(ret); 161 } 162 163 __strong_reference(_pthread_attr_getinheritsched, pthread_attr_getinheritsched); 164 165 int 166 _pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param) 167 { 168 int ret = 0; 169 170 if ((attr == NULL) || (*attr == NULL) || (param == NULL)) 171 ret = EINVAL; 172 else 173 param->sched_priority = (*attr)->prio; 174 175 return(ret); 176 } 177 178 __strong_reference(_pthread_attr_getschedparam, pthread_attr_getschedparam); 179 180 int 181 _pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) 182 { 183 int ret = 0; 184 185 if ((attr == NULL) || (*attr == NULL) || (policy == NULL)) 186 ret = EINVAL; 187 else 188 *policy = (*attr)->sched_policy; 189 190 return(ret); 191 } 192 193 __strong_reference(_pthread_attr_getschedpolicy, pthread_attr_getschedpolicy); 194 195 int 196 _pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope) 197 { 198 int ret = 0; 199 200 if ((attr == NULL) || (*attr == NULL) || (contentionscope == NULL)) 201 /* Return an invalid argument: */ 202 ret = EINVAL; 203 204 else 205 *contentionscope = (*attr)->flags & PTHREAD_SCOPE_SYSTEM ? 206 PTHREAD_SCOPE_SYSTEM : PTHREAD_SCOPE_PROCESS; 207 208 return(ret); 209 } 210 211 __strong_reference(_pthread_attr_getscope, pthread_attr_getscope); 212 213 int 214 _pthread_attr_getstack(const pthread_attr_t * __restrict attr, 215 void ** __restrict stackaddr, 216 size_t * __restrict stacksize) 217 { 218 int ret; 219 220 /* Check for invalid arguments: */ 221 if (attr == NULL || *attr == NULL || stackaddr == NULL 222 || stacksize == NULL ) 223 ret = EINVAL; 224 else { 225 /* Return the stack address and size */ 226 *stackaddr = (*attr)->stackaddr_attr; 227 *stacksize = (*attr)->stacksize_attr; 228 ret = 0; 229 } 230 return(ret); 231 } 232 233 __strong_reference(_pthread_attr_getstack, pthread_attr_getstack); 234 235 int 236 _pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) 237 { 238 int ret; 239 240 /* Check for invalid arguments: */ 241 if (attr == NULL || *attr == NULL || stackaddr == NULL) 242 ret = EINVAL; 243 else { 244 /* Return the stack address: */ 245 *stackaddr = (*attr)->stackaddr_attr; 246 ret = 0; 247 } 248 return(ret); 249 } 250 251 __strong_reference(_pthread_attr_getstackaddr, pthread_attr_getstackaddr); 252 253 int 254 _pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize) 255 { 256 int ret; 257 258 /* Check for invalid arguments: */ 259 if (attr == NULL || *attr == NULL || stacksize == NULL) 260 ret = EINVAL; 261 else { 262 /* Return the stack size: */ 263 *stacksize = (*attr)->stacksize_attr; 264 ret = 0; 265 } 266 return(ret); 267 } 268 269 __strong_reference(_pthread_attr_getstacksize, pthread_attr_getstacksize); 270 271 int 272 _pthread_attr_init(pthread_attr_t *attr) 273 { 274 int ret; 275 pthread_attr_t pattr; 276 277 /* Allocate memory for the attribute object: */ 278 if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) 279 /* Insufficient memory: */ 280 ret = ENOMEM; 281 else { 282 /* Initialise the attribute object with the defaults: */ 283 memcpy(pattr, &_pthread_attr_default, 284 sizeof(struct pthread_attr)); 285 286 /* Return a pointer to the attribute object: */ 287 *attr = pattr; 288 ret = 0; 289 } 290 return(ret); 291 } 292 293 __strong_reference(_pthread_attr_init, pthread_attr_init); 294 295 int 296 _pthread_attr_setcreatesuspend_np(pthread_attr_t *attr) 297 { 298 int ret; 299 300 if (attr == NULL || *attr == NULL) { 301 ret = EINVAL; 302 } else { 303 (*attr)->suspend = THR_CREATE_SUSPENDED; 304 ret = 0; 305 } 306 return(ret); 307 } 308 309 __strong_reference(_pthread_attr_setcreatesuspend_np, pthread_attr_setcreatesuspend_np); 310 311 int 312 _pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) 313 { 314 int ret; 315 316 /* Check for invalid arguments: */ 317 if (attr == NULL || *attr == NULL || 318 (detachstate != PTHREAD_CREATE_DETACHED && 319 detachstate != PTHREAD_CREATE_JOINABLE)) 320 ret = EINVAL; 321 else { 322 /* Check if detached state: */ 323 if (detachstate == PTHREAD_CREATE_DETACHED) 324 /* Set the detached flag: */ 325 (*attr)->flags |= PTHREAD_DETACHED; 326 else 327 /* Reset the detached flag: */ 328 (*attr)->flags &= ~PTHREAD_DETACHED; 329 ret = 0; 330 } 331 return(ret); 332 } 333 334 __strong_reference(_pthread_attr_setdetachstate, pthread_attr_setdetachstate); 335 336 int 337 _pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) 338 { 339 int ret; 340 341 /* Check for invalid arguments. */ 342 if (attr == NULL || *attr == NULL) 343 ret = EINVAL; 344 else { 345 /* Save the stack size. */ 346 (*attr)->guardsize_attr = guardsize; 347 ret = 0; 348 } 349 return(ret); 350 } 351 352 __strong_reference(_pthread_attr_setguardsize, pthread_attr_setguardsize); 353 354 int 355 _pthread_attr_setinheritsched(pthread_attr_t *attr, int sched_inherit) 356 { 357 int ret = 0; 358 359 if ((attr == NULL) || (*attr == NULL)) 360 ret = EINVAL; 361 else if (sched_inherit != PTHREAD_INHERIT_SCHED && 362 sched_inherit != PTHREAD_EXPLICIT_SCHED) 363 ret = ENOTSUP; 364 else 365 (*attr)->sched_inherit = sched_inherit; 366 367 return(ret); 368 } 369 370 __strong_reference(_pthread_attr_setinheritsched, pthread_attr_setinheritsched); 371 372 int 373 _pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param) 374 { 375 int ret = 0; 376 377 if ((attr == NULL) || (*attr == NULL)) 378 ret = EINVAL; 379 else if (param == NULL) { 380 ret = ENOTSUP; 381 } else { 382 int minv = sched_get_priority_min((*attr)->sched_policy); 383 int maxv = sched_get_priority_max((*attr)->sched_policy); 384 if (minv == -1 || maxv == -1 || 385 param->sched_priority < minv || 386 param->sched_priority > maxv) { 387 ret = ENOTSUP; 388 } else { 389 (*attr)->prio = param->sched_priority; 390 } 391 } 392 return(ret); 393 } 394 395 __strong_reference(_pthread_attr_setschedparam, pthread_attr_setschedparam); 396 397 int 398 _pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) 399 { 400 int ret = 0; 401 402 if ((attr == NULL) || (*attr == NULL)) 403 ret = EINVAL; 404 else if ((policy < SCHED_FIFO) || (policy > SCHED_RR)) { 405 ret = ENOTSUP; 406 } else 407 (*attr)->sched_policy = policy; 408 409 return(ret); 410 } 411 412 __strong_reference(_pthread_attr_setschedpolicy, pthread_attr_setschedpolicy); 413 414 int 415 _pthread_attr_setscope(pthread_attr_t *attr, int contentionscope) 416 { 417 int ret = 0; 418 419 if ((attr == NULL) || (*attr == NULL)) { 420 /* Return an invalid argument: */ 421 ret = EINVAL; 422 } else if ((contentionscope != PTHREAD_SCOPE_PROCESS) && 423 (contentionscope != PTHREAD_SCOPE_SYSTEM)) { 424 ret = EINVAL; 425 } else if (contentionscope == PTHREAD_SCOPE_SYSTEM) { 426 (*attr)->flags |= contentionscope; 427 } else { 428 (*attr)->flags &= ~PTHREAD_SCOPE_SYSTEM; 429 } 430 return (ret); 431 } 432 433 __strong_reference(_pthread_attr_setscope, pthread_attr_setscope); 434 435 int 436 _pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, 437 size_t stacksize) 438 { 439 int ret; 440 441 /* Check for invalid arguments: */ 442 if (attr == NULL || *attr == NULL || stackaddr == NULL 443 || stacksize < PTHREAD_STACK_MIN) 444 ret = EINVAL; 445 else { 446 /* Save the stack address and stack size */ 447 (*attr)->stackaddr_attr = stackaddr; 448 (*attr)->stacksize_attr = stacksize; 449 ret = 0; 450 } 451 return(ret); 452 } 453 454 __strong_reference(_pthread_attr_setstack, pthread_attr_setstack); 455 456 int 457 _pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) 458 { 459 int ret; 460 461 /* Check for invalid arguments: */ 462 if (attr == NULL || *attr == NULL || stackaddr == NULL) 463 ret = EINVAL; 464 else { 465 /* Save the stack address: */ 466 (*attr)->stackaddr_attr = stackaddr; 467 ret = 0; 468 } 469 return(ret); 470 } 471 472 __strong_reference(_pthread_attr_setstackaddr, pthread_attr_setstackaddr); 473 474 int 475 _pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) 476 { 477 int ret; 478 479 /* Check for invalid arguments: */ 480 if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) 481 ret = EINVAL; 482 else { 483 /* Save the stack size: */ 484 (*attr)->stacksize_attr = stacksize; 485 ret = 0; 486 } 487 return(ret); 488 } 489 490 __strong_reference(_pthread_attr_setstacksize, pthread_attr_setstacksize); 491 492