1 /* $OpenBSD: rthread_attr.c,v 1.8 2006/01/05 08:15:16 otto 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 = malloc(sizeof(*attr)); 64 if (!attr) 65 return (errno); 66 memset(attr, 0, sizeof(*attr)); 67 attr->stack_size = RTHREAD_STACK_SIZE_DEF; 68 attr->guard_size = sysconf(_SC_PAGESIZE); 69 attr->stack_size -= attr->guard_size; 70 attr->detach_state = PTHREAD_CREATE_JOINABLE; 71 *attrp = attr; 72 73 return (0); 74 } 75 76 int 77 pthread_attr_destroy(pthread_attr_t *attrp) 78 { 79 free(*attrp); 80 *attrp = NULL; 81 82 return (0); 83 } 84 85 int 86 pthread_attr_getguardsize(const pthread_attr_t *attrp, size_t *guardsize) 87 { 88 *guardsize = (*attrp)->guard_size; 89 90 return (0); 91 } 92 93 int 94 pthread_attr_setguardsize(pthread_attr_t *attrp, size_t guardsize) 95 { 96 if ((*attrp)->guard_size != guardsize) { 97 (*attrp)->stack_size += (*attrp)->guard_size; 98 (*attrp)->guard_size = guardsize; 99 (*attrp)->stack_size -= (*attrp)->guard_size; 100 } 101 102 return 0; 103 } 104 105 int 106 pthread_attr_getdetachstate(const pthread_attr_t *attrp, int *detachstate) 107 { 108 *detachstate = (*attrp)->detach_state; 109 110 return (0); 111 } 112 113 int 114 pthread_attr_setdetachstate(pthread_attr_t *attrp, int detachstate) 115 { 116 int retval; 117 118 retval = (detachstate == PTHREAD_CREATE_DETACHED || 119 detachstate == PTHREAD_CREATE_JOINABLE) ? 0 : EINVAL; 120 if (retval == 0) 121 (*attrp)->detach_state = detachstate; 122 123 return (retval); 124 } 125 126 int 127 pthread_attr_getstack(const pthread_attr_t *attrp, void **stackaddr, 128 size_t *stacksize) 129 { 130 *stackaddr = (*attrp)->stack_addr; 131 *stacksize = (*attrp)->stack_size + (*attrp)->guard_size; 132 133 return (0); 134 } 135 136 int 137 pthread_attr_setstack(pthread_attr_t *attrp, void *stackaddr, size_t stacksize) 138 { 139 int n; 140 141 if ((n = pthread_attr_setstackaddr(attrp, stackaddr))) 142 return (n); 143 (*attrp)->stack_size = stacksize; 144 (*attrp)->stack_size -= (*attrp)->guard_size; 145 146 return (0); 147 } 148 149 int 150 pthread_attr_getstacksize(const pthread_attr_t *attrp, size_t *stacksize) 151 { 152 *stacksize = (*attrp)->stack_size + (*attrp)->guard_size; 153 154 return (0); 155 } 156 157 int 158 pthread_attr_setstacksize(pthread_attr_t *attrp, size_t stacksize) 159 { 160 (*attrp)->stack_size = stacksize; 161 if ((*attrp)->stack_size > (*attrp)->guard_size) 162 (*attrp)->stack_size -= (*attrp)->guard_size; 163 else 164 (*attrp)->stack_size = 0; 165 166 return (0); 167 } 168 169 int 170 pthread_attr_getstackaddr(const pthread_attr_t *attrp, void **stackaddr) 171 { 172 *stackaddr = (*attrp)->stack_addr; 173 174 return (0); 175 } 176 177 int 178 pthread_attr_setstackaddr(pthread_attr_t *attrp, void *stackaddr) 179 { 180 size_t pgsz = sysconf(_SC_PAGESIZE); 181 182 if (pgsz == (size_t)-1) 183 return EINVAL; 184 if ((uintptr_t)stackaddr & (pgsz - 1)) 185 return EINVAL; 186 (*attrp)->stack_addr = stackaddr; 187 188 return (0); 189 } 190 191 int 192 pthread_attr_getscope(const pthread_attr_t *attrp, int *contentionscope) 193 { 194 *contentionscope = (*attrp)->contention_scope; 195 196 return (0); 197 } 198 199 int 200 pthread_attr_setscope(pthread_attr_t *attrp, int contentionscope) 201 { 202 /* XXX contentionscope should be validated here */ 203 (*attrp)->contention_scope = contentionscope; 204 205 return (0); 206 } 207 208 int 209 pthread_attr_setcreatesuspend_np(pthread_attr_t *attr) 210 { 211 (*attr)->create_suspended = 1; 212 return (0); 213 } 214 215