--- /dev/null
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <sys/time.h>
+
+#define THREADS 8
+#define ITERATIONS 100000
+
+pthread_barrier_t barr;
+
+static __inline__ unsigned long long rdtsc(void)
+{
+ unsigned hi, lo;
+ __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
+ return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
+}
+
+static __inline__ int64_t timeInMS () //time in microsec
+{
+ struct timeval t;
+
+ gettimeofday(&t, NULL);
+ return (
+ (int64_t)t.tv_sec * 1000000 +
+ (int64_t)t.tv_usec
+ );
+}
+
+void * thd (
+ void * unused
+ ) {
+ int count = 0;
+ unsigned long long tottime, time;
+ while(count<ITERATIONS) {
+ // Wait till we may fire away
+ int rc=pthread_barrier_wait(&barr);
+ if(rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf("Could not wait on barrier\n");
+ exit(-1);
+ }
+ //printf("t= %lld\n", rdtsc());
+ //time = timeInMS();
+ time = rdtsc();
+ tottime += time;
+ count++;
+ }
+ printf("time= %lld micro secs\n", tottime/ITERATIONS);
+}
+
+int main (
+ int argc,
+ char ** argv
+ ) {
+ int64_t start;
+ pthread_t t1, t2, t3, t4, t5, t6, t7, t8;
+ int64_t myTime;
+
+ // Barrier initialization
+ if(pthread_barrier_init(&barr, NULL, THREADS))
+ {
+ printf("Could not create a barrier\n");
+ return -1;
+ }
+
+ pthread_create(&t1, NULL, thd, NULL);
+ pthread_create(&t2, NULL, thd, NULL);
+ pthread_create(&t3, NULL, thd, NULL);
+ pthread_create(&t4, NULL, thd, NULL);
+ pthread_create(&t5, NULL, thd, NULL);
+ pthread_create(&t6, NULL, thd, NULL);
+ pthread_create(&t7, NULL, thd, NULL);
+ pthread_create(&t8, NULL, thd, NULL);
+
+ pthread_join(t1, NULL);
+ pthread_join(t2, NULL);
+ pthread_join(t3, NULL);
+ pthread_join(t4, NULL);
+ pthread_join(t5, NULL);
+ pthread_join(t6, NULL);
+ pthread_join(t7, NULL);
+ pthread_join(t8, NULL);
+
+ return 0;
+}
--- /dev/null
+/*******************************************************************
+ * This program has the sole purpose of showing some kernel API
+ * for CPU affinity for processes. Consider this merely a demo...
+ *
+ * adash@uci.edu
+ ********************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/sysinfo.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#define __USE_GNU
+#include <sched.h>
+#include <ctype.h>
+#include <string.h>
+
+/* Create us some pretty boolean types and definitions */
+typedef int bool;
+#define TRUE 1
+#define FALSE 0
+
+/* Method Declarations */
+void usage(); /* Simple generic usage function */
+bool do_cpu_stress(int numthreads); /* Entry point into CPU thrash */
+int do_cpu_expensive_op(int myitem); /* Single thread cpu intensive */
+bool check_cpu_expensive_op(int possible_result);/* Compare value to precomputed */
+
+
+int main(
+ int argc,
+ char **argv )
+{
+ int return_code = FALSE;
+
+ /* Determine the actual number of processors */
+ int NUM_PROCS = sysconf(_SC_NPROCESSORS_CONF);
+ printf("System has %i processor(s).\n", NUM_PROCS);
+
+ /* These need sane defaults, because the values will be used unless overriden */
+ int num_cpus_to_spin = NUM_PROCS;
+
+ /* Check for user specified parameters */
+ int option = 0;
+ while ((option = getopt(argc, argv, "m:c:l?ahd")) != -1)
+ {
+ switch (option)
+ {
+ case 'c': /* SPECIFY NUM CPUS TO MAKE BUSY */
+ num_cpus_to_spin = atoi(optarg);
+ if (num_cpus_to_spin < 1)
+ {
+ printf("WARNING: Must utilize at least 1 cpu. Spinning "
+ " all %i cpu(s) instead...\n", NUM_PROCS);
+ num_cpus_to_spin = 1;
+ }
+ else if (num_cpus_to_spin > NUM_PROCS)
+ {
+ printf("WARNING: %i cpu(s), are not "
+ "available on this system, spinning all %i cpu(s) "
+ "instead...\n", num_cpus_to_spin, NUM_PROCS);
+ num_cpus_to_spin = NUM_PROCS;
+ }
+ else
+ {
+ printf("Maxing computation on %i cpu(s)...\n",
+ num_cpus_to_spin);
+ }
+ break;
+
+
+ case '?':
+ if (isprint (optopt))
+ {
+ fprintf (stderr,
+ "Unknown option `-%c'.\n", optopt);
+ }
+ else
+ {
+ fprintf (stderr,
+ "Unknown option character `\\x%x'.\n",
+ optopt);
+ }
+ break;
+
+ default:
+ usage(argv[0]);
+ exit(0);
+ }
+ }
+
+ /* Kick off the actual work of spawning threads and computing */
+ do_cpu_stress(num_cpus_to_spin);
+ return return_code;
+}
+
+
+/* This method simply prints the usage information for this program */
+void usage()
+{
+ printf("[-c NUM_CPUS_TO_STRESS]\n");
+ printf("If no parameters are specified all cpu's will be made busy.\n");
+ return;
+}
+
+/* This method creates the threads and sets the affinity. */
+bool do_cpu_stress(int numthreads)
+{
+ int ret = TRUE;
+ int created_thread = 0;
+
+ /* We need a thread for each cpu we have... */
+ //pthread_create(&t1, NULL, thd, NULL);
+
+ while ( created_thread < numthreads - 1 )
+ {
+ int mypid = fork();
+
+ if (mypid == 0) /* Child process */
+ {
+ printf("\tCreating Child Thread: #%i\n", created_thread);
+ break;
+ }
+
+ else /* Only parent executes this */
+ {
+ /* Continue looping until we spawned enough threads! */ ;
+ created_thread++;
+ }
+ }
+
+
+
+ /* NOTE: All threads execute code from here down! */
+
+ cpu_set_t mask;
+
+ /* CPU_ZERO initializes all the bits in the mask to zero. */
+ CPU_ZERO( &mask );
+
+ printf("created_thread= %d\n", created_thread);
+ /* CPU_SET sets only the bit corresponding to cpu. */
+ CPU_SET( created_thread, &mask );
+
+ /* sched_setaffinity returns 0 in success */
+ if( sched_setaffinity( 0, sizeof(mask), &mask ) == -1 )
+ {
+ printf("WARNING: Could not set CPU Affinity, continuing...\n");
+ }
+ /* sched_setaffinity sets the CPU affinity mask of the process denoted by pid.
+ If pid is zero, then the current process is used.
+
+ The affinity mask is represented by the bitmask stored in mask. The least
+ significant bit corresponds to the first logical processor number on the
+ system, while the most significant bit corresponds to the last logical
+ processor number on the system. A set bit corresponds to a legally schedulable
+ CPU while an unset bit corresponds to an illegally schedulable CPU. In other
+ words, a process is bound to and will only run on processors whose
+ corresponding bit is set. Usually, all bits in the mask are set.
+
+ Also the affinity is passed on to any children!
+ */
+
+ /* Now we have a single thread bound to each cpu on the system */
+ int computation_res = do_cpu_expensive_op(41);
+ cpu_set_t mycpuid;
+ sched_getaffinity(0, sizeof(mycpuid), &mycpuid);
+
+
+ if ( check_cpu_expensive_op(computation_res) )
+ {
+ printf("SUCCESS: Thread completed computational task, and PASSED integrity check! %x\n",
+ mycpuid);
+ ret = TRUE;
+ }
+ else
+ {
+ printf("FAILURE: Thread failed integrity check!\n",
+ mycpuid);
+ ret = FALSE;
+ }
+
+ return ret;
+}
+
+
+/* Lame (computationally wasteful) recursive fibonaci sequence finder
+ Intentionally does not store known computed values.
+ */
+int do_cpu_expensive_op(int myitem)
+{
+ /* FIXME: Should check myitem size because this could overflow quick */
+ if (myitem == 0 || myitem == 1)
+ {
+ return myitem;
+ }
+
+ return ( do_cpu_expensive_op( myitem - 1 ) + do_cpu_expensive_op( myitem - 2 ) );
+}
+
+
+
+/* This method simply takes an integer argument
+ and compares it to a precomputed correct value.
+ */
+bool check_cpu_expensive_op(int possible_result)
+{
+ /* 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987 ... fib(41) = 165580141 */
+ int actual_result = 165580141;
+ return ( actual_result == possible_result );
+}
--- /dev/null
+/*******************************************************************
+ * This program has the sole purpose of showing some kernel API
+ * for CPU affinity used in pthreads. Consider this merely a demo...
+
+ * Uses pthread_setaffinity_np
+ * adash@uci.edu
+ ********************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/sysinfo.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#define __USE_GNU
+#include <sched.h>
+#include <ctype.h>
+#include <string.h>
+#include <pthread.h>
+
+/* Create us some pretty boolean types and definitions */
+typedef int bool;
+#define TRUE 1
+#define FALSE 0
+#define ITERATIONS 1000000
+pthread_barrier_t barr;
+
+
+/* Method Declarations */
+void usage(); /* Simple generic usage function */
+bool do_cpu_stress(int numthreads); /* Entry point into CPU thrash */
+static __inline__ unsigned long long rdtsc(void);
+void *thd(void *threadid);
+
+
+int main(
+ int argc,
+ char **argv )
+{
+ int return_code = FALSE;
+
+ /* Determine the actual number of processors */
+ int NUM_PROCS = sysconf(_SC_NPROCESSORS_CONF);
+ printf("System has %i processor(s).\n", NUM_PROCS);
+
+ /* These need sane defaults, because the values will be used unless overriden */
+ int num_cpus_to_spin = NUM_PROCS;
+
+ // Barrier initialization
+ if(pthread_barrier_init(&barr, NULL, NUM_PROCS))
+ {
+ printf("Could not create a barrier\n");
+ return -1;
+ }
+
+ /* Check for user specified parameters */
+ int option = 0;
+ while ((option = getopt(argc, argv, "m:c:l?ahd")) != -1)
+ {
+ switch (option)
+ {
+ case 'c': /* SPECIFY NUM CPUS TO MAKE BUSY */
+ num_cpus_to_spin = atoi(optarg);
+ if (num_cpus_to_spin < 1)
+ {
+ printf("WARNING: Must utilize at least 1 cpu. Spinning "
+ " all %i cpu(s) instead...\n", NUM_PROCS);
+ num_cpus_to_spin = 1;
+ }
+ else if (num_cpus_to_spin > NUM_PROCS)
+ {
+ printf("WARNING: %i cpu(s), are not "
+ "available on this system, spinning all %i cpu(s) "
+ "instead...\n", num_cpus_to_spin, NUM_PROCS);
+ num_cpus_to_spin = NUM_PROCS;
+ }
+ else
+ {
+ printf("Maxing computation on %i cpu(s)...\n",
+ num_cpus_to_spin);
+ }
+ break;
+
+
+ case '?':
+ if (isprint (optopt))
+ {
+ fprintf (stderr,
+ "Unknown option `-%c'.\n", optopt);
+ }
+ else
+ {
+ fprintf (stderr,
+ "Unknown option character `\\x%x'.\n",
+ optopt);
+ }
+ break;
+
+ default:
+ usage(argv[0]);
+ exit(0);
+ }
+ }
+
+ /* Kick off the actual work of spawning threads and computing */
+ do_cpu_stress(num_cpus_to_spin);
+ return return_code;
+}
+
+/* This method simply prints the usage information for this program */
+void usage()
+{
+ printf("[-c NUM_CPUS_TO_STRESS]\n");
+ printf("If no parameters are specified all cpu's will be made busy.\n");
+ return;
+}
+
+/* This method creates the threads and sets the affinity. */
+bool do_cpu_stress(int numthreads)
+{
+ int ret = TRUE;
+ int created_thread = 0;
+
+ pthread_t threads[numthreads];
+ int rc;
+ unsigned long t;
+ for(t=1; t<numthreads+1; t++){
+ rc = pthread_create(&threads[t-1], NULL, thd, (void *)t);
+ if (rc){
+ printf("ERROR; return code from pthread_create() is %d\n", rc);
+ exit(-1);
+ }
+ }
+
+ for(t=1; t<numthreads+1; t++){
+ pthread_join(threads[t-1], NULL);
+ }
+
+ return ret;
+}
+
+void *thd(void *threadid)
+{
+ unsigned long mask;
+ mask = (unsigned long)threadid;
+ printf("Hello World! It's me, thread #%ld!\n", mask);
+
+ /* bind process to processor threadid */
+ if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) <0) {
+ perror("pthread_setaffinity_np");
+ }
+
+ /* calculate the clock skew for each core */
+ int count = 0;
+ unsigned long long tottime, time;
+ while(count<ITERATIONS) {
+ // Wait till we may fire away
+ int rc=pthread_barrier_wait(&barr);
+ if(rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf("Could not wait on barrier\n");
+ exit(-1);
+ }
+ time = rdtsc();
+ tottime += time;
+ count++;
+ }
+ printf("time= %lld clock ticks, cpu id= %ld\n", tottime/ITERATIONS, mask);
+}
+
+static __inline__ unsigned long long rdtsc(void)
+{
+ unsigned hi, lo;
+ __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
+ return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
+}
--- /dev/null
+/*******************************************************************
+ * Example that uses sched_affinity for cpu pinning
+ *
+ * adash@uci.edu
+ ********************************************************************/
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <pthread.h>
+#include <sched.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#define ITERATIONS 100000
+pthread_barrier_t barr;
+
+static __inline__ unsigned long long rdtsc(void)
+{
+ unsigned hi, lo;
+ __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
+ return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
+}
+
+static void set_affinity(unsigned long cpu)
+{
+ int err;
+ cpu_set_t cpumask;
+
+ CPU_ZERO(&cpumask);
+ CPU_SET(cpu, &cpumask);
+ err = sched_setaffinity(syscall(SYS_gettid),
+ sizeof(cpu_set_t), &cpumask);
+
+ if (err == -1)
+ printf("set_affinity: %s\n", strerror(errno));
+}
+
+static void *_thread(void *data)
+{
+ /* thread_id, cpu id */
+ unsigned long cpu = (unsigned long) data;
+ long retval;
+
+ set_affinity(cpu);
+
+ int count = 0;
+ unsigned long long tottime, time;
+ /* calculate the clock skew for each core */
+ while(count<ITERATIONS) {
+ // Wait till we may fire away
+ int rc=pthread_barrier_wait(&barr);
+ if(rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf("Could not wait on barrier\n");
+ exit(-1);
+ }
+ time = rdtsc();
+ tottime += time;
+ count++;
+ }
+ printf("time= %lld clock ticks, cpu id= %ld\n", tottime/ITERATIONS, cpu);
+ pthread_exit(NULL);
+}
+
+int main(int argc, char *argv[])
+{
+ unsigned long nr_cpus;
+ pthread_t *readers;
+ unsigned long i;
+ int signal;
+
+ nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
+
+ // Barrier initialization
+ if(pthread_barrier_init(&barr, NULL, nr_cpus))
+ {
+ printf("Could not create a barrier\n");
+ return -1;
+ }
+
+ readers = calloc(nr_cpus, sizeof(pthread_t));
+ if (!readers)
+ printf("Out of memory!\n");
+
+ for (i = 0; i < nr_cpus; i++) {
+ int err;
+
+ err = pthread_create(&readers[i], NULL, _thread,
+ (void *) i);
+ if (err)
+ printf("Could not pthread_create(): %s!\n",
+ strerror(errno));
+ }
+
+ for (i = 0; i < nr_cpus; i++)
+ pthread_join(readers[i], NULL);
+
+ return 0;
+}