Index: include/bu.h
===================================================================
--- include/bu.h	(revision 54086)
+++ include/bu.h	(working copy)
@@ -403,6 +403,18 @@
 
 
 /*----------------------------------------------------------------------*/
+
+/** @file affinity.c
+ *
+ * Contains utility to set affinity mask of a thread to the CPU set it
+ * is currently running on.
+ *
+ */
+
+BU_EXPORT extern int bu_set_affinity(void);
+
+/*----------------------------------------------------------------------*/
+
 /** @addtogroup conv */
 /** @ingroup data */
 /** @{*/
Index: src/libbu/affinity.c
===================================================================
--- src/libbu/affinity.c	(revision 0)
+++ src/libbu/affinity.c	(revision 0)
@@ -0,0 +1,104 @@
+/*                         A F F I N I T Y . C
+ * BRL-CAD
+ *
+ * Copyright (c) 2012 Akshay Kashyap
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; see the file named COPYING for more
+ * information.
+ */
+
+/** @file affinity.c
+ *
+ * Contains utility to set affinity mask of a thread to the CPU set it
+ * is currently running on.
+ *
+ */
+
+#ifdef _GNU_SOURCE
+#  define _GNU_SOURCE
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef HAVE_PTHREAD_H
+#  include <pthread.h>
+#endif
+
+/*
+ * bu_set_affinity
+ * 
+ * Set affinity mask of current thread to the CPU set it is currently 
+ * running on. If it is not running on any CPUs in the set, it is
+ * migrated to CPU 0 by default.
+ * 
+ * Return: 0 on Suceess
+ *         -1 on Failure
+ * 
+ */
+int
+bu_set_affinity(void)
+{
+#if defined(_GNU_SOURCE) && defined(HAVE_PTHREAD_H)
+	
+    int cpulim = bu_avail_cpus();    /* Max number of CPUs available for the process */
+    int status;                      /* Status of thread setting/getting */
+    int cpu = 0;                     /* Default CPU number */
+    int j;                           /* Variable for iteration. */
+
+    cpu_set_t cpuset;                          /* CPU set structure. Defined in sched.h */
+    pthread_t curr_thread = pthread_self();	   /* Get current thread */
+
+    CPU_ZERO(&cpuset);
+
+    for(j = 0; j < cpulim; j++) {    /* Set affinity mask to include CPUs 0 to max available CPU */
+	CPU_SET(j, &cpuset);
+    }
+    
+    status = pthread_getaffinity_np(curr_thread, sizeof(cpu_set_t), &cpuset);    /* Check current affinity mask assigned to thread */
+
+    if(status != 0) {    /* Error in getting affinity mask */
+	return -1;
+    }
+	
+    for(j = 0; j < CPU_SETSIZE; j++) {    /* Check which set has been returned by pthread_get_affinity */
+	if(CPU_ISSET(j, &cpuset)) {
+	cpu = j;
+	break;	/* Break loop since CPU affinity mask has been found */
+	}
+    }
+
+    CPU_ZERO(&cpuset);
+    CPU_SET(cpu, &cpuset);        /* Clear CPU set and assign CPUs */
+
+    status = pthread_setaffinity_np(curr_thread, sizeof(cpu_set_t), &cpuset);        /* Set affinity mask of the current */
+                                                                                     /* thread to CPU set pointed by cpuset */
+ 
+    if(status != 0) {    /* Error in setting affinity mask */
+	return -1;
+    }
+
+#endif
+
+	return 0;
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * c-file-style: "stroustrup"
+ * End:
+ * ex: shiftwidth=4 tabstop=8
+ */

Property changes on: src/libbu/affinity.c
___________________________________________________________________
Added: svn:executable
   + *

Index: src/libbu/CMakeLists.txt
===================================================================
--- src/libbu/CMakeLists.txt	(revision 54086)
+++ src/libbu/CMakeLists.txt	(working copy)
@@ -11,6 +11,7 @@
 BRLCAD_LIB_INCLUDE_DIRS(bu BU_INCLUDE_DIRS BU_LOCAL_INCLUDE_DIRS)
 
 set(LIBBU_SOURCES
+  affinity.c
   argv.c
   avs.c
   backtrace.c
Index: src/libbu/parallel.c
===================================================================
--- src/libbu/parallel.c	(revision 54086)
+++ src/libbu/parallel.c	(working copy)
@@ -164,7 +164,13 @@
 } bu_taskcontrol[MAX_PSW];
 #endif
 
+struct thread_data {
+    void (*user_func)(int, genptr_t);
+    genptr_t user_arg;
+    int cpu_id;
+};
 
+
 void
 bu_nice_set(int newnice)
 {
@@ -585,13 +591,17 @@
 HIDDEN void
 parallel_interface(void)
 {
-    register int cpu;		/* our CPU (thread) number */
+    bu_set_affinity();
+    struct thread_data user_thread_data_pi;
 
+    user_thread_data_pi.user_func = parallel_func;
+    user_thread_data_pi.user_arg  = parallel_arg; 
+
     bu_semaphore_acquire(BU_SEM_SYSCALL);
-    cpu = parallel_nthreads_started++;
+    user_thread_data_pi.cpu_id = parallel_nthreads_started++;
     bu_semaphore_release(BU_SEM_SYSCALL);
 
-    (*parallel_func)(cpu, parallel_arg);
+    parallel_interface_arg(&user_thread_data_pi);
 
     bu_semaphore_acquire(BU_SEM_SYSCALL);
     parallel_nthreads_finished++;
@@ -607,6 +617,13 @@
     if (cpu) _exit(0);
 #  endif /* SGI */
 }
+
+HIDDEN void
+parallel_interface_arg(struct thread_data *user_thread_data)
+{
+    bu_set_affinity();
+    (*((*user_thread_data).user_func))((*user_thread_data).cpu_id, (*user_thread_data).user_arg);
+}
 #endif /* PARALLEL */
 
 #ifdef SGI_4D
@@ -691,6 +708,16 @@
     parallel_func = func;
     parallel_arg = arg;
 
+    struct thread_data *user_thread_data_bu;
+    user_thread_data_bu = (struct thread_data *)bu_calloc(ncpu, sizeof(*user_thread_data_bu), "struct thread_data *user_thread_data_bu");
+
+    /* Fill in the data of user_thread_data_bu structures of all threads */
+    for(x = 0; x < ncpu; x++) {
+	(user_thread_data_bu + x)->user_func = func;
+	(user_thread_data_bu + x)->user_arg  = arg;
+	(user_thread_data_bu + x)->cpu_id    = x;
+    }
+
     /* if we're in debug mode, allow additional cpus */
     if (!(bu_debug & BU_DEBUG_PARALLEL)) {
 	avail_cpus = bu_avail_cpus();
@@ -928,11 +955,11 @@
     /* Create the threads */
     for (x = 0; x < ncpu; x++) {
 
-	if (thr_create(0, 0, (void *(*)(void *))parallel_interface, 0, 0, &thread)) {
+	if (thr_create(0, 0, (void *(*)(void *))parallel_interface_arg, (user_thread_data_bu + x), 0, &thread)) {
 	    fprintf(stderr, "ERROR: bu_parallel: thr_create(0x0, 0x0, 0x%x, 0x0, 0, 0x%x) failed on processor %d\n",
-		    parallel_interface, &thread, x);
+		    parallel_interface_arg, &thread, x);
 	    bu_log("ERROR: bu_parallel: thr_create(0x0, 0x0, 0x%x, 0x0, 0, 0x%x) failed on processor %d\n",
-		   parallel_interface, &thread, x);
+		   parallel_interface_arg, &thread, x);
 	    /* Not much to do, lump it */
 	} else {
 	    if (UNLIKELY(bu_debug & BU_DEBUG_PARALLEL))
@@ -1003,17 +1030,17 @@
 	pthread_attr_init(&attrs);
 	pthread_attr_setstacksize(&attrs, 10*1024*1024);
 
-	if (pthread_create(&thread, &attrs, (void *(*)(void *))parallel_interface, NULL)) {
-	    fprintf(stderr, "ERROR: bu_parallel: thr_create(0x0, 0x0, 0x%lx, 0x0, 0, 0x%lx) failed on processor %d\n",
-		    (unsigned long int)parallel_interface, (unsigned long int)&thread, x);
-	    bu_log("ERROR: bu_parallel: thr_create(0x0, 0x0, 0x%lx, 0x0, 0, %p) failed on processor %d\n",
-		   (unsigned long int)parallel_interface, (void *)&thread, x);
+	if (pthread_create(&thread, &attrs, (void *(*)(void *))parallel_interface_arg, (user_thread_data_bu + x))) {
+	    fprintf(stderr, "ERROR: bu_parallel: pthread_create(0x0, 0x0, 0x%lx, 0x0, 0, 0x%lx) failed on processor %d\n",
+		    (unsigned long int)parallel_interface_arg, (unsigned long int)&thread, x);
+	    bu_log("ERROR: bu_parallel: pthread_create(0x0, 0x0, 0x%lx, 0x0, 0, %p) failed on processor %d\n",
+		   (unsigned long int)parallel_interface_arg, (void *)&thread, x);
 	    /* Not much to do, lump it */
 	} else {
 	    if (UNLIKELY(bu_debug & BU_DEBUG_PARALLEL)) {
 		bu_log("bu_parallel(): created thread: (thread: %p) (loop:%d) (nthreadc:%d)\n",
 		       (void*)thread, x, nthreadc);
-	    }
+		}
 
 	    thread_tbl[nthreadc] = thread;
 	    nthreadc++;
@@ -1078,13 +1105,15 @@
     /* Create the Win32 threads */
 
     for( int i = 0; i < ncpu; i++){
+		
 	hThreadArray[i] = CreateThread(
 	    NULL,
 	    0,
 	    (LPVOID)parallel_interface,
-	    NULL,
+	    (user_thread_data_bu + x),
 	    0,
 	    &dwThreadIdArray[i]);
+
 	if (hThreadArray[i] == NULL) {
 	    bu_log("bu_parallel(): Error in CreateThread");
 	    bu_exit();
@@ -1136,6 +1165,8 @@
 #  endif
     bu_pid_of_initiating_thread = 0;	/* No threads any more */
 
+    bu_free(user_thread_data_bu, "struct thread_data *user_thread_data_bu");
+
 #endif /* PARALLEL */
 
     return;
