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 34 #include "namespace.h" 35 #include <machine/tls.h> 36 37 #include <errno.h> 38 #include <pthread.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <pthread_np.h> 42 #include "un-namespace.h" 43 44 #include "thr_private.h" 45 46 /* Default thread attributes. */ 47 struct pthread_attr _pthread_attr_default = { 48 .sched_policy = SCHED_OTHER, 49 .sched_inherit = 0, 50 .prio = THR_DEFAULT_PRIORITY, 51 .suspend = THR_CREATE_RUNNING, 52 .flags = 0, 53 .stackaddr_attr = NULL, 54 .stacksize_attr = THR_STACK_DEFAULT, 55 .guardsize_attr = 0 56 }; 57 58 int 59 _pthread_attr_destroy(pthread_attr_t *attr) 60 { 61 int ret; 62 63 /* Check for invalid arguments: */ 64 if (attr == NULL || *attr == NULL) 65 /* Invalid argument: */ 66 ret = EINVAL; 67 else { 68 /* Free the memory allocated to the attribute object: */ 69 free(*attr); 70 71 /* 72 * Leave the attribute pointer NULL now that the memory 73 * has been freed: 74 */ 75 *attr = NULL; 76 ret = 0; 77 } 78 return(ret); 79 } 80 81 __strong_reference(_pthread_attr_destroy, pthread_attr_destroy); 82 83 int 84 _pthread_attr_get_np(pthread_t pid, pthread_attr_t *dst) 85 { 86 struct pthread *curthread; 87 struct pthread_attr attr; 88 int ret; 89 90 if (pid == NULL || dst == NULL || *dst == NULL) 91 return (EINVAL); 92 93 curthread = tls_get_curthread(); 94 if ((ret = _thr_ref_add(curthread, pid, /*include dead*/0)) != 0) 95 return (ret); 96 attr = pid->attr; 97 if (pid->tlflags & TLFLAGS_DETACHED) 98 attr.flags |= PTHREAD_DETACHED; 99 _thr_ref_delete(curthread, pid); 100 memcpy(*dst, &attr, sizeof(struct pthread_attr)); 101 102 return (0); 103 } 104 105 __strong_reference(_pthread_attr_get_np, pthread_attr_get_np); 106 107 int 108 _pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) 109 { 110 int ret; 111 112 /* Check for invalid arguments: */ 113 if (attr == NULL || *attr == NULL || detachstate == NULL) 114 ret = EINVAL; 115 else { 116 /* Check if the detached flag is set: */ 117 if ((*attr)->flags & PTHREAD_DETACHED) 118 /* Return detached: */ 119 *detachstate = PTHREAD_CREATE_DETACHED; 120 else 121 /* Return joinable: */ 122 *detachstate = PTHREAD_CREATE_JOINABLE; 123 ret = 0; 124 } 125 return(ret); 126 } 127 128 __strong_reference(_pthread_attr_getdetachstate, pthread_attr_getdetachstate); 129 130 int 131 _pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize) 132 { 133 int ret; 134 135 /* Check for invalid arguments: */ 136 if (attr == NULL || *attr == NULL || guardsize == NULL) 137 ret = EINVAL; 138 else { 139 /* Return the guard size: */ 140 *guardsize = (*attr)->guardsize_attr; 141 ret = 0; 142 } 143 return(ret); 144 } 145 146 __strong_reference(_pthread_attr_getguardsize, pthread_attr_getguardsize); 147 148 int 149 _pthread_attr_getinheritsched(const pthread_attr_t *attr, int *sched_inherit) 150 { 151 int ret = 0; 152 153 if ((attr == NULL) || (*attr == NULL)) 154 ret = EINVAL; 155 else 156 *sched_inherit = (*attr)->sched_inherit; 157 158 return(ret); 159 } 160 161 __strong_reference(_pthread_attr_getinheritsched, pthread_attr_getinheritsched); 162 163 int 164 _pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param) 165 { 166 int ret = 0; 167 168 if ((attr == NULL) || (*attr == NULL) || (param == NULL)) 169 ret = EINVAL; 170 else 171 param->sched_priority = (*attr)->prio; 172 173 return(ret); 174 } 175 176 __strong_reference(_pthread_attr_getschedparam, pthread_attr_getschedparam); 177 178 int 179 _pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) 180 { 181 int ret = 0; 182 183 if ((attr == NULL) || (*attr == NULL) || (policy == NULL)) 184 ret = EINVAL; 185 else 186 *policy = (*attr)->sched_policy; 187 188 return(ret); 189 } 190 191 __strong_reference(_pthread_attr_getschedpolicy, pthread_attr_getschedpolicy); 192 193 int 194 _pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope) 195 { 196 int ret = 0; 197 198 if ((attr == NULL) || (*attr == NULL) || (contentionscope == NULL)) 199 /* Return an invalid argument: */ 200 ret = EINVAL; 201 202 else 203 *contentionscope = (*attr)->flags & PTHREAD_SCOPE_SYSTEM ? 204 PTHREAD_SCOPE_SYSTEM : PTHREAD_SCOPE_PROCESS; 205 206 return(ret); 207 } 208 209 __strong_reference(_pthread_attr_getscope, pthread_attr_getscope); 210 211 int 212 _pthread_attr_getstack(const pthread_attr_t * __restrict attr, 213 void ** __restrict stackaddr, 214 size_t * __restrict stacksize) 215 { 216 int ret; 217 218 /* Check for invalid arguments: */ 219 if (attr == NULL || *attr == NULL || stackaddr == NULL 220 || stacksize == NULL ) 221 ret = EINVAL; 222 else { 223 /* Return the stack address and size */ 224 *stackaddr = (*attr)->stackaddr_attr; 225 *stacksize = (*attr)->stacksize_attr; 226 ret = 0; 227 } 228 return(ret); 229 } 230 231 __strong_reference(_pthread_attr_getstack, pthread_attr_getstack); 232 233 int 234 _pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) 235 { 236 int ret; 237 238 /* Check for invalid arguments: */ 239 if (attr == NULL || *attr == NULL || stackaddr == NULL) 240 ret = EINVAL; 241 else { 242 /* Return the stack address: */ 243 *stackaddr = (*attr)->stackaddr_attr; 244 ret = 0; 245 } 246 return(ret); 247 } 248 249 __strong_reference(_pthread_attr_getstackaddr, pthread_attr_getstackaddr); 250 251 int 252 _pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize) 253 { 254 int ret; 255 256 /* Check for invalid arguments: */ 257 if (attr == NULL || *attr == NULL || stacksize == NULL) 258 ret = EINVAL; 259 else { 260 /* Return the stack size: */ 261 *stacksize = (*attr)->stacksize_attr; 262 ret = 0; 263 } 264 return(ret); 265 } 266 267 __strong_reference(_pthread_attr_getstacksize, pthread_attr_getstacksize); 268 269 int 270 _pthread_attr_init(pthread_attr_t *attr) 271 { 272 int ret; 273 pthread_attr_t pattr; 274 275 /* Allocate memory for the attribute object: */ 276 if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) 277 /* Insufficient memory: */ 278 ret = ENOMEM; 279 else { 280 /* Initialise the attribute object with the defaults: */ 281 memcpy(pattr, &_pthread_attr_default, 282 sizeof(struct pthread_attr)); 283 284 /* Return a pointer to the attribute object: */ 285 *attr = pattr; 286 ret = 0; 287 } 288 return(ret); 289 } 290 291 __strong_reference(_pthread_attr_init, pthread_attr_init); 292 293 int 294 _pthread_attr_setcreatesuspend_np(pthread_attr_t *attr) 295 { 296 int ret; 297 298 if (attr == NULL || *attr == NULL) { 299 ret = EINVAL; 300 } else { 301 (*attr)->suspend = THR_CREATE_SUSPENDED; 302 ret = 0; 303 } 304 return(ret); 305 } 306 307 __strong_reference(_pthread_attr_setcreatesuspend_np, pthread_attr_setcreatesuspend_np); 308 309 int 310 _pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) 311 { 312 int ret; 313 314 /* Check for invalid arguments: */ 315 if (attr == NULL || *attr == NULL || 316 (detachstate != PTHREAD_CREATE_DETACHED && 317 detachstate != PTHREAD_CREATE_JOINABLE)) 318 ret = EINVAL; 319 else { 320 /* Check if detached state: */ 321 if (detachstate == PTHREAD_CREATE_DETACHED) 322 /* Set the detached flag: */ 323 (*attr)->flags |= PTHREAD_DETACHED; 324 else 325 /* Reset the detached flag: */ 326 (*attr)->flags &= ~PTHREAD_DETACHED; 327 ret = 0; 328 } 329 return(ret); 330 } 331 332 __strong_reference(_pthread_attr_setdetachstate, pthread_attr_setdetachstate); 333 334 int 335 _pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) 336 { 337 int ret; 338 339 /* Check for invalid arguments. */ 340 if (attr == NULL || *attr == NULL) 341 ret = EINVAL; 342 else { 343 /* Save the stack size. */ 344 (*attr)->guardsize_attr = guardsize; 345 ret = 0; 346 } 347 return(ret); 348 } 349 350 __strong_reference(_pthread_attr_setguardsize, pthread_attr_setguardsize); 351 352 int 353 _pthread_attr_setinheritsched(pthread_attr_t *attr, int sched_inherit) 354 { 355 int ret = 0; 356 357 if ((attr == NULL) || (*attr == NULL)) 358 ret = EINVAL; 359 else if (sched_inherit != PTHREAD_INHERIT_SCHED && 360 sched_inherit != PTHREAD_EXPLICIT_SCHED) 361 ret = EINVAL; 362 else 363 (*attr)->sched_inherit = sched_inherit; 364 365 return(ret); 366 } 367 368 __strong_reference(_pthread_attr_setinheritsched, pthread_attr_setinheritsched); 369 370 int 371 _pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param) 372 { 373 int ret = 0; 374 375 if ((attr == NULL) || (*attr == NULL)) 376 ret = EINVAL; 377 else if (param == NULL) { 378 ret = ENOTSUP; 379 } else { 380 int minv = sched_get_priority_min((*attr)->sched_policy); 381 int maxv = sched_get_priority_max((*attr)->sched_policy); 382 if (minv == -1 || maxv == -1 || 383 param->sched_priority < minv || 384 param->sched_priority > maxv) { 385 ret = ENOTSUP; 386 } else { 387 (*attr)->prio = param->sched_priority; 388 } 389 } 390 return(ret); 391 } 392 393 __strong_reference(_pthread_attr_setschedparam, pthread_attr_setschedparam); 394 395 int 396 _pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) 397 { 398 int ret = 0; 399 400 if ((attr == NULL) || (*attr == NULL)) 401 ret = EINVAL; 402 else if ((policy < SCHED_FIFO) || (policy > SCHED_RR)) { 403 ret = ENOTSUP; 404 } else 405 (*attr)->sched_policy = policy; 406 407 return(ret); 408 } 409 410 __strong_reference(_pthread_attr_setschedpolicy, pthread_attr_setschedpolicy); 411 412 int 413 _pthread_attr_setscope(pthread_attr_t *attr, int contentionscope) 414 { 415 int ret = 0; 416 417 if ((attr == NULL) || (*attr == NULL)) { 418 /* Return an invalid argument: */ 419 ret = EINVAL; 420 } else if ((contentionscope != PTHREAD_SCOPE_PROCESS) && 421 (contentionscope != PTHREAD_SCOPE_SYSTEM)) { 422 ret = EINVAL; 423 } else if (contentionscope == PTHREAD_SCOPE_SYSTEM) { 424 (*attr)->flags |= contentionscope; 425 } else { 426 (*attr)->flags &= ~PTHREAD_SCOPE_SYSTEM; 427 } 428 return (ret); 429 } 430 431 __strong_reference(_pthread_attr_setscope, pthread_attr_setscope); 432 433 int 434 _pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, 435 size_t stacksize) 436 { 437 int ret; 438 439 /* Check for invalid arguments: */ 440 if (attr == NULL || *attr == NULL || stackaddr == NULL 441 || stacksize < PTHREAD_STACK_MIN) 442 ret = EINVAL; 443 else { 444 /* Save the stack address and stack size */ 445 (*attr)->stackaddr_attr = stackaddr; 446 (*attr)->stacksize_attr = stacksize; 447 ret = 0; 448 } 449 return(ret); 450 } 451 452 __strong_reference(_pthread_attr_setstack, pthread_attr_setstack); 453 454 int 455 _pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) 456 { 457 int ret; 458 459 /* Check for invalid arguments: */ 460 if (attr == NULL || *attr == NULL || stackaddr == NULL) 461 ret = EINVAL; 462 else { 463 /* Save the stack address: */ 464 (*attr)->stackaddr_attr = stackaddr; 465 ret = 0; 466 } 467 return(ret); 468 } 469 470 __strong_reference(_pthread_attr_setstackaddr, pthread_attr_setstackaddr); 471 472 int 473 _pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) 474 { 475 int ret; 476 477 /* Check for invalid arguments: */ 478 if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) 479 ret = EINVAL; 480 else { 481 /* Save the stack size: */ 482 (*attr)->stacksize_attr = stacksize; 483 ret = 0; 484 } 485 return(ret); 486 } 487 488 __strong_reference(_pthread_attr_setstacksize, pthread_attr_setstacksize); 489 490