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_destroy, pthread_attr_destroy); 113 __weak_reference(_pthread_attr_init, pthread_attr_init); 114 __weak_reference(_pthread_attr_setcreatesuspend_np, 115 pthread_attr_setcreatesuspend_np); 116 __weak_reference(_pthread_attr_setdetachstate, pthread_attr_setdetachstate); 117 __weak_reference(_pthread_attr_setguardsize, pthread_attr_setguardsize); 118 __weak_reference(_pthread_attr_setinheritsched, pthread_attr_setinheritsched); 119 __weak_reference(_pthread_attr_setschedparam, pthread_attr_setschedparam); 120 __weak_reference(_pthread_attr_setschedpolicy, pthread_attr_setschedpolicy); 121 __weak_reference(_pthread_attr_setscope, pthread_attr_setscope); 122 __weak_reference(_pthread_attr_setstack, pthread_attr_setstack); 123 __weak_reference(_pthread_attr_setstackaddr, pthread_attr_setstackaddr); 124 __weak_reference(_pthread_attr_setstacksize, pthread_attr_setstacksize); 125 __weak_reference(_pthread_attr_get_np, pthread_attr_get_np); 126 __weak_reference(_pthread_attr_getdetachstate, pthread_attr_getdetachstate); 127 __weak_reference(_pthread_attr_getguardsize, pthread_attr_getguardsize); 128 __weak_reference(_pthread_attr_getinheritsched, pthread_attr_getinheritsched); 129 __weak_reference(_pthread_attr_getschedparam, pthread_attr_getschedparam); 130 __weak_reference(_pthread_attr_getschedpolicy, pthread_attr_getschedpolicy); 131 __weak_reference(_pthread_attr_getscope, pthread_attr_getscope); 132 __weak_reference(_pthread_attr_getstack, pthread_attr_getstack); 133 __weak_reference(_pthread_attr_getstackaddr, pthread_attr_getstackaddr); 134 __weak_reference(_pthread_attr_getstacksize, pthread_attr_getstacksize); 135 136 int 137 _pthread_attr_init(pthread_attr_t *attr) 138 { 139 pthread_attr_t pattr; 140 141 if ((pattr = (pthread_attr_t) 142 malloc(sizeof(struct pthread_attr))) == NULL) 143 return (ENOMEM); 144 145 memcpy(pattr, &pthread_attr_default, sizeof(struct pthread_attr)); 146 *attr = pattr; 147 148 return (0); 149 } 150 151 int 152 _pthread_attr_destroy(pthread_attr_t *attr) 153 { 154 if (attr == NULL || *attr == NULL) 155 return (EINVAL); 156 157 free(*attr); 158 *attr = NULL; 159 160 return (0); 161 } 162 163 int 164 _pthread_attr_setcreatesuspend_np(pthread_attr_t *attr) 165 { 166 if (attr == NULL || *attr == NULL) { 167 errno = EINVAL; 168 return (-1); 169 } 170 (*attr)->suspend = PTHREAD_CREATE_SUSPENDED; 171 172 return (0); 173 } 174 175 int 176 _pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) 177 { 178 if (attr == NULL || *attr == NULL || 179 (detachstate != PTHREAD_CREATE_DETACHED && 180 detachstate != PTHREAD_CREATE_JOINABLE)) 181 return (EINVAL); 182 183 if (detachstate == PTHREAD_CREATE_DETACHED) 184 (*attr)->flags |= PTHREAD_DETACHED; 185 else 186 (*attr)->flags &= ~PTHREAD_DETACHED; 187 188 return (0); 189 } 190 191 int 192 _pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) 193 { 194 195 if (attr == NULL || *attr == NULL) 196 return (EINVAL); 197 198 (*attr)->guardsize_attr = roundup(guardsize, _pthread_page_size); 199 200 return (0); 201 } 202 203 int 204 _pthread_attr_setinheritsched(pthread_attr_t *attr, int sched_inherit) 205 { 206 if (attr == NULL || *attr == NULL) 207 return (EINVAL); 208 209 (*attr)->sched_inherit = sched_inherit; 210 211 return (0); 212 } 213 214 int 215 _pthread_attr_setschedparam(pthread_attr_t *attr, 216 const struct sched_param *param) 217 { 218 if (attr == NULL || *attr == NULL) 219 return (EINVAL); 220 221 if (param == NULL) 222 return (ENOTSUP); 223 224 if (param->sched_priority < PTHREAD_MIN_PRIORITY || 225 param->sched_priority > PTHREAD_MAX_PRIORITY) 226 return (ENOTSUP); 227 228 (*attr)->prio = param->sched_priority; 229 230 return (0); 231 } 232 233 int 234 _pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) 235 { 236 if (attr == NULL || *attr == NULL) 237 return (EINVAL); 238 239 if (policy < SCHED_FIFO || policy > SCHED_RR) 240 return (ENOTSUP); 241 242 (*attr)->sched_policy = policy; 243 244 return (0); 245 } 246 247 int 248 _pthread_attr_setscope(pthread_attr_t *attr, int contentionscope) 249 { 250 if (attr == NULL || *attr == NULL) 251 return (EINVAL); 252 253 if (contentionscope != PTHREAD_SCOPE_PROCESS || 254 contentionscope == PTHREAD_SCOPE_SYSTEM) 255 /* We don't support PTHREAD_SCOPE_SYSTEM. */ 256 return (ENOTSUP); 257 258 (*attr)->flags |= contentionscope; 259 260 return (0); 261 } 262 263 int 264 _pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, 265 size_t stacksize) 266 { 267 if (attr == NULL || *attr == NULL || stackaddr == NULL 268 || stacksize < PTHREAD_STACK_MIN) 269 return (EINVAL); 270 271 (*attr)->stackaddr_attr = stackaddr; 272 (*attr)->stacksize_attr = stacksize; 273 274 return (0); 275 } 276 277 int 278 _pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) 279 { 280 if (attr == NULL || *attr == NULL || stackaddr == NULL) 281 return (EINVAL); 282 283 (*attr)->stackaddr_attr = stackaddr; 284 285 return (0); 286 } 287 288 int 289 _pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) 290 { 291 if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) 292 return (EINVAL); 293 294 (*attr)->stacksize_attr = stacksize; 295 296 return (0); 297 } 298 299 int 300 _pthread_attr_get_np(pthread_t pid, pthread_attr_t *dst) 301 { 302 int ret; 303 304 if (pid == NULL || dst == NULL || *dst == NULL) 305 return (EINVAL); 306 307 if ((ret = _find_thread(pid)) != 0) 308 return (ret); 309 310 memcpy(*dst, &pid->attr, sizeof(struct pthread_attr)); 311 312 /* 313 * Special case, if stack address was not provided by caller 314 * of pthread_create(), then return address allocated internally 315 */ 316 if ((*dst)->stackaddr_attr == NULL) 317 (*dst)->stackaddr_attr = pid->stack; 318 319 return (0); 320 } 321 322 int 323 _pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) 324 { 325 326 if (attr == NULL || *attr == NULL || detachstate == NULL) 327 return (EINVAL); 328 329 /* Check if the detached flag is set: */ 330 if ((*attr)->flags & PTHREAD_DETACHED) 331 *detachstate = PTHREAD_CREATE_DETACHED; 332 else 333 *detachstate = PTHREAD_CREATE_JOINABLE; 334 335 return (0); 336 } 337 338 int 339 _pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize) 340 { 341 if (attr == NULL || *attr == NULL || guardsize == NULL) 342 return (EINVAL); 343 344 *guardsize = (*attr)->guardsize_attr; 345 346 return (0); 347 } 348 349 int 350 _pthread_attr_getinheritsched(const pthread_attr_t *attr, int *sched_inherit) 351 { 352 if (attr == NULL || *attr == NULL) 353 return (EINVAL); 354 355 *sched_inherit = (*attr)->sched_inherit; 356 357 return (0); 358 } 359 360 int 361 _pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param) 362 { 363 if (attr == NULL || *attr == NULL || param == NULL) 364 return (EINVAL); 365 366 param->sched_priority = (*attr)->prio; 367 368 return (0); 369 } 370 371 int 372 _pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) 373 { 374 if (attr == NULL || *attr == NULL || policy == NULL) 375 return (EINVAL); 376 377 *policy = (*attr)->sched_policy; 378 379 return (0); 380 } 381 382 int 383 _pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope) 384 { 385 if (attr == NULL || *attr == NULL || contentionscope == NULL) 386 return (EINVAL); 387 388 *contentionscope = (*attr)->flags & PTHREAD_SCOPE_SYSTEM ? 389 PTHREAD_SCOPE_SYSTEM : PTHREAD_SCOPE_PROCESS; 390 391 return (0); 392 } 393 394 int 395 _pthread_attr_getstack(const pthread_attr_t * __restrict attr, 396 void ** __restrict stackaddr, 397 size_t * __restrict stacksize) 398 { 399 if (attr == NULL || *attr == NULL || stackaddr == NULL 400 || stacksize == NULL) 401 return (EINVAL); 402 403 *stackaddr = (*attr)->stackaddr_attr; 404 *stacksize = (*attr)->stacksize_attr; 405 406 return (0); 407 } 408 409 int 410 _pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) 411 { 412 if (attr == NULL || *attr == NULL || stackaddr == NULL) 413 return (EINVAL); 414 415 *stackaddr = (*attr)->stackaddr_attr; 416 417 return (0); 418 } 419 420 int 421 _pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize) 422 { 423 if (attr == NULL || *attr == NULL || stacksize == NULL) 424 return (EINVAL); 425 426 *stacksize = (*attr)->stacksize_attr; 427 428 return (0); 429 } 430