1//***************************************************************************************
2// Communicator manipulation and accessor routines.
3//***************************************************************************************
4//
5// Author: Rob F. Van der Wijngaart
6//         Intel Corporation
7// Date:   04/26/2010
8//
9//***************************************************************************************
10//
11// Copyright 2010 Intel Corporation
12//
13//    Licensed under the Apache License, Version 2.0 (the "License");
14//    you may not use this file except in compliance with the License.
15//    You may obtain a copy of the License at
16//
17//        http://www.apache.org/licenses/LICENSE-2.0
18//
19//    Unless required by applicable law or agreed to in writing, software
20//    distributed under the License is distributed on an "AS IS" BASIS,
21//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22//    See the License for the specific language governing permissions and
23//    limitations under the License.
24//
25#include "RCCE_lib.h"
26
27//--------------------------------------------------------------------------------------
28// FUNCTION: RCCE_comm_split
29// RCCE_comm_split works like MPI_Comm_split, but:
30// 1. Always uses the default global communicator as the basis, not an
31//    arbitrary communicator
32// 2. Uses the rank of the UE in the global communicator as the key
33// 3. Uses a function, operating on UE's global rank, to compute color
34//--------------------------------------------------------------------------------------
35int RCCE_comm_split(
36  int (*color)(int, void *), // function returning a color value for given ue and aux
37  void *aux,                 // optional user-supplied data structure
38  RCCE_COMM *comm            // new communicator
39  ) {
40
41  int i, my_color, error;
42
43  if (!comm) return(RCCE_error_return(RCCE_debug_comm,RCCE_ERROR_COMM_UNDEFINED));
44
45  // start with a barrier to make sure all UEs are participating, unless we are still
46  // defining the global communicator; there is no danger in skipping the barrier in
47  // that case, because the global communicator is defined in RCCE_init, which must be
48  // called by all cores before any other RCCE calls
49  if (comm != &RCCE_COMM_WORLD) RCCE_barrier(&RCCE_COMM_WORLD);
50
51  // determine the size of the communicator
52  my_color = color(RCCE_IAM, aux);
53
54  comm->size = 0;
55  for (i=0; i<RCCE_NP; i++) {
56    if (color(i, aux) == my_color) {
57    if (i == RCCE_IAM) comm->my_rank = comm->size;
58    comm->member[comm->size++] = i;
59    }
60  }
61
62  // note: we only need to allocate new synch flags if the communicator has not yet been
63  // initialized. It is legal to overwrite an initialized communcator, in which case the
64  // membership may change, but the same synchronization flags can be used
65  if (comm->initialized == RCCE_COMM_INITIALIZED) return(RCCE_SUCCESS);
66  if(error=RCCE_flag_alloc(&(comm->gather)))
67     return(RCCE_error_return(RCCE_debug_comm,error));
68  if(error=RCCE_flag_alloc(&(comm->release)))
69     return(RCCE_error_return(RCCE_debug_comm,error));
70  comm->initialized = RCCE_COMM_INITIALIZED;
71
72  return(RCCE_SUCCESS);
73}
74
75// DO NOT USE THIS FUNCTION IN NON-GORY MODE UNTIL MALLOC_FREE HAS BEEN IMPLEMENTED
76int RCCE_comm_free(RCCE_COMM *comm) {
77  printf("DO NOT USE IN NON-GORY MODE UNTIL MALLOC_FREE HAS BEEN IMPLEMENTED\n");
78  if (comm->initialized != RCCE_COMM_INITIALIZED)
79             return(RCCE_error_return(RCCE_debug_comm,RCCE_ERROR_COMM_INITIALIZED));
80  RCCE_flag_free(&(comm->gather));
81  RCCE_flag_free(&(comm->release));
82  comm->initialized = RCCE_COMM_NOT_INITIALIZED;
83
84  return(RCCE_SUCCESS);
85}
86
87//--------------------------------------------------------------------------------------
88// FUNCTION: RCCE_comm_size
89// returns the number of UEs inside the communicator
90//--------------------------------------------------------------------------------------
91int RCCE_comm_size(
92  RCCE_COMM comm, // communicator
93  int *size       // return value (size)
94  ) {
95
96  if (comm.initialized == RCCE_COMM_INITIALIZED) {
97    *size = comm.size;
98    return(RCCE_SUCCESS);
99  }
100  else return(RCCE_error_return(RCCE_debug_comm,RCCE_ERROR_COMM_INITIALIZED));
101}
102
103//--------------------------------------------------------------------------------------
104// FUNCTION: RCCE_comm_rank
105// returns the rank of the calling UE inside the communicator
106//--------------------------------------------------------------------------------------
107int RCCE_comm_rank(
108  RCCE_COMM comm, // communicator
109  int *rank       // return value (rank)
110  ) {
111
112  if (comm.initialized == RCCE_COMM_INITIALIZED) {
113    *rank = comm.my_rank;
114    return(RCCE_SUCCESS);
115  }
116  else return(RCCE_error_return(RCCE_debug_comm,RCCE_ERROR_COMM_INITIALIZED));
117}
118
119//--------------------------------------------------------------------------------------
120// FUNCTION: RCCE_global_color
121// use this trivial color function to define global communicator
122//--------------------------------------------------------------------------------------
123int RCCE_global_color(int rank, void *nothing) {return(1);}
124