1 /* $OpenBSD: rthread_attr.c,v 1.19 2012/03/22 15:26:04 kurt Exp $ */ 2 /* 3 * Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org> 4 * All Rights Reserved. 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 /* 19 * generic attribute support 20 */ 21 22 #include <inttypes.h> 23 #include <stdlib.h> 24 #include <unistd.h> 25 #include <errno.h> 26 27 #include <pthread.h> 28 #include <pthread_np.h> 29 30 #include "rthread.h" 31 32 /* 33 * Note: stack_size + guard_size == total stack used 34 * 35 * pthread_attr_init MUST be called before any other attribute function 36 * for proper operation. 37 * 38 * Every call to pthread_attr_init MUST be matched with a call to 39 * pthread_attr_destroy to avoid leaking memory. This is an implementation 40 * requirement, not a POSIX requirement. 41 */ 42 43 int 44 pthread_attr_init(pthread_attr_t *attrp) 45 { 46 pthread_attr_t attr; 47 int error; 48 49 /* make sure _rthread_attr_default has been initialized */ 50 if (!_threads_ready) 51 if ((error = _rthread_init())) 52 return (error); 53 54 attr = calloc(1, sizeof(*attr)); 55 if (!attr) 56 return (errno); 57 *attr = _rthread_attr_default; 58 *attrp = attr; 59 60 return (0); 61 } 62 63 int 64 pthread_attr_destroy(pthread_attr_t *attrp) 65 { 66 free(*attrp); 67 *attrp = NULL; 68 69 return (0); 70 } 71 72 int 73 pthread_attr_getguardsize(const pthread_attr_t *attrp, size_t *guardsize) 74 { 75 *guardsize = (*attrp)->guard_size; 76 77 return (0); 78 } 79 80 int 81 pthread_attr_setguardsize(pthread_attr_t *attrp, size_t guardsize) 82 { 83 (*attrp)->guard_size = guardsize; 84 85 return (0); 86 } 87 88 int 89 pthread_attr_getdetachstate(const pthread_attr_t *attrp, int *detachstate) 90 { 91 *detachstate = (*attrp)->detach_state; 92 93 return (0); 94 } 95 96 int 97 pthread_attr_setdetachstate(pthread_attr_t *attrp, int detachstate) 98 { 99 int error; 100 101 error = (detachstate == PTHREAD_CREATE_DETACHED || 102 detachstate == PTHREAD_CREATE_JOINABLE) ? 0 : EINVAL; 103 if (error == 0) 104 (*attrp)->detach_state = detachstate; 105 106 return (error); 107 } 108 109 int 110 pthread_attr_getstack(const pthread_attr_t *attrp, void **stackaddr, 111 size_t *stacksize) 112 { 113 *stackaddr = (*attrp)->stack_addr; 114 *stacksize = (*attrp)->stack_size; 115 116 return (0); 117 } 118 119 int 120 pthread_attr_setstack(pthread_attr_t *attrp, void *stackaddr, size_t stacksize) 121 { 122 int error; 123 124 /* 125 * XXX Add an alignment test, on stackaddr for stack-grows-up 126 * archs or on stackaddr+stacksize for stack-grows-down archs 127 */ 128 if (stacksize < PTHREAD_STACK_MIN) 129 return (EINVAL); 130 if ((error = pthread_attr_setstackaddr(attrp, stackaddr))) 131 return (error); 132 (*attrp)->stack_size = stacksize; 133 134 return (0); 135 } 136 137 int 138 pthread_attr_getstacksize(const pthread_attr_t *attrp, size_t *stacksize) 139 { 140 *stacksize = (*attrp)->stack_size; 141 142 return (0); 143 } 144 145 int 146 pthread_attr_setstacksize(pthread_attr_t *attrp, size_t stacksize) 147 { 148 if (stacksize < PTHREAD_STACK_MIN || 149 stacksize > ROUND_TO_PAGE(stacksize)) 150 return (EINVAL); 151 (*attrp)->stack_size = stacksize; 152 153 return (0); 154 } 155 156 int 157 pthread_attr_getstackaddr(const pthread_attr_t *attrp, void **stackaddr) 158 { 159 *stackaddr = (*attrp)->stack_addr; 160 161 return (0); 162 } 163 164 int 165 pthread_attr_setstackaddr(pthread_attr_t *attrp, void *stackaddr) 166 { 167 if (stackaddr == NULL || (uintptr_t)stackaddr & (_thread_pagesize - 1)) 168 return (EINVAL); 169 (*attrp)->stack_addr = stackaddr; 170 171 return (0); 172 } 173 174 int 175 pthread_attr_getscope(const pthread_attr_t *attrp, int *contentionscope) 176 { 177 *contentionscope = (*attrp)->contention_scope; 178 179 return (0); 180 } 181 182 int 183 pthread_attr_setscope(pthread_attr_t *attrp, int contentionscope) 184 { 185 if (contentionscope != PTHREAD_SCOPE_SYSTEM && 186 contentionscope != PTHREAD_SCOPE_PROCESS) 187 return (EINVAL); 188 (*attrp)->contention_scope = contentionscope; 189 190 return (0); 191 } 192 193