Code beautification with uncrustify
[alexxy/gromacs.git] / src / gromacs / gmxlib / thread_mpi / 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     "tMPI Initialization error",
81     "tMPI Finalize error",
82     "Invalid tMPI_Group",
83     "Invalid tMPI_Comm",
84     "Invalid tMPI_Status",
85     "Invalid tMPI_Group rank",
86     "Invalid Cartesian topology dimensions",
87     "Invalid Cartesian topology coordinates",
88     "Insufficient number processes for Cartesian topology",
89     "Invalid counterpart for MPI transfer",
90     "Receive buffer size too small for transmission",
91     "Overlapping send/receive buffers: probably due to thread-unsafe code.",
92     "Invalid send destination",
93     "Invalid receive source",
94     "Invalid buffer (null pointer in send or receive buffer)",
95     "Multicast operation mismatch (multicast not collective across comm)",
96     "Invalid reduce operator",
97     "Out of receive envelopes: this shouldn't happen (probably a bug).",
98     "Out of receive requests: this shouldn't happen (probably a bug).",
99     "Transmission failure",
100     "Unknown tMPI error"
101 };
102
103
104
105 int tMPI_Error(tMPI_Comm comm, int tmpi_errno)
106 {
107     if (comm)
108     {
109         comm->erh->err = tmpi_errno;
110         comm->erh->fn(&comm, &tmpi_errno);
111     }
112     else
113     {
114         /* initialization errors have no comm */
115         tmpi_errors_are_fatal_fn(NULL, &tmpi_errno);
116     }
117     return tmpi_errno;
118 }
119
120
121 int tMPI_Error_string(int errorcode, char *strn, size_t *resultlen)
122 {
123     if (errorcode < 0 || errorcode >= N_TMPI_ERR)
124     {
125         errorcode = TMPI_ERR_UNKNOWN;
126     }
127
128 #if !(defined( _WIN32 ) || defined( _WIN64 ) )
129     strncpy(strn, tmpi_errmsg[errorcode], TMPI_MAX_ERROR_STRING);
130 #else
131     strncpy_s(strn, TMPI_MAX_ERROR_STRING, tmpi_errmsg[errorcode], TMPI_MAX_ERROR_STRING);
132 #endif
133     *resultlen = strlen(strn);
134     return TMPI_SUCCESS;
135 }
136
137 int tMPI_Create_errhandler(tMPI_Errhandler_fn *function,
138                            tMPI_Errhandler    *errhandler)
139 {
140 #ifdef TMPI_TRACE
141     tMPI_Trace_print("tMPI_Create_errhandler(%p, %p)", function, errhandler);
142 #endif
143
144     /* we don't use a special malloc here because this is the error handler
145        creation function. */
146     *errhandler = (tMPI_Errhandler)malloc(sizeof(struct tmpi_errhandler_));
147     if (!*errhandler)
148     {
149         fprintf(stderr, "tMPI fatal error (%s), bailing out\n",
150                 tmpi_errmsg[TMPI_ERR_MALLOC]);
151         abort();
152     }
153     (*errhandler)->err = 0;
154     (*errhandler)->fn  = *function;
155     return TMPI_SUCCESS;
156 }
157
158 int tMPI_Errhandler_free(tMPI_Errhandler *errhandler)
159 {
160 #ifdef TMPI_TRACE
161     tMPI_Trace_print("tMPI_Errhandler_free(%p)", errhandler);
162 #endif
163
164     free(*errhandler);
165     return TMPI_SUCCESS;
166 }
167
168
169 int tMPI_Comm_set_errhandler(tMPI_Comm comm, tMPI_Errhandler errhandler)
170 {
171 #ifdef TMPI_TRACE
172     tMPI_Trace_print("tMPI_Comm_set_errhandler(%p, %p)", comm, errhandler);
173 #endif
174
175     comm->erh = errhandler;
176     return TMPI_SUCCESS;
177 }
178
179 int tMPI_Comm_get_errhandler(tMPI_Comm comm, tMPI_Errhandler *errhandler)
180 {
181 #ifdef TMPI_TRACE
182     tMPI_Trace_print("tMPI_Comm_get_errhandler(%p, %p)", comm, errhandler);
183 #endif
184
185     *errhandler = comm->erh;
186     return TMPI_SUCCESS;
187 }
188
189 void tmpi_errors_are_fatal_fn(tMPI_Comm *comm, int *err)
190 {
191     char   errstr[TMPI_MAX_ERROR_STRING];
192     size_t len;
193
194     tMPI_Error_string(*err, errstr, &len);
195     if (comm)
196     {
197         fprintf(stderr, "tMPI error: %s (in valid comm)\n", errstr);
198     }
199     else
200     {
201         fprintf(stderr, "tMPI error: %s\n", errstr);
202     }
203     abort();
204     /*exit(0);*/
205 }
206
207 void tmpi_errors_return_fn(tMPI_Comm *comm, int *err)
208 {
209     char   errstr[TMPI_MAX_ERROR_STRING];
210     size_t len;
211
212     tMPI_Error_string(*err, errstr, &len);
213     if (comm)
214     {
215         fprintf(stderr, "tMPI error: %s (in valid comm)\n", errstr);
216     }
217     else
218     {
219         fprintf(stderr, "tMPI error: %s\n", errstr);
220     }
221     return;
222 }