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