1 /* $OpenBSD: rthread_attr.c,v 1.9 2008/10/13 05:42:46 kevlo 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 <sys/param.h> 23 #include <sys/mman.h> 24 #include <sys/wait.h> 25 26 #include <machine/spinlock.h> 27 28 #include <inttypes.h> 29 #include <stdlib.h> 30 #include <unistd.h> 31 #include <signal.h> 32 #include <stdio.h> 33 #include <string.h> 34 #include <errno.h> 35 36 #include <pthread.h> 37 #include <pthread_np.h> 38 39 #include "rthread.h" 40 41 /* 42 * temp: these need to be added to pthread.h 43 */ 44 int pthread_attr_getguardsize(const pthread_attr_t *, size_t *); 45 int pthread_attr_setguardsize(pthread_attr_t *, size_t); 46 47 /* 48 * Note: stack_size + guard_size == total stack used 49 * 50 * pthread_attr_init MUST be called before any other attribute function 51 * for proper operation. 52 * 53 * Every call to pthread_attr_init MUST be matched with a call to 54 * pthread_attr_destroy to avoid leaking memory. This is an implementation 55 * requirement, not a POSIX requirement. 56 */ 57 58 int 59 pthread_attr_init(pthread_attr_t *attrp) 60 { 61 pthread_attr_t attr; 62 63 attr = calloc(1, sizeof(*attr)); 64 if (!attr) 65 return (errno); 66 attr->stack_size = RTHREAD_STACK_SIZE_DEF; 67 attr->guard_size = sysconf(_SC_PAGESIZE); 68 attr->stack_size -= attr->guard_size; 69 attr->detach_state = PTHREAD_CREATE_JOINABLE; 70 *attrp = attr; 71 72 return (0); 73 } 74 75 int 76 pthread_attr_destroy(pthread_attr_t *attrp) 77 { 78 free(*attrp); 79 *attrp = NULL; 80 81 return (0); 82 } 83 84 int 85 pthread_attr_getguardsize(const pthread_attr_t *attrp, size_t *guardsize) 86 { 87 *guardsize = (*attrp)->guard_size; 88 89 return (0); 90 } 91 92 int 93 pthread_attr_setguardsize(pthread_attr_t *attrp, size_t guardsize) 94 { 95 if ((*attrp)->guard_size != guardsize) { 96 (*attrp)->stack_size += (*attrp)->guard_size; 97 (*attrp)->guard_size = guardsize; 98 (*attrp)->stack_size -= (*attrp)->guard_size; 99 } 100 101 return 0; 102 } 103 104 int 105 pthread_attr_getdetachstate(const pthread_attr_t *attrp, int *detachstate) 106 { 107 *detachstate = (*attrp)->detach_state; 108 109 return (0); 110 } 111 112 int 113 pthread_attr_setdetachstate(pthread_attr_t *attrp, int detachstate) 114 { 115 int retval; 116 117 retval = (detachstate == PTHREAD_CREATE_DETACHED || 118 detachstate == PTHREAD_CREATE_JOINABLE) ? 0 : EINVAL; 119 if (retval == 0) 120 (*attrp)->detach_state = detachstate; 121 122 return (retval); 123 } 124 125 int 126 pthread_attr_getstack(const pthread_attr_t *attrp, void **stackaddr, 127 size_t *stacksize) 128 { 129 *stackaddr = (*attrp)->stack_addr; 130 *stacksize = (*attrp)->stack_size + (*attrp)->guard_size; 131 132 return (0); 133 } 134 135 int 136 pthread_attr_setstack(pthread_attr_t *attrp, void *stackaddr, size_t stacksize) 137 { 138 int n; 139 140 if ((n = pthread_attr_setstackaddr(attrp, stackaddr))) 141 return (n); 142 (*attrp)->stack_size = stacksize; 143 (*attrp)->stack_size -= (*attrp)->guard_size; 144 145 return (0); 146 } 147 148 int 149 pthread_attr_getstacksize(const pthread_attr_t *attrp, size_t *stacksize) 150 { 151 *stacksize = (*attrp)->stack_size + (*attrp)->guard_size; 152 153 return (0); 154 } 155 156 int 157 pthread_attr_setstacksize(pthread_attr_t *attrp, size_t stacksize) 158 { 159 (*attrp)->stack_size = stacksize; 160 if ((*attrp)->stack_size > (*attrp)->guard_size) 161 (*attrp)->stack_size -= (*attrp)->guard_size; 162 else 163 (*attrp)->stack_size = 0; 164 165 return (0); 166 } 167 168 int 169 pthread_attr_getstackaddr(const pthread_attr_t *attrp, void **stackaddr) 170 { 171 *stackaddr = (*attrp)->stack_addr; 172 173 return (0); 174 } 175 176 int 177 pthread_attr_setstackaddr(pthread_attr_t *attrp, void *stackaddr) 178 { 179 size_t pgsz = sysconf(_SC_PAGESIZE); 180 181 if (pgsz == (size_t)-1) 182 return EINVAL; 183 if ((uintptr_t)stackaddr & (pgsz - 1)) 184 return EINVAL; 185 (*attrp)->stack_addr = stackaddr; 186 187 return (0); 188 } 189 190 int 191 pthread_attr_getscope(const pthread_attr_t *attrp, int *contentionscope) 192 { 193 *contentionscope = (*attrp)->contention_scope; 194 195 return (0); 196 } 197 198 int 199 pthread_attr_setscope(pthread_attr_t *attrp, int contentionscope) 200 { 201 /* XXX contentionscope should be validated here */ 202 (*attrp)->contention_scope = contentionscope; 203 204 return (0); 205 } 206 207 int 208 pthread_attr_setcreatesuspend_np(pthread_attr_t *attr) 209 { 210 (*attr)->create_suspended = 1; 211 return (0); 212 } 213 214