File: osc_pt2pt_sync.h

package info (click to toggle)
openmpi 4.1.4-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 127,592 kB
  • sloc: ansic: 690,998; makefile: 43,047; f90: 19,220; sh: 7,182; java: 6,360; perl: 3,590; cpp: 2,227; python: 1,350; lex: 989; fortran: 61; tcl: 12
file content (189 lines) | stat: -rw-r--r-- 5,718 bytes parent folder | download | duplicates (2)
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
 * Copyright (c) 2015-2016 Los Alamos National Security, LLC.  All rights
 *                         reserved.
 * $COPYRIGHT$
 *
 * Additional copyrights may follow
 *
 * $HEADER$
 */

#ifndef OMPI_OSC_PT2PT_SYNC_H
#define OMPI_OSC_PT2PT_SYNC_H

#include "ompi_config.h"
#include "opal/class/opal_free_list.h"
#include "opal/threads/threads.h"

enum ompi_osc_pt2pt_sync_type_t {
    /** default value */
    OMPI_OSC_PT2PT_SYNC_TYPE_NONE,
    /** lock access epoch */
    OMPI_OSC_PT2PT_SYNC_TYPE_LOCK,
    /** fence access epoch */
    OMPI_OSC_PT2PT_SYNC_TYPE_FENCE,
    /* post-start-complete-wait access epoch */
    OMPI_OSC_PT2PT_SYNC_TYPE_PSCW,
};
typedef enum ompi_osc_pt2pt_sync_type_t ompi_osc_pt2pt_sync_type_t;

struct ompi_osc_pt2pt_module_t;
struct ompi_osc_pt2pt_peer_t;

/**
 * @brief synchronization object
 *
 * This structure holds information about an access epoch.
 */
struct ompi_osc_pt2pt_sync_t {
    opal_free_list_item_t super;

    struct ompi_osc_pt2pt_module_t *module;

    /** synchronization type */
    ompi_osc_pt2pt_sync_type_t type;

    /** synchronization data */
    union {
        /** lock specific synchronization data */
        struct {
            /** lock target rank (-1 for all) */
            int target;
            /** lock type: MPI_LOCK_SHARED, MPI_LOCK_EXCLUSIVE */
            int type;
            /** assert specified at lock acquire time */
            int assert;
        } lock;
        /** post/start/complete/wait specific synchronization data */
        struct {
            /** group passed to ompi_osc_pt2pt_start */
            ompi_group_t *group;
        } pscw;
    } sync;

    /** array of peers for this sync */
    union {
        /** multiple peers (lock all, pscw, fence) */
	struct ompi_osc_pt2pt_peer_t **peers;
        /** single peer (targeted lock) */
	struct ompi_osc_pt2pt_peer_t *peer;
    } peer_list;

    /** number of peers */
    int num_peers;

    /** number of synchronization messages expected */
    volatile int32_t sync_expected;

    /** eager sends are active to all peers in this access epoch */
    volatile bool eager_send_active;

    /** communication has started on this epoch */
    bool epoch_active;

    /** lock to protect sync structure members */
    opal_mutex_t lock;

    /** condition variable for changes in the sync object */
    opal_condition_t cond;
};
typedef struct ompi_osc_pt2pt_sync_t ompi_osc_pt2pt_sync_t;

OBJ_CLASS_DECLARATION(ompi_osc_pt2pt_sync_t);

/**
 * @brief allocate a new synchronization object
 *
 * @param[in] module   osc pt2pt module
 *
 * @returns NULL on failure
 * @returns a new synchronization object on success
 */
ompi_osc_pt2pt_sync_t *ompi_osc_pt2pt_sync_allocate (struct ompi_osc_pt2pt_module_t *module);

/**
 * @brief release a synchronization object
 *
 * @param[in] pt2pt_sync   synchronization object allocated by ompi_osc_pt2pt_sync_allocate()
 */
void ompi_osc_pt2pt_sync_return (ompi_osc_pt2pt_sync_t *pt2pt_sync);

/**
 * Check if the target is part of a PSCW access epoch
 *
 * @param[in] module   osc pt2pt module
 * @param[in] target   target rank
 * @param[out] peer    peer object
 *
 * @returns false if the window is not in a PSCW access epoch or the peer is not
 *          in the group passed to MPI_Win_start
 * @returns true otherwise
 *
 * This functions verifies the target is part of an active PSCW access epoch.
 */
bool ompi_osc_pt2pt_sync_pscw_peer (struct ompi_osc_pt2pt_module_t *module, int target, struct ompi_osc_pt2pt_peer_t **peer);

/**
 * Wait for all remote peers in the synchronization to respond
 */
static inline void ompi_osc_pt2pt_sync_wait_nolock (ompi_osc_pt2pt_sync_t *sync)
{
    while (!sync->eager_send_active) {
        OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
                             "waiting for access epoch to start"));
        opal_condition_wait(&sync->cond, &sync->lock);
    }

    OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
                         "access epoch ready"));
}

static inline void ompi_osc_pt2pt_sync_wait (ompi_osc_pt2pt_sync_t *sync)
{
    OPAL_THREAD_LOCK(&sync->lock);
    ompi_osc_pt2pt_sync_wait_nolock (sync);
    OPAL_THREAD_UNLOCK(&sync->lock);
}

/**
 * Wait for all remote peers in the synchronization to respond
 */
static inline void ompi_osc_pt2pt_sync_wait_expected (ompi_osc_pt2pt_sync_t *sync)
{
    OPAL_THREAD_LOCK(&sync->lock);
    while (sync->sync_expected) {
        OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
                             "waiting for %d syncronization messages",
                             sync->sync_expected));
        opal_condition_wait(&sync->cond, &sync->lock);
    }
    OPAL_THREAD_UNLOCK(&sync->lock);

    OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
                         "all synchronization messages received"));
}

static inline void ompi_osc_pt2pt_sync_expected (ompi_osc_pt2pt_sync_t *sync)
{
    int32_t new_value = OPAL_THREAD_ADD_FETCH32 (&sync->sync_expected, -1);
    if (0 == new_value) {
        OPAL_THREAD_LOCK(&sync->lock);
        if (!(sync->type == OMPI_OSC_PT2PT_SYNC_TYPE_LOCK && sync->num_peers > 1)) {
            sync->eager_send_active = true;
        }
        opal_condition_broadcast (&sync->cond);
        OPAL_THREAD_UNLOCK(&sync->lock);
    }
}

static inline void ompi_osc_pt2pt_sync_reset (ompi_osc_pt2pt_sync_t *sync)
{
    sync->type = OMPI_OSC_PT2PT_SYNC_TYPE_NONE;
    sync->eager_send_active = false;
    sync->epoch_active = 0;
    sync->peer_list.peers = NULL;
    sync->sync.pscw.group = NULL;
}

#endif /* OMPI_OSC_PT2PT_SYNC_H */