Changeset 12f91130 in mainline
- Timestamp:
- 2007-06-28T15:49:21Z (17 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 9591265
- Parents:
- bc1f1c2
- Location:
- uspace/lib/libc
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/libc/generic/async.c
rbc1f1c2 r12f91130 52 52 * 53 53 * 1) Multithreaded client application 54 * create_thread(thread1);55 * create_thread(thread2);54 * fibril_create(fibril1); 55 * fibril_create(fibril2); 56 56 * ... 57 57 * 58 * thread1() {58 * fibril1() { 59 59 * conn = ipc_connect_me_to(); 60 60 * c1 = send(conn); -
uspace/lib/libc/generic/fibril.c
rbc1f1c2 r12f91130 49 49 #endif 50 50 51 /** This futex serializes access to ready_list, serialized_list and manage_list. 52 */ 53 static atomic_t fibril_futex = FUTEX_INITIALIZER; 54 51 55 static LIST_INITIALIZE(ready_list); 52 56 static LIST_INITIALIZE(serialized_list); … … 55 59 static void fibril_main(void); 56 60 57 static atomic_t fibril_futex = FUTEX_INITIALIZER; 58 /** Number of threads that are in async_serialized mode */ 59 static int serialized_threads; /* Protected by async_futex */ 61 /** Number of fibrils that are in async_serialized mode */ 62 static int serialized_fibrils; /* Protected by async_futex */ 60 63 /** Thread-local count of serialization. If >0, we must not preempt */ 61 64 static __thread int serialization_count; … … 93 96 /** Function that spans the whole life-cycle of a fibril. 94 97 * 95 * Each fibril begins execution in this function. Then the function 96 * implementing the fibril logic is called. After its return, the return value 97 * is saved for a potentional joiner. If the joiner exists, it is woken up. The 98 * fibril then switches to another fibril, which cleans up after it. 98 * Each fibril begins execution in this function. Then the function implementing 99 * the fibril logic is called. After its return, the return value is saved. 100 * The fibril then switches to another fibril, which cleans up after it. 99 101 */ 100 102 void fibril_main(void) … … 102 104 fibril_t *f = __tcb_get()->fibril_data; 103 105 106 /* Call the implementing function. */ 104 107 f->retval = f->func(f->arg); 105 106 /*107 * If there is a joiner, wake it up and save our return value.108 */109 if (f->joiner) {110 list_append(&f->joiner->link, &ready_list);111 f->joiner->joinee_retval = f->retval;112 }113 108 114 109 fibril_schedule_next_adv(FIBRIL_FROM_DEAD); … … 121 116 * held. 122 117 * 123 * @param stype One of FIBRIL_SLEEP,FIBRIL_PREEMPT, FIBRIL_TO_MANAGER,118 * @param stype Switch type. One of FIBRIL_PREEMPT, FIBRIL_TO_MANAGER, 124 119 * FIBRIL_FROM_MANAGER, FIBRIL_FROM_DEAD. The parameter 125 120 * describes the circumstances of the switch. … … 136 131 if (stype == FIBRIL_PREEMPT && list_empty(&ready_list)) 137 132 goto ret_0; 138 if (stype == FIBRIL_SLEEP) {139 if (list_empty(&ready_list) && list_empty(&serialized_list))140 goto ret_0;141 }142 133 143 134 if (stype == FIBRIL_FROM_MANAGER) { … … 145 136 goto ret_0; 146 137 /* 147 * Do not preempt if there is not sufficient count of thread138 * Do not preempt if there is not sufficient count of fibril 148 139 * managers. 149 140 */ 150 141 if (list_empty(&serialized_list) && fibrils_in_manager <= 151 serialized_ threads) {142 serialized_fibrils) { 152 143 goto ret_0; 153 144 } … … 191 182 * any list, we should already be somewhere, or we will 192 183 * be lost. 193 *194 * The stype == FIBRIL_SLEEP case is similar. The fibril195 * has an external refernce which can be used to wake it196 * up once that time has come.197 184 */ 198 185 } … … 203 190 dstf = list_get_instance(manager_list.next, fibril_t, link); 204 191 if (serialization_count && stype == FIBRIL_TO_MANAGER) { 205 serialized_ threads++;192 serialized_fibrils++; 206 193 srcf->flags |= FIBRIL_SERIALIZED; 207 194 } … … 214 201 dstf = list_get_instance(serialized_list.next, fibril_t, 215 202 link); 216 serialized_ threads--;203 serialized_fibrils--; 217 204 } else { 218 205 dstf = list_get_instance(ready_list.next, fibril_t, … … 229 216 futex_up(&fibril_futex); 230 217 return retval; 231 }232 233 /** Wait for fibril to finish.234 *235 * Each fibril can be only joined by one other fibril. Moreover, the joiner must236 * be from the same thread as the joinee.237 *238 * @param fid Fibril to join.239 *240 * @return Value returned by the completed fibril.241 */242 int fibril_join(fid_t fid)243 {244 fibril_t *f;245 fibril_t *cur;246 247 /* Handle fid = Kernel address -> it is wait for call */248 f = (fibril_t *) fid;249 250 /*251 * The joiner is running so the joinee isn't.252 */253 cur = __tcb_get()->fibril_data;254 f->joiner = cur;255 fibril_schedule_next_adv(FIBRIL_SLEEP);256 257 /*258 * The joinee fills in the return value.259 */260 return cur->joinee_retval;261 218 } 262 219 … … 286 243 f->func = func; 287 244 f->clean_after_me = NULL; 288 f->joiner = NULL;289 f->joinee_retval = 0;290 245 f->retval = 0; 291 246 f->flags = 0; -
uspace/lib/libc/include/fibril.h
rbc1f1c2 r12f91130 50 50 51 51 typedef enum { 52 FIBRIL_SLEEP,53 52 FIBRIL_PREEMPT, 54 53 FIBRIL_TO_MANAGER, … … 68 67 69 68 struct fibril *clean_after_me; 70 struct fibril *joiner;71 int joinee_retval;72 69 int retval; 73 70 int flags; … … 79 76 80 77 extern fid_t fibril_create(int (*func)(void *), void *arg); 81 extern int fibril_join(fid_t fid);82 78 extern fibril_t *fibril_setup(void); 83 79 extern void fibril_teardown(fibril_t *f);
Note:
See TracChangeset
for help on using the changeset viewer.