3
3
#define _GNU_SOURCE
4
4
#include <err.h>
5
5
#include <errno.h>
6
+ #include <pthread.h>
6
7
#include <setjmp.h>
7
8
#include <stdio.h>
8
9
#include <string.h>
9
10
#include <stdbool.h>
10
11
#include <unistd.h>
11
12
#include <x86intrin.h>
12
13
13
- #include <linux/futex.h>
14
-
15
14
#include <sys/auxv.h>
16
15
#include <sys/mman.h>
17
16
#include <sys/shm.h>
@@ -259,7 +258,6 @@ void sig_print(char *msg)
259
258
260
259
static volatile bool noperm_signaled ;
261
260
static int noperm_errs ;
262
-
263
261
/*
264
262
* Signal handler for when AMX is used but
265
263
* permission has not been obtained.
@@ -674,6 +672,158 @@ static void test_fork(void)
674
672
_exit (0 );
675
673
}
676
674
675
+ /* Context switching test */
676
+
677
+ static struct _ctxtswtest_cfg {
678
+ unsigned int iterations ;
679
+ unsigned int num_threads ;
680
+ } ctxtswtest_config ;
681
+
682
+ struct futex_info {
683
+ pthread_t thread ;
684
+ int nr ;
685
+ pthread_mutex_t mutex ;
686
+ struct futex_info * next ;
687
+ };
688
+
689
+ static void * check_tiledata (void * info )
690
+ {
691
+ struct futex_info * finfo = (struct futex_info * )info ;
692
+ struct xsave_buffer * xbuf ;
693
+ int i ;
694
+
695
+ xbuf = alloc_xbuf ();
696
+ if (!xbuf )
697
+ fatal_error ("unable to allocate XSAVE buffer" );
698
+
699
+ /*
700
+ * Load random data into 'xbuf' and then restore
701
+ * it to the tile registers themselves.
702
+ */
703
+ load_rand_tiledata (xbuf );
704
+ for (i = 0 ; i < ctxtswtest_config .iterations ; i ++ ) {
705
+ pthread_mutex_lock (& finfo -> mutex );
706
+
707
+ /*
708
+ * Ensure the register values have not
709
+ * diverged from those recorded in 'xbuf'.
710
+ */
711
+ validate_tiledata_regs_same (xbuf );
712
+
713
+ /* Load new, random values into xbuf and registers */
714
+ load_rand_tiledata (xbuf );
715
+
716
+ /*
717
+ * The last thread's last unlock will be for
718
+ * thread 0's mutex. However, thread 0 will
719
+ * have already exited the loop and the mutex
720
+ * will already be unlocked.
721
+ *
722
+ * Because this is not an ERRORCHECK mutex,
723
+ * that inconsistency will be silently ignored.
724
+ */
725
+ pthread_mutex_unlock (& finfo -> next -> mutex );
726
+ }
727
+
728
+ free (xbuf );
729
+ /*
730
+ * Return this thread's finfo, which is
731
+ * a unique value for this thread.
732
+ */
733
+ return finfo ;
734
+ }
735
+
736
+ static int create_threads (int num , struct futex_info * finfo )
737
+ {
738
+ int i ;
739
+
740
+ for (i = 0 ; i < num ; i ++ ) {
741
+ int next_nr ;
742
+
743
+ finfo [i ].nr = i ;
744
+ /*
745
+ * Thread 'i' will wait on this mutex to
746
+ * be unlocked. Lock it immediately after
747
+ * initialization:
748
+ */
749
+ pthread_mutex_init (& finfo [i ].mutex , NULL );
750
+ pthread_mutex_lock (& finfo [i ].mutex );
751
+
752
+ next_nr = (i + 1 ) % num ;
753
+ finfo [i ].next = & finfo [next_nr ];
754
+
755
+ if (pthread_create (& finfo [i ].thread , NULL , check_tiledata , & finfo [i ]))
756
+ fatal_error ("pthread_create()" );
757
+ }
758
+ return 0 ;
759
+ }
760
+
761
+ static void affinitize_cpu0 (void )
762
+ {
763
+ cpu_set_t cpuset ;
764
+
765
+ CPU_ZERO (& cpuset );
766
+ CPU_SET (0 , & cpuset );
767
+
768
+ if (sched_setaffinity (0 , sizeof (cpuset ), & cpuset ) != 0 )
769
+ fatal_error ("sched_setaffinity to CPU 0" );
770
+ }
771
+
772
+ static void test_context_switch (void )
773
+ {
774
+ struct futex_info * finfo ;
775
+ int i ;
776
+
777
+ /* Affinitize to one CPU to force context switches */
778
+ affinitize_cpu0 ();
779
+
780
+ req_xtiledata_perm ();
781
+
782
+ printf ("[RUN]\tCheck tiledata context switches, %d iterations, %d threads.\n" ,
783
+ ctxtswtest_config .iterations ,
784
+ ctxtswtest_config .num_threads );
785
+
786
+
787
+ finfo = malloc (sizeof (* finfo ) * ctxtswtest_config .num_threads );
788
+ if (!finfo )
789
+ fatal_error ("malloc()" );
790
+
791
+ create_threads (ctxtswtest_config .num_threads , finfo );
792
+
793
+ /*
794
+ * This thread wakes up thread 0
795
+ * Thread 0 will wake up 1
796
+ * Thread 1 will wake up 2
797
+ * ...
798
+ * the last thread will wake up 0
799
+ *
800
+ * ... this will repeat for the configured
801
+ * number of iterations.
802
+ */
803
+ pthread_mutex_unlock (& finfo [0 ].mutex );
804
+
805
+ /* Wait for all the threads to finish: */
806
+ for (i = 0 ; i < ctxtswtest_config .num_threads ; i ++ ) {
807
+ void * thread_retval ;
808
+ int rc ;
809
+
810
+ rc = pthread_join (finfo [i ].thread , & thread_retval );
811
+
812
+ if (rc )
813
+ fatal_error ("pthread_join() failed for thread %d err: %d\n" ,
814
+ i , rc );
815
+
816
+ if (thread_retval != & finfo [i ])
817
+ fatal_error ("unexpected thread retval for thread %d: %p\n" ,
818
+ i , thread_retval );
819
+
820
+ }
821
+
822
+ printf ("[OK]\tNo incorrect case was found.\n" );
823
+
824
+ free (finfo );
825
+ }
826
+
677
827
int main (void )
678
828
{
679
829
/* Check hardware availability at first */
@@ -690,6 +840,10 @@ int main(void)
690
840
691
841
test_fork ();
692
842
843
+ ctxtswtest_config .iterations = 10 ;
844
+ ctxtswtest_config .num_threads = 5 ;
845
+ test_context_switch ();
846
+
693
847
clearhandler (SIGILL );
694
848
free_stashed_xsave ();
695
849
0 commit comments