Added affinity support check, visibility macros in thread_mpi
authorSander Pronk <pronk@kth.se>
Mon, 26 Nov 2012 17:20:03 +0000 (18:20 +0100)
committerRoland Schulz <roland@utk.edu>
Tue, 27 Nov 2012 01:09:17 +0000 (20:09 -0500)
- Fixed a bug where the return value of tMPI_Thread_setaffinity_single()
  is not 0 when there is no error under Windows.
- Added a function tMPI_Thread_setaffinity_support() that returns
  whether the platform supports setting thread affinity
- Added dynamic library visibility support macros

Change-Id: I9f74c5095bccc06b413443dd6a1ac2dd56e0d4b8

15 files changed:
include/thread_mpi/atomic.h
include/thread_mpi/barrier.h
include/thread_mpi/collective.h
include/thread_mpi/event.h
include/thread_mpi/hwinfo.h
include/thread_mpi/list.h
include/thread_mpi/lock.h
include/thread_mpi/mutex.h
include/thread_mpi/numa_malloc.h
include/thread_mpi/system_error.h
include/thread_mpi/threads.h
include/thread_mpi/tmpi.h
include/thread_mpi/visibility.h [new file with mode: 0644]
src/gmxlib/thread_mpi/pthreads.c
src/gmxlib/thread_mpi/winthreads.c

index fb665da0ea1b4a4e6815528cb9bf5413552e5634..1739be8b1a2d828cdcf31e31d33b1c2f2810b648 100644 (file)
@@ -76,6 +76,8 @@ files.
 
 #include <stdio.h>
 
