Changeset 596d65c in mainline for uspace/lib/c/generic/fibril.c
- Timestamp:
- 2010-04-17T01:15:39Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 3292623
- Parents:
- e35bf88
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/fibril.c
re35bf88 r596d65c 48 48 49 49 #ifndef FIBRIL_INITIAL_STACK_PAGES_NO 50 #define FIBRIL_INITIAL_STACK_PAGES_NO150 #define FIBRIL_INITIAL_STACK_PAGES_NO 1 51 51 #endif 52 52 53 53 /** 54 * This futex serializes access to ready_list, serialized_list and manager_list. 55 */ 54 * This futex serializes access to ready_list, 55 * serialized_list and manager_list. 56 */ 56 57 static atomic_t fibril_futex = FUTEX_INITIALIZER; 57 58 … … 60 61 static LIST_INITIALIZE(manager_list); 61 62 62 static void fibril_main(void);63 64 63 /** Number of threads that are executing a manager fibril. */ 65 64 static int threads_in_manager; 66 /** Number of threads that are executing a manager fibril and are serialized. */ 67 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 68 72 /** Fibril-local count of serialization. If > 0, we must not preempt */ 69 73 static fibril_local int serialization_count; 70 71 /** Setup fibril information into TCB structure */72 fibril_t *fibril_setup(void)73 {74 fibril_t *f;75 tcb_t *tcb;76 77 tcb = __make_tls();78 if (!tcb)79 return NULL;80 81 f = malloc(sizeof(fibril_t));82 if (!f) {83 __free_tls(tcb);84 return NULL;85 }86 87 tcb->fibril_data = f;88 f->tcb = tcb;89 90 f->func = NULL;91 f->arg = NULL;92 f->stack = NULL;93 f->clean_after_me = NULL;94 f->retval = 0;95 f->flags = 0;96 97 return f;98 }99 100 void fibril_teardown(fibril_t *f)101 {102 __free_tls(f->tcb);103 free(f);104 }105 74 106 75 /** Function that spans the whole life-cycle of a fibril. … … 109 78 * the fibril logic is called. After its return, the return value is saved. 110 79 * The fibril then switches to another fibril, which cleans up after it. 111 */ 112 void fibril_main(void) 113 { 114 fibril_t *f = __tcb_get()->fibril_data; 115 80 * 81 */ 82 static void fibril_main(void) 83 { 84 fibril_t *fibril = __tcb_get()->fibril_data; 85 116 86 /* Call the implementing function. */ 117 f ->retval = f->func(f->arg);118 87 fibril->retval = fibril->func(fibril->arg); 88 119 89 fibril_switch(FIBRIL_FROM_DEAD); 120 /* 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); 121 125 } 122 126 … … 126 130 * held. 127 131 * 128 * @param stype Switch type. One of FIBRIL_PREEMPT, FIBRIL_TO_MANAGER, 129 * FIBRIL_FROM_MANAGER, FIBRIL_FROM_DEAD. The parameter 130 * describes the circumstances of the switch. 131 * @return Return 0 if there is no ready fibril, 132 * 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 * 133 139 */ 134 140 int fibril_switch(fibril_switch_type_t stype) … … 246 252 /** Create a new fibril. 247 253 * 248 * @param func Implementing function of the new fibril. 249 * @param arg Argument to pass to func. 250 * 251 * @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 * 252 259 */ 253 260 fid_t fibril_create(int (*func)(void *), void *arg) 254 261 { 255 fibril_t *f ;256 257 f = fibril_setup();258 if ( !f)262 fibril_t *fibril; 263 264 fibril = fibril_setup(); 265 if (fibril == NULL) 259 266 return 0; 260 f->stack = (char *) malloc(FIBRIL_INITIAL_STACK_PAGES_NO * 261 getpagesize()); 262 if (!f->stack) { 263 fibril_teardown(f); 267 268 fibril->stack = 269 (char *) malloc(FIBRIL_INITIAL_STACK_PAGES_NO * getpagesize()); 270 if (!fibril->stack) { 271 fibril_teardown(fibril); 264 272 return 0; 265 273 } 266 274 267 f ->func = func;268 f ->arg = arg;269 270 context_save(&f ->ctx);271 context_set(&f ->ctx, FADDR(fibril_main), f->stack,272 FIBRIL_INITIAL_STACK_PAGES_NO * getpagesize(), f ->tcb);273 274 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; 275 283 } 276 284 277 285 /** Add a fibril to the ready list. 278 286 * 279 * @param fid Pointer to the fibril structure of the fibril to be 280 * added. 287 * @param fid Pointer to the fibril structure of the fibril to be 288 * added. 289 * 281 290 */ 282 291 void fibril_add_ready(fid_t fid) 283 292 { 284 fibril_t *f; 285 286 f = (fibril_t *) fid; 293 fibril_t *fibril = (fibril_t *) fid; 294 287 295 futex_down(&fibril_futex); 288 if ((f->flags & FIBRIL_SERIALIZED)) 289 list_append(&f->link, &serialized_list); 296 297 if ((fibril->flags & FIBRIL_SERIALIZED)) 298 list_append(&fibril->link, &serialized_list); 290 299 else 291 list_append(&f->link, &ready_list); 300 list_append(&fibril->link, &ready_list); 301 292 302 futex_up(&fibril_futex); 293 303 } … … 295 305 /** Add a fibril to the manager list. 296 306 * 297 * @param fid Pointer to the fibril structure of the fibril to be 298 * added. 307 * @param fid Pointer to the fibril structure of the fibril to be 308 * added. 309 * 299 310 */ 300 311 void fibril_add_manager(fid_t fid) 301 312 { 302 fibril_t *f; 303 304 f = (fibril_t *) fid; 305 313 fibril_t *fibril = (fibril_t *) fid; 314 306 315 futex_down(&fibril_futex); 307 list_append(&f ->link, &manager_list);316 list_append(&fibril->link, &manager_list); 308 317 futex_up(&fibril_futex); 309 318 } … … 313 322 { 314 323 futex_down(&fibril_futex); 315 if (list_empty(&manager_list)) { 316 futex_up(&fibril_futex); 317 return; 318 } 319 list_remove(manager_list.next); 324 325 if (!list_empty(&manager_list)) 326 list_remove(manager_list.next); 327 320 328 futex_up(&fibril_futex); 321 329 }
Note:
See TracChangeset
for help on using the changeset viewer.