win_get_attr.c 7.89 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/* -*- Mode: C; c-basic-offset:4 ; -*- */
/*
 *
 *  (C) 2001 by Argonne National Laboratory.
 *      See COPYRIGHT in top-level directory.
 */

#include "mpiimpl.h"

/* -- Begin Profiling Symbol Block for routine MPI_Win_get_attr */
#if defined(HAVE_PRAGMA_WEAK)
#pragma weak MPI_Win_get_attr = PMPI_Win_get_attr
#elif defined(HAVE_PRAGMA_HP_SEC_DEF)
#pragma _HP_SECONDARY_DEF PMPI_Win_get_attr  MPI_Win_get_attr
#elif defined(HAVE_PRAGMA_CRI_DUP)
#pragma _CRI duplicate MPI_Win_get_attr as PMPI_Win_get_attr
#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_Win_get_attr
#define MPI_Win_get_attr PMPI_Win_get_attr

26
27
28
#undef FUNCNAME
#define FUNCNAME MPIR_WinGetAttr

29
30
int MPIR_WinGetAttr( MPI_Win win, int win_keyval, void *attribute_val, 
		     int *flag, MPIR_AttrType outAttrType )
31
32
{
#ifdef HAVE_ERROR_CHECKING
33
    static const char FCNAME[] = "MPIR_WinGetAttr";
34
35
36
#endif
    int mpi_errno = MPI_SUCCESS;
    MPID_Win *win_ptr = NULL;
37
    MPIU_THREADPRIV_DECL;
38
    MPID_MPI_STATE_DECL(MPID_STATE_MPIR_WIN_GET_ATTR);
39
40
41

    MPIR_ERRTEST_INITIALIZED_ORDIE();
    
42
    MPIU_THREAD_CS_ENTER(ALLFUNC,);
43
    MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_WIN_GET_ATTR);
44
45
46
47
48
49
50
51
52
53
54
55

    /* Validate parameters, especially handles needing to be converted */
#   ifdef HAVE_ERROR_CHECKING
    {
        MPID_BEGIN_ERROR_CHECKS;
        {
	    MPIR_ERRTEST_WIN(win, mpi_errno);
	    MPIR_ERRTEST_KEYVAL(win_keyval, MPID_WIN, "window", mpi_errno);
#           ifdef NEEDS_POINTER_ALIGNMENT_ADJUST
            /* A common user error is to pass the address of a 4-byte
	       int when the address of a pointer (or an address-sized int)
	       should have been used.  We can test for this specific
56
	       case.  Note that this code assumes sizeof(MPIR_Pint) is
57
	       a power of 2. */
58
	    if ((MPIR_Pint)attribute_val & (sizeof(MPIR_Pint)-1)) {
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
		MPIU_ERR_SET(mpi_errno,MPI_ERR_ARG,"**attrnotptr");
	    }
#           endif
            if (mpi_errno != MPI_SUCCESS) goto fn_fail;
        }
        MPID_END_ERROR_CHECKS;
    }
#   endif
    
    /* Convert MPI object handles to object pointers */
    MPID_Win_get_ptr( win, win_ptr );
    
    /* Validate parameters and objects (post conversion) */
#   ifdef HAVE_ERROR_CHECKING
    {
	MPID_BEGIN_ERROR_CHECKS;
	{
            /* Validate win_ptr */
            MPID_Win_valid_ptr( win_ptr, mpi_errno );
	    /* If win_ptr is not valid, it will be reset to null */
	    MPIR_ERRTEST_ARGNULL(attribute_val, "attribute_val", mpi_errno);
	    MPIR_ERRTEST_ARGNULL(flag, "flag", mpi_errno);
            if (mpi_errno) goto fn_fail;
	}
	MPID_END_ERROR_CHECKS;
    }
