1 /* $OpenBSD: rthread_attr.c,v 1.23 2017/09/05 02:40:54 guenther 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 <stdint.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 48 /* make sure _rthread_attr_default has been initialized */ 49 if (!_threads_ready) 50 _rthread_init(); 51 52 attr = calloc(1, sizeof(*attr)); 53 if (!attr) 54 return (errno); 55 *attr = _rthread_attr_default; 56 *attrp = attr; 57 58 return (0); 59 } 60 61 int 62 pthread_attr_destroy(pthread_attr_t *attrp) 63 { 64 free(*attrp); 65 *attrp = NULL; 66 67 return (0); 68 } 69 70 int 71 pthread_attr_getguardsize(const pthread_attr_t *attrp, size_t *guardsize) 72 { 73 *guardsize = (*attrp)->guard_size; 74 75 return (0); 76 } 77 78 int 79 pthread_attr_setguardsize(pthread_attr_t *attrp, size_t guardsize) 80 { 81 (*attrp)->guard_size = guardsize; 82 83 return (0); 84 } 85 86 int 87 pthread_attr_getdetachstate(const pthread_attr_t *attrp, int *detachstate) 88 { 89 *detachstate = (*attrp)->detach_state; 90 91 return (0); 92 } 93 94 int 95 pthread_attr_setdetachstate(pthread_attr_t *attrp, int detachstate) 96 { 97 int error; 98 99 error = (detachstate == PTHREAD_CREATE_DETACHED || 100 detachstate == PTHREAD_CREATE_JOINABLE) ? 0 : EINVAL; 101 if (error == 0) 102 (*attrp)->detach_state = detachstate; 103 104 return (error); 105 } 106 107 int 108 pthread_attr_getstack(const pthread_attr_t *attrp, void **stackaddr, 109 size_t *stacksize) 110 { 111 *stackaddr = (*attrp)->stack_addr; 112 *stacksize = (*attrp)->stack_size; 113 114 return (0); 115 } 116 117 int 118 pthread_attr_setstack(pthread_attr_t *attrp, void *stackaddr, size_t stacksize) 119 { 120 int error; 121 122 /* 123 * XXX Add an alignment test, on stackaddr for stack-grows-up 124 * archs or on stackaddr+stacksize for stack-grows-down archs 125 */ 126 if (stacksize < PTHREAD_STACK_MIN) 127 return (EINVAL); 128 if ((error = pthread_attr_setstackaddr(attrp, stackaddr))) 129 return (error); 130 (*attrp)->stack_size = stacksize; 131 132 return (0); 133 } 134 135 int 136 pthread_attr_getstacksize(const pthread_attr_t *attrp, size_t *stacksize) 137 { 138 *stacksize = (*attrp)->stack_size; 139 140 return (0); 141 } 142 143 int 144 pthread_attr_setstacksize(pthread_attr_t *attrp, size_t stacksize) 145 { 146 if (!_threads_ready) /* for ROUND_TO_PAGE */ 147 _rthread_init(); 148 149 if (stacksize < PTHREAD_STACK_MIN || 150 stacksize > ROUND_TO_PAGE(stacksize)) 151 return (EINVAL); 152 (*attrp)->stack_size = stacksize; 153 154 return (0); 155 } 156 157 int 158 pthread_attr_getstackaddr(const pthread_attr_t *attrp, void **stackaddr) 159 { 160 *stackaddr = (*attrp)->stack_addr; 161 162 return (0); 163 } 164 165 int 166 pthread_attr_setstackaddr(pthread_attr_t *attrp, void *stackaddr) 167 { 168 if (!_threads_ready) 169 _rthread_init(); /* for _thread_pagesize */ 170 171 if (stackaddr == NULL || (uintptr_t)stackaddr & (_thread_pagesize - 1)) 172 return (EINVAL); 173 (*attrp)->stack_addr = stackaddr; 174 175 return (0); 176 } 177 DEF_NONSTD(pthread_attr_setstackaddr); 178 179 int 180 pthread_attr_getscope(const pthread_attr_t *attrp, int *contentionscope) 181 { 182 *contentionscope = (*attrp)->contention_scope; 183 184 return (0); 185 } 186 187 int 188 pthread_attr_setscope(pthread_attr_t *attrp, int contentionscope) 189 { 190 if (contentionscope != PTHREAD_SCOPE_SYSTEM && 191 contentionscope != PTHREAD_SCOPE_PROCESS) 192 return (EINVAL); 193 (*attrp)->contention_scope = contentionscope; 194 195 return (0); 196 } 197 198