1 #include <minix/mthread.h> 2 #include "global.h" 3 #include "proto.h" 4 5 static struct __mthread_attr *va_front, *va_rear; 6 static void mthread_attr_add(mthread_attr_t *a); 7 static void mthread_attr_remove(mthread_attr_t *a); 8 static int mthread_attr_valid(mthread_attr_t *a); 9 10 /*===========================================================================* 11 * mthread_init_valid_attributes * 12 *===========================================================================*/ 13 void mthread_init_valid_attributes(void) 14 { 15 /* Initialize list of valid attributs */ 16 va_front = va_rear = NULL; 17 } 18 19 20 /*===========================================================================* 21 * mthread_attr_add * 22 *===========================================================================*/ 23 static void mthread_attr_add(a) 24 mthread_attr_t *a; 25 { 26 /* Add attribute to list of valid, initialized attributes */ 27 28 if (va_front == NULL) { /* Empty list */ 29 va_front = *a; 30 (*a)->ma_prev = NULL; 31 } else { 32 va_rear->ma_next = *a; 33 (*a)->ma_prev = va_rear; 34 } 35 36 (*a)->ma_next = NULL; 37 va_rear = *a; 38 } 39 40 41 /*===========================================================================* 42 * mthread_attr_destroy * 43 *===========================================================================*/ 44 int mthread_attr_destroy(attr) 45 mthread_attr_t *attr; 46 { 47 /* Invalidate attribute and deallocate resources. */ 48 49 if (attr == NULL) 50 return(EINVAL); 51 52 if (!mthread_attr_valid(attr)) 53 return(EINVAL); 54 55 /* Valide attribute; invalidate it */ 56 mthread_attr_remove(attr); 57 free(*attr); 58 *attr = NULL; 59 60 return(0); 61 } 62 63 64 /*===========================================================================* 65 * mthread_attr_init * 66 *===========================================================================*/ 67 int mthread_attr_init(attr) 68 mthread_attr_t *attr; /* Attribute */ 69 { 70 /* Initialize the attribute to a known state. */ 71 struct __mthread_attr *a; 72 73 if (attr == NULL) 74 return(EAGAIN); 75 else if (mthread_attr_valid(attr)) 76 return(EBUSY); 77 78 if ((a = malloc(sizeof(struct __mthread_attr))) == NULL) 79 return(-1); 80 81 a->ma_detachstate = MTHREAD_CREATE_JOINABLE; 82 a->ma_stackaddr = NULL; 83 a->ma_stacksize = (size_t) 0; 84 85 *attr = (mthread_attr_t) a; 86 mthread_attr_add(attr); /* Validate attribute: attribute now in use */ 87 88 return(0); 89 } 90 91 /*===========================================================================* 92 * mthread_attr_getdetachstate * 93 *===========================================================================*/ 94 int mthread_attr_getdetachstate(attr, detachstate) 95 mthread_attr_t *attr; 96 int *detachstate; 97 { 98 /* Get detachstate of a thread attribute */ 99 struct __mthread_attr *a; 100 101 if (attr == NULL) 102 return(EINVAL); 103 104 a = (struct __mthread_attr *) *attr; 105 if (!mthread_attr_valid(attr)) 106 return(EINVAL); 107 108 *detachstate = a->ma_detachstate; 109 110 return(0); 111 } 112 113 114 /*===========================================================================* 115 * mthread_attr_setdetachstate * 116 *===========================================================================*/ 117 int mthread_attr_setdetachstate(attr, detachstate) 118 mthread_attr_t *attr; 119 int detachstate; 120 { 121 /* Set detachstate of a thread attribute */ 122 struct __mthread_attr *a; 123 124 if (attr == NULL) 125 return(EINVAL); 126 127 a = (struct __mthread_attr *) *attr; 128 if (!mthread_attr_valid(attr)) 129 return(EINVAL); 130 else if(detachstate != MTHREAD_CREATE_JOINABLE && 131 detachstate != MTHREAD_CREATE_DETACHED) 132 return(EINVAL); 133 134 a->ma_detachstate = detachstate; 135 136 return(0); 137 } 138 139 140 /*===========================================================================* 141 * mthread_attr_getstack * 142 *===========================================================================*/ 143 int mthread_attr_getstack(attr, stackaddr, stacksize) 144 mthread_attr_t *attr; 145 void **stackaddr; 146 size_t *stacksize; 147 { 148 /* Get stack attribute */ 149 struct __mthread_attr *a; 150 151 if (attr == NULL) 152 return(EINVAL); 153 154 a = (struct __mthread_attr *) *attr; 155 if (!mthread_attr_valid(attr)) 156 return(EINVAL); 157 158 *stackaddr = a->ma_stackaddr; 159 *stacksize = a->ma_stacksize; 160 161 return(0); 162 } 163 164 165 /*===========================================================================* 166 * mthread_attr_getstacksize * 167 *===========================================================================*/ 168 int mthread_attr_getstacksize(attr, stacksize) 169 mthread_attr_t *attr; 170 size_t *stacksize; 171 { 172 /* Get stack size attribute */ 173 struct __mthread_attr *a; 174 175 if (attr == NULL) 176 return(EINVAL); 177 178 a = (struct __mthread_attr *) *attr; 179 if (!mthread_attr_valid(attr)) 180 return(EINVAL); 181 182 *stacksize = a->ma_stacksize; 183 184 return(0); 185 } 186 187 188 /*===========================================================================* 189 * mthread_attr_setstack * 190 *===========================================================================*/ 191 int mthread_attr_setstack(attr, stackaddr, stacksize) 192 mthread_attr_t *attr; 193 void *stackaddr; 194 size_t stacksize; 195 { 196 /* Set stack attribute */ 197 struct __mthread_attr *a; 198 199 if (attr == NULL) 200 return(EINVAL); 201 202 a = (struct __mthread_attr *) *attr; 203 if (!mthread_attr_valid(attr) || stacksize < MTHREAD_STACK_MIN) 204 return(EINVAL); 205 206 /* We don't care about address alignment (POSIX standard). The ucontext 207 * system calls will make sure that the provided stack will be aligned (at 208 * the cost of some memory if needed). 209 */ 210 211 a->ma_stackaddr = stackaddr; 212 a->ma_stacksize = stacksize; 213 214 return(0); 215 } 216 217 218 /*===========================================================================* 219 * mthread_attr_setstacksize * 220 *===========================================================================*/ 221 int mthread_attr_setstacksize(attr, stacksize) 222 mthread_attr_t *attr; 223 size_t stacksize; 224 { 225 /* Set stack size attribute */ 226 struct __mthread_attr *a; 227 228 if (attr == NULL) 229 return(EINVAL); 230 231 a = (struct __mthread_attr *) *attr; 232 if (!mthread_attr_valid(attr) || stacksize < MTHREAD_STACK_MIN) 233 return(EINVAL); 234 235 a->ma_stacksize = stacksize; 236 237 return(0); 238 } 239 240 241 /*===========================================================================* 242 * mthread_attr_remove * 243 *===========================================================================*/ 244 static void mthread_attr_remove(a) 245 mthread_attr_t *a; 246 { 247 /* Remove attribute from list of valid, initialized attributes */ 248 249 if ((*a)->ma_prev == NULL) 250 va_front = (*a)->ma_next; 251 else 252 (*a)->ma_prev->ma_next = (*a)->ma_next; 253 254 if ((*a)->ma_next == NULL) 255 va_rear = (*a)->ma_prev; 256 else 257 (*a)->ma_next->ma_prev = (*a)->ma_prev; 258 } 259 260 261 /*===========================================================================* 262 * mthread_attr_valid * 263 *===========================================================================*/ 264 static int mthread_attr_valid(a) 265 mthread_attr_t *a; 266 { 267 /* Check to see if attribute is on the list of valid attributes */ 268 struct __mthread_attr *loopitem; 269 270 loopitem = va_front; 271 272 while (loopitem != NULL) { 273 if (loopitem == *a) 274 return(1); 275 276 loopitem = loopitem->ma_next; 277 } 278 279 return(0); 280 } 281 282 283 /*===========================================================================* 284 * mthread_attr_verify * 285 *===========================================================================*/ 286 #ifdef MDEBUG 287 int mthread_attr_verify(void) 288 { 289 /* Return true when no attributes are in use */ 290 struct __mthread_attr *loopitem; 291 292 loopitem = va_front; 293 294 while (loopitem != NULL) { 295 loopitem = loopitem->ma_next; 296 return(0); 297 } 298 299 return(1); 300 } 301 #endif 302 303 /* pthread compatibility layer. */ 304 __weak_alias(pthread_attr_destroy, mthread_attr_destroy) 305 __weak_alias(pthread_attr_getdetachstate, mthread_attr_getdetachstate) 306 __weak_alias(pthread_attr_getstack, mthread_attr_getstack) 307 __weak_alias(pthread_attr_getstacksize, mthread_attr_getstacksize) 308 __weak_alias(pthread_attr_init, mthread_attr_init) 309 __weak_alias(pthread_attr_setdetachstate, mthread_attr_setdetachstate) 310 __weak_alias(pthread_attr_setstack, mthread_attr_setstack) 311 __weak_alias(pthread_attr_setstacksize, mthread_attr_setstacksize) 312 313