inline bool lock_threadid(INT32 threadid) { INT32 prev_id; prev_id = compare_exchange32(&m_threadid, -1, threadid); return (prev_id == -1 && m_threadid == threadid); }
static void *poly_item_callback(void *param, int threadid) { while (1) { work_unit *unit = (work_unit *)param; polygon_info *polygon = unit->shared.polygon; int count = unit->shared.count_next & 0xffff; UINT32 orig_count_next; int curscan; /* if our previous item isn't done yet, enqueue this item to the end and proceed */ if (unit->shared.previtem != 0xffff) { work_unit *prevunit = polygon->poly->unit[unit->shared.previtem]; if (prevunit->shared.count_next != 0) { UINT32 unitnum = ((UINT8 *)unit - (UINT8 *)polygon->poly->unit[0]) / polygon->poly->unit_size; UINT32 new_count_next; /* attempt to atomically swap in this new value */ do { orig_count_next = prevunit->shared.count_next; new_count_next = orig_count_next | (unitnum << 16); } while (compare_exchange32((volatile INT32 *)&prevunit->shared.count_next, orig_count_next, new_count_next) != orig_count_next); #if KEEP_STATISTICS /* track resolved conflicts */ polygon->poly->conflicts[threadid]++; if (orig_count_next != 0) polygon->poly->resolved[threadid]++; #endif /* if we succeeded, skip out early so we can do other work */ if (orig_count_next != 0) break; } } /* iterate over extents */ for (curscan = 0; curscan < count; curscan++) { if (polygon->numverts == 3) { poly_extent tmpextent; convert_tri_extent_to_poly_extent(&tmpextent, &unit->tri.extent[curscan], polygon, unit->shared.scanline + curscan); (*polygon->callback)(polygon->dest, unit->shared.scanline + curscan, &tmpextent, polygon->extra, threadid); } else (*polygon->callback)(polygon->dest, unit->shared.scanline + curscan, &unit->quad.extent[curscan], polygon->extra, threadid); } /* set our count to 0 and re-fetch the original count value */ do { orig_count_next = unit->shared.count_next; } while (compare_exchange32((volatile INT32 *)&unit->shared.count_next, orig_count_next, 0) != orig_count_next); /* if we have no more work to do, do nothing */ orig_count_next >>= 16; if (orig_count_next == 0) break; param = polygon->poly->unit[orig_count_next]; } return NULL; }