mpid_nem_datatypes.h 9.04 KB
Newer Older
1
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2
3
4
5
6
7
8
9
10
/*
 *  (C) 2006 by Argonne National Laboratory.
 *      See COPYRIGHT in top-level directory.
 */

#ifndef MPID_NEM_DATATYPES_H
#define MPID_NEM_DATATYPES_H

#include "mpid_nem_debug.h"
11
#include "mpid_nem_atomics.h"
12
13
14
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
15
16
17
#ifdef HAVE_SYS_MMAN_H
    #include <sys/mman.h>
#endif
18
19
20
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
21
22
23
#ifdef HAVE_UNISTD_H
    #include <unistd.h>
#endif
24
25
#include <string.h>
#include <limits.h>
26
27
28
#ifdef HAVE_SCHED_H
    #include <sched.h>
#endif
29
#include "mpichconf.h"
30

31
32
33
34
35
36
/* FIXME We are using this as an interprocess lock in the queue code, although
   it's not strictly guaranteed to work for this scenario.  These should really
   use the "process locks" code, but it's in such terrible shape that it doesn't
   really work for us right now.  Also, because it has some inline assembly it's
   not really a fair comparison for studying the impact of atomic instructions.
   [goodell@ 2009-01-16] */
37
38
39
40

#if !defined(MPID_NEM_USE_LOCK_FREE_QUEUES)
 #include "mpid_thread.h" 
#endif
41

42
43
#define MPID_NEM_OFFSETOF(struc, field) ((int)(&((struc *)0)->field))
#define MPID_NEM_CACHE_LINE_LEN 64
44
45
#define MPID_NEM_NUM_CELLS      64
#define MPID_NEM_CELL_LEN       (64*1024)
46
47
48
49
50
51
52

/*
   The layout of the cell looks like this:

   --CELL------------------
   | next                 |
   | padding              |
53
   | --MPICH PKT-------- |
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
   | | packet headers   | |
   | | packet payload   | |
   | |   .              | |
   | |   .              | |
   | |   .              | |
   | |                  | |
   | -------------------- |
   ------------------------

   For optimization, we want the cell to start at a cacheline boundary
   and the cell length to be a multiple of cacheline size.  This will
   avoid false sharing.  We also want payload to start at an 8-byte
   boundary to to optimize memcpys and dataloop operations on the
   payload.  To ensure payload is 8-byte aligned, we add padding after
   the next pointer so the packet starts at the 8-byte boundary.

   Forgive the misnomers of the macros.

   MPID_NEM_CELL_LEN size of the whole cell (currently 64K)
   
   MPID_NEM_CELL_HEAD_LEN is the size of the next pointer plus the
       padding.
   
   MPID_NEM_CELL_PAYLOAD_LEN is the maximum length of the packet.
       This is MPID_NEM_CELL_LEN minus the size of the next pointer
       and any padding.

81
   MPID_NEM_MPICH_HEAD_LEN is the length of the mpich packet header
82
83
       fields.

84
   MPID_NEM_MPICH_DATA_LEN is the maximum length of the mpich packet
85
86
       payload and is basically what's left after the next pointer,
       padding and packet header.  This is MPID_NEM_CELL_PAYLOAD_LEN -
87
       MPID_NEM_MPICH_HEAD_LEN.
88
89
90
91
92
93
94

   MPID_NEM_CALC_CELL_LEN is the amount of data plus headers in the
       cell.  I.e., how much of a cell would need to be sent over a
       network.

   FIXME: Simplify this maddness!  Maybe something like this:

95
       typedef struct mpich_pkt {
96
97
98
           header_field1;
           header_field2;
           payload[1];
99
       } mpich_pkt_t;
100
101
102
103
104
105
106
107
108
109
110
111
   
       typedef struct cell {
           *next;
           padding;
           pkt;
       } cell_t;

       typedef union cell_container {
           cell_t cell;
           char padding[MPID_NEM_CELL_LEN];
       } cell_container_t;

112
       #define MPID_NEM_MPICH_DATA_LEN (sizeof(cell_container_t) - sizeof(cell_t) + 1)
113
114

   The packet payload can overflow the array in the packet struct up
115
   to MPID_NEM_MPICH_DATA_LEN bytes.
116
117
118
   
*/

119
120
121
122
123
124
125
126
127
#if (SIZEOF_OPA_PTR_T > 8)
#  if (SIZEOF_OPA_PTR_T > 16)
#    error unexpected size for OPA_ptr_t
#  endif
#  define MPID_NEM_CELL_HEAD_LEN  16 /* We use this to keep elements 64-bit aligned */
#else /* (SIZEOF_OPA_PTR_T <= 8) */
#  define MPID_NEM_CELL_HEAD_LEN  8 /* We use this to keep elements 64-bit aligned */
#endif

