Changeset e0a4686 in mainline for uspace/lib/c/generic/fibril.c
- Timestamp:
- 2018-03-08T18:25:31Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 53ad43c, 615e83d
- Parents:
- fd57cf17
- git-author:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-03-06 22:03:11)
- git-committer:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-03-08 18:25:31)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/fibril.c
rfd57cf17 re0a4686 44 44 #include <stdio.h> 45 45 #include <libarch/barrier.h> 46 #include < libarch/faddr.h>46 #include <context.h> 47 47 #include <futex.h> 48 48 #include <assert.h> … … 155 155 futex_lock(&fibril_futex); 156 156 157 fibril_t *srcf = __tcb_get()->fibril_data; 158 fibril_t *dstf = NULL; 159 160 /* Choose a new fibril to run */ 157 161 switch (stype) { 162 case FIBRIL_TO_MANAGER: 163 case FIBRIL_FROM_DEAD: 164 /* Make sure the async_futex is held. */ 165 assert((atomic_signed_t) async_futex.val.count <= 0); 166 167 /* If we are going to manager and none exists, create it */ 168 while (list_empty(&manager_list)) { 169 futex_unlock(&fibril_futex); 170 async_create_manager(); 171 futex_lock(&fibril_futex); 172 } 173 174 dstf = list_get_instance(list_first(&manager_list), 175 fibril_t, link); 176 177 if (stype == FIBRIL_FROM_DEAD) 178 dstf->clean_after_me = srcf; 179 break; 158 180 case FIBRIL_PREEMPT: 159 181 case FIBRIL_FROM_MANAGER: … … 162 184 return 0; 163 185 } 164 break; 165 case FIBRIL_TO_MANAGER: 166 case FIBRIL_FROM_DEAD: 167 /* Make sure the async_futex is held. */ 168 assert((atomic_signed_t) async_futex.val.count <= 0); 169 170 /* If we are going to manager and none exists, create it */ 171 while (list_empty(&manager_list)) { 172 futex_unlock(&fibril_futex); 173 async_create_manager(); 174 futex_lock(&fibril_futex); 175 } 176 break; 177 } 178 179 fibril_t *srcf = __tcb_get()->fibril_data; 180 if (stype != FIBRIL_FROM_DEAD) { 181 182 /* Save current state */ 183 if (!context_save(&srcf->ctx)) { 184 if (srcf->clean_after_me) { 185 /* 186 * Cleanup after the dead fibril from which we 187 * restored context here. 188 */ 189 void *stack = srcf->clean_after_me->stack; 190 if (stack) { 191 /* 192 * This check is necessary because a 193 * thread could have exited like a 194 * normal fibril using the 195 * FIBRIL_FROM_DEAD switch type. In that 196 * case, its fibril will not have the 197 * stack member filled. 198 */ 199 as_area_destroy(stack); 200 } 201 fibril_teardown(srcf->clean_after_me, true); 202 srcf->clean_after_me = NULL; 203 } 204 205 return 1; /* futex_unlock already done here */ 206 } 207 208 /* Put the current fibril into the correct run list */ 209 switch (stype) { 210 case FIBRIL_PREEMPT: 211 list_append(&srcf->link, &ready_list); 212 break; 213 case FIBRIL_FROM_MANAGER: 214 list_append(&srcf->link, &manager_list); 215 break; 216 default: 217 assert(stype == FIBRIL_TO_MANAGER); 218 219 srcf->switches++; 220 221 /* 222 * Don't put the current fibril into any list, it should 223 * already be somewhere, or it will be lost. 224 */ 225 break; 226 } 227 } 228 229 fibril_t *dstf; 230 231 /* Choose a new fibril to run */ 232 switch (stype) { 233 case FIBRIL_TO_MANAGER: 234 case FIBRIL_FROM_DEAD: 235 dstf = list_get_instance(list_first(&manager_list), fibril_t, 236 link); 237 238 if (stype == FIBRIL_FROM_DEAD) 239 dstf->clean_after_me = srcf; 240 break; 241 default: 186 242 187 dstf = list_get_instance(list_first(&ready_list), fibril_t, 243 188 link); 244 189 break; 245 190 } 246 247 191 list_remove(&dstf->link); 192 193 /* Put the current fibril into the correct run list */ 194 switch (stype) { 195 case FIBRIL_PREEMPT: 196 list_append(&srcf->link, &ready_list); 197 break; 198 case FIBRIL_FROM_MANAGER: 199 list_append(&srcf->link, &manager_list); 200 break; 201 case FIBRIL_FROM_DEAD: 202 // Nothing. 203 break; 204 case FIBRIL_TO_MANAGER: 205 srcf->switches++; 206 /* 207 * Don't put the current fibril into any list, it should 208 * already be somewhere, or it will be lost. 209 */ 210 break; 211 } 248 212 249 213 futex_unlock(&fibril_futex); … … 255 219 #endif 256 220 257 context_restore(&dstf->ctx); 258 /* not reached */ 221 /* Swap to the next fibril. */ 222 context_swap(&srcf->ctx, &dstf->ctx); 223 224 /* Restored by another fibril! */ 225 226 if (srcf->clean_after_me) { 227 /* 228 * Cleanup after the dead fibril from which we 229 * restored context here. 230 */ 231 void *stack = srcf->clean_after_me->stack; 232 if (stack) { 233 /* 234 * This check is necessary because a 235 * thread could have exited like a 236 * normal fibril using the 237 * FIBRIL_FROM_DEAD switch type. In that 238 * case, its fibril will not have the 239 * stack member filled. 240 */ 241 as_area_destroy(stack); 242 } 243 fibril_teardown(srcf->clean_after_me, true); 244 srcf->clean_after_me = NULL; 245 } 246 247 return 1; 259 248 } 260 249 … … 289 278 fibril->arg = arg; 290 279 291 context_save(&fibril->ctx); 292 context_set(&fibril->ctx, FADDR(fibril_main), fibril->stack, 293 stack_size, fibril->tcb); 294 280 context_create_t sctx = { 281 .fn = fibril_main, 282 .stack_base = fibril->stack, 283 .stack_size = stack_size, 284 .tls = fibril->tcb, 285 }; 286 287 context_create(&fibril->ctx, &sctx); 295 288 return (fid_t) fibril; 296 289 }
Note:
See TracChangeset
for help on using the changeset viewer.