Changeset c47e1a8 in mainline for uspace/lib/c/generic/fibril.c
- Timestamp:
- 2010-05-21T07:50:04Z (16 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- d51ee2b
- Parents:
- cf8cc36 (diff), 15b592b (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - File:
-
- 1 moved
-
uspace/lib/c/generic/fibril.c (moved) (moved from uspace/lib/libc/generic/fibril.c ) (15 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/fibril.c
rcf8cc36 rc47e1a8 41 41 #include <unistd.h> 42 42 #include <stdio.h> 43 #include <arch/barrier.h> 43 44 #include <libarch/faddr.h> 44 45 #include <futex.h> … … 47 48 48 49 #ifndef FIBRIL_INITIAL_STACK_PAGES_NO 49 #define FIBRIL_INITIAL_STACK_PAGES_NO150 #define FIBRIL_INITIAL_STACK_PAGES_NO 1 50 51 #endif 51 52 52 53 /** 53 * This futex serializes access to ready_list, serialized_list and manager_list. 54 */ 54 * This futex serializes access to ready_list, 55 * serialized_list and manager_list. 56 */ 55 57 static atomic_t fibril_futex = FUTEX_INITIALIZER; 56 58 … … 59 61 static LIST_INITIALIZE(manager_list); 60 62 61 static void fibril_main(void);62 63 63 /** Number of threads that are executing a manager fibril. */ 64 64 static int threads_in_manager; 65 /** Number of threads that are executing a manager fibril and are serialized. */ 66 static int serialized_threads; /* Protected by async_futex */ 65 66 /** 67 * Number of threads that are executing a manager fibril 68 * and are serialized. Protected by async_futex. 69 */ 70 static int serialized_threads; 71 67 72 /** Fibril-local count of serialization. If > 0, we must not preempt */ 68 73 static fibril_local int serialization_count; 69 70 /** Setup fibril information into TCB structure */71 fibril_t *fibril_setup(void)72 {73 fibril_t *f;74 tcb_t *tcb;75 76 tcb = __make_tls();77 if (!tcb)78 return NULL;79 80 f = malloc(sizeof(fibril_t));81 if (!f) {82 __free_tls(tcb);83 return NULL;84 }85 86 tcb->fibril_data = f;87 f->tcb = tcb;88 89 f->func = NULL;90 f->arg = NULL;91 f->stack = NULL;92 f->clean_after_me = NULL;93 f->retval = 0;94 f->flags = 0;95 96 return f;97 }98 99 void fibril_teardown(fibril_t *f)100 {101 __free_tls(f->tcb);102 free(f);103 }104 74 105 75 /** Function that spans the whole life-cycle of a fibril. … … 108 78 * the fibril logic is called. After its return, the return value is saved. 109 79 * The fibril then switches to another fibril, which cleans up after it. 110 */ 111 void fibril_main(void) 112 { 113 fibril_t *f = __tcb_get()->fibril_data; 114 80 * 81 */ 82 static void fibril_main(void) 83 { 84 fibril_t *fibril = __tcb_get()->fibril_data; 85 115 86 /* Call the implementing function. */ 116 f ->retval = f->func(f->arg);117 87 fibril->retval = fibril->func(fibril->arg); 88 118 89 fibril_switch(FIBRIL_FROM_DEAD); 119 /* not reached */ 90 /* Not reached */ 91 } 92 93 /** Setup fibril information into TCB structure 94 * 95 */ 96 fibril_t *fibril_setup(void) 97 { 98 tcb_t *tcb = __make_tls(); 99 if (!tcb) 100 return NULL; 101 102 fibril_t *fibril = malloc(sizeof(fibril_t)); 103 if (!fibril) { 104 __free_tls(tcb); 105 return NULL; 106 } 107 108 tcb->fibril_data = fibril; 109 fibril->tcb = tcb; 110 111 fibril->func = NULL; 112 fibril->arg = NULL; 113 fibril->stack = NULL; 114 fibril->clean_after_me = NULL; 115 fibril->retval = 0; 116 fibril->flags = 0; 117 118 return fibril; 119 } 120 121 void fibril_teardown(fibril_t *fibril) 122 { 123 __free_tls(fibril->tcb); 124 free(fibril); 120 125 } 121 126 … … 125 130 * held. 126 131 * 127 * @param stype Switch type. One of FIBRIL_PREEMPT, FIBRIL_TO_MANAGER, 128 * FIBRIL_FROM_MANAGER, FIBRIL_FROM_DEAD. The parameter 129 * describes the circumstances of the switch. 130 * @return Return 0 if there is no ready fibril, 131 * return 1 otherwise. 132 * @param stype Switch type. One of FIBRIL_PREEMPT, FIBRIL_TO_MANAGER, 133 * FIBRIL_FROM_MANAGER, FIBRIL_FROM_DEAD. The parameter 134 * describes the circumstances of the switch. 135 * 136 * @return 0 if there is no ready fibril, 137 * @return 1 otherwise. 138 * 132 139 */ 133 140 int fibril_switch(fibril_switch_type_t stype) 134 141 { 135 fibril_t *srcf, *dstf;136 142 int retval = 0; 137 143 138 144 futex_down(&fibril_futex); 139 145 140 146 if (stype == FIBRIL_PREEMPT && list_empty(&ready_list)) 141 147 goto ret_0; 142 148 143 149 if (stype == FIBRIL_FROM_MANAGER) { 144 if ( list_empty(&ready_list) && list_empty(&serialized_list))150 if ((list_empty(&ready_list)) && (list_empty(&serialized_list))) 145 151 goto ret_0; 152 146 153 /* 147 154 * Do not preempt if there is not enough threads to run the 148 155 * ready fibrils which are not serialized. 149 156 */ 150 if ( list_empty(&serialized_list) &&151 threads_in_manager <= serialized_threads) {157 if ((list_empty(&serialized_list)) && 158 (threads_in_manager <= serialized_threads)) { 152 159 goto ret_0; 153 160 } 154 161 } 162 155 163 /* If we are going to manager and none exists, create it */ 156 if ( stype == FIBRIL_TO_MANAGER || stype == FIBRIL_FROM_DEAD) {164 if ((stype == FIBRIL_TO_MANAGER) || (stype == FIBRIL_FROM_DEAD)) { 157 165 while (list_empty(&manager_list)) { 158 166 futex_up(&fibril_futex); … … 162 170 } 163 171 164 srcf = __tcb_get()->fibril_data;172 fibril_t *srcf = __tcb_get()->fibril_data; 165 173 if (stype != FIBRIL_FROM_DEAD) { 174 166 175 /* Save current state */ 167 176 if (!context_save(&srcf->ctx)) { 168 177 if (serialization_count) 169 178 srcf->flags &= ~FIBRIL_SERIALIZED; 179 170 180 if (srcf->clean_after_me) { 171 181 /* … … 173 183 * restored context here. 174 184 */ 175 void *stack = srcf->clean_after_me->stack; 185 void *stack = srcf->clean_after_me->stack; 176 186 if (stack) { 177 187 /* … … 188 198 srcf->clean_after_me = NULL; 189 199 } 200 190 201 return 1; /* futex_up already done here */ 191 202 } 192 203 193 204 /* Save myself to the correct run list */ 194 205 if (stype == FIBRIL_PREEMPT) … … 197 208 list_append(&srcf->link, &manager_list); 198 209 threads_in_manager--; 199 } else { 210 } else { 200 211 /* 201 212 * If stype == FIBRIL_TO_MANAGER, don't put ourselves to … … 207 218 208 219 /* Choose a new fibril to run */ 209 if (stype == FIBRIL_TO_MANAGER || stype == FIBRIL_FROM_DEAD) { 220 fibril_t *dstf; 221 if ((stype == FIBRIL_TO_MANAGER) || (stype == FIBRIL_FROM_DEAD)) { 210 222 dstf = list_get_instance(manager_list.next, fibril_t, link); 211 223 if (serialization_count && stype == FIBRIL_TO_MANAGER) { … … 214 226 } 215 227 threads_in_manager++; 216 228 217 229 if (stype == FIBRIL_FROM_DEAD) 218 230 dstf->clean_after_me = srcf; … … 228 240 } 229 241 list_remove(&dstf->link); 230 242 231 243 futex_up(&fibril_futex); 232 244 context_restore(&dstf->ctx); 233 245 /* not reached */ 234 246 235 247 ret_0: 236 248 futex_up(&fibril_futex); … … 240 252 /** Create a new fibril. 241 253 * 242 * @param func Implementing function of the new fibril. 243 * @param arg Argument to pass to func. 244 * 245 * @return Return 0 on failure or TLS of the new fibril. 254 * @param func Implementing function of the new fibril. 255 * @param arg Argument to pass to func. 256 * 257 * @return 0 on failure or TLS of the new fibril. 258 * 246 259 */ 247 260 fid_t fibril_create(int (*func)(void *), void *arg) 248 261 { 249 fibril_t *f ;250 251 f = fibril_setup();252 if ( !f)262 fibril_t *fibril; 263 264 fibril = fibril_setup(); 265 if (fibril == NULL) 253 266 return 0; 254 f->stack = (char *) malloc(FIBRIL_INITIAL_STACK_PAGES_NO * 255 getpagesize()); 256 if (!f->stack) { 257 fibril_teardown(f); 267 268 fibril->stack = 269 (char *) malloc(FIBRIL_INITIAL_STACK_PAGES_NO * getpagesize()); 270 if (!fibril->stack) { 271 fibril_teardown(fibril); 258 272 return 0; 259 273 } 260 274 261 f ->func = func;262 f ->arg = arg;263 264 context_save(&f ->ctx);265 context_set(&f ->ctx, FADDR(fibril_main), f->stack,266 FIBRIL_INITIAL_STACK_PAGES_NO * getpagesize(), f ->tcb);267 268 return (fid_t) f ;275 fibril->func = func; 276 fibril->arg = arg; 277 278 context_save(&fibril->ctx); 279 context_set(&fibril->ctx, FADDR(fibril_main), fibril->stack, 280 FIBRIL_INITIAL_STACK_PAGES_NO * getpagesize(), fibril->tcb); 281 282 return (fid_t) fibril; 269 283 } 270 284 271 285 /** Add a fibril to the ready list. 272 286 * 273 * @param fid Pointer to the fibril structure of the fibril to be 274 * added. 287 * @param fid Pointer to the fibril structure of the fibril to be 288 * added. 289 * 275 290 */ 276 291 void fibril_add_ready(fid_t fid) 277 292 { 278 fibril_t *f; 279 280 f = (fibril_t *) fid; 293 fibril_t *fibril = (fibril_t *) fid; 294 281 295 futex_down(&fibril_futex); 282 if ((f->flags & FIBRIL_SERIALIZED)) 283 list_append(&f->link, &serialized_list); 296 297 if ((fibril->flags & FIBRIL_SERIALIZED)) 298 list_append(&fibril->link, &serialized_list); 284 299 else 285 list_append(&f->link, &ready_list); 300 list_append(&fibril->link, &ready_list); 301 286 302 futex_up(&fibril_futex); 287 303 } … … 289 305 /** Add a fibril to the manager list. 290 306 * 291 * @param fid Pointer to the fibril structure of the fibril to be 292 * added. 307 * @param fid Pointer to the fibril structure of the fibril to be 308 * added. 309 * 293 310 */ 294 311 void fibril_add_manager(fid_t fid) 295 312 { 296 fibril_t *f; 297 298 f = (fibril_t *) fid; 299 313 fibril_t *fibril = (fibril_t *) fid; 314 300 315 futex_down(&fibril_futex); 301 list_append(&f ->link, &manager_list);316 list_append(&fibril->link, &manager_list); 302 317 futex_up(&fibril_futex); 303 318 } … … 307 322 { 308 323 futex_down(&fibril_futex); 309 if (list_empty(&manager_list)) { 310 futex_up(&fibril_futex); 311 return; 312 } 313 list_remove(manager_list.next); 324 325 if (!list_empty(&manager_list)) 326 list_remove(manager_list.next); 327 314 328 futex_up(&fibril_futex); 315 329 }
Note:
See TracChangeset
for help on using the changeset viewer.
