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 *attr, size_t *guardsize) 154 { 155 int ret; 156 157 /* Check for invalid arguments: */ 158 if (attr == NULL || *attr == NULL || guardsize == NULL) 159 ret = EINVAL; 160 else { 161 /* Return the guard size: */ 162 *guardsize = (*attr)->guardsize_attr; 163 ret = 0; 164 } 165 return(ret); 166 } 167 168 __strong_reference(_pthread_attr_getguardsize, pthread_attr_getguardsize); 169 170 int 171 _pthread_attr_getinheritsched(const pthread_attr_t *attr, int *sched_inherit) 172 { 173 int ret = 0; 174 175 if ((attr == NULL) || (*attr == NULL)) 176 ret = EINVAL; 177 else 178 *sched_inherit = (*attr)->sched_inherit; 179 180 return(ret); 181 } 182 183 __strong_reference(_pthread_attr_getinheritsched, pthread_attr_getinheritsched); 184 185 int 186 _pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param) 187 { 188 int ret = 0; 189 190 if ((attr == NULL) || (*attr == NULL) || (param == NULL)) 191 ret = EINVAL; 192 else 193 param->sched_priority = (*attr)->prio; 194 195 return(ret); 196 } 197 198 __strong_reference(_pthread_attr_getschedparam, pthread_attr_getschedparam); 199 200 int 201 _pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) 202 { 203 int ret = 0; 204 205 if ((attr == NULL) || (*attr == NULL) || (policy == NULL)) 206 ret = EINVAL; 207 else 208 *policy = (*attr)->sched_policy; 209 210 return(ret); 211 } 212 213 __strong_reference(_pthread_attr_getschedpolicy, pthread_attr_getschedpolicy); 214 215 int 216 _pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope) 217 { 218 int ret = 0; 219 220 if ((attr == NULL) || (*attr == NULL) || (contentionscope == NULL)) 221 /* Return an invalid argument: */ 222 ret = EINVAL; 223 224 else 225 *contentionscope = ((*attr)->flags & PTHREAD_SCOPE_SYSTEM) ? 226 PTHREAD_SCOPE_SYSTEM : PTHREAD_SCOPE_PROCESS; 227 228 return(ret); 229 } 230 231 __strong_reference(_pthread_attr_getscope, pthread_attr_getscope); 232 233 int 234 _pthread_attr_getstack(const pthread_attr_t * __restrict attr, 235 void ** __restrict stackaddr, 236 size_t * __restrict stacksize) 237 { 238 int ret; 239 240 /* Check for invalid arguments: */ 241 if (attr == NULL || *attr == NULL || stackaddr == NULL 242 || stacksize == NULL ) 243 ret = EINVAL; 244 else { 245 /* Return the stack address and size */ 246 *stackaddr = (*attr)->stackaddr_attr; 247 *stacksize = (*attr)->stacksize_attr; 248 ret = 0; 249 } 250 return(ret); 251 } 252 253 __strong_reference(_pthread_attr_getstack, pthread_attr_getstack); 254 255 int 256 _pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) 257 { 258 int ret; 259 260 /* Check for invalid arguments: */ 261 if (attr == NULL || *attr == NULL || stackaddr == NULL) 262 ret = EINVAL; 263 else { 264 /* Return the stack address: */ 265 *stackaddr = (*attr)->stackaddr_attr; 266 ret = 0; 267 } 268 return(ret); 269 } 270 271 __strong_reference(_pthread_attr_getstackaddr, pthread_attr_getstackaddr); 272 273 int 274 _pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize) 275 { 276 int ret; 277 278 /* Check for invalid arguments: */ 279 if (attr == NULL || *attr == NULL || stacksize == NULL) 280 ret = EINVAL; 281 else { 282 /* Return the stack size: */ 283 *stacksize = (*attr)->stacksize_attr; 284 ret = 0; 285 } 286 return(ret); 287 } 288 289 __strong_reference(_pthread_attr_getstacksize, pthread_attr_getstacksize); 290 291 int 292 _pthread_attr_init(pthread_attr_t *attr) 293 { 294 int ret; 295 pthread_attr_t pattr; 296 297 /* Allocate memory for the attribute object: */ 298 if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) 299 /* Insufficient memory: */ 300 ret = ENOMEM; 301 else { 302 /* Initialise the attribute object with the defaults: */ 303 memcpy(pattr, &_pthread_attr_default, 304 sizeof(struct pthread_attr)); 305 306 /* Return a pointer to the attribute object: */ 307 *attr = pattr; 308 ret = 0; 309 } 310 return(ret); 311 } 312 313 __strong_reference(_pthread_attr_init, pthread_attr_init); 314 315 int 316 _pthread_attr_setaffinity_np(pthread_attr_t *attr, size_t cpusetsize, 317 const cpu_set_t *mask) 318 { 319 cpu_set_t active, mask1; 320 size_t len, cplen = cpusetsize; 321 322 if (attr == NULL || *attr == NULL || mask == NULL) 323 return (EINVAL); 324 325 if (cplen > sizeof(mask1)) 326 cplen = sizeof(mask1); 327 CPU_ZERO(&mask1); 328 memcpy(&mask1, mask, cplen); 329 330 len = sizeof(active); 331 if (sysctlbyname("machdep.smp_active", &active, &len, NULL, 0) < 0) 332 return (errno); 333 334 CPUMASK_ANDMASK(mask1, active); 335 if (CPUMASK_TESTZERO(mask1)) 336 return (EPERM); 337 338 (*attr)->cpumask = mask1; 339 (*attr)->flags |= THR_CPUMASK; 340 return (0); 341 } 342 343 __strong_reference(_pthread_attr_setaffinity_np, pthread_attr_setaffinity_np); 344 345 int 346 _pthread_attr_setcreatesuspend_np(pthread_attr_t *attr) 347 { 348 int ret; 349 350 if (attr == NULL || *attr == NULL) { 351 ret = EINVAL; 352 } else { 353 (*attr)->suspend = THR_CREATE_SUSPENDED; 354 ret = 0; 355 } 356 return(ret); 357 } 358 359 __strong_reference(_pthread_attr_setcreatesuspend_np, pthread_attr_setcreatesuspend_np); 360 361 int 362 _pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) 363 { 364 int ret; 365 366 /* Check for invalid arguments: */ 367 if (attr == NULL || *attr == NULL || 368 (detachstate != PTHREAD_CREATE_DETACHED && 369 detachstate != PTHREAD_CREATE_JOINABLE)) 370 ret = EINVAL; 371 else { 372 /* Check if detached state: */ 373 if (detachstate == PTHREAD_CREATE_DETACHED) 374 /* Set the detached flag: */ 375 (*attr)->flags |= PTHREAD_DETACHED; 376 else 377 /* Reset the detached flag: */ 378 (*attr)->flags &= ~PTHREAD_DETACHED; 379 ret = 0; 380 } 381 return(ret); 382 } 383 384 __strong_reference(_pthread_attr_setdetachstate, pthread_attr_setdetachstate); 385 386 int 387 _pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) 388 { 389 int ret; 390 391 /* Check for invalid arguments. */ 392 if (attr == NULL || *attr == NULL) 393 ret = EINVAL; 394 else { 395 /* Save the stack size. */ 396 (*attr)->guardsize_attr = guardsize; 397 ret = 0; 398 } 399 return(ret); 400 } 401 402 __strong_reference(_pthread_attr_setguardsize, pthread_attr_setguardsize); 403 404 int 405 _pthread_attr_setinheritsched(pthread_attr_t *attr, int sched_inherit) 406 { 407 int ret = 0; 408 409 if ((attr == NULL) || (*attr == NULL)) 410 ret = EINVAL; 411 else if (sched_inherit != PTHREAD_INHERIT_SCHED && 412 sched_inherit != PTHREAD_EXPLICIT_SCHED) 413 ret = EINVAL; 414 else 415 (*attr)->sched_inherit = sched_inherit; 416 417 return(ret); 418 } 419 420 __strong_reference(_pthread_attr_setinheritsched, pthread_attr_setinheritsched); 421 422 int 423 _pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param) 424 { 425 int policy; 426 427 if ((attr == NULL) || (*attr == NULL)) 428 return (EINVAL); 429 430 if (param == NULL) 431 return (ENOTSUP); 432 433 policy = (*attr)->sched_policy; 434 435 { 436 int minv = sched_get_priority_min(policy); 437 int maxv = sched_get_priority_max(policy); 438 if (minv == -1 || maxv == -1 || 439 param->sched_priority < minv || 440 param->sched_priority > maxv) { 441 return (ENOTSUP); 442 } 443 } 444 445 (*attr)->prio = param->sched_priority; 446 447 return (0); 448 } 449 450 __strong_reference(_pthread_attr_setschedparam, pthread_attr_setschedparam); 451 452 int 453 _pthread_attr_setschedpolicy(pthread_attr_t *attr, int pol) 454 { 455 int ret = 0; 456 457 if ((attr == NULL) || (*attr == NULL)) 458 ret = EINVAL; 459 else if (pol != SCHED_FIFO && pol != SCHED_OTHER && pol != SCHED_RR) 460 ret = EINVAL; 461 else 462 (*attr)->sched_policy = pol; 463 464 return(ret); 465 } 466 467 __strong_reference(_pthread_attr_setschedpolicy, pthread_attr_setschedpolicy); 468 469 int 470 _pthread_attr_setscope(pthread_attr_t *attr, int contentionscope) 471 { 472 int ret = 0; 473 474 if ((attr == NULL) || (*attr == NULL)) { 475 /* Return an invalid argument: */ 476 ret = EINVAL; 477 } else if ((contentionscope != PTHREAD_SCOPE_PROCESS) && 478 (contentionscope != PTHREAD_SCOPE_SYSTEM)) { 479 ret = EINVAL; 480 } else if (contentionscope == PTHREAD_SCOPE_SYSTEM) { 481 (*attr)->flags |= contentionscope; 482 } else { 483 (*attr)->flags &= ~PTHREAD_SCOPE_SYSTEM; 484 } 485 return (ret); 486 } 487 488 __strong_reference(_pthread_attr_setscope, pthread_attr_setscope); 489 490 int 491 _pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, 492 size_t stacksize) 493 { 494 int ret; 495 496 /* Check for invalid arguments: */ 497 if (attr == NULL || *attr == NULL || stackaddr == NULL 498 || stacksize < PTHREAD_STACK_MIN) 499 ret = EINVAL; 500 else { 501 /* Save the stack address and stack size */ 502 (*attr)->stackaddr_attr = stackaddr; 503 (*attr)->stacksize_attr = stacksize; 504 ret = 0; 505 } 506 return(ret); 507 } 508 509 __strong_reference(_pthread_attr_setstack, pthread_attr_setstack); 510 511 int 512 _pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) 513 { 514 int ret; 515 516 /* Check for invalid arguments: */ 517 if (attr == NULL || *attr == NULL || stackaddr == NULL) 518 ret = EINVAL; 519 else { 520 /* Save the stack address: */ 521 (*attr)->stackaddr_attr = stackaddr; 522 ret = 0; 523 } 524 return(ret); 525 } 526 527 __strong_reference(_pthread_attr_setstackaddr, pthread_attr_setstackaddr); 528 529 int 530 _pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) 531 { 532 int ret; 533 534 /* Check for invalid arguments: */ 535 if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) 536 ret = EINVAL; 537 else { 538 /* Save the stack size: */ 539 (*attr)->stacksize_attr = stacksize; 540 ret = 0; 541 } 542 return(ret); 543 } 544 545 __strong_reference(_pthread_attr_setstacksize, pthread_attr_setstacksize); 546