@@ -474,6 +474,116 @@ shutdown(int sig)
474474 exit (EXIT_SUCCESS );
475475}
476476
477+ static void create_cpuset_str (cpuset_data_t * cpu_data )
478+ {
479+ unsigned int cpu_count = CPU_COUNT_S (cpu_data -> cpusetsize ,
480+ cpu_data -> cpuset );
481+ unsigned int i ;
482+ unsigned int idx = 0 ;
483+
484+ /*
485+ * Assume we can go up to 9999 cpus. Each cpu would take up to 4 + 2
486+ * bytes (4 for the number and 2 for the comma and space). 2 bytes
487+ * for beginning bracket + space and 2 bytes for end bracket and space
488+ * and finally null-terminator.
489+ */
490+ unsigned int size_needed = cpu_count * 6 + 2 + 2 + 1 ;
491+
492+ if (cpu_count > 9999 ) {
493+ log_error ("Too many cpus specified. Up to 9999 cpus supported" );
494+ exit (EXIT_FAILURE );
495+ }
496+
497+ cpu_data -> cpuset_str = malloc (size_needed );
498+ strcpy (cpu_data -> cpuset_str , "[ " );
499+ idx += 2 ;
500+
501+ for (i = 0 ; i < 10000 && cpu_count ; ++ i ) {
502+ unsigned int n ;
503+
504+ if (CPU_ISSET (i , cpu_data -> cpuset )) {
505+ -- cpu_count ;
506+ if (size_needed <= (idx + 1 )) {
507+ log_error ("Not enough memory for array" );
508+ exit (EXIT_FAILURE );
509+ }
510+ n = snprintf (& cpu_data -> cpuset_str [idx ],
511+ size_needed - idx - 1 , "%d" , i );
512+ if (n > 0 ) {
513+ idx += n ;
514+ } else {
515+ log_error ("Error creating array" );
516+ exit (EXIT_FAILURE );
517+ }
518+ if (size_needed <= (idx + 1 )) {
519+ log_error ("Not enough memory for array" );
520+ exit (EXIT_FAILURE );
521+ }
522+ if (cpu_count ) {
523+ strncat (cpu_data -> cpuset_str , ", " ,
524+ size_needed - idx - 1 );
525+ idx += 2 ;
526+ }
527+ }
528+ }
529+ strncat (cpu_data -> cpuset_str , " ]" , size_needed - idx - 1 );
530+ }
531+
532+ static void set_thread_affinity (thread_data_t * data , cpuset_data_t * cpu_data )
533+ {
534+ int ret ;
535+ cpuset_data_t * actual_cpu_data = & data -> cpu_data ;
536+
537+ if (data -> def_cpu_data .cpuset == NULL ) {
538+ /* Get default affinity */
539+ cpu_set_t cpuset ;
540+ unsigned int cpu_count ;
541+ unsigned int cpu = 0 ;
542+
543+ ret = pthread_getaffinity_np (pthread_self (),
544+ sizeof (cpu_set_t ), & cpuset );
545+ if (ret != 0 ) {
546+ errno = ret ;
547+ perror ("pthread_get_affinity" );
548+ exit (EXIT_FAILURE );
549+ }
550+ cpu_count = CPU_COUNT (& cpuset );
551+ data -> def_cpu_data .cpusetsize = CPU_ALLOC_SIZE (cpu_count );
552+ data -> def_cpu_data .cpuset = CPU_ALLOC (cpu_count );
553+ memcpy (data -> def_cpu_data .cpuset , & cpuset ,
554+ data -> def_cpu_data .cpusetsize );
555+ create_cpuset_str (& data -> def_cpu_data );
556+ data -> curr_cpu_data = & data -> def_cpu_data ;
557+ }
558+
559+ /*
560+ * Order of preference:
561+ * 1. Phase cpuset
562+ * 2. Task level cpuset
563+ * 3. Default cpuset
564+ */
565+ if (cpu_data -> cpuset != NULL )
566+ actual_cpu_data = cpu_data ;
567+
568+ if (actual_cpu_data -> cpuset == NULL )
569+ actual_cpu_data = & data -> def_cpu_data ;
570+
571+ if (!CPU_EQUAL (actual_cpu_data -> cpuset , data -> curr_cpu_data -> cpuset ))
572+ {
573+ log_debug ("[%d] setting cpu affinity to CPU(s) %s" , data -> ind ,
574+ actual_cpu_data -> cpuset_str );
575+ ret = pthread_setaffinity_np (pthread_self (),
576+ actual_cpu_data -> cpusetsize ,
577+ actual_cpu_data -> cpuset );
578+ if (ret != 0 ) {
579+ errno = ret ;
580+ perror ("pthread_setaffinity_np" );
581+ exit (EXIT_FAILURE );
582+ }
583+ data -> curr_cpu_data = actual_cpu_data ;
584+ }
585+ }
586+
477587void * thread_body (void * arg )
478588{
479589 thread_data_t * data = (thread_data_t * ) arg ;
@@ -501,20 +611,6 @@ void *thread_body(void *arg)
501611 /* Get the 1st phase's data */
502612 pdata = & data -> phases [0 ];
503613
504- /* Set thread affinity */
505- if (data -> cpuset != NULL )
506- {
507- log_notice ("[%d] setting cpu affinity to CPU(s) %s" , data -> ind ,
508- data -> cpuset_str );
509- ret = pthread_setaffinity_np (pthread_self (), sizeof (cpu_set_t ),
510- data -> cpuset );
511- if (ret < 0 ) {
512- errno = ret ;
513- perror ("pthread_setaffinity_np" );
514- exit (EXIT_FAILURE );
515- }
516- }
517-
518614 /* Set scheduling policy and print pretty info on stdout */
519615 log_notice ("[%d] Using %s policy with priority %d" , data -> ind , data -> sched_policy_descr , data -> sched_prio );
520616 switch (data -> sched_policy )
@@ -662,6 +758,8 @@ void *thread_body(void *arg)
662758 while (continue_running && (i != data -> loop )) {
663759 struct timespec t_diff , t_rel_start ;
664760
761+ set_thread_affinity (data , & pdata -> cpu_data );
762+
665763 if (opts .ftrace )
666764 log_ftrace (ft_data .marker_fd , "[%d] begins loop %d phase %d step %d" , data -> ind , i , j , loop );
667765 log_debug ("[%d] begins loop %d phase %d step %d" , data -> ind , i , j , loop );;
0 commit comments