Changeset 2654afb in mainline
- Timestamp:
- 2015-06-16T22:17:31Z (10 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 47726b5e, cf3aee19, e96047c
- Parents:
- c721d26
- Location:
- uspace/lib/c
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/fibril.c
rc721d26 r2654afb 57 57 /** 58 58 * This futex serializes access to ready_list, 59 * serialized_list,manager_list and fibril_list.59 * manager_list and fibril_list. 60 60 */ 61 61 static futex_t fibril_futex = FUTEX_INITIALIZER; 62 62 63 63 static LIST_INITIALIZE(ready_list); 64 static LIST_INITIALIZE(serialized_list);65 64 static LIST_INITIALIZE(manager_list); 66 65 static LIST_INITIALIZE(fibril_list); 67 68 /** Number of threads that are executing a manager fibril. */69 static int threads_in_manager;70 71 /**72 * Number of threads that are executing a manager fibril73 * and are serialized. Protected by async_futex.74 */75 static int serialized_threads;76 77 /** Fibril-local count of serialization. If > 0, we must not preempt */78 static fibril_local int serialization_count;79 66 80 67 /** Function that spans the whole life-cycle of a fibril. … … 161 148 int fibril_switch(fibril_switch_type_t stype) 162 149 { 163 int retval = 0; 164 165 futex_lock(&fibril_futex); 166 167 if (stype == FIBRIL_PREEMPT && list_empty(&ready_list)) 168 goto ret_0; 169 170 if (stype == FIBRIL_FROM_MANAGER) { 171 if ((list_empty(&ready_list)) && (list_empty(&serialized_list))) 172 goto ret_0; 173 174 /* 175 * Do not preempt if there is not enough threads to run the 176 * ready fibrils which are not serialized. 177 */ 178 if ((list_empty(&serialized_list)) && 179 (threads_in_manager <= serialized_threads)) { 180 goto ret_0; 150 futex_lock(&fibril_futex); 151 152 switch (stype) { 153 case FIBRIL_PREEMPT: 154 case FIBRIL_FROM_MANAGER: 155 if (list_empty(&ready_list)) { 156 futex_unlock(&fibril_futex); 157 return 0; 181 158 } 182 } 183 184 /* If we are going to manager and none exists, create it */ 185 if ((stype == FIBRIL_TO_MANAGER) || (stype == FIBRIL_FROM_DEAD)) { 159 break; 160 case FIBRIL_TO_MANAGER: 161 case FIBRIL_FROM_DEAD: 186 162 /* Make sure the async_futex is held. */ 187 163 assert((atomic_signed_t) async_futex.val.count <= 0); 188 164 165 /* If we are going to manager and none exists, create it */ 189 166 while (list_empty(&manager_list)) { 190 167 futex_unlock(&fibril_futex); … … 192 169 futex_lock(&fibril_futex); 193 170 } 171 break; 194 172 } 195 173 … … 199 177 /* Save current state */ 200 178 if (!context_save(&srcf->ctx)) { 201 if (serialization_count)202 srcf->flags &= ~FIBRIL_SERIALIZED;203 204 179 if (srcf->clean_after_me) { 205 180 /* … … 226 201 } 227 202 228 /* Save myself to the correct run list */ 229 if (stype == FIBRIL_PREEMPT) 203 /* Put the current fibril into the correct run list */ 204 switch (stype) { 205 case FIBRIL_PREEMPT: 230 206 list_append(&srcf->link, &ready_list); 231 else if (stype == FIBRIL_FROM_MANAGER) { 207 break; 208 case FIBRIL_FROM_MANAGER: 232 209 list_append(&srcf->link, &manager_list); 233 threads_in_manager--; 234 } else { 210 break; 211 default: 212 assert(stype == FIBRIL_TO_MANAGER); 213 235 214 /* 236 * If stype == FIBRIL_TO_MANAGER, don't put ourselves to 237 * any list, we should already be somewhere, or we will 238 * be lost. 215 * Don't put the current fibril into any list, it should 216 * already be somewhere, or it will be lost. 239 217 */ 218 break; 240 219 } 241 220 } 242 221 222 fibril_t *dstf; 223 243 224 /* Choose a new fibril to run */ 244 fibril_t *dstf; 245 if ((stype == FIBRIL_TO_MANAGER) || (stype == FIBRIL_FROM_DEAD)) { 225 switch (stype) { 226 case FIBRIL_TO_MANAGER: 227 case FIBRIL_FROM_DEAD: 246 228 dstf = list_get_instance(list_first(&manager_list), fibril_t, 247 229 link); 248 if (serialization_count && stype == FIBRIL_TO_MANAGER) {249 serialized_threads++;250 srcf->flags |= FIBRIL_SERIALIZED;251 }252 threads_in_manager++;253 230 254 231 if (stype == FIBRIL_FROM_DEAD) 255 232 dstf->clean_after_me = srcf; 256 } else { 257 if (!list_empty(&serialized_list)) { 258 dstf = list_get_instance(list_first(&serialized_list), 259 fibril_t, link); 260 serialized_threads--; 261 } else { 262 dstf = list_get_instance(list_first(&ready_list), 263 fibril_t, link); 264 } 265 } 233 break; 234 default: 235 dstf = list_get_instance(list_first(&ready_list), fibril_t, 236 link); 237 break; 238 } 239 266 240 list_remove(&dstf->link); 267 241 … … 276 250 context_restore(&dstf->ctx); 277 251 /* not reached */ 278 279 ret_0:280 futex_unlock(&fibril_futex);281 return retval;282 252 } 283 253 … … 346 316 347 317 futex_lock(&fibril_futex); 348 349 if ((fibril->flags & FIBRIL_SERIALIZED)) 350 list_append(&fibril->link, &serialized_list); 351 else 352 list_append(&fibril->link, &ready_list); 353 318 list_append(&fibril->link, &ready_list); 354 319 futex_unlock(&fibril_futex); 355 320 } … … 374 339 { 375 340 futex_lock(&fibril_futex); 376 377 341 if (!list_empty(&manager_list)) 378 342 list_remove(list_first(&manager_list)); 379 380 343 futex_unlock(&fibril_futex); 381 344 } … … 391 354 } 392 355 393 /** Disable preemption394 *395 * If the fibril wants to send several message in a row and does not want to be396 * preempted, it should start async_serialize_start() in the beginning of397 * communication and async_serialize_end() in the end. If it is a true398 * multithreaded application, it should protect the communication channel by a399 * futex as well.400 *401 */402 void fibril_inc_sercount(void)403 {404 serialization_count++;405 }406 407 /** Restore the preemption counter to the previous state. */408 void fibril_dec_sercount(void)409 {410 serialization_count--;411 }412 413 int fibril_get_sercount(void)414 {415 return serialization_count;416 }417 418 356 /** @} 419 357 */ -
uspace/lib/c/generic/fibril_synch.c
rc721d26 r2654afb 105 105 fibril_t *f = (fibril_t *) fibril_get_id(); 106 106 107 if (fibril_get_sercount() != 0)108 abort();109 110 107 futex_down(&async_futex); 111 108 if (fm->counter-- <= 0) { … … 197 194 fibril_t *f = (fibril_t *) fibril_get_id(); 198 195 199 if (fibril_get_sercount() != 0)200 abort();201 202 196 futex_down(&async_futex); 203 197 if (frw->writers) { … … 224 218 fibril_t *f = (fibril_t *) fibril_get_id(); 225 219 226 if (fibril_get_sercount() != 0)227 abort();228 229 220 futex_down(&async_futex); 230 221 if (frw->writers || frw->readers) { -
uspace/lib/c/include/fibril.h
rc721d26 r2654afb 47 47 } while (0) 48 48 49 #define FIBRIL_SERIALIZED 1 50 #define FIBRIL_WRITER 2 49 #define FIBRIL_WRITER 1 51 50 52 51 struct fibril;
Note:
See TracChangeset
for help on using the changeset viewer.