128
129
#define MPID_NEM_CELL_PAYLOAD_LEN (MPID_NEM_CELL_LEN - MPID_NEM_CELL_HEAD_LEN)

130
#define MPID_NEM_CALC_CELL_LEN(cellp) (MPID_NEM_CELL_HEAD_LEN + MPID_NEM_MPICH_HEAD_LEN + MPID_NEM_CELL_DLEN (cell))
131
132
133
134

#define MPID_NEM_ALIGNED(addr, bytes) ((((unsigned long)addr) & (((unsigned long)bytes)-1)) == 0)

#define MPID_NEM_PKT_UNKNOWN     0
135
136
#define MPID_NEM_PKT_MPICH      1
#define MPID_NEM_PKT_MPICH_HEAD 2
137

138
139
140
141
142
#define MPID_NEM_FBOX_SOURCE(cell) (MPID_nem_mem_region.local_procs[(cell)->pkt.mpich.source])
#define MPID_NEM_CELL_SOURCE(cell) ((cell)->pkt.mpich.source)
#define MPID_NEM_CELL_DEST(cell)   ((cell)->pkt.mpich.dest)
#define MPID_NEM_CELL_DLEN(cell)   ((cell)->pkt.mpich.datalen)
#define MPID_NEM_CELL_SEQN(cell)   ((cell)->pkt.mpich.seqno)
143

144
145
#define MPID_NEM_MPICH_HEAD_LEN sizeof(MPID_nem_pkt_header_t)
#define MPID_NEM_MPICH_DATA_LEN (MPID_NEM_CELL_PAYLOAD_LEN - MPID_NEM_MPICH_HEAD_LEN)
146

147
148
149
150
151
152
153
154
155
156
157
#define MPID_NEM_PKT_HEADER_FIELDS   	    \
    int source;                             \
    int dest;                               \
    MPIR_Pint datalen;                      \
    unsigned short seqno;                   \
    unsigned short type; /* currently used only with checkpointing */

typedef struct MPID_nem_pkt_header
{
    MPID_NEM_PKT_HEADER_FIELDS;
} MPID_nem_pkt_header_t;
158

159
typedef struct MPID_nem_pkt_mpich
160
161
{
    MPID_NEM_PKT_HEADER_FIELDS;
162
163
164
165
    union {
        char payload[MPID_NEM_MPICH_DATA_LEN];
        double dummy; /* align paylod to double */
    } p;
166
} MPID_nem_pkt_mpich_t;
167
168

typedef union
169
{
170
    MPID_nem_pkt_header_t      header;
171
    MPID_nem_pkt_mpich_t      mpich;
172
173
174
175
176
177
178
179
180
181
} MPID_nem_pkt_t;

/* Nemesis cells which are to be used in shared memory need to use
 * "relative pointers" because the absolute pointers to a cell from
 * different processes may be different.  Relative pointers are
 * offsets from the beginning of the mmapped region where they live.
 * We use different types for relative and absolute pointers to help
 * catch errors.  Use MPID_NEM_REL_TO_ABS and MPID_NEM_ABS_TO_REL to
 * convert between relative and absolute pointers. */

182
/* This should always be exactly the size of a pointer */
183
184
typedef struct MPID_nem_cell_rel_ptr
{
185
    OPA_ptr_t p;
186
187
188
189
190
191
192
193
194
195
196
197
}
MPID_nem_cell_rel_ptr_t;

/* MPID_nem_cell and MPID_nem_abs_cell must be kept in sync so that we
 * can cast between them.  MPID_nem_abs_cell should only be used when
 * a cell is enqueued on a queue local to a single process (e.g., a
 * queue in a network module) where relative pointers are not
 * needed. */

typedef struct MPID_nem_cell
{
    MPID_nem_cell_rel_ptr_t next;
198
#if (MPID_NEM_CELL_HEAD_LEN > SIZEOF_OPA_PTR_T)
199
    char padding[MPID_NEM_CELL_HEAD_LEN - sizeof(MPID_nem_cell_rel_ptr_t)];
200
#endif
201
    volatile MPID_nem_pkt_t pkt;
202
} MPID_nem_cell_t;
203
typedef MPID_nem_cell_t *MPID_nem_cell_ptr_t;
204
205
206
207

