Index: tests/concurrent/examples/multiSort.cfa
===================================================================
--- tests/concurrent/examples/multiSort.cfa	(revision 373aad760273872fddca861a394d29df7f2c0882)
+++ tests/concurrent/examples/multiSort.cfa	(revision 373aad760273872fddca861a394d29df7f2c0882)
@@ -0,0 +1,121 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2022 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// multiSort.c -- compute sort single array multiple times
+//			make sure sorting works, thread don't screw up
+//			and trampolines work on thread stacks
+//
+// Author           : Peter A. Buhr
+// Created On       : Tue 05 24 11:34:23 2022
+// Last Modified By :
+// Last Modified On :
+// Update Count     :
+//
+
+#include <barrier.hfa>
+#include <fstream.hfa>
+#include <math.trait.hfa>
+#include <stdlib.hfa>
+#include <thread.hfa>
+
+forall(T) {
+	struct MyVec2 {
+		T val1;
+		T val2;
+	};
+
+	forall(| Equality( T ))
+	int ?!=?( MyVec2(T) lhs, MyVec2(T) rhs ) { return lhs.val1 != rhs.val1 || lhs.val2 != rhs.val2; }
+
+	forall(| Relational(T)) {
+		static inline int ?<?( MyVec2(T) lhs, MyVec2(T) rhs ) {
+			if(lhs.val1 < rhs.val1) return true;
+			if(lhs.val1 > rhs.val1) return false;
+			if(lhs.val2 < rhs.val2) return true;
+			if(lhs.val2 > rhs.val2) return false;
+			return false;
+		}
+	}
+
+	forall(| { T random( void ); })
+	MyVec2(T) random( void ) {
+		MyVec2(T) r;
+		r.val1 = random();
+		r.val2 = random();
+		return r;
+	}
+}
+
+
+
+const unsigned nthreads = 7;
+const unsigned nvecs = 313;
+barrier bar = { nthreads + 1 };
+const MyVec2(long int) * original;
+
+thread Sorter {
+	MyVec2(long int) * copy;
+};
+
+void ^?{}( Sorter & mutex this ) {
+	free(this.copy);
+}
+
+// Make this a polymorphic call to prevent thunks from being hosted
+forall( T | Relational(T) | sized(MyVec2(T)) )
+void block_sort( MyVec2(T) * vals, size_t dim ) __attribute__((noinline)) {
+	MyVec2(T) dummy = vals[0];
+	block( bar );
+
+	qsort(vals, dim);
+}
+
+
+void main( Sorter & this ) {
+	this.copy = aalloc(nvecs);
+	for(i; nvecs) {
+		this.copy[i] = original[i];
+	}
+
+	block_sort(this.copy, nvecs);
+}
+
+int main() {
+	sout | "Generating";
+	MyVec2(long int) * local = aalloc( nvecs );
+	for(i; nvecs) {
+		local[i] = random();
+	}
+
+	original = local;
+
+	sout | "Launching";
+
+	processor p; {
+		Sorter sorters[nthreads];
+
+		block( bar );
+
+		sout | "Sorting";
+
+		qsort(local, nvecs);
+
+		sout | "Checking";
+
+		for(i; nthreads) {
+			const MyVec2(long int) * copy = join( sorters[i] ).copy;
+			for(j; nvecs) {
+				if(copy[j] != original[j]) {
+					sout | "Error at thread" | i | ", index" | j | ": data doesn't match!";
+				}
+			}
+		}
+	}
+
+	free(local);
+
+	sout | "Done";
+}
