trunk/src/osd/modules/sync/work_osd.c
| r242720 | r242721 | |
| 96 | 96 | #define osd_yield_processor YieldProcessor |
| 97 | 97 | #endif |
| 98 | 98 | |
| 99 | template<typename _PtrType> |
| 100 | static void spin_while(const volatile _PtrType * volatile ptr, const _PtrType val, const osd_ticks_t timeout, const int invert = 0) |
| 101 | { |
| 102 | osd_ticks_t stopspin = osd_ticks() + timeout; |
| 99 | 103 | |
| 104 | #if defined(OSD_WINDOWS) |
| 105 | while (((*ptr == val) ^ invert) && osd_ticks() < stopspin) |
| 106 | osd_yield_processor(); |
| 107 | #else |
| 108 | do { |
| 109 | int spin = 100000; |
| 110 | while (--spin && ((*ptr == val) ^ invert)) |
| 111 | osd_yield_processor(); |
| 112 | } while (((*ptr == val) ^ invert) && osd_ticks() < stopspin); |
| 113 | #endif |
| 114 | } |
| 100 | 115 | |
| 116 | template<typename _PtrType> |
| 117 | static void spin_while_not(const volatile _PtrType * volatile ptr, const _PtrType val, const osd_ticks_t timeout) |
| 118 | { |
| 119 | spin_while(ptr, val, timeout, 1); |
| 120 | } |
| 121 | |
| 122 | |
| 101 | 123 | //============================================================ |
| 102 | 124 | // TYPE DEFINITIONS |
| 103 | 125 | //============================================================ |
| r242720 | r242721 | |
| 169 | 191 | static void * worker_thread_entry(void *param); |
| 170 | 192 | static void worker_thread_process(osd_work_queue *queue, work_thread_info *thread); |
| 171 | 193 | static bool queue_has_list_items(osd_work_queue *queue); |
| 172 | | static void spin_on_queue(work_thread_info *thread, osd_work_queue *queue, osd_ticks_t timeout); |
| 173 | 194 | |
| 174 | 195 | |
| 175 | 196 | //============================================================ |
| r242720 | r242721 | |
| 312 | 333 | // if we're a high frequency queue, spin until done |
| 313 | 334 | if (queue->flags & WORK_QUEUE_FLAG_HIGH_FREQ && queue->items != 0) |
| 314 | 335 | { |
| 315 | | spin_on_queue(thread, queue, timeout); |
| 336 | // spin until we're done |
| 337 | begin_timing(thread->spintime); |
| 338 | spin_while_not(&queue->items, 0, timeout); |
| 339 | end_timing(thread->spintime); |
| 340 | |
| 316 | 341 | begin_timing(thread->waittime); |
| 317 | 342 | return (queue->items == 0); |
| 318 | 343 | } |
| r242720 | r242721 | |
| 550 | 575 | // if we don't have an event, we need to spin (shouldn't ever really happen) |
| 551 | 576 | if (item->event == NULL) |
| 552 | 577 | { |
| 553 | | // TODO: merge this with spin_on_queue() |
| 554 | 578 | // TODO: do we need to measure the spin time here as well? and how can we do it? |
| 555 | | osd_ticks_t stopspin = osd_ticks() + timeout; |
| 556 | | #if defined(OSD_WINDOWS) |
| 557 | | while (!item->done && osd_ticks() < stopspin) |
| 558 | | osd_yield_processor(); |
| 559 | | #else |
| 560 | | do { |
| 561 | | int spin = 10000; |
| 562 | | while (--spin && !item->done) |
| 563 | | osd_yield_processor(); |
| 564 | | } while (!item->done && osd_ticks() < stopspin); |
| 565 | | #endif |
| 579 | spin_while(&item->done, 0, timeout); |
| 566 | 580 | } |
| 567 | 581 | |
| 568 | 582 | // otherwise, block on the event until done |
| r242720 | r242721 | |
| 680 | 694 | // if we're a high frequency queue, spin for a while before giving up |
| 681 | 695 | if (queue->flags & WORK_QUEUE_FLAG_HIGH_FREQ && queue->list == NULL) |
| 682 | 696 | { |
| 683 | | spin_on_queue(thread, queue, SPIN_LOOP_TIME); |
| 697 | // spin for a while looking for more work |
| 698 | begin_timing(thread->spintime); |
| 699 | spin_while(&queue->list, (osd_work_item *)NULL, SPIN_LOOP_TIME); |
| 700 | end_timing(thread->spintime); |
| 684 | 701 | } |
| 685 | 702 | |
| 686 | 703 | // if nothing more, release the processor |
| r242720 | r242721 | |
| 795 | 812 | osd_scalable_lock_release(queue->lock, lockslot); |
| 796 | 813 | return has_list_items; |
| 797 | 814 | } |
| 798 | | |
| 799 | | void spin_on_queue(work_thread_info *thread, osd_work_queue *queue, osd_ticks_t timeout) |
| 800 | | { |
| 801 | | osd_ticks_t stopspin = osd_ticks() + timeout; |
| 802 | | |
| 803 | | begin_timing(thread->spintime); |
| 804 | | |
| 805 | | // TODO: chose either |
| 806 | | #if defined(OSD_WINDOWS) |
| 807 | | while (queue->list == NULL && osd_ticks() < stopspin) |
| 808 | | osd_yield_processor(); |
| 809 | | #else |
| 810 | | do { |
| 811 | | int spin = 10000; |
| 812 | | while (--spin && queue->list == NULL) |
| 813 | | osd_yield_processor(); |
| 814 | | } while (queue->list == NULL && osd_ticks() < stopspin); |
| 815 | | #endif |
| 816 | | |
| 817 | | end_timing(thread->spintime); |
| 818 | | } |
| | No newline at end of file |