comm_set_attr.c 8.87 KB
Newer Older
1
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
 *
 *  (C) 2001 by Argonne National Laboratory.
 *      See COPYRIGHT in top-level directory.
 */

#include "mpiimpl.h"
#include "attr.h"

/* -- Begin Profiling Symbol Block for routine MPI_Comm_set_attr */
#if defined(HAVE_PRAGMA_WEAK)
#pragma weak MPI_Comm_set_attr = PMPI_Comm_set_attr
#elif defined(HAVE_PRAGMA_HP_SEC_DEF)
#pragma _HP_SECONDARY_DEF PMPI_Comm_set_attr  MPI_Comm_set_attr
#elif defined(HAVE_PRAGMA_CRI_DUP)
#pragma _CRI duplicate MPI_Comm_set_attr as PMPI_Comm_set_attr
18
19
#elif defined(HAVE_WEAK_ATTRIBUTE)
int MPI_Comm_set_attr(MPI_Comm comm, int comm_keyval, void *attribute_val) __attribute__((weak,alias("PMPI_Comm_set_attr")));
20
21
22
23
24
25
26
27
#endif
/* -- End Profiling Symbol Block */

/* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
   the MPI routines */
#ifndef MPICH_MPI_FROM_PMPI
#undef MPI_Comm_set_attr
#define MPI_Comm_set_attr PMPI_Comm_set_attr
28
29

#undef FUNCNAME
30
31
32
33
34
#define FUNCNAME MPIR_Comm_set_attr_impl
#undef FCNAME
#define FCNAME MPIU_QUOTE(FUNCNAME)
int MPIR_Comm_set_attr_impl(MPID_Comm *comm_ptr, int comm_keyval, void *attribute_val, 
                            MPIR_AttrType attrType)
35
36
{
    int mpi_errno = MPI_SUCCESS;
37
    MPID_Keyval *keyval_ptr = NULL;
38
    MPID_Attribute *p;
39

40
    MPIU_ERR_CHKANDJUMP(comm_keyval == MPI_KEYVAL_INVALID, mpi_errno, MPI_ERR_KEYVAL, "**keyvalinvalid");
41

42
43
    /* CHANGE FOR MPI 2.2:  Look for attribute.  They are ordered by when they
       were added, with the most recent first. This uses 
44
45
       a simple linear list algorithm because few applications use more than a 
       handful of attributes */
46

47
    MPID_Keyval_get_ptr( comm_keyval, keyval_ptr );
48
49
    MPIU_Assert(keyval_ptr != NULL);

50
51
    /* printf( "Setting attr val to %x\n", attribute_val ); */
    p     = comm_ptr->attributes;
52
53
54
55
    while (p) {
	if (p->keyval->handle == keyval_ptr->handle) {
	    /* If found, call the delete function before replacing the 
	       attribute */
56
	    mpi_errno = MPIR_Call_attr_delete( comm_ptr->handle, p );
57
58
59
	    if (mpi_errno) {
		goto fn_fail;
	    }
60
	    p->attrType = attrType;
61
62
63
64
65
66
67
	    /* FIXME: This code is incorrect in some cases, particularly
	       in the case where MPIR_Pint is different from MPI_Aint, 
	       since in that case, the Fortran 9x interface will provide
	       more bytes in the attribute_val than this allows. The 
	       dual casts are a sign that this is faulty. This will 
	       need to be fixed in the type/win set_attr routines as 
	       well. */
68
	    p->value    = (MPID_AttrVal_t)(MPIR_Pint)attribute_val;
69
	    /* printf( "Updating attr at %x\n", &p->value ); */
70
71
72
73
74
	    /* Does not change the reference count on the keyval */
	    break;
	}
	p = p->next;
    }
75
    /* CHANGE FOR MPI 2.2: If not found, add at the beginning */
76
    if (!p) {
77
	MPID_Attribute *new_p = MPID_Attr_alloc();
78
79
80
	MPIU_ERR_CHKANDJUMP(!new_p,mpi_errno,MPI_ERR_OTHER,"**nomem");
	/* Did not find in list.  Add at end */
	new_p->keyval	     = keyval_ptr;
81
	new_p->attrType      = attrType;
82
	new_p->pre_sentinal  = 0;
83
	/* FIXME: See the comment above on this dual cast. */
84
	new_p->value	     = (MPID_AttrVal_t)(MPIR_Pint)attribute_val;
85
	new_p->post_sentinal = 0;
86
	new_p->next	     = comm_ptr->attributes;
87
	MPIR_Keyval_add_ref( keyval_ptr );
88
	comm_ptr->attributes = new_p;
89
	/* printf( "Creating attr at %x\n", &new_p->value ); */
90
91
92
93
94
95
96
    }
    
    /* Here is where we could add a hook for the device to detect attribute
       value changes, using something like
       MPID_Dev_comm_attr_hook( comm_ptr, keyval, attribute_val );
    */
    
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

 fn_exit:
    return mpi_errno;
 fn_fail:
    goto fn_exit;
}


