Fix use of inline in IMD
[alexxy/gromacs.git] / src / external / thread_mpi / src / errhandler.c
1 /*
2    This source code file is part of thread_mpi.
3    Written by Sander Pronk, Erik Lindahl, and possibly others.
4
5    Copyright (c) 2009, Sander Pronk, Erik Lindahl.
6    All rights reserved.
7
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.
18
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.
29
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
35    files.
36  */
37
38 #ifdef HAVE_TMPI_CONFIG_H
39 #include "tmpi_config.h"
40 #endif
41
42 #ifdef HAVE_CONFIG_H
43 #include "config.h"
44 #endif
45
46 #ifdef HAVE_UNISTD_H
47 #include <unistd.h>
48 #endif
49
50 #include <errno.h>
51 #include <stdlib.h>
52 #include <stdio.h>
53 #include <string.h>
54 #if !(defined( _WIN32 ) || defined( _WIN64 ) )
55 #include <sys/time.h>
56 #endif
57
58 #include "impl.h"
59
60
61
62
63
64
65 struct tmpi_errhandler_ tmpi_errors_are_fatal = { 0, tmpi_errors_are_fatal_fn };
66 struct tmpi_errhandler_ tmpi_errors_return = { 0, tmpi_errors_return_fn };
67
68
69 tMPI_Errhandler TMPI_ERRORS_ARE_FATAL = &tmpi_errors_are_fatal;
70 tMPI_Errhandler TMPI_ERRORS_RETURN    = &tmpi_errors_return;
71
72
73
74
75 /* error messages. Must match error codes in thread_mpi.h */
76 static const char *tmpi_errmsg[] =
77 {
78     "No error",
79     "malloc failure in tMPI (out of memory)",
80     "I/O or system error",
81     "tMPI Initialization error",
82     "tMPI Finalize error",
83     "Invalid tMPI_Group",
84     "Invalid tMPI_Comm",
85     "Invalid tMPI_Status",
86     "Invalid tMPI_Group rank",
87     "Invalid Cartesian topology dimensions",
88     "Invalid Cartesian topology coordinates",
89     "Insufficient number processes for Cartesian topology",
90     "Invalid counterpart for MPI transfer",
91     "Receive buffer size too small for transmission",
92     "Overlapping send/receive buffers: probably due to thread-unsafe code.",
93     "Invalid send destination",
94     "Invalid receive source",
95     "Invalid buffer (null pointer in send or receive buffer)",
96     "Multicast operation mismatch (multicast not collective across comm)",
97     "Invalid reduce operator",
98     "Out of receive envelopes: this shouldn't happen (probably a bug).",
99     "Out of receive requests: this shouldn't happen (probably a bug).",
100     "Out of copy buffers: this shouldn't happen (probably a bug).",
101     "Copy buffer size too small: this shouldn't happen (probably a bug).",
102     "Error in MPI_Status",
103     "Error getting/setting processor layout/affinity",
104     "Transmission failure",
105     "Unknown tMPI error"
106 };
107
108
109
110 int tMPI_Error(tMPI_Comm comm, int tmpi_errno)
111 {
112     if (comm)
113     {
114         comm->erh->err = tmpi_errno;
115         comm->erh->fn(&comm, &tmpi_errno);
116     }
117     else
118     {
119         /* initialization errors have no comm */
120         tmpi_errors_are_fatal_fn(NULL, &tmpi_errno);
121     }
122     return tmpi_errno;
123 }
124
125
126 int tMPI_Error_string(int errorcode, char *strn, size_t *resultlen)
127 {
128     if (errorcode < 0 || errorcode >= N_TMPI_ERR)
129     {
130         errorcode = TMPI_ERR_UNKNOWN;
131     }
132
133     if (errorcode != TMPI_ERR_IO)
134     {
135 #if !(defined( _WIN32 ) || defined( _WIN64 ) )
136         strncpy(strn, tmpi_errmsg[errorcode], TMPI_MAX_ERROR_STRING);
137 #else
138         strncpy_s(strn, TMPI_MAX_ERROR_STRING, tmpi_errmsg[errorcode],
139                   TMPI_MAX_ERROR_STRING);
140 #endif
141     }
142     else
143     {
144 #if !(defined( _WIN32 ) || defined( _WIN64 ) )
145         snprintf(strn, TMPI_MAX_ERROR_STRING,
146                  "%s: %s", tmpi_errmsg[errorcode], strerror(errno));
147 #else
148         char buf[TMPI_MAX_ERROR_STRING];
149
150         strerror_s(buf, TMPI_MAX_ERROR_STRING-1, errno);
151         _snprintf_s(strn, TMPI_MAX_ERROR_STRING, _TRUNCATE,
152                     "%s: %s", tmpi_errmsg[errorcode], buf);
153 #endif
154
155     }
156     *resultlen = strlen(strn);
157     return TMPI_SUCCESS;
158 }
159
160 int tMPI_Create_errhandler(tMPI_Errhandler_fn *function,
161                            tMPI_Errhandler    *errhandler)
162 {
163 #ifdef TMPI_TRACE
164     tMPI_Trace_print("tMPI_Create_errhandler(%p, %p)", function, errhandler);
165 #endif
166
167     /* we don't use a special malloc here because this is the error handler
168        creation function. */
169     *errhandler = (tMPI_Errhandler)malloc(sizeof(struct tmpi_errhandler_));
170     if (!*errhandler)
171     {
172         fprintf(stderr, "tMPI fatal error (%s), bailing out\n",
173                 tmpi_errmsg[TMPI_ERR_NO_MEM]);
174         abort();
175     }
176     (*errhandler)->err = 0;
177     (*errhandler)->fn  = *function;
178     return TMPI_SUCCESS;
179 }
180
181 int tMPI_Errhandler_free(tMPI_Errhandler *errhandler)
182 {
183 #ifdef TMPI_TRACE
184     tMPI_Trace_print("tMPI_Errhandler_free(%p)", errhandler);
185 #endif
186
187     free(*errhandler);
188     return TMPI_SUCCESS;
189 }
190
191
192 int tMPI_Comm_set_errhandler(tMPI_Comm comm, tMPI_Errhandler errhandler)
193 {
194 #ifdef TMPI_TRACE
195     tMPI_Trace_print("tMPI_Comm_set_errhandler(%p, %p)", comm, errhandler);
196 #endif
197
198     comm->erh = errhandler;
199     return TMPI_SUCCESS;
200 }
201
202 int tMPI_Comm_get_errhandler(tMPI_Comm comm, tMPI_Errhandler *errhandler)
203 {
204 #ifdef TMPI_TRACE
205     tMPI_Trace_print("tMPI_Comm_get_errhandler(%p, %p)", comm, errhandler);
206 #endif
207
208     *errhandler = comm->erh;
209     return TMPI_SUCCESS;
210 }
211
212 void tmpi_errors_are_fatal_fn(tMPI_Comm *comm, int *err)
213 {
214     char   errstr[TMPI_MAX_ERROR_STRING];
215     size_t len;
216
217     tMPI_Error_string(*err, errstr, &len);
218     if (comm)
219     {
220         fprintf(stderr, "tMPI error: %s (in valid comm)\n", errstr);
221     }
222     else
223     {
224         fprintf(stderr, "tMPI error: %s\n", errstr);
225     }
226     abort();
227     /*exit(0);*/
228 }
229
230 void tmpi_errors_return_fn(tMPI_Comm *comm, int *err)
231 {
232     char   errstr[TMPI_MAX_ERROR_STRING];
233     size_t len;
234
235     tMPI_Error_string(*err, errstr, &len);
236     if (comm)
237     {
238         fprintf(stderr, "tMPI error: %s (in valid comm)\n", errstr);
239     }
240     else
241     {
242         fprintf(stderr, "tMPI error: %s\n", errstr);
243     }
244     return;
245 }