2 This source code file is part of thread_mpi.
3 Written by Sander Pronk, Erik Lindahl, and possibly others.
5 Copyright (c) 2009, Sander Pronk, Erik Lindahl.
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are met:
10 1) Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2) Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3) Neither the name of the copyright holders nor the
16 names of its contributors may be used to endorse or promote products
17 derived from this software without specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY US ''AS IS'' AND ANY
20 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL WE BE LIABLE FOR ANY
23 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 If you want to redistribute modifications, please consider that
31 scientific software is very special. Version control is crucial -
32 bugs must be traceable. We will be happy to consider code for
33 inclusion in the official distribution, but derived work should not
34 be called official thread_mpi. Details are found in the README & COPYING
39 #ifndef _TMPI_THREAD_H_
40 #define _TMPI_THREAD_H_
44 * \brief Platform-independent multithreading support.
46 * This file provides an portable thread interface very similar to POSIX
47 * threads, as a thin wrapper around the threads provided operating system
48 * (whether they be POSIX threads or something else).
50 * In other words, while the naming conventions are very similar to
51 * pthreads, you should NOT assume that a thread_mpi thread type
52 * (thread,mutex,key, etc) is the same as the Pthreads equivalent,
53 * even on platforms where we are using pthreads.
55 * Because the synchronization functions here are similar to the basic
56 * mutexes/conditions/barriers provided by the operating system,
57 * performance will most likely be worse than when using the atomic
58 * synchronization functions of atomic.h. On the other hand, because the
59 * operating system can schedule out waiting threads using these functions,
60 * they are the appropriate ones for I/O and initialization.
62 * Since this module is merely intended to be a transparent wrapper around
63 * a system-dependent thread implementation, we simply echo errors to stderr.
64 * The user should check the return codes\] and take appropriate action
65 * when using these functions (fat chance, but errors are rare).
72 #include "thread_mpi/atomic.h"
80 } /* Avoids screwing up auto-indentation */
87 /*! \brief Pthread implementation of the abstract tMPI_Thread type
89 * The contents of this structure depends on the actual threads
90 * implementation used.
92 typedef struct tMPI_Thread
* tMPI_Thread_t
;
96 /*! \brief Opaque mutex datatype
98 * This type is only defined in the header to enable static
99 * initialization with TMPI_THREAD_MUTEX_INITIALIZER.
100 * You should _never_ touch the contents or create a variable
101 * with automatic storage class without calling tMPI_Thread_mutex_init().
105 tMPI_Atomic_t initialized
;
106 struct tMPI_Mutex
* mutex
;
107 } tMPI_Thread_mutex_t
;
108 /*! \brief Static initializer for tMPI_Thread_mutex_t
110 * See the description of the tMPI_Thread_mutex_t datatype for instructions
111 * on how to use this. Note that any variables initialized with this value
112 * MUST have static storage allocation.
114 #define TMPI_THREAD_MUTEX_INITIALIZER { {0} , NULL }
120 /*! \brief Pthread implementation of the abstract tMPI_Thread_key type
122 * The contents of this structure depends on the actual threads
123 * implementation used.
127 tMPI_Atomic_t initialized
;
128 struct tMPI_Thread_key
*key
;
135 /*! \brief One-time initialization data for thread
137 * This is an opaque datatype which is necessary for tMPI_Thread_once(),
138 * but since it needs to be initialized statically it must be defined
139 * in the header. You will be sorry if you touch the contents.
140 * Variables of this type should always be initialized statically to
141 * TMPI_THREAD_ONCE_INIT.
143 * This type is used as control data for single-time initialization.
144 * The most common example is a mutex at file scope used when calling
145 * a non-threadsafe function, e.g. the FFTW initialization routines.
151 } tMPI_Thread_once_t
;
152 /*! \brief Static initializer for tMPI_Thread_once_t
154 * See the description of the tMPI_Thread_once_t datatype for instructions
155 * on how to use this. Normally, all variables of that type should be
156 * initialized statically to this value.
158 #define TMPI_THREAD_ONCE_INIT { {0} }
163 /*! \brief Condition variable handle for threads
165 * Condition variables are useful for synchronization together
166 * with a mutex: Lock the mutex and check if our thread is the last
167 * to the barrier. If no, wait for the condition to be signaled.
168 * If yes, reset whatever data you want and then signal the condition.
170 * This should be considered an opaque structure, but since it is sometimes
171 * useful to initialize it statically it must go in the header.
172 * You will be sorry if you touch the contents.
174 * There are two alternatives: Either initialize it as a static variable
175 * with TMPI_THREAD_COND_INITIALIZER, or call tMPI_Thread_cond_init()
180 tMPI_Atomic_t initialized
;
181 struct tMPI_Thread_cond
* condp
;
182 } tMPI_Thread_cond_t
;
183 /*! \brief Static initializer for tMPI_Thread_cond_t
185 * See the description of the tMPI_Thread_cond_t datatype for instructions
186 * on how to use this. Note that any variables initialized with this value
187 * MUST have static storage allocation.
189 #define TMPI_THREAD_COND_INITIALIZER { {0}, NULL}
196 /*! \brief Pthread implementation of barrier type.
198 * The contents of this structure depends on the actual threads
199 * implementation used.
203 tMPI_Atomic_t initialized
;
204 struct tMPI_Thread_barrier
* barrierp
;
205 volatile int threshold
; /*!< Total number of members in barrier */
206 volatile int count
; /*!< Remaining count before completion */
207 volatile int cycle
; /*!< Alternating 0/1 to indicate round */
208 }tMPI_Thread_barrier_t
;
209 /*! \brief Static initializer for tMPI_Thread_barrier_t
211 * See the description of the tMPI_Thread_barrier_t datatype for instructions
212 * on how to use this. Note that variables initialized with this value
213 * MUST have static storage allocation.
215 * \param count Threshold for barrier
217 #define TMPI_THREAD_BARRIER_INITIALIZER(count) {\
218 NULL, count, count, 0 \
226 /** Thread support status enumeration */
227 enum tMPI_Thread_support
229 TMPI_THREAD_SUPPORT_NO
= 0, /*!< Starting threads will fail */
230 TMPI_THREAD_SUPPORT_YES
= 1 /*!< Thread support available */
234 /** handle a fatal error.
236 \param file source code file name of error.
237 \param line source code line number of error.
238 \param message format string for error message.
240 void tMPI_Fatal_error(const char *file
, int line
, const char *message
, ...);
241 #define TMPI_FARGS __FILE__,__LINE__
245 /** Check if threads are supported
247 * This routine provides a cleaner way to check if threads are supported
248 * instead of sprinkling your code with preprocessor conditionals.
250 * All thread functions are still available even without thread support,
251 * but some of them might return failure error codes, for instance if you try
254 * \return 1 if threads are supported, 0 if not.
256 enum tMPI_Thread_support
tMPI_Thread_support(void);
260 /** Create a new thread
262 * The new thread will call start_routine() with the argument arg.
263 * Please be careful not to change arg after calling this function.
265 * \param thread Pointer to opaque thread datatype
266 * \param start_routine The function to call in the new thread
267 * \param arg Argument to call with
269 * \return Status - 0 on success, or an error code.
271 int tMPI_Thread_create (tMPI_Thread_t
* thread
,
272 void * (*start_routine
)(void *),
278 /** Wait for a specific thread to finish executing
280 * If the thread has already finished the routine returns immediately.
282 * \param thread Opaque thread datatype to wait for.
283 * \param value_ptr Pointer to location where to store pointer to exit value
284 * from threads that called tMPI_Thread_exit().
286 * \return 0 if the join went ok, or a non-zero error code.
288 int tMPI_Thread_join (tMPI_Thread_t thread
,
293 /** Initialize a new mutex
295 * This routine must be called before using any mutex not initialized
296 * with static storage class and TMPI_THREAD_MUTEX_INITIALIZER.
298 * \param mtx Pointer to a mutex opaque type.
299 * \return 0 or an error code.
301 int tMPI_Thread_mutex_init(tMPI_Thread_mutex_t
*mtx
);
306 /** Kill a mutex you no longer need
308 * Note that this call only frees resources allocated inside the mutex. It
309 * does not free the tMPI_Thread_mutex_t memory area itself if you created it
310 * with dynamic memory allocation.
312 * \param mtx Pointer to a mutex variable to get rid of.
313 * \return 0 or a non-zero error code.
315 int tMPI_Thread_mutex_destroy(tMPI_Thread_mutex_t
*mtx
);
320 /** Wait for exclusive access to a mutex
322 * This routine does not return until the mutex has been acquired.
324 * \param mtx Pointer to the mutex to lock
325 * \return 0 or a non-zero error code.
327 int tMPI_Thread_mutex_lock(tMPI_Thread_mutex_t
*mtx
);
332 /** Try to lock a mutex, return if busy
334 * This routine always return directly. If the mutex was available and
335 * we successfully locked it we return 0, otherwise a non-zero
336 * error code (usually meaning the mutex was already locked).
338 * \param mtx Pointer to the mutex to try and lock
339 * \return 0 or a non-zero error code.
341 int tMPI_Thread_mutex_trylock(tMPI_Thread_mutex_t
*mtx
);
346 /** Release the exclusive access to a mutex
348 * \param mtx Pointer to the mutex to release
349 * \return 0 or a non-zero error code.
351 int tMPI_Thread_mutex_unlock(tMPI_Thread_mutex_t
*mtx
);
356 /** Initialize thread-specific-storage handle
358 * The tMPI_Thread_key_t handle must always be initialized dynamically with
359 * this routine. If you need to initialize it statically in a file, use the
360 * tMPI_Thread_once() routine and corresponding data to initialize the
361 * thread-specific-storage key the first time you access it.
363 * \param key Pointer to opaque thread key type.
364 * \param destructor Routine to call (to free memory of key) when we quit
366 * \return status - 0 on sucess or a standard error code.
369 int tMPI_Thread_key_create(tMPI_Thread_key_t
*key
, void (*destructor
)(void *));
374 /** Delete thread-specific-storage handle
376 * Calling this routine will kill the handle, and invoke the automatic
377 * destructor routine for each non-NULL value pointed to by key.
379 * \param key Opaque key type to destroy
380 * \return 0 or a non-zero error message.
382 int tMPI_Thread_key_delete(tMPI_Thread_key_t key
);
387 /** Get value for thread-specific-storage in this thread
389 * If it has not yet been set, NULL is returned.
391 * \param key Thread-specific-storage handle.
392 * \return Pointer-to-void, the value of the data in this thread.
394 void * tMPI_Thread_getspecific(tMPI_Thread_key_t key
);
398 /** Set value for thread-specific-storage in this thread
400 * \param key Thread-specific-storage handle.
401 * \param value What to set the data to (pointer-to-void).
402 * \return 0 or a non-zero error message.
404 int tMPI_Thread_setspecific(tMPI_Thread_key_t key
, void *value
);
408 /** Run the provided routine exactly once
410 * The control data must have been initialized before calling this routine,
411 * but you can do it with the static initialzer TMPI_THREAD_ONCE_INIT.
413 * tMPI_Thread_once() will not return to any of the calling routines until
414 * the initialization function has been completed.
416 * \param once_data Initialized one-time execution data
417 * \param init_routine Function to call exactly once
418 * \return 0 or a non-zero error message.
420 int tMPI_Thread_once(tMPI_Thread_once_t
*once_data
,
421 void (*init_routine
)(void));
425 /** Initialize condition variable
427 * This routine must be called before using any condition variable
428 * not initialized with static storage class and TMPI_THREAD_COND_INITIALIZER.
430 * \param cond Pointer to previously allocated condition variable
431 * \return 0 or a non-zero error message.
433 int tMPI_Thread_cond_init(tMPI_Thread_cond_t
* cond
);
437 /** Destroy condition variable
439 * This routine should be called when you are done with a condition variable.
440 * Note that it only releases memory allocated internally, not the
441 * tMPI_Thread_cond_t structure you provide a pointer to.
443 * \param cond Pointer to condition variable.
444 * \return 0 or a non-zero error message.
446 int tMPI_Thread_cond_destroy(tMPI_Thread_cond_t
* cond
);
450 /** Wait for a condition to be signaled
452 * This routine releases the mutex, and waits for the condition to be
453 * signaled by another thread before it returns.
455 * Note that threads waiting for conditions with tMPI_Thread_cond_wait
456 * may be subject to spurious wakeups: use this function in a while loop
457 * and check the state of a predicate associated with the wakeup
458 * before leaving the loop.
460 * \param cond condition variable
461 * \param mtx Mutex protecting the condition variable
463 * \return 0 or a non-zero error message.
465 int tMPI_Thread_cond_wait(tMPI_Thread_cond_t
* cond
,
466 tMPI_Thread_mutex_t
* mtx
);
471 /** Unblock one waiting thread
473 * This routine signals a condition variable to one
474 * thread (if any) waiting for it after calling
475 * tMPI_Thread_cond_wait().
477 * \param cond condition variable
479 * \return 0 or a non-zero error message.
481 int tMPI_Thread_cond_signal(tMPI_Thread_cond_t
* cond
);
484 /** Unblock all waiting threads
486 * This routine signals a condition variable to all
487 * (if any) threads that are waiting for it after calling
488 * tMPI_Thread_cond_wait().
490 * \param cond condition variable
492 * \return 0 or a non-zero error message.
494 int tMPI_Thread_cond_broadcast(tMPI_Thread_cond_t
* cond
);
499 /** Terminate calling thread
503 * \param value_ptr Pointer to a return value. Threads waiting for us to
504 * join them can read this value if they try.
507 void tMPI_Thread_exit(void * value_ptr
);
511 /** Ask a thread to exit
513 * This routine tries to end the execution of another thread, but there are
514 * no guarantees it will succeed.
516 * \param thread Handle to thread we want to see dead.
517 * \return 0 or a non-zero error message.
519 int tMPI_Thread_cancel(tMPI_Thread_t thread
);
526 /** Initialize a synchronization barrier type
528 * You only need to initialize a barrier once. They cycle
529 * automatically, so after release it is immediately ready
530 * to accept waiting threads again.
532 * \param barrier Pointer to previously allocated barrier type
533 * \param count Number of threads to synchronize. All threads
534 * will be released after \a count calls to
535 * tMPI_Thread_barrier_wait().
537 int tMPI_Thread_barrier_init(tMPI_Thread_barrier_t
*barrier
, int count
);
541 /** Release data in a barrier datatype
543 * \param barrier Pointer to previously
544 * initialized barrier.
546 int tMPI_Thread_barrier_destroy(tMPI_Thread_barrier_t
*barrier
);
549 /** Perform barrier synchronization
551 * This routine blocks until it has been called N times,
552 * where N is the count value the barrier was initialized with.
553 * After N total calls all threads return. The barrier automatically
554 * cycles, and thus requires another N calls to unblock another time.
556 * \param barrier Pointer to previously create barrier.
558 * \return The last thread returns -1, all the others 0.
560 int tMPI_Thread_barrier_wait(tMPI_Thread_barrier_t
*barrier
);
569 #endif /* _TMPI_THREAD_H_ */