1 | // sequential equivalent swap |
---|
2 | void swap( uint victim_idx, uint my_idx ) { |
---|
3 | // Step 0: |
---|
4 | work_queue * my_queue = request_queues[my_idx]; |
---|
5 | work_queue * vic_queue = request_queues[victim_idx]; |
---|
6 | // Step 2: |
---|
7 | request_queues[my_idx] = 0p; |
---|
8 | // Step 3: |
---|
9 | request_queues[victim_idx] = my_queue; |
---|
10 | // Step 4: |
---|
11 | request_queues[my_idx] = vic_queue; |
---|
12 | } |
---|
13 | |
---|
14 | // This routine is atomic |
---|
15 | bool CAS( work_queue ** ptr, work_queue ** old, work_queue * new ) { |
---|
16 | if ( *ptr != *old ) |
---|
17 | return false; |
---|
18 | *ptr = new; |
---|
19 | return true; |
---|
20 | } |
---|
21 | |
---|
22 | bool try_swap_queues( worker & this, uint victim_idx, uint my_idx ) with(this) { |
---|
23 | // Step 0: |
---|
24 | // request_queues is the shared array of all sharded queues |
---|
25 | work_queue * my_queue = request_queues[my_idx]; |
---|
26 | work_queue * vic_queue = request_queues[victim_idx]; |
---|
27 | |
---|
28 | // Step 1: |
---|
29 | // If either queue is 0p then they are in the process of being stolen |
---|
30 | // 0p is CForAll's equivalent of C++'s nullptr |
---|
31 | if ( vic_queue == 0p ) return false; |
---|
32 | |
---|
33 | // Step 2: |
---|
34 | // Try to set thief's queue ptr to be 0p. |
---|
35 | // If this CAS fails someone stole thief's queue so return false |
---|
36 | if ( !CAS( &request_queues[my_idx], &my_queue, 0p ) ) |
---|
37 | return false; |
---|
38 | |
---|
39 | // Step 3: |
---|
40 | // Try to set victim queue ptr to be thief's queue ptr. |
---|
41 | // If it fails someone stole the other queue, so fix up then return false |
---|
42 | if ( !CAS( &request_queues[victim_idx], &vic_queue, my_queue ) ) { |
---|
43 | request_queues[my_idx] = my_queue; // reset queue ptr back to prev val |
---|
44 | return false; |
---|
45 | } |
---|
46 | |
---|
47 | // Step 4: |
---|
48 | // Successfully swapped. |
---|
49 | // Thief's ptr is 0p so no one will touch it |
---|
50 | // Write back without CAS is safe |
---|
51 | request_queues[my_idx] = vic_queue; |
---|
52 | return true; |
---|
53 | } |
---|