Skip to content

Commit 88a0957

Browse files
committed
first pass at errhandler support
Signed-off-by: Howard Pritchard <howardp@lanl.gov>
1 parent 70bfcb3 commit 88a0957

17 files changed

+225
-54
lines changed

ompi/errhandler/errhandler.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,8 @@ void ompi_errhandler_free (ompi_errhandler_t *errhandler)
255255

256256
ompi_errhandler_t *ompi_errhandler_create(ompi_errhandler_type_t object_type,
257257
ompi_errhandler_generic_handler_fn_t *func,
258-
ompi_errhandler_lang_t lang)
258+
ompi_errhandler_lang_t lang,
259+
ompi_errhandler_converter_fn_t *converter)
259260
{
260261
ompi_errhandler_t *new_errhandler;
261262
int ret;
@@ -298,6 +299,11 @@ ompi_errhandler_t *ompi_errhandler_create(ompi_errhandler_type_t object_type,
298299
default:
299300
break;
300301
}
302+
if (NULL != converter) {
303+
new_errhandler->eh_converter_fn = converter;
304+
} else {
305+
new_errhandler->eh_converter_fn = NULL;
306+
}
301307
}
302308

303309
if (NULL != new_errhandler) {
@@ -626,9 +632,9 @@ static void ompi_errhandler_destruct(ompi_errhandler_t *errhandler)
626632
/* reset the ompi_errhandler_f_to_c_table entry - make sure that the
627633
entry is in the table */
628634

629-
if (NULL!= opal_pointer_array_get_item(&ompi_errhandler_f_to_c_table,
635+
if (NULL!= opal_pointer_array_get_item(&ompi_errhandler_f_to_c_table,
630636
errhandler->eh_f_to_c_index)) {
631-
opal_pointer_array_set_item(&ompi_errhandler_f_to_c_table,
632-
errhandler->eh_f_to_c_index, NULL);
633-
}
637+
opal_pointer_array_set_item(&ompi_errhandler_f_to_c_table,
638+
errhandler->eh_f_to_c_index, NULL);
639+
}
634640
}

ompi/errhandler/errhandler.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* reserved.
1818
* Copyright (c) 2016 Research Organization for Information Science
1919
* and Technology (RIST). All rights reserved.
20-
* Copyright (c) 2018-2021 Triad National Security, LLC. All rights
20+
* Copyright (c) 2018-2025 Triad National Security, LLC. All rights
2121
* reserved.
2222
* $COPYRIGHT$
2323
*
@@ -68,6 +68,13 @@ typedef void (ompi_errhandler_fortran_handler_fn_t)(MPI_Fint *,
6868
*/
6969
typedef void (ompi_errhandler_generic_handler_fn_t)(void *, int *, ...);
7070

71+
72+
/**
73+
* Typedef for convert function (internal MPI ABI support)
74+
*/
75+
76+
typedef void (ompi_errhandler_converter_fn_t)(void *object, int object_type, int *err_code);
77+
7178
/**
7279
* Enum to denote what language the error handler was created from
7380
*/
@@ -108,12 +115,17 @@ struct ompi_errhandler_t {
108115
/* Function pointers. Note that we *have* to have all 4 types
109116
(vs., for example, a union) because the predefined errhandlers
110117
can be invoked on any MPI object type, so we need callbacks for
111-
all of three. */
118+
all of four. */
112119
MPI_Comm_errhandler_function *eh_comm_fn;
113120
ompi_file_errhandler_function *eh_file_fn;
114121
MPI_Win_errhandler_function *eh_win_fn;
115122
MPI_Session_errhandler_function *eh_instance_fn;
116123
ompi_errhandler_fortran_handler_fn_t *eh_fort_fn;
124+
/*
125+
* use a single function for converting OMPI internal handles to ABI
126+
* compliant ones. Only used for user defined errhandlers.
127+
*/
128+
ompi_errhandler_converter_fn_t *eh_converter_fn;
117129

118130
/* index in Fortran <-> C translation array */
119131
int eh_f_to_c_index;
@@ -185,6 +197,7 @@ OMPI_DECLSPEC extern ompi_errhandler_t* ompi_initial_error_handler_eh;
185197
*/
186198
OMPI_DECLSPEC extern void (*ompi_initial_error_handler)(struct ompi_communicator_t **comm, int *error_code, ...);
187199

200+
188201
/**
189202
* Forward declaration so that we don't have to include
190203
* request/request.h here.
@@ -381,6 +394,7 @@ extern opal_atomic_int32_t ompi_instance_count;
381394
* @param[in] object_type Enum of the type of MPI object
382395
* @param[in] func Function pointer of the error handler
383396
* @param[in] language Calling language
397+
* @param[in] converter Optional converter function (used internally for MPI ABI)
384398
*
385399
* @returns errhandler Pointer to the ompi_errorhandler_t that will be
386400
* created and returned
@@ -400,7 +414,8 @@ extern opal_atomic_int32_t ompi_instance_count;
400414
*/
401415
OMPI_DECLSPEC ompi_errhandler_t *ompi_errhandler_create(ompi_errhandler_type_t object_type,
402416
ompi_errhandler_generic_handler_fn_t *func,
403-
ompi_errhandler_lang_t language);
417+
ompi_errhandler_lang_t language,
418+
ompi_errhandler_converter_fn_t *converter);
404419

405420
OMPI_DECLSPEC void ompi_errhandler_free (ompi_errhandler_t *errhandler);
406421

ompi/errhandler/errhandler_invoke.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ int ompi_errhandler_invoke(ompi_errhandler_t *errhandler, void *mpi_object,
8484
comm = (ompi_communicator_t *) mpi_object;
8585
switch (errhandler->eh_lang) {
8686
case OMPI_ERRHANDLER_LANG_C:
87+
if(NULL != errhandler->eh_converter_fn) errhandler->eh_converter_fn((void *)&comm, object_type, &err_code);
8788
errhandler->eh_comm_fn(&comm, &err_code, message, NULL);
8889
break;
8990

@@ -99,6 +100,7 @@ int ompi_errhandler_invoke(ompi_errhandler_t *errhandler, void *mpi_object,
99100
win = (ompi_win_t *) mpi_object;
100101
switch (errhandler->eh_lang) {
101102
case OMPI_ERRHANDLER_LANG_C:
103+
if(NULL != errhandler->eh_converter_fn) errhandler->eh_converter_fn((void *)&win, object_type, &err_code);
102104
errhandler->eh_win_fn(&win, &err_code, message, NULL);
103105
break;
104106

@@ -114,6 +116,7 @@ int ompi_errhandler_invoke(ompi_errhandler_t *errhandler, void *mpi_object,
114116
file = (ompi_file_t *) mpi_object;
115117
switch (errhandler->eh_lang) {
116118
case OMPI_ERRHANDLER_LANG_C:
119+
if(NULL != errhandler->eh_converter_fn) errhandler->eh_converter_fn((void *)&file, object_type, &err_code);
117120
errhandler->eh_file_fn(&file, &err_code, message, NULL);
118121
break;
119122

@@ -129,6 +132,7 @@ int ompi_errhandler_invoke(ompi_errhandler_t *errhandler, void *mpi_object,
129132
instance = (ompi_instance_t *) mpi_object;
130133
switch (errhandler->eh_lang) {
131134
case OMPI_ERRHANDLER_LANG_C:
135+
if(NULL != errhandler->eh_converter_fn) errhandler->eh_converter_fn((void *)&instance, object_type, &err_code);
132136
errhandler->eh_instance_fn(&instance, &err_code, message, NULL);
133137
break;
134138

ompi/mpi/bindings/bindings.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ def main():
5959
parser_header.set_defaults(handler=lambda args, out: c.generate_header(args, out))
6060
parser_header = subparsers_c.add_parser('converters', help='generate converter header file')
6161
parser_header.set_defaults(handler=lambda args, out: c.generate_converters(args, out))
62+
parser_header = subparsers_c.add_parser('converter_aux_functions', help='generate converter auxiliary functions')
63+
parser_header.set_defaults(handler=lambda args, out: c.generate_converter_auxiliary_funcs(args, out))
6264
parser_gen = subparsers_c.add_parser('source', help='generate source file from template file')
6365
# parser = argparse.ArgumentParser(description='C ABI binding generation code')
6466
parser_gen.add_argument('type', choices=('ompi', 'standard'),

ompi/mpi/bindings/c_header.py

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,14 @@
4040
"MPI_Win",
4141
"MPI_Comm_copy_attr_function",
4242
"MPI_Comm_delete_attr_function",
43+
"MPI_Comm_errhandler_function",
44+
"MPI_File_errhandler_function",
45+
"MPI_Session_errhandler_function",
4346
"MPI_Type_copy_attr_function",
4447
"MPI_Type_delete_attr_function",
4548
"MPI_Win_delete_attr_function",
4649
"MPI_Win_copy_attr_function",
50+
"MPI_Win_errhandler_function",
4751
"MPI_T_enum",
4852
"MPI_T_cvar_handle",
4953
"MPI_T_pvar_handle",
@@ -58,21 +62,29 @@
5862
]
5963

6064
DEPRECATED_FUNCTIONS = [
61-
"MPI_Keyval_create",
62-
"MPI_Keyval_free",
63-
"MPI_Attr_put",
64-
"MPI_Attr_get",
65-
"MPI_Attr_delete",
6665
"MPI_Address",
67-
"MPI_Errhandler_create",
68-
"MPI_Errhandler_get",
69-
"MPI_Errhandler_set",
70-
"MPI_Type_extent",
7166
"MPI_Type_hindexed",
7267
"MPI_Type_hvector",
73-
"MPI_Type_lb",
7468
"MPI_Type_struct",
75-
"MPI_Type_ub",
69+
"MPI_Type_extent",
70+
"MPI_Type_lb",
71+
"MPI_Type_lb",
72+
"MPI_LB",
73+
"MPI_UB",
74+
"MPI_Errhandler_create",
75+
"MPI_Errhandler_get",
76+
"MPI_Errhandler_set",
77+
"MPI_Keyval_create",
78+
"MPI_Keyval_free",
79+
"MPI_DUP_FN"
80+
"MPI_NULL_COPY_FN"
81+
"MPI_NULL_DELETE_FN"
82+
"MPI_Attr_delete",
83+
"MPI_Attr_get",
84+
"MPI_Attr_put",
85+
"MPI_COMBINER_HVECTOR_INTEGER",
86+
"MPI_COMBINER_HINDEXED_INTEGER",
87+
"MPI_COMBINER_STRUCT_INTEGER",
7688
]
7789

7890
ENUM_CATEGORIES = [
@@ -323,6 +335,7 @@ def output_constant(const, use_enum: bool, mangle_name: bool):
323335
line = re.sub(datatype_pattern, f"\\g<1>\\g<2>{ABI_INTERNAL}\\g<3>", line)
324336
# TODO: need to enhance pympistandard to be able to prune out deprecated functions
325337
# This stands in as a workaround
338+
comment_out = False
326339
comment_out = any(i in line for i in DEPRECATED_FUNCTIONS)
327340

328341
# function is not in the ABI standard (things in MPI 5.1 chapter 19 sections 19.3.4 and 19.3.5

ompi/mpi/bindings/ompi_bindings/c.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,36 @@ def generate_status_convert_fn_intern_to_abi(self):
672672
# Ignoring the private fields for now
673673
self.dump('}')
674674

675+
def generate_errhandler_args_convert_fn_intern_to_abi(self):
676+
self.dump(f'{consts.INLINE_ATTRS} void ompi_convert_errhandler_args_intern_to_abi(void *object, int object_type, int *err_code)')
677+
self.dump('{')
678+
lines = []
679+
lines.append('ompi_communicator_t **comm;')
680+
lines.append('ompi_file_t **file;')
681+
lines.append('ompi_instance_t **instance;')
682+
lines.append('ompi_win_t **win;')
683+
lines.append(f'*err_code = {ConvertOMPIToStandard.ERROR_CLASS}(*err_code);')
684+
lines.append('switch(object_type) {')
685+
lines.append('case OMPI_ERRHANDLER_TYPE_COMM:')
686+
lines.append('comm = (ompi_communicator_t **)object;')
687+
lines.append(f'*comm = (MPI_Comm *){ConvertOMPIToStandard.COMM}(*comm);')
688+
lines.append('break;')
689+
lines.append('case OMPI_ERRHANDLER_TYPE_WIN:')
690+
lines.append('win = (ompi_win_t **)object;')
691+
lines.append(f'*win = (MPI_Win *){ConvertOMPIToStandard.WIN}(*win);')
692+
lines.append('break;')
693+
lines.append('case OMPI_ERRHANDLER_TYPE_FILE:')
694+
lines.append('file = (ompi_file_t **)object;')
695+
lines.append(f'*file = (MPI_File *){ConvertOMPIToStandard.FILE}(*file);')
696+
lines.append('break;')
697+
lines.append('case OMPI_ERRHANDLER_TYPE_INSTANCE:')
698+
lines.append('instance = (ompi_instance_t **)object;')
699+
lines.append(f'*instance = (MPI_Session *){ConvertOMPIToStandard.SESSION}(*instance);')
700+
lines.append('break;')
701+
lines.append('};')
702+
self.dump_lines(lines);
703+
self.dump('}')
704+
675705
def define(self, type_, name, value):
676706
self.dump(f'#define {name} OMPI_CAST_CONSTANT({type_}, {value})')
677707

@@ -713,6 +743,12 @@ def dump_code(self):
713743
lines.append('}')
714744
lines.append('\n')
715745
self.dump_lines(lines)
746+
#
747+
# TODO: need to do something smarter
748+
#
749+
self.dump('\n')
750+
self.dump(f'void ompi_convert_errhandler_args_intern_to_abi(void *object, int object_type, int *err_code);')
751+
self.dump('\n')
716752

717753
# Now generate the conversion code - there's a reason for the order here
718754
# some converters depend on others being declared earlier in the include
@@ -810,6 +846,55 @@ def dump_code(self):
810846
""")
811847
self.dump(f'#endif /* {header_guard} */')
812848

849+
class ABIConverterGlobalBuilder(ABIConverterBuilder):
850+
851+
def generate_errhandler_args_convert_fn_intern_to_abi(self):
852+
self.dump(f'void ompi_convert_errhandler_args_intern_to_abi(void *object, int object_type, int *err_code)')
853+
self.dump('{')
854+
lines = []
855+
lines.append('ompi_communicator_t **comm;')
856+
lines.append('ompi_file_t **file;')
857+
lines.append('ompi_instance_t **instance;')
858+
lines.append('ompi_win_t **win;')
859+
lines.append(f'*err_code = {ConvertOMPIToStandard.ERROR_CLASS}(*err_code);')
860+
lines.append('switch(object_type) {')
861+
lines.append('case OMPI_ERRHANDLER_TYPE_COMM:')
862+
lines.append('comm = (ompi_communicator_t **)object;')
863+
lines.append(f'*comm = (ompi_communicator_t *){ConvertOMPIToStandard.COMM}(*comm);')
864+
lines.append('break;')
865+
lines.append('case OMPI_ERRHANDLER_TYPE_WIN:')
866+
lines.append('win = (ompi_win_t **)object;')
867+
lines.append(f'*win = (ompi_win_t *){ConvertOMPIToStandard.WIN}(*win);')
868+
lines.append('break;')
869+
lines.append('case OMPI_ERRHANDLER_TYPE_FILE:')
870+
lines.append('file = (ompi_file_t **)object;')
871+
lines.append(f'*file = (ompi_file_t *){ConvertOMPIToStandard.FILE}(*file);')
872+
lines.append('break;')
873+
lines.append('case OMPI_ERRHANDLER_TYPE_INSTANCE:')
874+
lines.append('instance = (ompi_instance_t **)object;')
875+
lines.append(f'*instance = (ompi_instance_t *){ConvertOMPIToStandard.SESSION}(*instance);')
876+
lines.append('break;')
877+
lines.append('};')
878+
self.dump_lines(lines);
879+
self.dump('}')
880+
881+
def dump_code(self):
882+
self.dump('#include "stddef.h"')
883+
self.dump('#include "stdint.h"')
884+
self.dump('#include "ompi/communicator/communicator.h"')
885+
self.dump('#include "ompi/win/win.h"')
886+
self.dump('#include "ompi/file/file.h"')
887+
self.dump('#include "ompi/instance/instance.h"')
888+
self.dump('#include "ompi/errhandler/errhandler.h"')
889+
self.dump('#include "ompi/mpi/c/abi.h"')
890+
self.dump('#include "ompi/mpi/c/abi_converters.h"')
891+
892+
#
893+
# special case converters:
894+
# - errhandler functions convert
895+
#
896+
self.generate_errhandler_args_convert_fn_intern_to_abi()
897+
813898
def print_profiling_header(fn_name, out):
814899
"""Print the profiling header code."""
815900
out.dump('#if OMPI_BUILD_MPI_PROFILING')
@@ -956,6 +1041,12 @@ def generate_function(prototype, fn_name, internal_fn, out, enable_count=False):
9561041
enable_count=True)
9571042

9581043

1044+
def generate_converter_auxiliary_funcs(args, out):
1045+
"""Generate ABI auxiliary files. """
1046+
out.dump(f'/* {consts.GENERATED_MESSAGE} */')
1047+
builder = ABIConverterGlobalBuilder(out)
1048+
builder.dump_code()
1049+
9591050
def generate_converters(args, out):
9601051
"""Generate ABI conversion methods. """
9611052
out.dump(f'/* {consts.GENERATED_MESSAGE} */')

0 commit comments

Comments
 (0)