root/mpich2/trunk/src/mpi/errhan/dynerrutil.c @ 3717

Revision 3717, 9.8 KB (checked in by gropp, 11 months ago)

Added ATTRIBUTE((unused)) in several places; removed unused variables and code; added some fixmes

Line 
1/* -*- Mode: C; c-basic-offset:4 ; -*- */
2/*
3 *
4 *  (C) 2001 by Argonne National Laboratory.
5 *      See COPYRIGHT in top-level directory.
6 */
7
8#include "mpiimpl.h"
9#include "errcodes.h"
10
11#include <string.h>
12
13/*
14 * This file contains the routines needed to implement the MPI routines that
15 * can add error classes and codes during runtime.  This file is organized
16 * so that applications that do not use the MPI-2 routines to create new
17 * error codes will not load any of this code. 
18 *
19 * ROMIO has been customized to provide error messages with the same tools
20 * as the rest of MPICH2 and will not rely on the dynamically assigned
21 * error classes.  This leaves all of the classes and codes for the user.
22 *
23 * Because we have customized ROMIO, we do not need to implement
24 * instance-specific messages for the dynamic error codes. 
25 */
26
27/* Local data structures.
28   A message may be associated with each class and code.
29   Since we limit the number of user-defined classes and code (no more
30   than 256 of each), we allocate an array of pointers to the messages here.
31
32   We *could* allow 256 codes with each class.  However, we don't expect
33   any need for this many codes, so we simply allow 256 (actually
34   ERROR_MAX_NCODE) codes, and distribute these among the error codes.
35
36   A user-defined error code has the following format.  The ERROR_xxx
37   is the macro that may be used to extract the data (usually a MASK and
38   a (right)shift)
39
40   [0-6] Class (same as predefined error classes);  ERROR_CLASS_MASK
41   [7]   Is dynamic; ERROR_DYN_MASK and ERROR_DYN_SHIFT
42   [8-18] Code index (for messages); ERROR_GENERIC_MASK and ERROR_GENERIC_SHIFT
43   [19-31] Zero (unused but defined as zero)
44*/
45
46static int  not_initialized = 1;  /* This allows us to use atomic decr */
47static const char *(user_class_msgs[ERROR_MAX_NCLASS]) = { 0 };
48static const char *(user_code_msgs[ERROR_MAX_NCODE]) = { 0 };
49static int  first_free_class = 0;
50static int  first_free_code  = 1;  /* code 0 is reserved */
51
52/* Forward reference */
53const char *MPIR_Err_get_dynerr_string( int code );
54
55/* This external allows this package to define the routine that converts
56   dynamically assigned codes and classes to their corresponding strings.
57   A cleaner implementation could replace this exposed global with a method
58   defined in the error_string.c file that allowed this package to set
59   the routine. */
60
61static int MPIR_Dynerrcodes_finalize( void * );
62
63/* Local routine to initialize the data structures for the dynamic
64   error classes and codes.
65
66   MPIR_Init_err_dyncodes is called if not_initialized is true. 
67   Because all of the routines in this file are called by the
68   MPI_Add_error_xxx routines, and those routines use the SINGLE_CS
69   when the implementation is multithreaded, these routines (until
70   we implement finer-grain thread-synchronization) need not worry about
71   multiple threads
72 */
73static void MPIR_Init_err_dyncodes( void )
74{
75    int i;
76
77    /* FIXME: Does this need a thread-safe init? */
78    not_initialized = 0;
79   
80    for (i=0; i<ERROR_MAX_NCLASS; i++) {
81        user_class_msgs[i] = 0;
82    }
83    for (i=0; i<ERROR_MAX_NCODE; i++) {
84        user_code_msgs[i] = 0;
85    }
86    /* Set the routine to provides access to the dynamically created
87       error strings */
88    MPIR_Process.errcode_to_string = MPIR_Err_get_dynerr_string;
89
90    /* Add a finalize handler to free any allocated space */
91    MPIR_Add_finalize( MPIR_Dynerrcodes_finalize, (void*)0, 9 );
92}
93
94/*
95  MPIR_Err_set_msg - Change the message for an error code or class
96
97  Input Parameter:
98+ code - Error code or class
99- msg  - New message to use
100
101  Notes:
102  This routine is needed to implement 'MPI_Add_error_string'.
103*/
104int MPIR_Err_set_msg( int code, const char *msg_string )
105{
106    int errcode, errclass;
107    size_t msg_len;
108    char *str;
109    static const char FCNAME[] = "MPIR_Err_set_msg";
110
111    /* --BEGIN ERROR HANDLING-- */
112    if (not_initialized) {
113        /* Just to keep the rest of the code more robust, we'll
114           initialize the dynamic error codes *anyway*, but this is
115           an error (see MPI_Add_error_string in the standard) */
116        MPIR_Init_err_dyncodes();
117        return MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, 
118                                     "MPIR_Err_set_msg", __LINE__, 
119                                     MPI_ERR_ARG, "**argerrcode", 
120                                     "**argerrcode %d", code );
121    }
122    /* --END ERROR HANDLING-- */
123   
124    /* Error strings are attached to a particular error code, not class.
125       As a special case, if the code is 0, we use the class message */
126    errclass = code & ERROR_CLASS_MASK;
127    errcode  = (code & ERROR_GENERIC_MASK) >> ERROR_GENERIC_SHIFT;
128
129    /* --BEGIN ERROR HANDLING-- */
130    if (code & ~(ERROR_CLASS_MASK | ERROR_DYN_MASK | ERROR_GENERIC_MASK)) {
131        /* Check for invalid error code */
132        return MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, 
133                                     FCNAME, __LINE__, 
134                                     MPI_ERR_ARG, "**argerrcode", 
135                                     "**argerrcode %d", code );
136    }
137    /* --END ERROR HANDLING-- */
138
139    /* --------------------------------------------------------------------- */
140    msg_len = strlen( msg_string );
141    str = (char *)MPIU_Malloc( msg_len + 1 );
142    /* --BEGIN ERROR HANDLING-- */
143    if (!str) {
144        return MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE,
145                                     FCNAME, __LINE__, MPI_ERR_OTHER, 
146                                     "**nomem", "**nomem %s %d", 
147                                     "error message string", msg_len );
148    }
149    /* --END ERROR HANDLING-- */
150
151    /* --------------------------------------------------------------------- */
152    MPIU_Strncpy( str, msg_string, msg_len + 1 );
153    if (errcode) {
154        if (errcode < first_free_code) {
155            if (user_code_msgs[errcode]) {
156                MPIU_Free( (void*)(user_code_msgs[errcode]) );
157            }
158            user_code_msgs[errcode] = (const char *)str;
159        }
160        else {
161            /* FIXME : Unallocated error code? */
162            MPIU_Free( str );
163        }
164    }
165    else {
166        if (errclass < first_free_class) {
167            if (user_class_msgs[errclass]) {
168                MPIU_Free( (void*)(user_class_msgs[errclass]) );
169            }
170            user_class_msgs[errclass] = (const char *)str;
171        }
172        else {
173            /* FIXME : Unallocated error code? */
174            MPIU_Free( str );
175        }
176    }
177       
178    return MPI_SUCCESS;
179}
180
181/*
182  MPIR_Err_add_class - Creata a new error class
183
184  Return value:
185  An error class.  Returns -1 if no more classes are available.
186
187  Notes:
188  This is used to implement 'MPI_Add_error_class'; it may also be used by a
189  device to add device-specific error classes. 
190
191  Predefined classes are handled directly; this routine is not used to
192  initialize the predefined MPI error classes.  This is done to reduce the
193  number of steps that must be executed when starting an MPI program.
194
195  This routine should be run within a SINGLE_CS in the multithreaded case.
196*/
197int MPIR_Err_add_class()
198{
199    int new_class;
200
201    if (not_initialized)
202        MPIR_Init_err_dyncodes();
203       
204    /* Get new class */
205    MPIR_Fetch_and_increment( &first_free_class, &new_class );
206
207    /* --BEGIN ERROR HANDLING-- */
208    if (new_class >= ERROR_MAX_NCLASS) {
209        /* Fail if out of classes */
210        return -1;
211    }
212    /* --END ERROR HANDLING-- */
213
214    /* Note that the MPI interface always adds an error class without
215       a string.  */
216    user_class_msgs[new_class] = 0;
217
218    return (new_class | ERROR_DYN_MASK);
219}
220
221/*
222  MPIR_Err_add_code - Create a new error code that is associated with an
223  existing error class
224
225  Input Parameters:
226. class - Error class to which the code belongs.
227
228  Return value:
229  An error code.
230
231  Notes:
232  This is used to implement 'MPI_Add_error_code'; it may also be used by a
233  device to add device-specific error codes. 
234
235  */
236int MPIR_Err_add_code( int class )
237{
238    int new_code;
239
240    /* Note that we can add codes to existing classes, so we may
241       need to initialize the dynamic error routines in this function */
242    if (not_initialized)
243        MPIR_Init_err_dyncodes();
244
245    /* Get the new code */
246    MPIR_Fetch_and_increment( &first_free_code, &new_code );
247    /* --BEGIN ERROR HANDLING-- */
248    if (new_code >= ERROR_MAX_NCODE) {
249        /* Fail if out of codes */
250        return -1;
251    }
252    /* --END ERROR HANDLING-- */
253
254    /* Create the full error code */
255    new_code = class | ERROR_DYN_MASK | (new_code << ERROR_GENERIC_SHIFT);
256
257    /* FIXME: For robustness, we should make sure that the associated string
258       is initialized to null */
259    return new_code;
260}
261
262/*
263  MPIR_Err_get_dynerr_string - Get the message string that corresponds to a
264  dynamically created error class or code
265
266  Input Parameter:
267+ code - An error class or code.  If a code, it must have been created by
268  'MPIR_Err_create_code'.
269
270  Return value:
271  A pointer to a null-terminated text string with the corresponding error
272  message.  A null return indicates an error; usually the value of 'code' is
273  neither a valid error class or code.
274
275  Notes:
276  This routine is used to implement 'MPI_ERROR_STRING'.  It is only called
277  for dynamic error codes. 
278  */
279const char *MPIR_Err_get_dynerr_string( int code )
280{
281    int errcode, errclass;
282    const char *errstr = 0;
283
284    /* Error strings are attached to a particular error code, not class.
285       As a special case, if the code is 0, we use the class message */
286    errclass = code & ERROR_CLASS_MASK;
287    errcode  = (code & ERROR_GENERIC_MASK) >> ERROR_GENERIC_SHIFT;
288
289    if (code & ~(ERROR_CLASS_MASK | ERROR_DYN_MASK | ERROR_GENERIC_MASK)) {
290        /* Check for invalid error code */
291        return 0;
292    }
293
294    if (errcode) {
295        if (errcode < first_free_code) {
296            errstr = user_code_msgs[errcode];
297        }
298    }
299    else {
300        if (errclass < first_free_class) {
301            errstr = user_class_msgs[errclass];
302        }
303    }
304       
305    return errstr;
306}
307
308
309static int MPIR_Dynerrcodes_finalize( void *p ATTRIBUTE((unused)) )
310{
311    int i;
312
313    MPIU_UNREFERENCED_ARG(p);
314
315    if (not_initialized == 0) {
316
317        for (i=0; i<first_free_class; i++) {
318            if (user_class_msgs[i])
319                MPIU_Free((char *) user_class_msgs[i]);
320        }
321
322        for (i=0; i<first_free_code; i++) {
323            if (user_code_msgs[i])
324                MPIU_Free((char *) user_code_msgs[i]);
325        }
326    }
327    return 0;
328}
Note: See TracBrowser for help on using the browser.