00001 /* 00002 * Copyright (C) 2007 Jolien Creighton 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with with program; see the file COPYING. If not, write to the 00016 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 00017 * MA 02111-1307 USA 00018 */ 00019 00020 /****************************** <lalVerbatim file="LALGSLHV"> 00021 Author: Creighton, J. D. E. 00022 $Id: LALGSL.h,v 1.5 2007/06/08 14:41:52 bema Exp $ 00023 ******************************* </lalVerbatim> */ 00024 00025 /* <lalLaTeX> 00026 00027 \section{Header \texttt{LALGSL.h}} 00028 \label{s:LALGSL.h} 00029 00030 Provides macros for integrating the GSL error handler with 00031 the LAL status structure. 00032 00033 \subsection*{Synopsis} 00034 \begin{verbatim} 00035 #include <lal/LALGSL.h> 00036 \end{verbatim} 00037 00038 \noindent This header provides macros and functions for tracking and 00039 reporting the runtime status of a GSL calls. The intent is 00040 simultaneously to standardize the error reporting, and to make the 00041 reporting as transparent as possible to people coding individual 00042 routines. 00043 00044 \emph{Please always use these macros when making a GSL call 00045 within LAL. This will ensure that the LAL functions always have the 00046 same behaviour and will also ensure that the LAL functions are reenterant 00047 and threadsafe (when LAL is configured appropriately).} 00048 00049 \subsubsection{GSL function calls} 00050 00051 The behaviour of GSL functions depends on the error handler that has been 00052 assigned. In order that LAL functions always have the same behaviour, it 00053 is necessary to use a LAL-specific GSL error handler. This error handler 00054 populates a LAL status structure with the GSL error message and code so that 00055 GSL functions behave much the same way as LAL functions. After the GSL 00056 functions are called, the error handler needs to be restored to the original 00057 handler so that the program calling the LAL routine has the same error handler 00058 after the LAL function was called as it did before the LAL function was called. 00059 00060 This module provides a simple set of macros and the default LAL GSL error 00061 handler. The macros provide a standard way to assign the LAL GSL error 00062 handler before a GSL function call and to restore the original handler after 00063 the call. 00064 00065 Note that changing the GSL error handler is \emph{not} a thread-safe 00066 action. Therefore it is necessary to block other threads from performing 00067 GSL function calls while one thread has changed the handler. These macros 00068 ensure that such blocking is done for GSL function calls 00069 \emph{within other LAL routines} if LAL is configured with the 00070 \verb+--enable-pthread-lock+ flag. See below for instructions on how 00071 to make other GSL function calls outside LAL thread-safe when used with LAL. 00072 00073 \begin{verbatim} 00074 ATTATCHSTATUSPTR( status ); 00075 CALLGSL( gsl_function( x ), status ); 00076 CHECKSTATUSPTR( status ); 00077 DETATCHSTATUSPTR( status ); 00078 \end{verbatim} 00079 Note that the LAL function must attach (and detach) a status pointer as if 00080 a LAL routine were called. 00081 Note also that you need to use the \verb+CHECKSTATUSPTR+ macro to check 00082 the status of the call. The equivalent to the \verb+TRY+ macro for GSL 00083 functions is the \verb+TRYGSL+ macro, which is used as follows: 00084 \begin{verbatim} 00085 ATTATCHSTATUSPTR( status ); 00086 TRYGSL( gsl_function( x ), status ); 00087 DETATCHSTATUSPTR( status ); 00088 \end{verbatim} 00089 00090 If you are using GSL functions both in LAL and in the calling program, and 00091 you are worried about thread-safety, the GSL function calls outside of LAL 00092 need to be blocked so that they do not access the GSL error handler while 00093 it has been changed to the LAL GSL error handler in a LAL function. To do 00094 this, you need to do the following: 00095 \begin{verbatim} 00096 #include<lal/LALGSL.h> 00097 ... 00098 LALGSL_PTHREAD_MUTEX_LOCK; 00099 gsl_function( x ); 00100 LALGSL_PTHREAD_MUTEX_UNLOCK; 00101 \end{verbatim} 00102 This ensures that \verb+gsl_function+ is not called while a LAL routine 00103 is calling a GSL function in a different thread. You can do this even if 00104 you don't always run your code with multiple threads. If you configure LAL 00105 without the \verb+--enable-pthread-lock+ flag, the macros 00106 \verb+LALGSL_PTHREAD_MUTEX_LOCK+ and \verb+LALGSL_PTHREAD_MUTEX_UNLOCK+ 00107 do nothing. 00108 00109 \vfill{\footnotesize\input{LALGSLHV}} 00110 \newpage\input{LALGSLC} 00111 \newpage\input{LALGSLTestC} 00112 </lalLaTeX> */ 00113 00114 #ifndef _LALGSL_H 00115 #define _LALGSL_H 00116 00117 #include <lal/LALConfig.h> 00118 #ifdef NDEBUG 00119 #ifndef LAL_NDEBUG 00120 #define LAL_NDEBUG 00121 #endif 00122 #endif 00123 00124 #include <stdlib.h> 00125 #include <string.h> 00126 00127 #include <lal/LALMalloc.h> 00128 #include <lal/LALDatatypes.h> 00129 #include <lal/LALError.h> 00130 #include <lal/LALRCSID.h> 00131 00132 #include <lal/XLALGSL.h> 00133 00134 #include <gsl/gsl_errno.h> 00135 00136 #ifdef __cplusplus 00137 extern "C" { 00138 #endif 00139 00140 NRCSID( LALGSLH, "$Id: LALGSL.h,v 1.5 2007/06/08 14:41:52 bema Exp $" ); 00141 00142 extern LALStatus * lalGSLGlobalStatusPtr; 00143 void 00144 LALGSLErrorHandler( 00145 const char *reason, 00146 const char *file, 00147 int line, 00148 int errnum 00149 ); 00150 00151 #ifdef LAL_PTHREAD_LOCK 00152 #include <pthread.h> 00153 extern pthread_mutex_t lalGSLPthreadMutex; 00154 #define LALGSL_PTHREAD_MUTEX_LOCK pthread_mutex_lock( &lalGSLPthreadMutex ) 00155 #define LALGSL_PTHREAD_MUTEX_UNLOCK pthread_mutex_unlock( &lalGSLPthreadMutex ) 00156 #else 00157 #define LALGSL_PTHREAD_MUTEX_LOCK ((void)(0)) 00158 #define LALGSL_PTHREAD_MUTEX_UNLOCK ((void)(0)) 00159 #endif 00160 00161 /* 00162 * 00163 * FIXME: Must disable pthread safety commands.... Problems arise if the 00164 * statement calls a LAL function that tries to call a GSL function using 00165 * CALLGSL ... this blocks! TODO: Instead, use thread-specific globals. 00166 * 00167 */ 00168 00169 #define CALLGSL( statement, statusptr ) \ 00170 if ( (statusptr) ) \ 00171 { \ 00172 LALStatus *saveLALGSLGlobalStatusPtr_; \ 00173 gsl_error_handler_t *saveGSLErrorHandler_; \ 00174 if ( !( (statusptr)->statusPtr ) ) \ 00175 { ABORT( (statusptr), -8, "CALLGSL: null status pointer pointer" ); } \ 00176 /* LALGSL_PTHREAD_MUTEX_LOCK; */ 00177 saveGSLErrorHandler_ = gsl_set_error_handler( LALGSLErrorHandler ); 00178 saveLALGSLGlobalStatusPtr_ = lalGSLGlobalStatusPtr; 00179 lalGSLGlobalStatusPtr = (statusptr)->statusPtr; 00180 statement; 00181 lalGSLGlobalStatusPtr = saveLALGSLGlobalStatusPtr_; 00182 gsl_set_error_handler( saveGSLErrorHandler_ ); 00183 /* LALGSL_PTHREAD_MUTEX_UNLOCK; */ 00184 } 00185 else 00186 lalAbortHook( "Abort: CALLGSL, file %s, line %d\n" 00187 " Null status pointer passed to CALLGSL\n", 00188 __FILE__, __LINE__ ) 00189 00190 00191 #define TRYGSL( statement, statusptr ) \ 00192 if ( (statusptr) ) \ 00193 { \ 00194 LALStatus *saveLALGSLGlobalStatusPtr_; \ 00195 gsl_error_handler_t *saveGSLErrorHandler_; \ 00196 if ( !( (statusptr)->statusPtr ) ) \ 00197 { ABORT( (statusptr), -8, "CALLGSL: null status pointer pointer" ); } \ 00198 /* LALGSL_PTHREAD_MUTEX_LOCK; */ 00199 saveGSLErrorHandler_ = gsl_set_error_handler( LALGSLErrorHandler ); 00200 saveLALGSLGlobalStatusPtr_ = lalGSLGlobalStatusPtr; 00201 lalGSLGlobalStatusPtr = (statusptr)->statusPtr; 00202 statement; 00203 lalGSLGlobalStatusPtr = saveLALGSLGlobalStatusPtr_; 00204 gsl_set_error_handler( saveGSLErrorHandler_ ); 00205 /* LALGSL_PTHREAD_MUTEX_UNLOCK; */ 00206 if ( (statusptr)->statusPtr->statusCode ) 00207 { 00208 SETSTATUS( statusptr, -1, "Recursive error" ); 00209 (void) LALError( statusptr, "Statement \"" #statement "\" failed:" ); 00210 (void) LALTrace( statusptr, 1 ); 00211 return; 00212 } 00213 } 00214 else 00215 lalAbortHook( "Abort: CALLGSL, file %s, line %d\n" 00216 " Null status pointer passed to CALLGSL\n", 00217 __FILE__, __LINE__ ) 00218 00219 #ifdef __cplusplus 00220 } 00221 #endif 00222 00223 #endif /* _LALGSL_H */
1.5.2