1 /* -*- Mode: C; c-basic-offset:4 ; -*- */
2 /*
3  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
4  *                         University Research and Technology
5  *                         Corporation.  All rights reserved.
6  * Copyright (c) 2004-2017 The University of Tennessee and The University
7  *                         of Tennessee Research Foundation.  All rights
8  *                         reserved.
9  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
10  *                         University of Stuttgart.  All rights reserved.
11  * Copyright (c) 2004-2005 The Regents of the University of California.
12  *                         All rights reserved.
13  * Copyright (c) 2006-2007 University of Houston. All rights reserved.
14  * Copyright (c) 2007-2012 Cisco Systems, Inc.  All rights reserved.
15  * Copyright (c) 2009      Sun Microsystems, Inc. All rights reserved.
16  * Copyright (c) 2012      Oak Ridge National Labs.  All rights reserved.
17  * Copyright (c) 2015      Research Organization for Information Science
18  *                         and Technology (RIST). All rights reserved.
19  * $COPYRIGHT$
20  *
21  * Additional copyrights may follow
22  *
23  * $HEADER$
24  */
25 
26 #include "ompi_config.h"
27 #include "ompi/group/group.h"
28 #include "ompi/constants.h"
29 #include "mpi.h"
30 
31 /* define class information */
32 static void ompi_group_construct(ompi_group_t *);
33 static void ompi_group_destruct(ompi_group_t *);
34 
35 OBJ_CLASS_INSTANCE(ompi_group_t,
36                    opal_object_t,
37                    ompi_group_construct,
38                    ompi_group_destruct);
39 
40 /*
41  * Table for Fortran <-> C group handle conversion
42  */
43 opal_pointer_array_t ompi_group_f_to_c_table = {{0}};
44 
45 /*
46  * Predefined group objects
47  */
48 ompi_predefined_group_t ompi_mpi_group_empty = {{{0}}};
49 ompi_predefined_group_t ompi_mpi_group_null = {{{0}}};
50 ompi_predefined_group_t *ompi_mpi_group_empty_addr = &ompi_mpi_group_empty;
51 ompi_predefined_group_t *ompi_mpi_group_null_addr = &ompi_mpi_group_null;
52 
53 
54 /*
55  * Allocate a new group structure
56  */
ompi_group_allocate(int group_size)57 ompi_group_t *ompi_group_allocate(int group_size)
58 {
59     /* local variables */
60     ompi_proc_t **procs = calloc (group_size, sizeof (ompi_proc_t *));
61     ompi_group_t *new_group;
62 
63     if (NULL == procs) {
64         return NULL;
65     }
66 
67     new_group = ompi_group_allocate_plist_w_procs (procs, group_size);
68     if (NULL == new_group) {
69         free (procs);
70     }
71 
72     return new_group;
73 }
74 
ompi_group_allocate_plist_w_procs(ompi_proc_t ** procs,int group_size)75 ompi_group_t *ompi_group_allocate_plist_w_procs (ompi_proc_t **procs, int group_size)
76 {
77     /* local variables */
78     ompi_group_t * new_group = NULL;
79 
80     assert (group_size >= 0);
81 
82     /* create new group group element */
83     new_group = OBJ_NEW(ompi_group_t);
84 
85     if (NULL == new_group) {
86         return NULL;
87     }
88 
89     if (0 > new_group->grp_f_to_c_index) {
90         OBJ_RELEASE (new_group);
91         return NULL;
92     }
93 
94     /*
95      * Allocate array of (ompi_proc_t *)'s, one for each
96      * process in the group.
97      */
98     new_group->grp_proc_pointers = procs;
99 
100     /* set the group size */
101     new_group->grp_proc_count = group_size;
102 
103     /* initialize our rank to MPI_UNDEFINED */
104     new_group->grp_my_rank = MPI_UNDEFINED;
105     OMPI_GROUP_SET_DENSE(new_group);
106 
107     ompi_group_increment_proc_count (new_group);
108 
109     return new_group;
110 }
111 
ompi_group_allocate_sporadic(int group_size)112 ompi_group_t *ompi_group_allocate_sporadic(int group_size)
113 {
114     /* local variables */
115     ompi_group_t *new_group = NULL;
116 
117     assert (group_size >= 0);
118 
119     /* create new group group element */
120     new_group = OBJ_NEW(ompi_group_t);
121     if( NULL == new_group) {
122         goto error_exit;
123     }
124     if (0 > new_group->grp_f_to_c_index) {
125         OBJ_RELEASE(new_group);
126         new_group = NULL;
127         goto error_exit;
128     }
129     /* allocate array of (grp_sporadic_list )'s */
130     if (0 < group_size) {
131         new_group->sparse_data.grp_sporadic.grp_sporadic_list =
132             (struct ompi_group_sporadic_list_t *)malloc
133             (sizeof(struct ompi_group_sporadic_list_t ) * group_size);
134 
135         /* non-empty group */
136         if ( NULL == new_group->sparse_data.grp_sporadic.grp_sporadic_list) {
137             /* sporadic list allocation failed */
138             OBJ_RELEASE (new_group);
139             new_group = NULL;
140             goto error_exit;
141         }
142     }
143 
144     /* set the group size */
145     new_group->grp_proc_count = group_size; /* actually it's the number of
146                                                elements in the sporadic list*/
147 
148     /* initialize our rank to MPI_UNDEFINED */
149     new_group->grp_my_rank       = MPI_UNDEFINED;
150     new_group->grp_proc_pointers = NULL;
151     OMPI_GROUP_SET_SPORADIC(new_group);
152 
153  error_exit:
154     return new_group;
155 }
156 
ompi_group_allocate_strided(void)157 ompi_group_t *ompi_group_allocate_strided(void)
158 {
159     ompi_group_t *new_group = NULL;
160 
161     /* create new group group element */
162     new_group = OBJ_NEW(ompi_group_t);
163     if( NULL == new_group ) {
164         goto error_exit;
165     }
166     if (0 > new_group->grp_f_to_c_index) {
167         OBJ_RELEASE(new_group);
168         new_group = NULL;
169         goto error_exit;
170     }
171     /* initialize our rank to MPI_UNDEFINED */
172     new_group->grp_my_rank    = MPI_UNDEFINED;
173     new_group->grp_proc_pointers     = NULL;
174     OMPI_GROUP_SET_STRIDED(new_group);
175     new_group->sparse_data.grp_strided.grp_strided_stride         = -1;
176     new_group->sparse_data.grp_strided.grp_strided_offset         = -1;
177     new_group->sparse_data.grp_strided.grp_strided_last_element   = -1;
178  error_exit:
179     /* return */
180     return new_group;
181 }
ompi_group_allocate_bmap(int orig_group_size,int group_size)182 ompi_group_t *ompi_group_allocate_bmap(int orig_group_size , int group_size)
183 {
184     ompi_group_t *new_group = NULL;
185 
186     assert (group_size >= 0);
187 
188     /* create new group group element */
189     new_group = OBJ_NEW(ompi_group_t);
190     if( NULL == new_group) {
191         goto error_exit;
192     }
193     if (0 > new_group->grp_f_to_c_index) {
194         OBJ_RELEASE(new_group);
195         new_group = NULL;
196         goto error_exit;
197     }
198     /* allocate the unsigned char list */
199     new_group->sparse_data.grp_bitmap.grp_bitmap_array = (unsigned char *)malloc
200         (sizeof(unsigned char) * ompi_group_div_ceil(orig_group_size,BSIZE));
201 
202     new_group->sparse_data.grp_bitmap.grp_bitmap_array_len =
203         ompi_group_div_ceil(orig_group_size,BSIZE);
204 
205     new_group->grp_proc_count = group_size;
206 
207     /* initialize our rank to MPI_UNDEFINED */
208     new_group->grp_my_rank    = MPI_UNDEFINED;
209     new_group->grp_proc_pointers     = NULL;
210     OMPI_GROUP_SET_BITMAP(new_group);
211 
212  error_exit:
213     /* return */
214     return new_group;
215 }
216 
217 /*
218  * increment the reference count of the proc structures
219  */
ompi_group_increment_proc_count(ompi_group_t * group)220 void ompi_group_increment_proc_count(ompi_group_t *group)
221 {
222     ompi_proc_t * proc_pointer;
223     for (int proc = 0 ; proc < group->grp_proc_count ; ++proc) {
224 	proc_pointer = ompi_group_peer_lookup_existing (group, proc);
225 	if (proc_pointer) {
226 	    OBJ_RETAIN(proc_pointer);
227 	}
228     }
229 }
230 
231 /*
232  * decrement the reference count of the proc structures
233  */
234 
ompi_group_decrement_proc_count(ompi_group_t * group)235 void ompi_group_decrement_proc_count(ompi_group_t *group)
236 {
237     ompi_proc_t * proc_pointer;
238     for (int proc = 0 ; proc < group->grp_proc_count ; ++proc) {
239 	proc_pointer = ompi_group_peer_lookup_existing (group, proc);
240 	if (proc_pointer) {
241 	    OBJ_RELEASE(proc_pointer);
242 	}
243     }
244 }
245 
246 /*
247  * group constructor
248  */
ompi_group_construct(ompi_group_t * new_group)249 static void ompi_group_construct(ompi_group_t *new_group)
250 {
251     int ret_val;
252 
253     /* Note that we do *NOT* increase the refcount on all the included
254        procs here because that is handled at a different level (e.g.,
255        the proc counts are not decreased during the desstructor,
256        either). */
257 
258     /* assign entry in fortran <-> c translation array */
259     ret_val = opal_pointer_array_add(&ompi_group_f_to_c_table, new_group);
260     new_group->grp_f_to_c_index = ret_val;
261     new_group->grp_flags = 0;
262 
263     /* default the sparse values for groups */
264     new_group->grp_parent_group_ptr = NULL;
265 }
266 
267 
268 /*
269  * group destructor
270  */
ompi_group_destruct(ompi_group_t * group)271 static void ompi_group_destruct(ompi_group_t *group)
272 {
273     /* Note that we do *NOT* decrease the refcount on all the included
274        procs here because that is handled at a different level (e.g.,
275        the proc counts are not increased during the constructor,
276        either). */
277 
278 #if OMPI_GROUP_SPARSE
279     if (OMPI_GROUP_IS_DENSE(group))
280 	/* sparse groups do not increment proc reference counters */
281 #endif
282 	ompi_group_decrement_proc_count (group);
283 
284     /* release thegrp_proc_pointers memory */
285     if (NULL != group->grp_proc_pointers) {
286         free(group->grp_proc_pointers);
287     }
288 
289     if (OMPI_GROUP_IS_SPORADIC(group)) {
290         if (NULL != group->sparse_data.grp_sporadic.grp_sporadic_list) {
291             free(group->sparse_data.grp_sporadic.grp_sporadic_list);
292         }
293     }
294 
295     if (OMPI_GROUP_IS_BITMAP(group)) {
296         if (NULL != group->sparse_data.grp_bitmap.grp_bitmap_array) {
297             free(group->sparse_data.grp_bitmap.grp_bitmap_array);
298         }
299     }
300 
301     if (NULL != group->grp_parent_group_ptr){
302         OBJ_RELEASE(group->grp_parent_group_ptr);
303     }
304 
305     /* reset the ompi_group_f_to_c_table entry - make sure that the
306      * entry is in the table */
307     if (NULL != opal_pointer_array_get_item(&ompi_group_f_to_c_table,
308                                             group->grp_f_to_c_index)) {
309         opal_pointer_array_set_item(&ompi_group_f_to_c_table,
310                                     group->grp_f_to_c_index, NULL);
311     }
312 }
313 
314 
315 /*
316  * Initialize OMPI group infrastructure
317  */
ompi_group_init(void)318 int ompi_group_init(void)
319 {
320     /* initialize ompi_group_f_to_c_table */
321     OBJ_CONSTRUCT( &ompi_group_f_to_c_table, opal_pointer_array_t);
322     if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_group_f_to_c_table, 4,
323                                                 OMPI_FORTRAN_HANDLE_MAX, 16) ) {
324         return OMPI_ERROR;
325     }
326 
327     /* add MPI_GROUP_NULL to table */
328     OBJ_CONSTRUCT(&ompi_mpi_group_null, ompi_group_t);
329     ompi_mpi_group_null.group.grp_proc_count        = 0;
330     ompi_mpi_group_null.group.grp_my_rank           = MPI_PROC_NULL;
331     ompi_mpi_group_null.group.grp_proc_pointers     = NULL;
332     ompi_mpi_group_null.group.grp_flags            |= OMPI_GROUP_DENSE;
333     ompi_mpi_group_null.group.grp_flags            |= OMPI_GROUP_INTRINSIC;
334 
335     /* add MPI_GROUP_EMPTY to table */
336     OBJ_CONSTRUCT(&ompi_mpi_group_empty, ompi_group_t);
337     ompi_mpi_group_empty.group.grp_proc_count        = 0;
338     ompi_mpi_group_empty.group.grp_my_rank           = MPI_UNDEFINED;
339     ompi_mpi_group_empty.group.grp_proc_pointers     = NULL;
340     ompi_mpi_group_empty.group.grp_flags            |= OMPI_GROUP_DENSE;
341     ompi_mpi_group_empty.group.grp_flags            |= OMPI_GROUP_INTRINSIC;
342 
343     return OMPI_SUCCESS;
344 }
345 
346 
347 /*
348  * Clean up group infrastructure
349  */
ompi_group_finalize(void)350 int ompi_group_finalize(void)
351 {
352     ompi_mpi_group_null.group.grp_flags = 0;
353     OBJ_DESTRUCT(&ompi_mpi_group_null);
354 
355     ompi_mpi_group_null.group.grp_flags = 0;
356     OBJ_DESTRUCT(&ompi_mpi_group_empty);
357 
358     OBJ_DESTRUCT(&ompi_group_f_to_c_table);
359 
360     return OMPI_SUCCESS;
361 }
362