| 1 | #include <fstream.hfa>
 | 
|---|
| 2 | #include <kernel.hfa>
 | 
|---|
| 3 | #include <thread.hfa>
 | 
|---|
| 4 | 
 | 
|---|
| 5 | #include <stdatomic.h>
 | 
|---|
| 6 | #include <assert.h>
 | 
|---|
| 7 | 
 | 
|---|
| 8 | struct cluster_wrapper {
 | 
|---|
| 9 |         cluster self;
 | 
|---|
| 10 |         const uint64_t canary;
 | 
|---|
| 11 |         struct {
 | 
|---|
| 12 |                 volatile uint64_t want;
 | 
|---|
| 13 |                 volatile uint64_t have;
 | 
|---|
| 14 |         } checksum;
 | 
|---|
| 15 | };
 | 
|---|
| 16 | 
 | 
|---|
| 17 | void ?{}( cluster_wrapper & this ) {
 | 
|---|
| 18 |         (this.self){};
 | 
|---|
| 19 |         (*(uint64_t *)&this.canary) = 0xDEAD2BADDEAD2BAD;
 | 
|---|
| 20 |         this.checksum.want = 0;
 | 
|---|
| 21 |         this.checksum.have = 0;
 | 
|---|
| 22 | }
 | 
|---|
| 23 | 
 | 
|---|
| 24 | void ^?{}( cluster_wrapper & this ) {
 | 
|---|
| 25 |         assert(this.canary == 0xDEAD2BADDEAD2BAD);
 | 
|---|
| 26 | }
 | 
|---|
| 27 | 
 | 
|---|
| 28 | static cluster_wrapper * the_clusters;
 | 
|---|
| 29 | static unsigned cluster_cnt;
 | 
|---|
| 30 | 
 | 
|---|
| 31 | thread MyThread {
 | 
|---|
| 32 | 
 | 
|---|
| 33 | };
 | 
|---|
| 34 | 
 | 
|---|
| 35 | void ?{}( MyThread & this ) {}
 | 
|---|
| 36 | 
 | 
|---|
| 37 | void checkcl( MyThread & this, cluster * cl) {
 | 
|---|
| 38 |         if(((thread&)this).curr_cluster != cl) {
 | 
|---|
| 39 |                 abort | "Thread has unexpected cluster";
 | 
|---|
| 40 |         }
 | 
|---|
| 41 | }
 | 
|---|
| 42 | 
 | 
|---|
| 43 | void main( MyThread & this ) {
 | 
|---|
| 44 |         waitfor( migrate : this ) {
 | 
|---|
| 45 |                 assert( ((thread&)this).curr_cluster == active_cluster() );
 | 
|---|
| 46 |                 assert( ((thread&)this).curr_cluster == active_processor()->cltr );
 | 
|---|
| 47 |         }
 | 
|---|
| 48 | 
 | 
|---|
| 49 |         struct cluster_wrapper * curr = (struct cluster_wrapper *)&the_clusters[0];
 | 
|---|
| 50 | 
 | 
|---|
| 51 |         for(100) {
 | 
|---|
| 52 |                 unsigned idx = prng( this, cluster_cnt );
 | 
|---|
| 53 | 
 | 
|---|
| 54 |                 struct cluster_wrapper * next = &the_clusters[ idx ];
 | 
|---|
| 55 |                 assert(next->canary == 0xDEAD2BADDEAD2BAD);
 | 
|---|
| 56 | 
 | 
|---|
| 57 |                 // next->
 | 
|---|
| 58 | 
 | 
|---|
| 59 |                 migrate( this, next->self );
 | 
|---|
| 60 | 
 | 
|---|
| 61 |                 assert( active_cluster() == &next->self );
 | 
|---|
| 62 |                 assert( ((thread&)this).curr_cluster == active_cluster() );
 | 
|---|
| 63 |                 assert( ((thread&)this).curr_cluster == active_processor()->cltr );
 | 
|---|
| 64 |         }
 | 
|---|
| 65 | }
 | 
|---|
| 66 | 
 | 
|---|
| 67 | int main() {
 | 
|---|
| 68 |         cluster_cnt = 3;
 | 
|---|
| 69 |         cluster_wrapper cl[cluster_cnt];
 | 
|---|
| 70 |         the_clusters = cl;
 | 
|---|
| 71 | 
 | 
|---|
| 72 |         {
 | 
|---|
| 73 |                 set_concurrency( cl[0].self, 2 );
 | 
|---|
| 74 |                 set_concurrency( cl[1].self, 2 );
 | 
|---|
| 75 |                 set_concurrency( cl[2].self, 1 );
 | 
|---|
| 76 | 
 | 
|---|
| 77 |                 MyThread threads[17];
 | 
|---|
| 78 |                 for(i;17) {
 | 
|---|
| 79 |                         migrate( threads[i], cl[0].self );
 | 
|---|
| 80 |                 }
 | 
|---|
| 81 | 
 | 
|---|
| 82 |         }
 | 
|---|
| 83 |         // non-empty .expect file
 | 
|---|
| 84 |         printf( "done\n" );
 | 
|---|
| 85 | }
 | 
|---|