1 /*
2  * Copyright (C) by Argonne National Laboratory
3  *     See COPYRIGHT in top-level directory
4  */
5 
6 #ifndef MPIR_CONTEXTID_H_INCLUDED
7 #define MPIR_CONTEXTID_H_INCLUDED
8 
9 #ifdef HAVE_EXTENDED_CONTEXT_BITS
10 #define MPIR_CONTEXT_ID_T_DATATYPE MPI_UINT32_T
11 typedef uint32_t MPIR_Context_id_t;
12 #define MPIR_INVALID_CONTEXT_ID ((MPIR_Context_id_t)0xffffffff)
13 #define MPIR_CONTEXT_ID_BITS (20)
14 #define CONTEXT_ID_FMT PRIu32
15 #else
16 /* Default context id type is uint16_t. Instead of always using uint32_t, we take a conservative
17  * approach to ensure the smallest possible packet header size for ch3 and ch4 active messages.
18  */
19 #define MPIR_CONTEXT_ID_T_DATATYPE MPI_UINT16_T
20 typedef uint16_t MPIR_Context_id_t;
21 #define MPIR_INVALID_CONTEXT_ID ((MPIR_Context_id_t)0xffff)
22 #define MPIR_CONTEXT_ID_BITS (16)
23 #define CONTEXT_ID_FMT PRIu16
24 #endif
25 
26 /* The following preprocessor macros provide bitfield access information for
27  * context ID values.  They follow a uniform naming pattern:
28  *
29  * MPIR_CONTEXT_foo_WIDTH - the width in bits of the field
30  * MPIR_CONTEXT_foo_MASK  - A valid bit mask for bit-wise AND and OR operations
31  *                          with exactly all of the bits in the field set.
32  * MPIR_CONTEXT_foo_SHIFT - The number of bits that the field should be shifted
33  *                          rightwards to place it in the least significant bits
34  *                          of the ID.  There may still be higher order bits
35  *                          from other fields, so the _MASK should be used first
36  *                          if you want to reliably retrieve the exact value of
37  *                          the field.
38  */
39 
40 /* yields an rvalue that is the value of the field_name_ in the least significant bits */
41 #define MPIR_CONTEXT_READ_FIELD(field_name_,id_) \
42     (((id_) & MPIR_CONTEXT_##field_name_##_MASK) >> MPIR_CONTEXT_##field_name_##_SHIFT)
43 /* yields an rvalue that is the old_id_ with field_name_ set to field_val_ */
44 #define MPIR_CONTEXT_SET_FIELD(field_name_,old_id_,field_val_) \
45     ((old_id_ & ~MPIR_CONTEXT_##field_name_##_MASK) | ((field_val_) << MPIR_CONTEXT_##field_name_##_SHIFT))
46 
47 /* Context suffixes for separating pt2pt and collective communication */
48 #define MPIR_CONTEXT_SUFFIX_WIDTH (1)
49 #define MPIR_CONTEXT_SUFFIX_SHIFT (0)
50 #define MPIR_CONTEXT_SUFFIX_MASK ((1 << MPIR_CONTEXT_SUFFIX_WIDTH) - 1)
51 #define MPIR_CONTEXT_INTRA_PT2PT (0)
52 #define MPIR_CONTEXT_INTRA_COLL  (1)
53 #define MPIR_CONTEXT_INTER_PT2PT (0)
54 #define MPIR_CONTEXT_INTER_COLL  (1)
55 
56 /* Used to derive context IDs for sub-communicators from a parent communicator's
57    context ID value.  This field comes after the one bit suffix.
58    values are shifted left by 1. */
59 #define MPIR_CONTEXT_SUBCOMM_WIDTH (2)
60 #define MPIR_CONTEXT_SUBCOMM_SHIFT (MPIR_CONTEXT_SUFFIX_WIDTH + MPIR_CONTEXT_SUFFIX_SHIFT)
61 #define MPIR_CONTEXT_SUBCOMM_MASK      (((1 << MPIR_CONTEXT_SUBCOMM_WIDTH) - 1) << MPIR_CONTEXT_SUBCOMM_SHIFT)
62 
63 /* these values may be added/subtracted directly to/from an existing context ID
64  * in order to determine the context ID of the child/parent */
65 #define MPIR_CONTEXT_PARENT_OFFSET    (0 << MPIR_CONTEXT_SUBCOMM_SHIFT)
66 #define MPIR_CONTEXT_INTRANODE_OFFSET (1 << MPIR_CONTEXT_SUBCOMM_SHIFT)
67 #define MPIR_CONTEXT_INTERNODE_OFFSET (2 << MPIR_CONTEXT_SUBCOMM_SHIFT)
68 
69 /* this field (IS_LOCALCOM) is used to derive a context ID for local
70  * communicators of intercommunicators without communication */
71 #define MPIR_CONTEXT_IS_LOCALCOMM_WIDTH (1)
72 #define MPIR_CONTEXT_IS_LOCALCOMM_SHIFT (MPIR_CONTEXT_SUBCOMM_SHIFT + MPIR_CONTEXT_SUBCOMM_WIDTH)
73 #define MPIR_CONTEXT_IS_LOCALCOMM_MASK (((1 << MPIR_CONTEXT_IS_LOCALCOMM_WIDTH) - 1) << MPIR_CONTEXT_IS_LOCALCOMM_SHIFT)
74 
75 /* MPIR_MAX_CONTEXT_MASK is the number of ints that make up the bit vector that
76  * describes the context ID prefix space.
77  *
78  * The following must hold:
79  * (num_bits_in_vector) <= (maximum_context_id_prefix)
80  *   which is the following in concrete terms:
81  * MPIR_MAX_CONTEXT_MASK*MPIR_CONTEXT_INT_BITS <= 2**(MPIR_CONTEXT_ID_BITS - (MPIR_CONTEXT_PREFIX_SHIFT + MPIR_CONTEXT_DYNAMIC_PROC_WIDTH))
82  *
83  * We currently always assume MPIR_CONTEXT_INT_BITS is 32, regardless of the
84  * value of sizeof(int)*CHAR_BITS.  We also make the assumption that CHAR_BITS==8.
85  *
86  * For a 16-bit context id field and CHAR_BITS==8, this implies MPIR_MAX_CONTEXT_MASK <= 256
87  */
88 
89 /* number of bits to shift right by in order to obtain the context ID prefix */
90 #define MPIR_CONTEXT_PREFIX_SHIFT (MPIR_CONTEXT_IS_LOCALCOMM_SHIFT + MPIR_CONTEXT_IS_LOCALCOMM_WIDTH)
91 #define MPIR_CONTEXT_PREFIX_WIDTH (MPIR_CONTEXT_ID_BITS - (MPIR_CONTEXT_PREFIX_SHIFT + MPIR_CONTEXT_DYNAMIC_PROC_WIDTH))
92 #define MPIR_CONTEXT_PREFIX_MASK (((1 << MPIR_CONTEXT_PREFIX_WIDTH) - 1) << MPIR_CONTEXT_PREFIX_SHIFT)
93 
94 #define MPIR_CONTEXT_DYNAMIC_PROC_WIDTH (1)     /* the upper half is reserved for dynamic procs */
95 #define MPIR_CONTEXT_DYNAMIC_PROC_SHIFT (MPIR_CONTEXT_ID_BITS - MPIR_CONTEXT_DYNAMIC_PROC_WIDTH)        /* the upper half is reserved for dynamic procs */
96 #define MPIR_CONTEXT_DYNAMIC_PROC_MASK (((1 << MPIR_CONTEXT_DYNAMIC_PROC_WIDTH) - 1) << MPIR_CONTEXT_DYNAMIC_PROC_SHIFT)
97 
98 /* should probably be (sizeof(int)*CHAR_BITS) once we make the code CHAR_BITS-clean */
99 #define MPIR_CONTEXT_INT_BITS (32)
100 #define MPIR_MAX_CONTEXT_MASK \
101     ((1 << (MPIR_CONTEXT_ID_BITS - (MPIR_CONTEXT_PREFIX_SHIFT + MPIR_CONTEXT_DYNAMIC_PROC_WIDTH))) / MPIR_CONTEXT_INT_BITS)
102 
103 /* Utility routines.  Where possible, these are kept in the source directory
104    with the other comm routines (src/mpi/comm, in mpicomm.h).  However,
105    to create a new communicator after a spawn or connect-accept operation,
106    the device may need to create a new contextid */
107 int MPIR_Get_contextid_sparse(MPIR_Comm * comm_ptr, MPIR_Context_id_t * context_id, int ignore_id);
108 int MPIR_Get_contextid_sparse_group(MPIR_Comm * comm_ptr, MPIR_Group * group_ptr, int tag,
109                                     MPIR_Context_id_t * context_id, int ignore_id);
110 
111 int MPIR_Get_contextid_nonblock(MPIR_Comm * comm_ptr, MPIR_Comm * newcommp, MPIR_Request ** req);
112 int MPIR_Get_intercomm_contextid_nonblock(MPIR_Comm * comm_ptr, MPIR_Comm * newcommp,
113                                           MPIR_Request ** req);
114 
115 void MPIR_Free_contextid(MPIR_Context_id_t);
116 
117 #endif /* MPIR_CONTEXTID_H_INCLUDED */
118