[LTP] [PATCH 7/7] pi_test: use only available CPUs

Cyril Hrubis chrubis@suse.cz
Wed Jan 27 16:35:21 CET 2016


Hi!
> +#ifndef CPU_ALLOC
> +#define CPU_ALLOC(ncpus) malloc(sizeof(cpu_set_t)); \
> +if (ncpus > CPU_SETSIZE) { \
> +	EPRINTF("UNRESOLVED: Your libc does not support masks with %ld cpus", \
> +		ncpus); \
> +	exit(UNRESOLVED); \
> +}
> +#endif
> +
> +#ifndef CPU_FREE
> +#define CPU_FREE(ptr) free(ptr)
> +#endif
> +
> +#ifndef CPU_ALLOC_SIZE
> +#define CPU_ALLOC_SIZE(size) sizeof(cpu_set_t)
> +#endif
> +
> +#ifndef CPU_ZERO_S
> +#define CPU_ZERO_S(size, mask) CPU_ZERO(mask)
> +#endif
> +
> +#ifndef CPU_SET_S
> +#define CPU_SET_S(cpu, size, mask) CPU_SET(cpu, mask)
> +#endif
> +
>  struct thread_param {
>  	int index;
>  	volatile int stop;
> @@ -52,7 +77,6 @@ struct sample_param {
>  	int priority;
>  };
>  
> -static int cpus;
>  static volatile int ts_stop;
>  static volatile double base_time;
>  
> @@ -141,21 +165,141 @@ static void do_work(unsigned granularity_top, volatile unsigned *progress)
>  	}
>  }
>  
> +static void *test_calloc(size_t nmemb, size_t size)
> +{
> +	void *r;
> +
> +	r = calloc(nmemb, size);
> +	if (r == NULL) {
> +		EPRINTF("UNRESOLVED: calloc failed");
> +		exit(UNRESOLVED);
> +	}
> +
> +	return r;
> +}
> +
> +static int first_available_cpu(int ncpus_max, size_t mask_size, cpu_set_t *mask)
> +{
> +	int i;
> +
> +	for (i = 0; i < ncpus_max; i++) {
> +		if (CPU_ISSET_S(i, mask_size, mask))
> +			return i;
> +	}
> +	return -1;
> +}
> +
> +/*
> + * Allocates a new array of 'struct thread_param' with
> + * the number of TF entries increased to 'online CPUs - 1'.
> + * All non-TF entries are bind to the first available online CPU,
> + * each TF-entry is bind to its own online CPU.
> + */
> +static void init_tparam(struct thread_param *tpbase, int len,
> +		  struct thread_param **tpnew, int *newlen)
> +{
> +	struct thread_param *tp;
> +	cpu_set_t *mask;
> +	size_t mask_size;
> +	int i, cpu, ncpus_max, ncpus_online;
> +
> +	ncpus_max = sysconf(_SC_NPROCESSORS_CONF);
> +	ncpus_online = sysconf(_SC_NPROCESSORS_ONLN);
> +
> +	if (ncpus_online < 2) {
> +		EPRINTF("UNRESOLVED: we need at least %d online CPUs, got %d",
> +			2, ncpus_online);
> +		exit(UNRESOLVED);
> +	}
> +
> +	*newlen = len - 1 + (ncpus_online - 1);
> +
> +	mask_size = CPU_ALLOC_SIZE(ncpus_max);
> +	mask = CPU_ALLOC(ncpus_max);
> +	if (mask == NULL) {
> +		EPRINTF("UNRESOLVED: failed to allocate a CPU mask");
> +		exit(UNRESOLVED);
> +	}
> +
> +	if (sched_getaffinity(0, mask_size, mask)) {
> +		EPRINTF("UNRESOLVED: sched_getaffinity: %s", strerror(errno));
> +		CPU_FREE(mask);
> +		exit(UNRESOLVED);
> +	}
> +
> +	/* This is the CPU where all non-TF threads will be running */
> +	cpu = first_available_cpu(ncpus_max, mask_size, mask);
> +	if (cpu == -1) {
> +		EPRINTF("UNRESOLVED: first_available_cpu failed");
> +		CPU_FREE(mask);
> +		exit(UNRESOLVED);
> +	}
> +	CPU_CLR_S(cpu, mask_size, mask);
> +
> +	tp = calloc(*newlen, sizeof(struct thread_param));
> +
> +	for (i = 0; i < len - 1; i++) {
> +		tp[i] = tpbase[i];
> +		tp[i].cpu = cpu;
> +	}
> +	for (i = len - 1; i < *newlen; i++) {
> +		tp[i] = tpbase[len - 1];
> +
> +		cpu = first_available_cpu(ncpus_max, mask_size, mask);
> +		if (cpu == -1) {
> +			EPRINTF("UNRESOLVED: first_available_cpu failed");
> +			CPU_FREE(mask);
> +			exit(UNRESOLVED);
> +		}
> +		tp[i].cpu = cpu;
> +		CPU_CLR_S(cpu, mask_size, mask);
> +	}
> +
> +	CPU_FREE(mask);
> +
> +	*tpnew = tp;
> +}
> +
> +static void test_set_affinity(pid_t pid, int cpu)
> +{
> +	cpu_set_t *mask;
> +	size_t mask_size;
> +	int ncpus_max, ncpus_online;
> +
> +	ncpus_max = sysconf(_SC_NPROCESSORS_CONF);
> +	ncpus_online = sysconf(_SC_NPROCESSORS_ONLN);
> +
> +	if (cpu >= ncpus_max) {
> +		EPRINTF("UNRESOLVED: invalid CPU specified: %d", cpu);
> +		exit(UNRESOLVED);
> +	}
> +
> +	mask_size = CPU_ALLOC_SIZE(ncpus_max);
> +	mask = CPU_ALLOC(ncpus_max);
> +	if (mask == NULL) {
> +		EPRINTF("UNRESOLVED: failed to allocate a CPU mask");
> +		exit(UNRESOLVED);
> +	}
> +
> +	CPU_ZERO_S(mask_size, mask);
> +	CPU_SET_S(cpu, mask_size, mask);
> +
> +	if (sched_setaffinity(pid, mask_size, mask)) {
> +		EPRINTF("UNRESOLVED: pid %d: sched_setaffinity failed: %s",
> +			pid, strerror(errno));
> +		CPU_FREE(mask);
> +		exit(UNRESOLVED);
> +	}
> +	CPU_FREE(mask);
> +}

Technically we must not use linux specific calls in the open posix
testsuite without #ifdefing them around.

And we have most of this functionality allready in
open_posix_testsuite/include/affinity.h you should really use or
modify and use functions from there since that makes it the only place
that needs to be ported to other POSIX compatible OSes.

-- 
Cyril Hrubis
chrubis@suse.cz


More information about the Ltp mailing list