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 |