typedef struct MPID_nem_abs_cell
{
    struct MPID_nem_abs_cell *next;
208
#if (MPID_NEM_CELL_HEAD_LEN > SIZEOF_VOID_P)
209
    char padding[MPID_NEM_CELL_HEAD_LEN - sizeof(struct MPID_nem_abs_cell*)];
210
#endif
211
212
213
214
215
216
217
218
219
    volatile MPID_nem_pkt_t pkt;
} MPID_nem_abs_cell_t;
typedef MPID_nem_abs_cell_t *MPID_nem_abs_cell_ptr_t;

#define MPID_NEM_CELL_TO_PACKET(cellp) (&(cellp)->pkt)
#define MPID_NEM_PACKET_TO_CELL(packetp) \
    ((MPID_nem_cell_ptr_t) ((char*)(packetp) - (char *)MPID_NEM_CELL_TO_PACKET((MPID_nem_cell_ptr_t)0)))
#define MPID_NEM_MIN_PACKET_LEN (sizeof (MPID_nem_pkt_header_t))
#define MPID_NEM_MAX_PACKET_LEN (sizeof (MPID_nem_pkt_t))
220
#define MPID_NEM_PACKET_LEN(pkt) ((pkt)->mpich.datalen + MPID_NEM_MPICH_HEAD_LEN)
221
222
223

#define MPID_NEM_OPT_LOAD     16 
#define MPID_NEM_OPT_SIZE     ((sizeof(MPIDI_CH3_Pkt_t)) + (MPID_NEM_OPT_LOAD))
224
#define MPID_NEM_OPT_HEAD_LEN ((MPID_NEM_MPICH_HEAD_LEN) + (MPID_NEM_OPT_SIZE))
225
226

#define MPID_NEM_PACKET_OPT_LEN(pkt) \
227
    (((pkt)->mpich.datalen < MPID_NEM_OPT_SIZE) ? (MPID_NEM_OPT_HEAD_LEN) : (MPID_NEM_PACKET_LEN(pkt)))
228

229
#define MPID_NEM_PACKET_PAYLOAD(pkt) ((pkt)->mpich.payload)
230
231
232

typedef struct MPID_nem_queue
{
233
234
    MPID_nem_cell_rel_ptr_t head;
    MPID_nem_cell_rel_ptr_t tail;
235
#if (MPID_NEM_CACHE_LINE_LEN > (2 * SIZEOF_OPA_PTR_T))
236
    char padding1[MPID_NEM_CACHE_LINE_LEN - 2 * sizeof(MPID_nem_cell_rel_ptr_t)];
237
#endif
238
    MPID_nem_cell_rel_ptr_t my_head;
239
#if (MPID_NEM_CACHE_LINE_LEN > SIZEOF_OPA_PTR_T)
240
    char padding2[MPID_NEM_CACHE_LINE_LEN - sizeof(MPID_nem_cell_rel_ptr_t)];
241
#endif
242
#if !defined(MPID_NEM_USE_LOCK_FREE_QUEUES)
243
244
245
    /* see FIXME in mpid_nem_queue.h */
#define MPID_nem_queue_mutex_t MPID_Thread_mutex_t
    MPID_nem_queue_mutex_t lock;
246
247
    char padding3[MPID_NEM_CACHE_LINE_LEN - sizeof(MPID_Thread_mutex_t)];
#endif
248
249
250
251
252
} MPID_nem_queue_t, *MPID_nem_queue_ptr_t;

/* Fast Boxes*/ 
typedef union
{
253
    OPA_int_t value;
254
#if MPID_NEM_CACHE_LINE_LEN != 0
255
    char padding[MPID_NEM_CACHE_LINE_LEN];
256
#endif
257
258
259
260
261
262
263
264
}
MPID_nem_opt_volint_t;

typedef struct MPID_nem_fbox_common
{
    MPID_nem_opt_volint_t  flag;
} MPID_nem_fbox_common_t, *MPID_nem_fbox_common_ptr_t;

265
typedef struct MPID_nem_fbox_mpich
266
267
268
{
    MPID_nem_opt_volint_t flag;
    MPID_nem_cell_t cell;
269
} MPID_nem_fbox_mpich_t;
270

271
#define MPID_NEM_FBOX_DATALEN MPID_NEM_MPICH_DATA_LEN
272
273
274
275

typedef union 
{
    MPID_nem_fbox_common_t common;
276
    MPID_nem_fbox_mpich_t mpich;
277
278
279
280
281
282
283
284
285
286
} MPID_nem_fastbox_t;


typedef struct MPID_nem_fbox_arrays
{
    MPID_nem_fastbox_t **in;
    MPID_nem_fastbox_t **out;
} MPID_nem_fbox_arrays_t;

#endif /* MPID_NEM_DATATYPES_H */