#undef FUNCNAME
#define FUNCNAME MPIR_CommSetAttr
#undef FCNAME
#define FCNAME MPIU_QUOTE(FUNCNAME)
int MPIR_CommSetAttr( MPI_Comm comm, int comm_keyval, void *attribute_val, 
		      MPIR_AttrType attrType )
{
    int mpi_errno = MPI_SUCCESS;
    MPID_Comm *comm_ptr = NULL;
    MPID_MPI_STATE_DECL(MPID_STATE_MPIR_COMM_SET_ATTR);

    MPIR_ERRTEST_INITIALIZED_ORDIE();
    
    MPIU_THREAD_CS_ENTER(ALLFUNC,);
    MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_COMM_SET_ATTR);

    /* Validate parameters, especially handles needing to be converted */
#   ifdef HAVE_ERROR_CHECKING
    {
        MPID_BEGIN_ERROR_CHECKS;
        {
	    MPIR_ERRTEST_COMM(comm, mpi_errno);
	    MPIR_ERRTEST_KEYVAL(comm_keyval, MPID_COMM, "communicator", mpi_errno);
	    MPIR_ERRTEST_KEYVAL_PERM(comm_keyval, mpi_errno);
        }
        MPID_END_ERROR_CHECKS;
    }
#   endif

    /* Convert MPI object handles to object pointers */
    MPID_Comm_get_ptr( comm, comm_ptr );

    /* Validate parameters and objects (post conversion) */
#   ifdef HAVE_ERROR_CHECKING
    {
        MPID_BEGIN_ERROR_CHECKS;
        {
142
143
            MPID_Keyval *keyval_ptr = NULL;

144
145
146
147
            /* Validate comm_ptr */
            MPID_Comm_valid_ptr( comm_ptr, mpi_errno );
	    /* If comm_ptr is not valid, it will be reset to null */
	    /* Validate keyval_ptr */
148
            MPID_Keyval_get_ptr( comm_keyval, keyval_ptr );
149
150
151
152
153
154
155
156
157
158
159
	    MPID_Keyval_valid_ptr( keyval_ptr, mpi_errno );
            if (mpi_errno) goto fn_fail;
	}
        MPID_END_ERROR_CHECKS;
    }
#   endif /* HAVE_ERROR_CHECKING */

    /* ... body of routine ...  */
    mpi_errno = MPIR_Comm_set_attr_impl(comm_ptr, comm_keyval, attribute_val, attrType);
    if (mpi_errno) goto fn_fail;
        
160
161
162
    /* ... end of body of routine ... */

  fn_exit:
163
    MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_COMM_SET_ATTR);
164
    MPIU_THREAD_CS_EXIT(ALLFUNC,);
165
166
167
    return mpi_errno;

  fn_fail:
168
169
170
171
172
173
174
175
176
    /* --BEGIN ERROR HANDLING-- */
#   ifdef HAVE_ERROR_CHECKING
    {
	mpi_errno = MPIR_Err_create_code(
	    mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_comm_set_attr",
	    "**mpi_comm_set_attr %C %d %p", comm, comm_keyval, attribute_val);
    }
#   endif
    mpi_errno = MPIR_Err_return_comm( comm_ptr, FCNAME, mpi_errno );
177
    goto fn_exit;
178
    /* --END ERROR HANDLING-- */
179
}
180
181
182
183
#endif /* MPICH_MPI_FROM_PMPI */

