Rev 2492 | Rev 2586 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 2492 | Rev 2568 | ||
|---|---|---|---|
| Line 73... | Line 73... | ||
| 73 | 73 | ||
| 74 | tcb = __make_tls(); |
74 | tcb = __make_tls(); |
| 75 | if (!tcb) |
75 | if (!tcb) |
| 76 | return NULL; |
76 | return NULL; |
| 77 | 77 | ||
| 78 | f = malloc(sizeof(*f)); |
78 | f = malloc(sizeof(fibril_t)); |
| 79 | if (!f) { |
79 | if (!f) { |
| 80 | __free_tls(tcb); |
80 | __free_tls(tcb); |
| 81 | return NULL; |
81 | return NULL; |
| 82 | } |
82 | } |
| 83 | 83 | ||
| 84 | tcb->fibril_data = f; |
84 | tcb->fibril_data = f; |
| 85 | f->tcb = tcb; |
85 | f->tcb = tcb; |
| 86 | 86 | ||
| - | 87 | f->func = NULL; |
|
| - | 88 | f->arg = NULL; |
|
| - | 89 | f->stack = NULL; |
|
| - | 90 | f->clean_after_me = NULL; |
|
| - | 91 | f->retval = 0; |
|
| - | 92 | f->flags = 0; |
|
| - | 93 | ||
| 87 | return f; |
94 | return f; |
| 88 | } |
95 | } |
| 89 | 96 | ||
| 90 | void fibril_teardown(fibril_t *f) |
97 | void fibril_teardown(fibril_t *f) |
| 91 | { |
98 | { |
| Line 104... | Line 111... | ||
| 104 | fibril_t *f = __tcb_get()->fibril_data; |
111 | fibril_t *f = __tcb_get()->fibril_data; |
| 105 | 112 | ||
| 106 | /* Call the implementing function. */ |
113 | /* Call the implementing function. */ |
| 107 | f->retval = f->func(f->arg); |
114 | f->retval = f->func(f->arg); |
| 108 | 115 | ||
| 109 | fibril_schedule_next_adv(FIBRIL_FROM_DEAD); |
116 | fibril_switch(FIBRIL_FROM_DEAD); |
| 110 | /* not reached */ |
117 | /* not reached */ |
| 111 | } |
118 | } |
| 112 | 119 | ||
| 113 | /** Schedule next fibril. |
120 | /** Switch from the current fibril. |
| 114 | * |
121 | * |
| 115 | * If calling with FIBRIL_TO_MANAGER parameter, the async_futex should be |
122 | * If calling with FIBRIL_TO_MANAGER parameter, the async_futex should be |
| 116 | * held. |
123 | * held. |
| 117 | * |
124 | * |
| 118 | * @param stype Switch type. One of FIBRIL_PREEMPT, FIBRIL_TO_MANAGER, |
125 | * @param stype Switch type. One of FIBRIL_PREEMPT, FIBRIL_TO_MANAGER, |
| 119 | * FIBRIL_FROM_MANAGER, FIBRIL_FROM_DEAD. The parameter |
126 | * FIBRIL_FROM_MANAGER, FIBRIL_FROM_DEAD. The parameter |
| 120 | * describes the circumstances of the switch. |
127 | * describes the circumstances of the switch. |
| 121 | * @return Return 0 if there is no ready fibril, |
128 | * @return Return 0 if there is no ready fibril, |
| 122 | * return 1 otherwise. |
129 | * return 1 otherwise. |
| 123 | */ |
130 | */ |
| 124 | int fibril_schedule_next_adv(fibril_switch_type_t stype) |
131 | int fibril_switch(fibril_switch_type_t stype) |
| 125 | { |
132 | { |
| 126 | fibril_t *srcf, *dstf; |
133 | fibril_t *srcf, *dstf; |
| 127 | int retval = 0; |
134 | int retval = 0; |
| 128 | 135 | ||
| 129 | futex_down(&fibril_futex); |
136 | futex_down(&fibril_futex); |
| Line 136... | Line 143... | ||
| 136 | goto ret_0; |
143 | goto ret_0; |
| 137 | /* |
144 | /* |
| 138 | * Do not preempt if there is not sufficient count of fibril |
145 | * Do not preempt if there is not sufficient count of fibril |
| 139 | * managers. |
146 | * managers. |
| 140 | */ |
147 | */ |
| 141 | if (list_empty(&serialized_list) && fibrils_in_manager <= |
148 | if (list_empty(&serialized_list) && |
| 142 | serialized_fibrils) { |
149 | fibrils_in_manager <= serialized_fibrils) { |
| 143 | goto ret_0; |
150 | goto ret_0; |
| 144 | } |
151 | } |
| 145 | } |
152 | } |
| 146 | /* If we are going to manager and none exists, create it */ |
153 | /* If we are going to manager and none exists, create it */ |
| 147 | if (stype == FIBRIL_TO_MANAGER || stype == FIBRIL_FROM_DEAD) { |
154 | if (stype == FIBRIL_TO_MANAGER || stype == FIBRIL_FROM_DEAD) { |
| Line 161... | Line 168... | ||
| 161 | if (srcf->clean_after_me) { |
168 | if (srcf->clean_after_me) { |
| 162 | /* |
169 | /* |
| 163 | * Cleanup after the dead fibril from which we |
170 | * Cleanup after the dead fibril from which we |
| 164 | * restored context here. |
171 | * restored context here. |
| 165 | */ |
172 | */ |
| 166 | free(srcf->clean_after_me->stack); |
173 | void *stack = srcf->clean_after_me->stack; |
| - | 174 | if (stack) { |
|
| - | 175 | /* |
|
| - | 176 | * This check is necessary because a |
|
| - | 177 | * thread could have exited like a |
|
| - | 178 | * normal fibril using the |
|
| - | 179 | * FIBRIL_FROM_DEAD switch type. In that |
|
| - | 180 | * case, its fibril will not have the |
|
| - | 181 | * stack member filled. |
|
| - | 182 | */ |
|
| - | 183 | free(stack); |
|
| - | 184 | } |
|
| 167 | fibril_teardown(srcf->clean_after_me); |
185 | fibril_teardown(srcf->clean_after_me); |
| 168 | srcf->clean_after_me = NULL; |
186 | srcf->clean_after_me = NULL; |
| 169 | } |
187 | } |
| 170 | return 1; /* futex_up already done here */ |
188 | return 1; /* futex_up already done here */ |
| 171 | } |
189 | } |
| Line 182... | Line 200... | ||
| 182 | * any list, we should already be somewhere, or we will |
200 | * any list, we should already be somewhere, or we will |
| 183 | * be lost. |
201 | * be lost. |
| 184 | */ |
202 | */ |
| 185 | } |
203 | } |
| 186 | } |
204 | } |
| 187 | 205 | ||
| 188 | /* Choose a new fibril to run */ |
206 | /* Choose a new fibril to run */ |
| 189 | if (stype == FIBRIL_TO_MANAGER || stype == FIBRIL_FROM_DEAD) { |
207 | if (stype == FIBRIL_TO_MANAGER || stype == FIBRIL_FROM_DEAD) { |
| 190 | dstf = list_get_instance(manager_list.next, fibril_t, link); |
208 | dstf = list_get_instance(manager_list.next, fibril_t, link); |
| 191 | if (serialization_count && stype == FIBRIL_TO_MANAGER) { |
209 | if (serialization_count && stype == FIBRIL_TO_MANAGER) { |
| 192 | serialized_fibrils++; |
210 | serialized_fibrils++; |
| 193 | srcf->flags |= FIBRIL_SERIALIZED; |
211 | srcf->flags |= FIBRIL_SERIALIZED; |
| 194 | } |
212 | } |
| 195 | fibrils_in_manager++; |
213 | fibrils_in_manager++; |
| 196 | 214 | ||
| 197 | if (stype == FIBRIL_FROM_DEAD) |
215 | if (stype == FIBRIL_FROM_DEAD) |
| 198 | dstf->clean_after_me = srcf; |
216 | dstf->clean_after_me = srcf; |
| 199 | } else { |
217 | } else { |
| 200 | if (!list_empty(&serialized_list)) { |
218 | if (!list_empty(&serialized_list)) { |
| 201 | dstf = list_get_instance(serialized_list.next, fibril_t, |
219 | dstf = list_get_instance(serialized_list.next, fibril_t, |
| 202 | link); |
220 | link); |
| Line 231... | Line 249... | ||
| 231 | f = fibril_setup(); |
249 | f = fibril_setup(); |
| 232 | if (!f) |
250 | if (!f) |
| 233 | return 0; |
251 | return 0; |
| 234 | f->stack = (char *) malloc(FIBRIL_INITIAL_STACK_PAGES_NO * |
252 | f->stack = (char *) malloc(FIBRIL_INITIAL_STACK_PAGES_NO * |
| 235 | getpagesize()); |
253 | getpagesize()); |
| 236 | - | ||
| 237 | if (!f->stack) { |
254 | if (!f->stack) { |
| 238 | fibril_teardown(f); |
255 | fibril_teardown(f); |
| 239 | return 0; |
256 | return 0; |
| 240 | } |
257 | } |
| 241 | 258 | ||
| 242 | f->arg = arg; |
- | |
| 243 | f->func = func; |
259 | f->func = func; |
| 244 | f->clean_after_me = NULL; |
- | |
| 245 | f->retval = 0; |
- | |
| 246 | f->flags = 0; |
260 | f->arg = arg; |
| 247 | 261 | ||
| 248 | context_save(&f->ctx); |
262 | context_save(&f->ctx); |
| 249 | context_set(&f->ctx, FADDR(fibril_main), f->stack, |
263 | context_set(&f->ctx, FADDR(fibril_main), f->stack, |
| 250 | FIBRIL_INITIAL_STACK_PAGES_NO * getpagesize(), f->tcb); |
264 | FIBRIL_INITIAL_STACK_PAGES_NO * getpagesize(), f->tcb); |
| 251 | 265 | ||