#   endif /* HAVE_ERROR_CHECKING */    

    /* ... body of routine ...  */
    
    /* Check for builtin attribute */
    /* This code is ok for correct programs, but it would be better
       to copy the values from the per-process block and pass the user
       a pointer to a copy */
    /* Note that if we are called from Fortran, we must return the values,
       not the addresses, of these attributes */
    if (HANDLE_GET_KIND(win_keyval) == HANDLE_KIND_BUILTIN) {
	int attr_idx = win_keyval & 0x0000000f;
	void **attr_val_p = (void **)attribute_val;
#ifdef HAVE_FORTRAN_BINDING
	/* Note that this routine only has a Fortran 90 binding,
	   so the attribute value is an address-sized int */
101
	MPIR_Pint  *attr_int = (MPIR_Pint *)attribute_val;
102
103
104
105
106
107
#endif
	*flag = 1;

	/* 
	 * The C versions of the attributes return the address of a 
	 * *COPY* of the value (to prevent the user from changing it)
108
	 * and the Fortran versions provide the actual value (as a Fint)
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
	 */
	switch (attr_idx) {
	case 1: /* WIN_BASE */
	    *attr_val_p = win_ptr->base;
	    break;
	case 3: /* SIZE */
	    win_ptr->copySize = win_ptr->size;
	    *attr_val_p = &win_ptr->copySize;
	    break;
	case 5: /* DISP_UNIT */
	    win_ptr->copyDispUnit = win_ptr->disp_unit;
	    *attr_val_p = &win_ptr->copyDispUnit;
	    break;
#ifdef HAVE_FORTRAN_BINDING
	case 2: /* Fortran BASE */
	    /* The Fortran routine that matches this routine should
	       provide an address-sized integer, not an MPI_Fint */
126
	    *attr_int = MPI_VOID_PTR_CAST_TO_MPI_AINT(win_ptr->base);
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
	    break;
	case 4: /* Fortran SIZE */
	    /* We do not need to copy because we return the value,
	       not a pointer to the value */
	    *attr_int = win_ptr->size;
	    break;
	case 6: /* Fortran DISP_UNIT */
	    /* We do not need to copy because we return the value,
	       not a pointer to the value */
	    *attr_int = win_ptr->disp_unit;
	    break;
#endif
	}
    }
    else {
	MPID_Attribute *p = win_ptr->attributes;

	*flag = 0;
	while (p) {
	    if (p->keyval->handle == win_keyval) {
		*flag = 1;
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
		if (outAttrType == MPIR_ATTR_PTR) {
		    if (p->attrType == MPIR_ATTR_INT) {
			/* This is the tricky case: if the system is
			   bigendian, and we have to return a pointer to
			   an int, then we may need to point to the 
			   correct location in the word. */
#if defined(WORDS_LITTLEENDIAN) || (SIZEOF_VOID_P == SIZEOF_INT)
			*(void**)attribute_val = &(p->value);
#else
			int *p_loc = (int *)&(p->value);
#if SIZEOF_VOID_P == 2 * SIZEOF_INT
			p_loc++;
#else 
#error Expected sizeof(void*) to be either sizeof(int) or 2*sizeof(int)
#endif
			*(void **)attribute_val = p_loc;
#endif
		    }
		    else if (p->attrType == MPIR_ATTR_AINT) {
			*(void**)attribute_val = &(p->value);
		    }
		    else {
			*(void**)attribute_val = (p->value);
		    }
		}
173
174
		else
		    *(void**)attribute_val = (p->value);
175
		
176
177
178
179
180
181
182
183
184
185
186
		break;
	    }
	    p = p->next;
	}
    }

    /* ... end of body of routine ... */

#ifdef HAVE_ERROR_CHECKING
  fn_exit:
#endif
187
    MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_WIN_GET_ATTR);
188
    MPIU_THREAD_CS_EXIT(ALLFUNC,);
189
190
191
192
193
194
195
196
    return mpi_errno;

    /* --BEGIN ERROR HANDLING-- */
#   ifdef HAVE_ERROR_CHECKING
  fn_fail:
    {
	mpi_errno = MPIR_Err_create_code(
	    mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, 
197
198
	    "**mpir_wingetattr", 
	    "**mpir_wingetattr %W %d %p %p", 
199
200
201
202
203
204
205
	    win, win_keyval, attribute_val, flag);
    }
    mpi_errno = MPIR_Err_return_win( win_ptr, FCNAME, mpi_errno );
    goto fn_exit;
#   endif
    /* --END ERROR HANDLING-- */
}
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
#endif

#undef FUNCNAME
#define FUNCNAME MPI_Win_get_attr

/*@
   MPI_Win_get_attr - Get attribute cached on an MPI window object

   Input Parameters:
+ win - window to which the attribute is attached (handle) 
- win_keyval - key value (integer) 

   Output Parameters:
+ attribute_val - attribute value, unless flag is false 
- flag - false if no attribute is associated with the key (logical) 

   Notes:
   The following attributes are predefined for all MPI Window objects\:

+ MPI_WIN_BASE - window base address. 
. MPI_WIN_SIZE - window size, in bytes. 
- MPI_WIN_DISP_UNIT - displacement unit associated with the window. 

.N ThreadSafe

.N Fortran

.N Errors
.N MPI_SUCCESS
.N MPI_ERR_WIN
.N MPI_ERR_KEYVAL
.N MPI_ERR_OTHER
@*/
int MPI_Win_get_attr(MPI_Win win, int win_keyval, void *attribute_val, 
		     int *flag)
{
    static const char FCNAME[] = "MPI_Win_get_attr";
    int mpi_errno = MPI_SUCCESS;
    MPID_Win *win_ptr = NULL;
    MPID_MPI_STATE_DECL(MPID_STATE_MPI_WIN_GET_ATTR);

    MPIR_ERRTEST_INITIALIZED_ORDIE();
    
    MPID_MPI_FUNC_ENTER(MPID_STATE_MPI_WIN_GET_ATTR);

    /* ... body of routine ...  */
    mpi_errno = MPIR_WinGetAttr( win, win_keyval, attribute_val, flag, 
				 MPIR_ATTR_PTR );
    if (mpi_errno) goto fn_fail;
    /* ... end of body of routine ... */

  fn_exit:
    MPID_MPI_FUNC_EXIT(MPID_STATE_MPI_WIN_GET_ATTR);
    return mpi_errno;

    /* --BEGIN ERROR HANDLING-- */
  fn_fail:
263
#ifdef HAVE_ERROR_CHECKING
264
265
266
267
268
269
270
271
    {
	mpi_errno = MPIR_Err_create_code(
	    mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, 
	    "**mpi_win_get_attr", 
	    "**mpi_win_get_attr %W %d %p %p", 
	    win, win_keyval, attribute_val, flag);
    }
    mpi_errno = MPIR_Err_return_win( win_ptr, FCNAME, mpi_errno );
272
#endif
273
274
275
    goto fn_exit;
    /* --END ERROR HANDLING-- */
}