#undef FUNCNAME
#define FUNCNAME MPI_Comm_set_attr
184
185
#undef FCNAME
#define FCNAME MPIU_QUOTE(FUNCNAME)
186
187
188
189
190
/*@
   MPI_Comm_set_attr - Stores attribute value associated with a key

Input Parameters:
+ comm - communicator to which attribute will be attached (handle) 
191
. comm_keyval - key value, as returned by  'MPI_Comm_create_keyval' (integer)
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
- attribute_val - attribute value 

Notes:
Values of the permanent attributes 'MPI_TAG_UB', 'MPI_HOST', 'MPI_IO', 
'MPI_WTIME_IS_GLOBAL', 'MPI_UNIVERSE_SIZE', 'MPI_LASTUSEDCODE', and 
'MPI_APPNUM' may not be changed. 

The type of the attribute value depends on whether C, C++, or Fortran
is being used. 
In C and C++, an attribute value is a pointer ('void *'); in Fortran, it is an 
address-sized integer.

If an attribute is already present, the delete function (specified when the
corresponding keyval was created) will be called.

.N ThreadSafe

.N Fortran

.N Errors
.N MPI_SUCCESS
.N MPI_ERR_COMM
.N MPI_ERR_KEYVAL
.N MPI_ERR_PERM_KEY

.seealso MPI_Comm_create_keyval, MPI_Comm_delete_attr
@*/
int MPI_Comm_set_attr(MPI_Comm comm, int comm_keyval, void *attribute_val)
{
    int mpi_errno = MPI_SUCCESS;
222
    MPID_Comm *comm_ptr = NULL;
223
224
    MPID_MPI_STATE_DECL(MPID_STATE_MPI_COMM_SET_ATTR);

225
    MPIU_THREAD_CS_ENTER(ALLFUNC,);
226
    MPID_MPI_FUNC_ENTER(MPID_STATE_MPI_COMM_SET_ATTR);
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248

     /* Validate parameters, especially handles needing to be converted */
#   ifdef HAVE_ERROR_CHECKING
    {
        MPID_BEGIN_ERROR_CHECKS;
        {
	    MPIR_ERRTEST_COMM(comm, mpi_errno);
	    MPIR_ERRTEST_KEYVAL(comm_keyval, MPID_COMM, "communicator", mpi_errno);
	    MPIR_ERRTEST_KEYVAL_PERM(comm_keyval, mpi_errno);
        }
        MPID_END_ERROR_CHECKS;
    }
#   endif

    /* Convert MPI object handles to object pointers */
    MPID_Comm_get_ptr( comm, comm_ptr );

    /* Validate parameters and objects (post conversion) */
#   ifdef HAVE_ERROR_CHECKING
    {
        MPID_BEGIN_ERROR_CHECKS;
        {
249
250
            MPID_Keyval *keyval_ptr = NULL;

251
252
253
254
            /* Validate comm_ptr */
            MPID_Comm_valid_ptr( comm_ptr, mpi_errno );
	    /* If comm_ptr is not valid, it will be reset to null */
	    /* Validate keyval_ptr */
255
            MPID_Keyval_get_ptr( comm_keyval, keyval_ptr );
256
257
258
259
260
261
262
263
264
	    MPID_Keyval_valid_ptr( keyval_ptr, mpi_errno );
            if (mpi_errno) goto fn_fail;
	}
        MPID_END_ERROR_CHECKS;
    }
#   endif /* HAVE_ERROR_CHECKING */

    /* ... body of routine ...  */
    mpi_errno = MPIR_Comm_set_attr_impl(comm_ptr, comm_keyval, attribute_val, MPIR_ATTR_PTR);
265
    if (mpi_errno) goto fn_fail;
266
267
    /* ... end of body of routine ... */

268
269
 fn_exit:
    MPID_MPI_FUNC_EXIT(MPID_STATE_MPI_COMM_SET_ATTR);
270
    MPIU_THREAD_CS_EXIT(ALLFUNC,);
271
272
273
274
275
276
277
278
279
280
281
282
283
284
    return mpi_errno;

  fn_fail:
    /* --BEGIN ERROR HANDLING-- */
#   ifdef HAVE_ERROR_CHECKING
    {
	mpi_errno = MPIR_Err_create_code(
	    mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_comm_set_attr",
	    "**mpi_comm_set_attr %C %d %p", comm, comm_keyval, attribute_val);
    }
#   endif
    goto fn_exit;
    /* --END ERROR HANDLING-- */
}