1 /*
2  * Copyright (C) by Argonne National Laboratory
3  *     See COPYRIGHT in top-level directory
4  */
5 
6 #include "mpiimpl.h"
7 #include "mpir_info.h"
8 
9 #include <string.h>
10 
11 /* -- Begin Profiling Symbol Block for routine MPI_Info_dup */
12 #if defined(HAVE_PRAGMA_WEAK)
13 #pragma weak MPI_Info_dup = PMPI_Info_dup
14 #elif defined(HAVE_PRAGMA_HP_SEC_DEF)
15 #pragma _HP_SECONDARY_DEF PMPI_Info_dup  MPI_Info_dup
16 #elif defined(HAVE_PRAGMA_CRI_DUP)
17 #pragma _CRI duplicate MPI_Info_dup as PMPI_Info_dup
18 #elif defined(HAVE_WEAK_ATTRIBUTE)
19 int MPI_Info_dup(MPI_Info info, MPI_Info * newinfo) __attribute__ ((weak, alias("PMPI_Info_dup")));
20 #endif
21 /* -- End Profiling Symbol Block */
22 
23 /* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
24    the MPI routines */
25 #ifndef MPICH_MPI_FROM_PMPI
26 #undef MPI_Info_dup
27 #define MPI_Info_dup PMPI_Info_dup
28 
MPIR_Info_dup_impl(MPIR_Info * info_ptr,MPIR_Info ** new_info_ptr)29 int MPIR_Info_dup_impl(MPIR_Info * info_ptr, MPIR_Info ** new_info_ptr)
30 {
31     int mpi_errno = MPI_SUCCESS;
32     MPIR_Info *curr_old, *curr_new;
33 
34     *new_info_ptr = NULL;
35     if (!info_ptr)
36         goto fn_exit;
37 
38     /* Note that this routine allocates info elements one at a time.
39      * In the multithreaded case, each allocation may need to acquire
40      * and release the allocation lock.  If that is ever a problem, we
41      * may want to add an "allocate n elements" routine and execute this
42      * it two steps: count and then allocate */
43     /* FIXME : multithreaded */
44     mpi_errno = MPIR_Info_alloc(&curr_new);
45     MPIR_ERR_CHECK(mpi_errno);
46     *new_info_ptr = curr_new;
47 
48     curr_old = info_ptr->next;
49     while (curr_old) {
50         mpi_errno = MPIR_Info_alloc(&curr_new->next);
51         MPIR_ERR_CHECK(mpi_errno);
52 
53         curr_new = curr_new->next;
54         curr_new->key = MPL_strdup(curr_old->key);
55         curr_new->value = MPL_strdup(curr_old->value);
56 
57         curr_old = curr_old->next;
58     }
59 
60   fn_exit:
61     return mpi_errno;
62   fn_fail:
63     goto fn_exit;
64 }
65 
66 #endif
67 
68 /*@
69     MPI_Info_dup - Returns a duplicate of the info object
70 
71 Input Parameters:
72 . info - info object (handle)
73 
74 Output Parameters:
75 . newinfo - duplicate of info object (handle)
76 
77 .N ThreadSafeInfoRead
78 
79 .N Fortran
80 
81 .N Errors
82 .N MPI_SUCCESS
83 .N MPI_ERR_OTHER
84 @*/
MPI_Info_dup(MPI_Info info,MPI_Info * newinfo)85 int MPI_Info_dup(MPI_Info info, MPI_Info * newinfo)
86 {
87     MPIR_Info *info_ptr = 0, *new_info_ptr;
88     int mpi_errno = MPI_SUCCESS;
89     MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_INFO_DUP);
90 
91     MPIR_ERRTEST_INITIALIZED_ORDIE();
92 
93     MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
94     MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPI_INFO_DUP);
95 
96     /* Validate parameters, especially handles needing to be converted */
97 #ifdef HAVE_ERROR_CHECKING
98     {
99         MPID_BEGIN_ERROR_CHECKS;
100         {
101             MPIR_ERRTEST_INFO(info, mpi_errno);
102         }
103         MPID_END_ERROR_CHECKS;
104     }
105 #endif /* HAVE_ERROR_CHECKING */
106 
107     /* Convert MPI object handles to object pointers */
108     MPIR_Info_get_ptr(info, info_ptr);
109 
110     /* Validate parameters and objects (post conversion) */
111 #ifdef HAVE_ERROR_CHECKING
112     {
113         MPID_BEGIN_ERROR_CHECKS;
114         {
115             /* Validate info_ptr */
116             MPIR_Info_valid_ptr(info_ptr, mpi_errno);
117             MPIR_ERRTEST_ARGNULL(newinfo, "newinfo", mpi_errno);
118         }
119         MPID_END_ERROR_CHECKS;
120     }
121 #endif /* HAVE_ERROR_CHECKING */
122 
123     /* ... body of routine ...  */
124 
125     mpi_errno = MPIR_Info_dup_impl(info_ptr, &new_info_ptr);
126     if (mpi_errno != MPI_SUCCESS)
127         goto fn_fail;
128 
129     *newinfo = new_info_ptr->handle;
130 
131     /* ... end of body of routine ... */
132 
133   fn_exit:
134     MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPI_INFO_DUP);
135     MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
136     return mpi_errno;
137 
138   fn_fail:
139     /* --BEGIN ERROR HANDLING-- */
140 #ifdef HAVE_ERROR_CHECKING
141     {
142         mpi_errno =
143             MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, __func__, __LINE__, MPI_ERR_OTHER,
144                                  "**mpi_info_dup", "**mpi_info_dup %I %p", info, newinfo);
145     }
146 #endif
147     mpi_errno = MPIR_Err_return_comm(NULL, __func__, mpi_errno);
148     goto fn_exit;
149     /* --END ERROR HANDLING-- */
150 }
151