+#include "visibility.h"
+
 #ifdef __cplusplus
 extern "C" 
 {  
@@ -98,7 +100,6 @@ extern "C"
 
 
 
-
 /* now check specifically for several architectures: */
 #if ((defined(i386) || defined(__x86_64__)) && ! defined(__OPEN64__))
 /* first x86: */
@@ -346,6 +347,7 @@ static inline int tMPI_Atomic_get(tMPI_Atomic_t &a);
  *
  *  \hideinitializer
  */
+TMPI_EXPORT
 static inline void tMPI_Atomic_set(tMPI_Atomic_t *a, int i)
 {
     /* Mutexes here are necessary to guarantee memory visibility */
@@ -384,6 +386,7 @@ static inline void* tMPI_Atomic_ptr_get(tMPI_Atomic_ptr_t &a);
  *
  *  \hideinitializer
  */
+TMPI_EXPORT
 static inline void tMPI_Atomic_ptr_set(tMPI_Atomic_t *a, void *p)
 {
     /* Mutexes here are necessary to guarantee memory visibility */
@@ -403,6 +406,7 @@ static inline void tMPI_Atomic_ptr_set(tMPI_Atomic_t *a, void *p)
  *
  *  \return The new value (after summation).
  */
+TMPI_EXPORT
 static inline int tMPI_Atomic_add_return(tMPI_Atomic_t *a, int i)
 {
     int t;
@@ -430,6 +434,7 @@ static inline int tMPI_Atomic_add_return(tMPI_Atomic_t *a, int i)
  *
  *  \return    The value of the atomic variable before addition.
  */
+TMPI_EXPORT
 static inline int tMPI_Atomic_fetch_add(tMPI_Atomic_t *a, int i)
 {
     int old_value;
@@ -471,6 +476,7 @@ static inline int tMPI_Atomic_fetch_add(tMPI_Atomic_t *a, int i)
  * 
  *   \note   The exchange occured if the return value is identical to \a old.
  */
+TMPI_EXPORT
 static inline int tMPI_Atomic_cas(tMPI_Atomic_t *a, int old_val, int new_val)
 {
     int t=0;
@@ -508,6 +514,7 @@ static inline int tMPI_Atomic_cas(tMPI_Atomic_t *a, int old_val, int new_val)
  * 
  *   \note   The exchange occured if the return value is identical to \a old.
  */
+TMPI_EXPORT
 static inline int tMPI_Atomic_ptr_cas(tMPI_Atomic_ptr_t * a, void *old_val,
                                       void *new_val)
 {
@@ -593,6 +600,7 @@ void tMPI_Spinlock_unlock( tMPI_Spinlock_t &x);
  *
  *  \return 1 if the spinlock is locked, 0 otherwise.
  */
+TMPI_EXPORT
 static inline int tMPI_Spinlock_islocked(const tMPI_Spinlock_t *x)
 {
     if(tMPI_Spinlock_trylock(x) != 0)
@@ -616,6 +624,7 @@ static inline int tMPI_Spinlock_islocked(const tMPI_Spinlock_t *x)
  *
  *  \param x  Spinlock pointer
  */
+TMPI_EXPORT
 static inline void tMPI_Spinlock_wait(tMPI_Spinlock_t *x)
 {
     tMPI_Spinlock_lock(x);
@@ -639,6 +648,7 @@ static inline void tMPI_Spinlock_wait(tMPI_Spinlock_t *x)
   \param b  Value to swap 
   \return the original value of a
 */
+TMPI_EXPORT
 static inline int tMPI_Atomic_swap(tMPI_Atomic_t *a, int b)
 {
     int oldval;
@@ -658,6 +668,7 @@ static inline int tMPI_Atomic_swap(tMPI_Atomic_t *a, int b)
   \param b  Value to swap 
   \return the original value of a
 */
+TMPI_EXPORT
 static inline void *tMPI_Atomic_ptr_swap(tMPI_Atomic_ptr_t *a, void *b)
 {
     void *oldval;
index 17aa1462100d2e0f61dcb5f415380948fd0c4abe..520c2444d76aca97427a417262f8715cb4da1114 100644 (file)
@@ -38,6 +38,7 @@ files.
 #ifndef TMPI_BARRIER_H_
 #define TMPI_BARRIER_H_
 
+#include "visibility.h"
 #include "wait.h"
 
 /** Fast (possibly busy-wait-based) barrier type
@@ -76,6 +77,7 @@ struct tMPI_Barrier_t
  *                  will be released after \a count calls to 
  *                  tMPI_Barrier_wait().  
  */
+TMPI_EXPORT
 void tMPI_Barrier_init(tMPI_Barrier_t *barrier, int count);
 
 
@@ -90,6 +92,7 @@ void tMPI_Barrier_init(tMPI_Barrier_t *barrier, int count);
   *
   *  \return The last thread returns -1, all the others 0.
   */
+TMPI_EXPORT
 int tMPI_Barrier_wait(tMPI_Barrier_t *barrier);
 
 
@@ -103,6 +106,7 @@ int tMPI_Barrier_wait(tMPI_Barrier_t *barrier);
   *
   *  \return the number of threads to synchronize
   */
+TMPI_EXPORT
 int tMPI_Barrier_N(tMPI_Barrier_t *barrier);
 #else
 #define tMPI_Barrier_N(barrier)  ((barrier)->threshold)
index 302db793c73d0cb37a2c7241d034d80232b1489c..d9320a16703f68a4e3719dfd649e4a559a119269 100644 (file)
@@ -44,6 +44,7 @@ files.
  * 
 */
 
+#include "visibility.h"
 
 #ifdef __cplusplus
 extern "C" 
@@ -68,6 +69,7 @@ extern "C"
     \param[in] comm         The communicator.
     \returns MPI_SUCCESS on success.
 */
+TMPI_EXPORT
 int tMPI_Once(tMPI_Comm comm,void (*function)(void*), void *param, 
               int *was_first);
 
@@ -87,6 +89,7 @@ int tMPI_Once(tMPI_Comm comm,void (*function)(void*), void *param,
     \param[in] comm         The communicator.
     \returns the return value of the function
 */
+TMPI_EXPORT
 void* tMPI_Once_wait(tMPI_Comm comm,void* (*function)(void*), void *param, 
                      int *was_first);
 
@@ -97,6 +100,7 @@ void* tMPI_Once_wait(tMPI_Comm comm,void* (*function)(void*), void *param,
     \param[in] comm         The communicator
     \param[in] size         The size in bytes to allocate 
 */
+TMPI_EXPORT
 void* tMPI_Shmalloc(tMPI_Comm comm, size_t size);
 
 
@@ -114,34 +118,8 @@ typedef struct
 } tMPI_Reduce_req;
 
 /** Allocate data structure for asynchronous reduce. */
+TMPI_EXPORT
 tMPI_Reduce_req *tMPI_Reduce_req_alloc(tMPI_Comm comm);
-#if 0
-/** Execute fast a asynchronous reduce over comm.
-
-  Reduces array input with supplied funtion. This function may return before 
-  the input array is ready to be written to again; to check for its completion,
-  use the tMPI_Reduce_wait functions.
-
-  \param[in] function   The function to reduce with (takes three arguments,
-                        a size argument, two input pointers, and an output
-                        pointer (which may be the same as one of the input
-                        arguments, if res==NULL).
-  \param[in] n          A size argument to pass to the function.
-  \param[inout] input   The array of input data.
-  \param[out] res       A temporary results array. May be NULL, in which case
-                        the input data in 'in' gets overwritten.
-*/
-void tMPI_Reduce_async(tMPI_Reduce_req *req, 
-                       void (*function)(int, void*, void*, void *), 
-                       size_t n, void *input, void *res);
-
-
-void tMPI_Reduce_wait(tMPI_Reduce_req *req);
-
-void tMPI_Reduce_wait_results(tMPI_Reduce_req *req, void *res);
-
-#endif
-
 
 #ifdef __cplusplus
 } /* closing extern "C" */
index 31ac7bca068d339ede2e89476e2170851d31e597..be8fe8b60c2bcadef0eef6e722c7552a92b3977e 100644 (file)
@@ -38,6 +38,7 @@ files.
 #ifndef TMPI_EVENT_H_
 #define TMPI_EVENT_H_
 
+#include "visibility.h"
 #include "wait.h"
 
 /*! \file
@@ -74,11 +75,13 @@ struct tMPI_Event_t
 /*! \brief Initialize the event object.
     
     \param ev The event structure to be intialized. */
+TMPI_EXPORT
 void tMPI_Event_init(tMPI_Event *ev);
 
 /*! \brief Deallocate the internals of the contents of event object.
 
     \param ev The event structure to be destroyed. */
+TMPI_EXPORT
 void tMPI_Event_destroy(tMPI_Event *ev);
 
 /*! \brief Wait for an event to occur. 
@@ -87,12 +90,14 @@ void tMPI_Event_destroy(tMPI_Event *ev);
    \param ev The event structure to wait on.
    \returns  The number of events that have occurred at function
              return time. */
+TMPI_EXPORT
 int tMPI_Event_wait(tMPI_Event *ev);
 
 #ifdef DOXYGEN
 /*! \brief Signal an event, possibly waking an tMPI_Event_wait().
 
     \param ev  The event to signal. */
+TMPI_EXPORT
 void tMPI_Event_signal(tMPI_Event *ev); 
 #else
 #define tMPI_Event_signal(ev) \
@@ -111,6 +116,7 @@ void tMPI_Event_signal(tMPI_Event *ev);
   
   \param ev  The event object.
   \param N   The number of processed events. */
+TMPI_EXPORT
 void tMPI_Event_process(tMPI_Event *ev, int N);
 #else
 #define tMPI_Event_process(ev, N) \
index 7a17bc473c5c5ecf4bb6c184599b4cfaf2f70aa3..836c0d8c5a19048a86e007ba352a2a57ff5a08e0 100644 (file)
@@ -52,6 +52,7 @@ files.
          If this number cannot be determined for the current architecture,
          -1 is returned.
   */
+TMPI_EXPORT
 int tMPI_Get_hw_nthreads(void);
 
 
@@ -64,6 +65,7 @@ int tMPI_Get_hw_nthreads(void);
 
     \returns The maximum number of threads to run on.
   */
+TMPI_EXPORT
 int tMPI_Get_recommended_nthreads(void);
 
 
index 5cad8275eada1a1b99b941ede1badd6b50e4c696..78335129c61a45a21163dab3979aff03e41bcb80 100644 (file)
@@ -74,18 +74,23 @@ typedef struct tMPI_Stack_element
 
 
 /**  Initialize a stack */
+TMPI_EXPORT
 void tMPI_Stack_init(tMPI_Stack *st);
 
 /**  Deallocates a stack */
+TMPI_EXPORT
 void tMPI_Stack_destroy(tMPI_Stack *st);
 
 /**  Pushes a stack element onto a stack */
+TMPI_EXPORT
 void tMPI_Stack_push(tMPI_Stack *st, tMPI_Stack_element *el);
 
 /**  Pops a stack element from  a stack */
+TMPI_EXPORT
 tMPI_Stack_element *tMPI_Stack_pop(tMPI_Stack *st);
 
 /**  Detaches entire stack for use by a single thread */
+TMPI_EXPORT
 tMPI_Stack_element *tMPI_Stack_detach(tMPI_Stack *st);
 
 
index 65e65aa45399fa53145e3d7e4b094e63f86efa48..850a56092d209dddb55423763109fcf115b982a0 100644 (file)
@@ -38,6 +38,7 @@ files.
 #ifndef TMPI_FASTLOCK_H_
 #define TMPI_FASTLOCK_H_
 
+#include "visibility.h"
 #include "wait.h"
 #include "atomic.h"
 
@@ -67,6 +68,7 @@ struct tMPI_Lock
  *
  *  \param lock     Pointer to the new lock. 
  */
+TMPI_EXPORT
 void tMPI_Lock_init(tMPI_Lock_t *lock);
 
 
@@ -76,24 +78,28 @@ void tMPI_Lock_init(tMPI_Lock_t *lock);
   *
   *  \param lock  Pointer to previously created lock.
   */
+TMPI_EXPORT
 void tMPI_Lock_lock(tMPI_Lock_t *lock);
 
 /** Unlock the lock
   *
   *  \param lock  Pointer to previously created lock.
   */
+TMPI_EXPORT
 void tMPI_Lock_unlock(tMPI_Lock_t *lock);
 
 /** Try to lock the lock but don't block if it is locked.
   *
   *  \param lock  Pointer to previously created lock.
   */
+TMPI_EXPORT
 int tMPI_Lock_trylock(tMPI_Lock_t *lock);
 
 /** Check the status of the lock without affecting its state
   *
   *  \param lock  Pointer to previously created lock.
   */
+TMPI_EXPORT
 int tMPI_Lock_islocked(const tMPI_Lock_t *lock);
 
 
index f657a11c2ce9999b395ec170311089083f7e6cb6..827d5c558b6ce4477937f57a72a125908b66f227 100644 (file)
@@ -46,6 +46,7 @@ files.
 #ifndef TMPI_MUTEX_H_
 #define TMPI_MUTEX_H_
 
+#include "visibility.h"
 #include "system_error.h"
 #include "threads.h"
 
@@ -70,7 +71,7 @@ namespace tMPI
             count += 1;
         }
     */
-    template <class Mutex> class lock_guard 
+    template <class Mutex> class TMPI_EXPORT lock_guard
     {
     public:
         typedef Mutex mutex_type;
@@ -97,7 +98,7 @@ namespace tMPI
     };
 
     /*! \brief A basic mutex class with C++11 compatibility.  */
-    class mutex
+    class TMPI_EXPORT mutex
     {
     public:
         typedef tMPI_Thread_mutex_t* native_handle_type;
index 10331245598484a16a283533beefca1ffe78e298..1084bc9fe0205ba2c08b8e6b98ca754ba1d68019 100644 (file)
@@ -59,6 +59,7 @@ files.
  */
 
 
+#include "visibility.h"
 
 #ifdef __cplusplus
 extern "C" 
@@ -84,6 +85,7 @@ extern "C"
    
     \return Pointer to allocated memory, or NULL in case of failure
  */
+TMPI_EXPORT
 void *tMPI_Malloc_local(size_t size);
 
 
@@ -96,6 +98,7 @@ void *tMPI_Malloc_local(size_t size);
     
     \return Pointer to allocated memory, or NULL in case of failure
  */
+TMPI_EXPORT
 void *tMPI_Calloc_local(size_t nmemb, size_t size);
 
 
@@ -109,6 +112,7 @@ void *tMPI_Calloc_local(size_t nmemb, size_t size);
     
     \return Pointer to allocated memory, or NULL in case of failure
  */
+TMPI_EXPORT
 void *tMPI_Realloc_local(void *ptr, size_t size); 
 
 
@@ -121,6 +125,7 @@ void *tMPI_Realloc_local(void *ptr, size_t size);
     \return Returns debug info: 0 if the memory was allocated with a NUMA  
             allocator, 1 if it was allocated by another allocator.
  */
+TMPI_EXPORT
 int tMPI_Free_numa(void *ptr);
 
 
index f00f28ca0865341b78f78d214d49bd7fab75ec2d..d332c0483de6d4102cd7a8b9ff77d94abc66ce4b 100644 (file)
@@ -46,8 +46,9 @@ files.
 
 #include <stdexcept>
 
-#ifdef __cplusplus
+#include "visibility.h"
 
+#ifdef __cplusplus
 
 namespace tMPI
 {
@@ -65,7 +66,7 @@ namespace tMPI
         system_error(error_code ec) ;
 
         /*! \brief Returns the error code */
-        const error_code& code() const 
+        const error_code& code() const
         {
             return ec_;
         }
index 7d5da2c6e309ff7b7cb64b1692163a02ed1aa9fb..dfe3a35158a96bc353f04ba08d47b21f4366b848 100644 (file)
@@ -69,6 +69,7 @@ files.
 
 #include <stdio.h>
 
+#include "visibility.h"
 #include "atomic.h"
 
 
@@ -231,12 +232,24 @@ enum tMPI_Thread_support
 };
 
 
+/** Thread setaffinity support status enumeration */
+enum tMPI_Thread_setaffinity_support
+{
+    TMPI_SETAFFINITY_SUPPORT_NO = 0,  /*!< Setting thread affinity not
+                                           supported */
+    TMPI_SETAFFINITY_SUPPORT_YES = 1  /*!< Setting thread affinity supported */
+};
+
+
+
+
 /** handle a fatal error.
 
   \param file     source code file name of error.
   \param line     source code line number of error.
   \param message  format string for error message.
 */
+TMPI_EXPORT
 void tMPI_Fatal_error(const char *file, int line, const char *message, ...);
 /** Convenience macro for the first two arguments to tMPI_Fatal_error(). */
 #define TMPI_FARGS __FILE__,__LINE__
@@ -256,6 +269,7 @@ void tMPI_Fatal_error(const char *file, int line, const char *message, ...);
  * 
  *  \return 1 if threads are supported, 0 if not.
  */
+TMPI_EXPORT
 enum tMPI_Thread_support tMPI_Thread_support(void);
 
 
@@ -267,6 +281,7 @@ enum tMPI_Thread_support tMPI_Thread_support(void);
         If this number cannot be determined for the current architecture,
         0 is returned.
  */
+TMPI_EXPORT
 int tMPI_Thread_get_hw_number(void);
 
 
@@ -282,35 +297,11 @@ int tMPI_Thread_get_hw_number(void);
  *  
  *  \return Status - 0 on success, or an error code.
  */
+TMPI_EXPORT
 int tMPI_Thread_create(tMPI_Thread_t *thread,
                       void* (*start_routine)(void *),
                       void* arg);
 
-/** Create a new thread with processor affinity 
- *
- *  The new thread will call start_routine() with the argument arg.
- * 
- *  The new thread will have processor affinity assigned in a 
- *  round-robin way, starting at processor 1.  The first thread to call 
- *  this function will be assigned to processor 0.
- *
- *  This means that this funtion should ONLY be called when starting a
- *  thread on each processor: in any other case, this will lead to 
- *  imbalances because processors 0 and 1 will be oversubscribed.
- *
- *  Please be careful not to change arg after calling this function.
- * 
- *  \param[out] thread         Pointer to thread ID
- *  \param[in] start_routine   The function to call in the new thread
- *  \param[in] arg             Argument to call with
- *  
- *  \return Status - 0 on success, or an error code.
- */
-int tMPI_Thread_create_aff(tMPI_Thread_t *thread,
-                           void *(*start_routine)(void *),
-                           void *arg);
-
-
 
 
 
@@ -325,6 +316,7 @@ int tMPI_Thread_create_aff(tMPI_Thread_t *thread,
  *  
  *  \return 0 if the join went ok, or a non-zero error code.
  */
+TMPI_EXPORT
 int tMPI_Thread_join(tMPI_Thread_t thread, void **value_ptr);
 
 
@@ -336,6 +328,7 @@ int tMPI_Thread_join(tMPI_Thread_t thread, void **value_ptr);
  *                     join them can read this value if they try.
  *  \return 
  */
+TMPI_EXPORT
 void tMPI_Thread_exit(void *value_ptr);
 
 
@@ -348,6 +341,7 @@ void tMPI_Thread_exit(void *value_ptr);
  *  \param thread     Handle to thread we want to see dead.
  *  \return 0 or a non-zero error message.
  */
+TMPI_EXPORT
 int tMPI_Thread_cancel(tMPI_Thread_t thread);
 
 
@@ -360,6 +354,7 @@ int tMPI_Thread_cancel(tMPI_Thread_t thread);
   * example assign thread affinities to any thread. 
   *
   * \return A thread ID of the calling thread */
+TMPI_EXPORT
 tMPI_Thread_t tMPI_Thread_self(void);
 
 
@@ -370,9 +365,24 @@ tMPI_Thread_t tMPI_Thread_self(void);
   * \param[in]  t2  Thread ID 2
   * \return non-zero if the thread structs refer to the same thread, 
             0 if the threads are different*/
+TMPI_EXPORT
 int tMPI_Thread_equal(tMPI_Thread_t t1, tMPI_Thread_t t2);
 
 
+/** Check whether this platform supports setting of thread affinity
+  *
+  * This function returns TMPI_SETAFFINITY_SUPPORT_YES if setting thread
+  * affinity is supported by the platform, and TMPI_SETAFFINITY_SUPPORT_NO
+  * if not. If this function returns 0, the function
+  * tMPI_Thread_setaffinity_single will simply return 0 itself, effectively
+  * ignoring the request.
+  *
+  * \return TMPI_SETAFFINITY_SUPPORT_YES if setting affinity is supported,
+            TMPI_SETAFFINITY_SUPPORT_NO otherwise */
+TMPI_EXPORT
+enum tMPI_Thread_setaffinity_support tMPI_Thread_setaffinity_support(void);
+
+
 /** Set thread affinity to a single core
   *
   * This function sets the thread affinity of a thread to a a specific 
@@ -381,7 +391,9 @@ int tMPI_Thread_equal(tMPI_Thread_t t1, tMPI_Thread_t t2);
   * by tMPI_Thread_get_hw_number().
   *
   * \param[in] thread   Thread ID of the thread to set affinity for
-  * \param[in] nr       Processor number to set affinity to */
+  * \param[in] nr       Processor number to set affinity to
+  * \return zero on success, non-zero on error */
+TMPI_EXPORT
 int tMPI_Thread_setaffinity_single(tMPI_Thread_t thread, unsigned int nr);
 
 
@@ -398,6 +410,7 @@ int tMPI_Thread_setaffinity_single(tMPI_Thread_t thread, unsigned int nr);
  *  \param mtx   Pointer to a mutex opaque type.
  *  \return      0 or an error code.
  */
+TMPI_EXPORT
 int tMPI_Thread_mutex_init(tMPI_Thread_mutex_t *mtx);
 
 
@@ -412,6 +425,7 @@ int tMPI_Thread_mutex_init(tMPI_Thread_mutex_t *mtx);
 *  \param mtx  Pointer to a mutex variable to get rid of.
 *  \return 0 or a non-zero error code.
 */
+TMPI_EXPORT
 int tMPI_Thread_mutex_destroy(tMPI_Thread_mutex_t *mtx);
 
 
@@ -424,6 +438,7 @@ int tMPI_Thread_mutex_destroy(tMPI_Thread_mutex_t *mtx);
 *  \param mtx  Pointer to the mutex to lock
 *  \return 0 or a non-zero error code.
 */
+TMPI_EXPORT
 int tMPI_Thread_mutex_lock(tMPI_Thread_mutex_t *mtx);
 
 
@@ -438,6 +453,7 @@ int tMPI_Thread_mutex_lock(tMPI_Thread_mutex_t *mtx);
  *  \param mtx  Pointer to the mutex to try and lock
  *  \return 0 or a non-zero return error code.
  */
+TMPI_EXPORT
 int tMPI_Thread_mutex_trylock(tMPI_Thread_mutex_t *mtx);
 
 
@@ -448,6 +464,7 @@ int tMPI_Thread_mutex_trylock(tMPI_Thread_mutex_t *mtx);
  *  \param mtx  Pointer to the mutex to release
  *  \return 0 or a non-zero error code.
  */
+TMPI_EXPORT
 int tMPI_Thread_mutex_unlock(tMPI_Thread_mutex_t *mtx);
 
 
@@ -470,6 +487,7 @@ int tMPI_Thread_mutex_unlock(tMPI_Thread_mutex_t *mtx);
  *  \return status - 0 on sucess or a standard error code.
  *
  */
+TMPI_EXPORT
 int tMPI_Thread_key_create(tMPI_Thread_key_t *key, void (*destructor)(void *));
 
 
@@ -483,6 +501,7 @@ int tMPI_Thread_key_create(tMPI_Thread_key_t *key, void (*destructor)(void *));
  *  \param  key  Opaque key type to destroy
  *  \return 0 or a non-zero error message.
  */
+TMPI_EXPORT
 int tMPI_Thread_key_delete(tMPI_Thread_key_t key);
 
 
@@ -495,6 +514,7 @@ int tMPI_Thread_key_delete(tMPI_Thread_key_t key);
  *  \param key   Thread-specific-storage handle.
  *  \return Pointer-to-void, the value of the data in this thread.
 */
+TMPI_EXPORT
 void * tMPI_Thread_getspecific(tMPI_Thread_key_t key);
 
 
@@ -505,6 +525,7 @@ void * tMPI_Thread_getspecific(tMPI_Thread_key_t key);
  *  \param value   What to set the data to (pointer-to-void).
  *  \return 0 or a non-zero error message.
  */
+TMPI_EXPORT
 int tMPI_Thread_setspecific(tMPI_Thread_key_t key, void *value);
 
 
@@ -525,6 +546,7 @@ int tMPI_Thread_setspecific(tMPI_Thread_key_t key, void *value);
  *  \param init_routine  Function to call exactly once
  *  \return 0 or a non-zero error message.
  */
+TMPI_EXPORT
 int tMPI_Thread_once(tMPI_Thread_once_t *once_data, 
                      void (*init_routine)(void));    
 
@@ -541,6 +563,7 @@ int tMPI_Thread_once(tMPI_Thread_once_t *once_data,
  *  \param cond  Pointer to previously allocated condition variable
  *  \return      0 or a non-zero error message.
  */
+TMPI_EXPORT
 int tMPI_Thread_cond_init(tMPI_Thread_cond_t *cond);
 
 
@@ -554,6 +577,7 @@ int tMPI_Thread_cond_init(tMPI_Thread_cond_t *cond);
  *  \param cond Pointer to condition variable.
  *  \return 0 or a non-zero error message.
  */
+TMPI_EXPORT
 int tMPI_Thread_cond_destroy(tMPI_Thread_cond_t *cond);
 
 
@@ -573,6 +597,7 @@ int tMPI_Thread_cond_destroy(tMPI_Thread_cond_t *cond);
  *
  *  \return 0 or a non-zero error message.
  */
+TMPI_EXPORT
 int tMPI_Thread_cond_wait(tMPI_Thread_cond_t *cond,
                           tMPI_Thread_mutex_t *mtx);
 
@@ -589,6 +614,7 @@ int tMPI_Thread_cond_wait(tMPI_Thread_cond_t *cond,
  *
  *  \return 0 or a non-zero error message.
  */
+TMPI_EXPORT
 int tMPI_Thread_cond_signal(tMPI_Thread_cond_t *cond);
 
 
@@ -602,6 +628,7 @@ int tMPI_Thread_cond_signal(tMPI_Thread_cond_t *cond);
 *
 *  \return 0 or a non-zero error message.
 */
+TMPI_EXPORT
 int tMPI_Thread_cond_broadcast(tMPI_Thread_cond_t *cond);
 
 
@@ -622,6 +649,7 @@ int tMPI_Thread_cond_broadcast(tMPI_Thread_cond_t *cond);
  *                  will be released after \a count calls to 
  *                  tMPI_Thread_barrier_wait(). 
  */
+TMPI_EXPORT
 int tMPI_Thread_barrier_init(tMPI_Thread_barrier_t *barrier, int count);
 
 
@@ -631,6 +659,7 @@ int tMPI_Thread_barrier_init(tMPI_Thread_barrier_t *barrier, int count);
  *  \param barrier  Pointer to previously 
  *                  initialized barrier.
  */
+TMPI_EXPORT
 int tMPI_Thread_barrier_destroy(tMPI_Thread_barrier_t *barrier);
 
 
@@ -645,6 +674,7 @@ int tMPI_Thread_barrier_destroy(tMPI_Thread_barrier_t *barrier);
  *
  *  \return The last thread returns -1, all the others 0.
  */
+TMPI_EXPORT
 int tMPI_Thread_barrier_wait(tMPI_Thread_barrier_t *barrier);
 
 /*! \} */
index d8d3fc7528a8d4243b6405262539e78a0f7d7a96..400a484af99cb403ca4eb6449d5ef1fbd8006144 100644 (file)
@@ -60,6 +60,7 @@ files.
    library for this is in C. */
 #include <stddef.h>
 
+#include "visibility.h"
 
 #ifdef __cplusplus
 extern "C" 
@@ -125,28 +126,45 @@ typedef struct tmpi_datatype_ *tMPI_Datatype;
     These are MPI data types as specified by the MPI standard. 
     Note that not all are available.  */
 /*! \{ */
+TMPI_EXPORT
 extern const tMPI_Datatype TMPI_CHAR;               /**< char */
+TMPI_EXPORT
 extern const tMPI_Datatype TMPI_SHORT;              /**< short */
+TMPI_EXPORT
 extern const tMPI_Datatype TMPI_INT;                /**< int */
+TMPI_EXPORT
 extern const tMPI_Datatype TMPI_LONG;               /**< long */
 #ifdef SIZEOF_LONG_LONG_INT
+TMPI_EXPORT
 extern const tMPI_Datatype TMPI_LONG_LONG;          /**< long long */
+TMPI_EXPORT
 extern const tMPI_Datatype TMPI_LONG_LONG_INT;      /**< long long int */
 #endif
+TMPI_EXPORT
 extern const tMPI_Datatype TMPI_SIGNED_CHAR;        /**< signed char */
+TMPI_EXPORT
 extern const tMPI_Datatype TMPI_UNSIGNED_CHAR;      /**< unsigned char */
+TMPI_EXPORT
 extern const tMPI_Datatype TMPI_UNSIGNED_SHORT;     /**< unsigned short */
+TMPI_EXPORT
 extern const tMPI_Datatype TMPI_UNSIGNED;           /**< unsigned int */
+TMPI_EXPORT
 extern const tMPI_Datatype TMPI_UNSIGNED_LONG;      /**< unsigned long */
 #ifdef SIZEOF_LONG_LONG_INT
+TMPI_EXPORT
 extern const tMPI_Datatype TMPI_UNSIGNED_LONG_LONG; /**< unsigned long long */
 #endif
+TMPI_EXPORT
 extern const tMPI_Datatype TMPI_FLOAT;              /**< float */
+TMPI_EXPORT
 extern const tMPI_Datatype TMPI_DOUBLE;             /**< double */
+TMPI_EXPORT
 extern const tMPI_Datatype TMPI_LONG_DOUBLE;        /**< long double */
 /*extern tMPI_Datatype tMPI_UNSIGNED_WCHAR */
+TMPI_EXPORT
 extern const tMPI_Datatype TMPI_BYTE;               /**< byte (for binary 
                                                                xmissions) */
+TMPI_EXPORT
 extern const tMPI_Datatype TMPI_POINTER;            /**< pointer (thread_mpi 
                                                                   specific) */
 
@@ -230,6 +248,7 @@ extern tMPI_Errhandler TMPI_ERRORS_RETURN;
 
 
 /** Pre-initialized communicator with all available threads. */
+TMPI_EXPORT
 extern tMPI_Comm TMPI_COMM_WORLD;
 
 
@@ -339,6 +358,7 @@ tMPI_Comm tMPI_Get_comm_self(void);
                                 int start_function(int argc, char *argv[]);
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Init(int *argc, char ***argv, 
               int (*start_function)(int, char**));
 
@@ -373,6 +393,7 @@ int tMPI_Init(int *argc, char ***argv,
 
     \return  TMPI_FAILURE on failure, TMPI_SUCCESS on succes (after all
              threads have finished if main_thread_returns=true).  */
+TMPI_EXPORT
 int tMPI_Init_fn(int main_thread_returns, int N,
                  tMPI_Affinity_strategy aff_strategy,
                  void (*start_function)(void*), void *arg);
@@ -395,6 +416,7 @@ int tMPI_Init_fn(int main_thread_returns, int N,
     \param[out] nthreads                the number of threads
     
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Get_N(int *argc, char ***argv, const char *optname, int *nthreads);
 
 
@@ -402,6 +424,7 @@ int tMPI_Get_N(int *argc, char ***argv, const char *optname, int *nthreads);
 /** Waits for all other threads to finish and cleans up 
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Finalize(void);
 
 
@@ -413,6 +436,7 @@ int tMPI_Finalize(void);
     \param[in] errorcode    Error code to exit with
     
     \return Never returns. */
+TMPI_EXPORT
 int tMPI_Abort(tMPI_Comm comm, int errorcode);
 
 /** whether tMPI_Init, but not yet tMPI_Finalize, has been run
@@ -421,6 +445,7 @@ int tMPI_Abort(tMPI_Comm comm, int errorcode);
                          FALSE if not.
     
     \return     always returns TMPI_SUCCESS. */
+TMPI_EXPORT
 int tMPI_Initialized(int *flag);
 
 /** Determine whether tMPI_Finalize has been run.
@@ -429,6 +454,7 @@ int tMPI_Initialized(int *flag);
                             called, FALSE if not.
      
     \return     always returns TMPI_SUCCESS.  */
+TMPI_EXPORT
 int tMPI_Finalized(int *flag);
 /** \} */
 
@@ -448,6 +474,7 @@ int tMPI_Finalized(int *flag);
     \param[out] errhandler      The error handler.
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Create_errhandler(tMPI_Errhandler_fn *function,
                            tMPI_Errhandler *errhandler);
 
@@ -456,6 +483,7 @@ int tMPI_Create_errhandler(tMPI_Errhandler_fn *function,
     
     \param[in] errhandler       The error handler.
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Errhandler_free(tMPI_Errhandler *errhandler);
 
 /** Set the error handler.
@@ -464,8 +492,9 @@ int tMPI_Errhandler_free(tMPI_Errhandler *errhandler);
     \param[in] errhandler   the error handler.
     
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
-
+TMPI_EXPORT
 int tMPI_Comm_set_errhandler(tMPI_Comm comm, tMPI_Errhandler errhandler);
+
 /** get the error handler.
 
     Gets the error handler associated with a comm
@@ -474,7 +503,7 @@ int tMPI_Comm_set_errhandler(tMPI_Comm comm, tMPI_Errhandler errhandler);
     \param[out] errhandler   the error handler.
     
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
-
+TMPI_EXPORT
 int tMPI_Comm_get_errhandler(tMPI_Comm comm, tMPI_Errhandler *errhandler);
 
 /** get the error string associated with an error code. 
@@ -487,6 +516,7 @@ int tMPI_Comm_get_errhandler(tMPI_Comm comm, tMPI_Errhandler *errhandler);
                             never be longer than TMPI_MAX_ERROR_STRING.  
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Error_string(int errorcode, char *string, size_t *resultlen);
 /** \} */
 
@@ -508,16 +538,19 @@ int tMPI_Error_string(int errorcode, char *string, size_t *resultlen);
                             for some reason defines all sizes as int
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Get_processor_name(char *name, int *resultlen);
 
 /** get a time value as a double, in seconds.
 
     \return time value.
     */
+TMPI_EXPORT
 double tMPI_Wtime(void);
 /** get the resolution of tMPI_Wtime as a double, in seconds 
 
     \return time resolution. */
+TMPI_EXPORT
 double tMPI_Wtick(void);
 
 #ifndef DOXYGEN
@@ -547,6 +580,7 @@ int tMPI_This_Threadnr(void);
     \param[in]  group       The group.
     \param[out] size        Size.
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Group_size(tMPI_Group group, int *size);
 
 /** Get the rank of a thread in a group 
@@ -555,6 +589,7 @@ int tMPI_Group_size(tMPI_Group group, int *size);
     \param[out] rank        Variable for the rank, or TMPI_UNDEFINED 
                             if not in group.
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Group_rank(tMPI_Group group, int *rank);
 
 /** Create a new group as a the collection of threads with given ranks. 
@@ -565,6 +600,7 @@ int tMPI_Group_rank(tMPI_Group group, int *rank);
     \param[out] newgroup    The new group.
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Group_incl(tMPI_Group group, int n, int *ranks, tMPI_Group *newgroup);
 
 /** Get a pointer to the group in the comm. 
@@ -573,12 +609,14 @@ int tMPI_Group_incl(tMPI_Group group, int n, int *ranks, tMPI_Group *newgroup);
     \param[out] group       The comm's group. 
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Comm_group(tMPI_Comm comm, tMPI_Group *group);
 
 /** De-allocate a group 
 
     \param[in] group        The group to de-allocate.
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Group_free(tMPI_Group *group);
 /*! \} */
 
@@ -595,6 +633,7 @@ int tMPI_Group_free(tMPI_Group *group);
     \param[in] comm         The comm to query.
     \param[out] size        The comm size.
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Comm_size(tMPI_Comm comm, int *size);
 
 /** get the rank in comm of the current process 
@@ -602,6 +641,7 @@ int tMPI_Comm_size(tMPI_Comm comm, int *size);
     \param[in]  comm        The comm to query.
     \param[out] rank        Thread rank in comm.
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Comm_rank(tMPI_Comm comm, int *rank);
 
 /** Compare two comms. Returns TMPI_IDENT if the two comms point to
@@ -615,6 +655,7 @@ int tMPI_Comm_rank(tMPI_Comm comm, int *rank);
     \param[out] result       The output result, one of the values
                              described above. 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Comm_compare(tMPI_Comm comm1, tMPI_Comm comm2, int *result);
 
 
@@ -624,6 +665,7 @@ int tMPI_Comm_compare(tMPI_Comm comm1, tMPI_Comm comm2, int *result);
 
     \param[in] comm         The comm to free.
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Comm_free(tMPI_Comm *comm);
 
 /** Create a comm based on group membership.
@@ -636,6 +678,7 @@ int tMPI_Comm_free(tMPI_Comm *comm);
     \param[out] newcomm     The new comm.
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Comm_create(tMPI_Comm comm, tMPI_Group group, tMPI_Comm *newcomm);
 
 /** Split up a group into same-colored sub-groups ordered by key.
@@ -656,6 +699,7 @@ int tMPI_Comm_create(tMPI_Comm comm, tMPI_Group group, tMPI_Comm *newcomm);
     \param[in]  key         This thread's key (determines rank).
     \param[out] newcomm     The new comm.
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Comm_split(tMPI_Comm comm, int color, int key, tMPI_Comm *newcomm);
 
 /** Make a duplicate of a comm.
@@ -665,6 +709,7 @@ int tMPI_Comm_split(tMPI_Comm comm, int color, int key, tMPI_Comm *newcomm);
     \param[in] comm         The originating comm.
     \param[in] newcomm      The new comm.
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Comm_dup(tMPI_Comm comm, tMPI_Comm *newcomm);
 /*! \} */
 
@@ -684,6 +729,7 @@ int tMPI_Comm_dup(tMPI_Comm comm, tMPI_Comm *newcomm);
     \param[out] status      The type of topology. 
     
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Topo_test(tMPI_Comm comm, int *status);
 
 /** Get the dimensionality of a comm with a topology.
@@ -693,6 +739,7 @@ int tMPI_Topo_test(tMPI_Comm comm, int *status);
     
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
 
+TMPI_EXPORT
 int tMPI_Cartdim_get(tMPI_Comm comm, int *ndims);
 /** Get the size and pbc a of a comm with a Cartesian topology has.
 
@@ -705,6 +752,7 @@ int tMPI_Cartdim_get(tMPI_Comm comm, int *ndims);
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
 
+TMPI_EXPORT
 int tMPI_Cart_get(tMPI_Comm comm, int maxdims, int *dims, int *periods, 
                   int *coords);
 
@@ -717,6 +765,7 @@ int tMPI_Cart_get(tMPI_Comm comm, int maxdims, int *dims, int *periods,
     \param[out] rank        The rank associated with the coordinates.
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Cart_rank(tMPI_Comm comm, int *coords, int *rank);
 
 /** Get coordinates of a process rank in a Cartesian topology.
@@ -728,6 +777,7 @@ int tMPI_Cart_rank(tMPI_Comm comm, int *coords, int *rank);
     \param[out] coords      The coordinates in each dimension.
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Cart_coords(tMPI_Comm comm, int rank, int maxdims, int *coords);
 
 /** Get optimal rank this process would have in a Cartesian topology. 
@@ -740,6 +790,7 @@ int tMPI_Cart_coords(tMPI_Comm comm, int rank, int maxdims, int *coords);
     \param[out] newrank     The rank the thread would have given the topology.
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Cart_map(tMPI_Comm comm, int ndims, int *dims, int *periods, 
                   int *newrank);
 
@@ -754,6 +805,7 @@ int tMPI_Cart_map(tMPI_Comm comm, int ndims, int *dims, int *periods,
     \param[out] comm_cart   The new comm with Cartesian topology.
    
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Cart_create(tMPI_Comm comm_old, int ndims, int *dims, int *periods, 
                      int reorder, tMPI_Comm *comm_cart);
 
@@ -768,6 +820,7 @@ int tMPI_Cart_create(tMPI_Comm comm_old, int ndims, int *dims, int *periods,
     \param[out] newcomm     The new split communicator
    
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Cart_sub(tMPI_Comm comm, int *remain_dims, tMPI_Comm *newcomm);
 
 /*! \} */
@@ -789,6 +842,7 @@ int tMPI_Cart_sub(tMPI_Comm comm, int *remain_dims, tMPI_Comm *newcomm);
     \param[in]  oldtype     The old data type.
     \param[out] newtype     The new data type (still needs to be committed).
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Type_contiguous(int count, tMPI_Datatype oldtype, 
                         tMPI_Datatype *newtype);
 
@@ -797,6 +851,7 @@ int tMPI_Type_contiguous(int count, tMPI_Datatype oldtype,
 
     \param[in,out] datatype  The new datatype.
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Type_commit(tMPI_Datatype *datatype);
 /*! \} */
 
@@ -822,6 +877,7 @@ int tMPI_Type_commit(tMPI_Datatype *datatype);
     \param[in]  tag         The message tag. 
     \param[in]  comm        The shared communicator.
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Send(void* buf, int count, tMPI_Datatype datatype, int dest, 
              int tag, tMPI_Comm comm);
 
@@ -835,6 +891,7 @@ int tMPI_Send(void* buf, int count, tMPI_Datatype datatype, int dest,
     \param[in]  comm        The shared communicator.
     \param[out] status      The message status. 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Recv(void* buf, int count, tMPI_Datatype datatype, int source, 
              int tag, tMPI_Comm comm, tMPI_Status *status);
 
@@ -855,6 +912,7 @@ int tMPI_Recv(void* buf, int count, tMPI_Datatype datatype, int source,
     \param[in]  comm        The shared communicator.
     \param[out] status      The received message status. 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Sendrecv(void *sendbuf, int sendcount, tMPI_Datatype sendtype, 
                  int dest, int sendtag, void *recvbuf, int recvcount, 
                  tMPI_Datatype recvtype, int source, int recvtag, 
@@ -880,6 +938,7 @@ int tMPI_Sendrecv(void *sendbuf, int sendcount, tMPI_Datatype sendtype,
     \param[out] request     The request object that can be used in tMPI_Wait(),
                             tMPI_Test, etc.
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Isend(void* buf, int count, tMPI_Datatype datatype, int dest, 
               int tag, tMPI_Comm comm, tMPI_Request *request);
 
@@ -898,6 +957,7 @@ int tMPI_Isend(void* buf, int count, tMPI_Datatype datatype, int dest,
     \param[out] request     The request object that can be used in tMPI_Wait(),
                             tMPI_Test, etc.
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Irecv(void* buf, int count, tMPI_Datatype datatype, int source, 
               int tag, tMPI_Comm comm, tMPI_Request *request);
 
@@ -912,6 +972,7 @@ int tMPI_Irecv(void* buf, int count, tMPI_Datatype datatype, int source,
     \param[out]     status  Message status (can be set to TMPI_STATUS_IGNORE).
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Test(tMPI_Request *request, int *flag, tMPI_Status *status);
 
 /** Wait until a message is transferred.
@@ -920,6 +981,7 @@ int tMPI_Test(tMPI_Request *request, int *flag, tMPI_Status *status);
     \param[out]     status  Message status.
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Wait(tMPI_Request *request, tMPI_Status *status);
 
 
@@ -934,6 +996,7 @@ int tMPI_Wait(tMPI_Request *request, tMPI_Status *status);
                                         be set to TMPI_STATUSES_IGNORE).
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Waitall(int count, tMPI_Request *array_of_requests, 
                 tMPI_Status *array_of_statuses);
 
@@ -947,6 +1010,7 @@ int tMPI_Waitall(int count, tMPI_Request *array_of_requests,
                                         be set to TMPI_STATUSES_IGNORE).
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Testall(int count, tMPI_Request *array_of_requests, int *flag,
                 tMPI_Status *array_of_statuses);
 
@@ -961,6 +1025,7 @@ int tMPI_Testall(int count, tMPI_Request *array_of_requests, int *flag,
                                         associated with completed request.
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Waitany(int count, tMPI_Request *array_of_requests, 
                  int *index, tMPI_Status *status);
 
@@ -976,6 +1041,7 @@ int tMPI_Waitany(int count, tMPI_Request *array_of_requests,
                                         associated with completed request.
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Testany(int count, tMPI_Request *array_of_requests, 
                  int *index, int *flag, tMPI_Status *status);
 
@@ -992,6 +1058,7 @@ int tMPI_Testany(int count, tMPI_Request *array_of_requests,
                                         be set to TMPI_STATUSES_IGNORE).
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Waitsome(int incount, tMPI_Request *array_of_requests,
                   int *outcount, int *array_of_indices,
                   tMPI_Status *array_of_statuses);
@@ -1008,6 +1075,7 @@ int tMPI_Waitsome(int incount, tMPI_Request *array_of_requests,
                                         be set to TMPI_STATUSES_IGNORE).
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Testsome(int incount, tMPI_Request *array_of_requests,
                  int *outcount, int *array_of_indices,
                  tMPI_Status *array_of_statuses);
@@ -1025,6 +1093,7 @@ int tMPI_Testsome(int incount, tMPI_Request *array_of_requests,
     \param[out] count       The number of items actually received.
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Get_count(tMPI_Status *status, tMPI_Datatype datatype, int *count);
 /*! \} */
 
@@ -1042,6 +1111,7 @@ int tMPI_Get_count(tMPI_Status *status, tMPI_Datatype datatype, int *count);
     \param[in]  comm    The comm object.
   
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Barrier(tMPI_Comm comm);
 /*! \} */
 
@@ -1066,6 +1136,7 @@ int tMPI_Barrier(tMPI_Comm comm);
     \param[in]      comm        The communicator.
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Bcast(void* buffer, int count, tMPI_Datatype datatype, int root, 
               tMPI_Comm comm);
 
@@ -1086,6 +1157,7 @@ int tMPI_Bcast(void* buffer, int count, tMPI_Datatype datatype, int root,
     \param[in]      comm        The communicator.
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Gather(void* sendbuf, int sendcount, tMPI_Datatype sendtype, 
                void* recvbuf, int recvcount, tMPI_Datatype recvtype, int root, 
                tMPI_Comm comm);
@@ -1110,6 +1182,7 @@ int tMPI_Gather(void* sendbuf, int sendcount, tMPI_Datatype sendtype,
     \param[in]      comm        The communicator.
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Gatherv(void* sendbuf, int sendcount, tMPI_Datatype sendtype, 
                 void* recvbuf, int *recvcounts, int *displs, 
                 tMPI_Datatype recvtype, int root, tMPI_Comm comm);
@@ -1132,6 +1205,7 @@ int tMPI_Gatherv(void* sendbuf, int sendcount, tMPI_Datatype sendtype,
     \param[in]      comm        The communicator.
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Scatter(void* sendbuf, int sendcount, tMPI_Datatype sendtype, 
                 void* recvbuf, int recvcount, tMPI_Datatype recvtype, int root, 
                 tMPI_Comm comm);
@@ -1156,6 +1230,7 @@ int tMPI_Scatter(void* sendbuf, int sendcount, tMPI_Datatype sendtype,
     \param[in]      comm        The communicator.
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Scatterv(void* sendbuf, int *sendcounts, int *displs, 
                  tMPI_Datatype sendtype, void* recvbuf, int recvcount, 
                  tMPI_Datatype recvtype, int root, tMPI_Comm comm); 
@@ -1176,6 +1251,7 @@ int tMPI_Scatterv(void* sendbuf, int *sendcounts, int *displs,
     \param[in]      comm        The communicator.
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Alltoall(void* sendbuf, int sendcount, tMPI_Datatype sendtype, 
                   void* recvbuf, int recvcount, tMPI_Datatype recvtype, 
                   tMPI_Comm comm);
@@ -1201,6 +1277,7 @@ int tMPI_Alltoall(void* sendbuf, int sendcount, tMPI_Datatype sendtype,
     \param[in]      comm        The communicator.
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Alltoallv(void* sendbuf, int *sendcounts, int *sdispls, 
                   tMPI_Datatype sendtype, void* recvbuf, int *recvcounts, 
                   int *rdispls, tMPI_Datatype recvtype, tMPI_Comm comm);
@@ -1233,6 +1310,7 @@ int tMPI_Alltoallv(void* sendbuf, int *sendcounts, int *sdispls,
     \param[in]  comm        The communicator.
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Reduce(void* sendbuf, void* recvbuf, int count, 
                tMPI_Datatype datatype, tMPI_Op op, int root, tMPI_Comm comm);
 
@@ -1254,6 +1332,7 @@ int tMPI_Reduce(void* sendbuf, void* recvbuf, int count,
     \param[in]  comm        The communicator.
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Allreduce(void* sendbuf, void* recvbuf, int count, 
                   tMPI_Datatype datatype, tMPI_Op op, tMPI_Comm comm);
 
@@ -1279,6 +1358,7 @@ int tMPI_Allreduce(void* sendbuf, void* recvbuf, int count,
     \param[in]      comm        The communicator.
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Reduce_fast(void* sendbuf, void* recvbuf, int count, 
                      tMPI_Datatype datatype, tMPI_Op op, int root, 
                      tMPI_Comm comm);
@@ -1299,6 +1379,7 @@ int tMPI_Reduce_fast(void* sendbuf, void* recvbuf, int count,
     \param[in]     comm        The communicator.
 
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+TMPI_EXPORT
 int tMPI_Scan(void* sendbuf, void* recvbuf, int count, 
               tMPI_Datatype datatype, tMPI_Op op, tMPI_Comm comm);
 
diff --git a/include/thread_mpi/visibility.h b/include/thread_mpi/visibility.h
new file mode 100644 (file)
index 0000000..1c19fe3
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+This source code file is part of thread_mpi.  
+Written by Sander Pronk, Erik Lindahl, and possibly others. 
+
+Copyright (c) 2009, Sander Pronk, Erik Lindahl.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1) Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2) Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3) Neither the name of the copyright holders nor the
+   names of its contributors may be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY US ''AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL WE BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you want to redistribute modifications, please consider that
+scientific software is very special. Version control is crucial -
+bugs must be traceable. We will be happy to consider code for
+inclusion in the official distribution, but derived work should not
+be called official thread_mpi. Details are found in the README & COPYING
+files.
+*/
+
+#ifndef TMPI_VISIBILITY_H_
+#define TMPI_VISIBILITY_H_
+
+/** \file 
+ *
+ * \brief Visibility macros
+ * 
+ * These macros enable dynamic library visibility support. Either set the 
+ * 'TMPI_USE_VISIBILITY', or set the TMPI_EXPORT to the right export 
+ * statement, when incorporating thread_mpi into a larger project. 
+ *
+ * All exported functions and classes will be tagged by the visibility macro.
+ * 
+ * \sa http://gcc.gnu.org/wiki/Visibility
+ *
+*/
+
+#ifdef TMPI_USE_VISIBILITY  /* off by default */
+
+/* only set if the macro hasn't been set elsewhere */
+#ifndef TMPI_EXPORT
+
+/* gcc-like */
+#if defined(__GNUC__)
+
+#define TMPI_EXPORT __attribute__((__visibility__("default")))
+
+#elif defined _WIN32 || defined __CYGWIN__ || defined WINDOWS
+
+#ifdef TMPI_EXPORTS
+#define TMPI_EXPORT __declspec(dllexport)
+#else
+#define TMPI_EXPORT __declspec(dllimport)
+#endif
+
+#else /* no viable visibility */
+
+#define TMPI_EXPORT
+
+#endif /* compiler check */
+
+#endif /* TMPI_EXPORT */
+
+#else /* TMPI_USE_VISIBILITY */
+
+#define TMPI_EXPORT
+
+#endif /* TMPI_USE_VISIBILITY */
+
+#endif /* TMPI_VISIBILITY_H_ */
+
+
index c04413b2f134e0d7e3fbe027bab26a7670a9dcce..612604697d03e4de3d3464a504b4a133de00ff97 100644 (file)
@@ -269,6 +269,17 @@ int tMPI_Thread_equal(tMPI_Thread_t t1, tMPI_Thread_t t2)
     return pthread_equal(t1->th, t2->th);
 }
 
+
+enum tMPI_Thread_setaffinity_support tMPI_Thread_setaffinity_support(void)
+{
+#ifdef HAVE_PTHREAD_SETAFFINITY
+    return TMPI_SETAFFINITY_SUPPORT_YES;
+#else
+    return TMPI_SETAFFINITY_SUPPORT_NO;
+#endif
+}
+
+
 /* set thread's own affinity to a processor number n */
 int tMPI_Thread_setaffinity_single(tMPI_Thread_t thread, unsigned int nr)
 {
index c0dd8b71e68bd1446668273fc04227b137e9362e..92f5b6055b342eb373040d3735c0a624c0a97c44 100644 (file)
@@ -437,17 +437,6 @@ int tMPI_Init_NUMA(void)
 
     iRet = 0 ;
 
-#if 0   
-    // TODO: debug DISCARD                        
-    printf("primary thread tid=%lu group=%lu mask=0x%I64x group=%lu number=%lu ulThreadIndex=%lu\n",
-        GetCurrentThreadId(),
-        CurrentThreadGroupAffinity.Group,
-        (ULONGLONG)CurrentThreadGroupAffinity.Mask,
-        (ULONG)CurrentProcessorNumber.Group,
-        (ULONG)CurrentProcessorNumber.Number,
-        g_ulThreadIndex);
-#endif
-
 cleanup:
 
     if( iRet != 0 )
@@ -480,7 +469,8 @@ static void tMPI_Init_initers(void)
             InitializeCriticalSection(&barrier_init);
             thread_id_key=TlsAlloc();
 
-            /* fatal errors are handled by the routine by calling tMPI_Fatal_error() */
+            /* fatal errors are handled by the routine by calling 
+               tMPI_Fatal_error() */
             tMPI_Init_NUMA();  
 
             tMPI_Atomic_memory_barrier_rel();
@@ -665,7 +655,7 @@ tMPI_Thread_t tMPI_Thread_self(void)
             return NULL;
         }
         /* if not, create an ID, set it and return it */
-        th=(struct tMPI_Thread*)malloc(sizeof(struct tMPI_Thread)*1);
+        th=(struct tMPI_Thread*)tMPI_Malloc(sizeof(struct tMPI_Thread)*1);
 
         /* to create a handle that can be used outside of the current
            thread, the handle from GetCurrentThread() must first
@@ -692,6 +682,12 @@ int tMPI_Thread_equal(tMPI_Thread_t t1, tMPI_Thread_t t2)
     return (t1 == t2);
 }
 
+enum tMPI_Thread_setaffinity_support tMPI_Thread_setaffinity_support(void)
+{
+    /* Windows supports seting of thread affinities */
+    return TMPI_SETAFFINITY_SUPPORT_YES;
+}
+
 int tMPI_Thread_setaffinity_single(tMPI_Thread_t thread, unsigned int nr)
 {
     GROUP_AFFINITY GroupAffinity;
@@ -734,20 +730,22 @@ int tMPI_Thread_setaffinity_single(tMPI_Thread_t thread, unsigned int nr)
             if(func_GetNumaNodeProcessorMaskEx(NumaNodeNumber,
                                                &GroupAffinity))
             {
-                /* set the current thread affinity to prevent it from running on 
-                   other NUMA nodes */
+                /* set the current thread affinity to prevent it from running
+                   on other NUMA nodes */
                 func_SetThreadGroupAffinity(thread->th,
                                             &GroupAffinity,
                                             NULL);
+                               return 0;
             }
         }
+        return 1;
     }
     else
     {
         /* No NUMA-style calls. We just do a simpler thing. */
         if ( (func_SetThreadIdealProcessor != NULL) )
         {
-            return func_SetThreadIdealProcessor(thread->th, nr);
+            return (func_SetThreadIdealProcessor(thread->th, nr) == -1);
         }
     }
     return 0;