1 /* 2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2008, Axel Dörfler, axeld@pinc-software.de. 4 * Copyright 2006, Jérôme Duval. All rights reserved. 5 * Distributed under the terms of the MIT License. 6 */ 7 8 9 #include <pthread.h> 10 #include "pthread_private.h" 11 12 #include <limits.h> 13 #include <stdlib.h> 14 15 #include <Debug.h> 16 17 #include <syscalls.h> 18 #include <thread_defs.h> 19 20 21 int __pthread_getattr_np(pthread_t thread, pthread_attr_t *_attr); 22 23 24 int 25 pthread_attr_init(pthread_attr_t *_attr) 26 { 27 pthread_attr *attr; 28 29 if (_attr == NULL) 30 return B_BAD_VALUE; 31 32 attr = (pthread_attr *)malloc(sizeof(pthread_attr)); 33 if (attr == NULL) 34 return B_NO_MEMORY; 35 36 attr->detach_state = PTHREAD_CREATE_JOINABLE; 37 attr->sched_priority = B_NORMAL_PRIORITY; 38 attr->stack_size = USER_STACK_SIZE; 39 attr->guard_size = USER_STACK_GUARD_SIZE; 40 attr->stack_address = NULL; 41 42 *_attr = attr; 43 return B_OK; 44 } 45 46 47 int 48 pthread_attr_destroy(pthread_attr_t *_attr) 49 { 50 pthread_attr *attr; 51 52 if (_attr == NULL || (attr = *_attr) == NULL) 53 return B_BAD_VALUE; 54 55 *_attr = NULL; 56 free(attr); 57 58 return B_OK; 59 } 60 61 62 int 63 pthread_attr_getdetachstate(const pthread_attr_t *_attr, int *state) 64 { 65 pthread_attr *attr; 66 67 if (_attr == NULL || (attr = *_attr) == NULL || state == NULL) 68 return B_BAD_VALUE; 69 70 *state = attr->detach_state; 71 72 return B_OK; 73 } 74 75 76 int 77 pthread_attr_setdetachstate(pthread_attr_t *_attr, int state) 78 { 79 pthread_attr *attr; 80 81 if (_attr == NULL || (attr = *_attr) == NULL) 82 return B_BAD_VALUE; 83 84 if (state != PTHREAD_CREATE_JOINABLE && state != PTHREAD_CREATE_DETACHED) 85 return B_BAD_VALUE; 86 87 attr->detach_state = state; 88 89 return B_OK; 90 } 91 92 93 int 94 pthread_attr_getstacksize(const pthread_attr_t *_attr, size_t *stacksize) 95 { 96 pthread_attr *attr; 97 98 if (_attr == NULL || (attr = *_attr) == NULL || stacksize == NULL) 99 return B_BAD_VALUE; 100 101 *stacksize = attr->stack_size; 102 103 return 0; 104 } 105 106 107 int 108 pthread_attr_setstacksize(pthread_attr_t *_attr, size_t stacksize) 109 { 110 pthread_attr *attr; 111 112 if (_attr == NULL || (attr = *_attr) == NULL) 113 return B_BAD_VALUE; 114 115 STATIC_ASSERT(PTHREAD_STACK_MIN >= MIN_USER_STACK_SIZE 116 && PTHREAD_STACK_MIN <= MAX_USER_STACK_SIZE); 117 if (stacksize < PTHREAD_STACK_MIN || stacksize > MAX_USER_STACK_SIZE) 118 return B_BAD_VALUE; 119 120 attr->stack_size = stacksize; 121 122 return 0; 123 } 124 125 126 int 127 pthread_attr_getscope(const pthread_attr_t *attr, int *contentionScope) 128 { 129 if (attr == NULL || contentionScope == NULL) 130 return EINVAL; 131 132 *contentionScope = PTHREAD_SCOPE_SYSTEM; 133 return 0; 134 } 135 136 137 int 138 pthread_attr_setscope(pthread_attr_t *attr, int contentionScope) 139 { 140 if (attr == NULL) 141 return EINVAL; 142 143 if (contentionScope != PTHREAD_SCOPE_SYSTEM) 144 return ENOTSUP; 145 146 return 0; 147 } 148 149 150 int 151 pthread_attr_setschedparam(pthread_attr_t *attr, 152 const struct sched_param *param) 153 { 154 if (attr == NULL || param == NULL) 155 return EINVAL; 156 157 (*attr)->sched_priority = param->sched_priority; 158 159 return 0; 160 } 161 162 163 int 164 pthread_attr_getschedparam(const pthread_attr_t *attr, 165 struct sched_param *param) 166 { 167 if (attr == NULL || param == NULL) 168 return EINVAL; 169 170 param->sched_priority = (*attr)->sched_priority; 171 172 return 0; 173 } 174 175 176 int 177 pthread_attr_getguardsize(const pthread_attr_t *_attr, size_t *guardsize) 178 { 179 pthread_attr *attr; 180 181 if (_attr == NULL || (attr = *_attr) == NULL || guardsize == NULL) 182 return B_BAD_VALUE; 183 184 *guardsize = attr->guard_size; 185 186 return 0; 187 } 188 189 190 int 191 pthread_attr_setguardsize(pthread_attr_t *_attr, size_t guardsize) 192 { 193 pthread_attr *attr; 194 195 if (_attr == NULL || (attr = *_attr) == NULL) 196 return B_BAD_VALUE; 197 198 attr->guard_size = guardsize; 199 200 return 0; 201 } 202 203 204 int 205 pthread_attr_getstack(const pthread_attr_t *_attr, void **stackaddr, 206 size_t *stacksize) 207 { 208 pthread_attr *attr; 209 210 if (_attr == NULL || (attr = *_attr) == NULL || stackaddr == NULL 211 || stacksize == NULL) { 212 return B_BAD_VALUE; 213 } 214 215 *stacksize = attr->stack_size; 216 *stackaddr = attr->stack_address; 217 218 return 0; 219 } 220 221 222 int 223 pthread_attr_setstack(pthread_attr_t *_attr, void *stackaddr, 224 size_t stacksize) 225 { 226 pthread_attr *attr; 227 228 if (_attr == NULL || (attr = *_attr) == NULL) 229 return B_BAD_VALUE; 230 231 STATIC_ASSERT(PTHREAD_STACK_MIN >= MIN_USER_STACK_SIZE 232 && PTHREAD_STACK_MIN <= MAX_USER_STACK_SIZE); 233 if (stacksize < PTHREAD_STACK_MIN || stacksize > MAX_USER_STACK_SIZE) 234 return B_BAD_VALUE; 235 236 attr->stack_size = stacksize; 237 attr->stack_address = stackaddr; 238 239 return 0; 240 } 241 242 243 int 244 __pthread_getattr_np(pthread_t thread, pthread_attr_t *_attr) 245 { 246 pthread_attr *attr; 247 status_t status; 248 thread_info info; 249 250 if (_attr == NULL || (attr = *_attr) == NULL) 251 return B_BAD_VALUE; 252 253 status = _kern_get_thread_info(thread->id, &info); 254 if (status == B_BAD_THREAD_ID) 255 return ESRCH; 256 257 if ((thread->flags & THREAD_DETACHED) != 0) 258 attr->detach_state = PTHREAD_CREATE_DETACHED; 259 else 260 attr->detach_state = PTHREAD_CREATE_JOINABLE; 261 attr->sched_priority = info.priority; 262 attr->stack_address = info.stack_base; 263 attr->stack_size = (size_t)info.stack_end - (size_t)info.stack_base; 264 // not in thread_info 265 attr->guard_size = 0; 266 267 return 0; 268 } 269 270 271 B_DEFINE_WEAK_ALIAS(__pthread_getattr_np, pthread_getattr_np); 272 B_DEFINE_WEAK_ALIAS(__pthread_getattr_np, pthread_attr_get_np); 273 274