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