Changeset 596d65c in mainline
- Timestamp:
- 2010-04-17T01:15:39Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 3292623
- Parents:
- e35bf88
- Location:
- uspace/lib/c
- Files:
-
- 3 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 } -
uspace/lib/c/generic/futex.c
re35bf88 r596d65c 31 31 */ 32 32 /** @file 33 */ 33 */ 34 34 35 35 #include <futex.h> … … 40 40 /** Initialize futex counter. 41 41 * 42 * @param futex Futex. 43 * @param val Initialization value. 42 * @param futex Futex. 43 * @param val Initialization value. 44 * 44 45 */ 45 46 void futex_initialize(futex_t *futex, int val) … … 50 51 /** Try to down the futex. 51 52 * 52 * @param futex Futex. 53 * @return Non-zero if the futex was acquired. 54 * @return Zero if the futex was not acquired. 53 * @param futex Futex. 54 * 55 * @return Non-zero if the futex was acquired. 56 * @return Zero if the futex was not acquired. 57 * 55 58 */ 56 59 int futex_trydown(futex_t *futex) … … 61 64 /** Down the futex. 62 65 * 63 * @param futex Futex. 64 * @return ENOENT if there is no such virtual address. 65 * @return Zero in the uncontended case. 66 * @return Otherwise one of ESYNCH_OK_ATOMIC or ESYNCH_OK_BLOCKED. 66 * @param futex Futex. 67 * 68 * @return ENOENT if there is no such virtual address. 69 * @return Zero in the uncontended case. 70 * @return Otherwise one of ESYNCH_OK_ATOMIC or ESYNCH_OK_BLOCKED. 71 * 67 72 */ 68 73 int futex_down(futex_t *futex) … … 70 75 if ((atomic_signed_t) atomic_predec(futex) < 0) 71 76 return __SYSCALL1(SYS_FUTEX_SLEEP, (sysarg_t) &futex->count); 72 77 73 78 return 0; 74 79 } … … 76 81 /** Up the futex. 77 82 * 78 * @param futex Futex. 79 * @return ENOENT if there is no such virtual address. 80 * @return Zero in the uncontended case. 83 * @param futex Futex. 84 * 85 * @return ENOENT if there is no such virtual address. 86 * @return Zero in the uncontended case. 87 * 81 88 */ 82 89 int futex_up(futex_t *futex) … … 84 91 if ((atomic_signed_t) atomic_postinc(futex) < 0) 85 92 return __SYSCALL1(SYS_FUTEX_WAKEUP, (sysarg_t) &futex->count); 86 93 87 94 return 0; 88 95 } -
uspace/lib/c/include/futex.h
re35bf88 r596d65c 39 39 #include <sys/types.h> 40 40 41 #define FUTEX_INITIALIZER 41 #define FUTEX_INITIALIZER {1} 42 42 43 43 typedef atomic_t futex_t;
Note:
See TracChangeset
for help on using the changeset viewer.