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