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 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
|
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2021 Google, LLC. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
/**
* @file
*
* Shared Memory Single Copy
*
* This framework provides support for copying memory from one process to another on the same host
* system. The components expose process read, write, and may provide a way to map peer memory into
* this processes memory space.
*/
#ifndef OPAL_MCA_SMSC_H
#define OPAL_MCA_SMSC_H
#include "opal_config.h"
#include "opal/class/opal_object.h"
#include "opal/util/proc.h"
#define MCA_SMSC_BASE_MAJOR_VERSION 1
#define MCA_SMSC_BASE_MINOR_VERSION 0
#define MCA_SMSC_BASE_PATCH_VERSION 0
struct mca_smsc_module_t;
struct mca_smsc_endpoint_t {
opal_object_t super;
/** Opal proc object for this peer. */
opal_proc_t *proc;
};
typedef struct mca_smsc_endpoint_t mca_smsc_endpoint_t;
OBJ_CLASS_DECLARATION(mca_smsc_endpoint_t);
/**
* @brief Get an endpoint for a peer proc.
*
* @param(in) module shared-memory single-copy module
* @param(in) peer_proc proc to get an endpoint for
*/
typedef mca_smsc_endpoint_t *(*mca_smsc_module_get_endpoint_fn_t)(opal_proc_t *peer_proc);
/**
* @brief Return a shared-memory single-copy endpoint.
*
* @param(in) module shared-memory single-copy module
* @param(in) endpoint shared-memory single-copy endpoint
*
* This method returns an endpoint created by get_endpoint. The endpoint should be considered
* invalid and may be freed after this call completes.
*/
typedef void (*mca_smsc_module_return_endpoint_fn_t)(mca_smsc_endpoint_t *endpoint);
/**
* @brief Copy to/from a peer process.
*
* @param(in) module shared-memory single-copy module
* @param(in) endpoint shared-memory single-copy endpoint
* @param(in) local_address local address to use
* @param(in) remote_address remote address to use
* @param(in) size amount to copy
* @param(in) reg_data pointer to memory containing registration data (if required)
*
* A module must provide both copy_from and copy_to function.
*/
typedef int (*mca_smsc_module_copy_fn_t)(mca_smsc_endpoint_t *endpoint, void *local_address,
void *remote_address, size_t size, void *reg_data);
/**
* @brief Map a peer's memory onto local memory.
*
* @param(in) module shared-memory single-copy module
* @param(in) endpoint shared-memory single-copy endpoint
* @param(in) flags flags for this map operation (set to 0)
* @param(in) remote_address pointer valid in peer's address space
* @param(in) size size of region to map
* @param(out) local_mapping local address for peer region
*
* @returns a reference to the mapping
*
* This method, if provided, provides support for mapping a local peer's memory into this address
* space. The caller is responsible for verifying that the address is valid or access to the region
* may result in an access violation (SEGV). The function returns a reference (if needed) that can
* be used to clear the mapping. It is the caller's responsibility to unmap the region using the
* returned context.
*/
typedef void *(*mca_smsc_module_map_peer_region_fn_t)(mca_smsc_endpoint_t *endpoint, uint64_t flags,
void *remote_address, size_t size,
void **local_mapping);
/**
* @brief Clear a memory mapping.
*
* @param(in) module shared-memory single-copy module
* @param(in) ctx memory mapping context
*/
typedef void (*mca_smsc_module_unmap_peer_region_fn_t)(void *ctx);
/**
* @brief Register a memory region for remote access.
*
* @param(in) module shared-memory single-copy module
* @param(in) local_address local address to register (ideally page-aligned)
* @param(in) size size of the memory region (ideally page-aligned)
*
* @returns a pointer to registration data that can be used for copy by a peer process
*
* This method registers a region for access by a local peer. The returned data can be passed to a
* local peer and used by that peer for either copy_to or copy_from.
*/
typedef void *(*mca_smsc_module_register_region_fn_t)(void *local_address, size_t size);
/**
* @brief Deregister a registered region.
*
* @param(in) module shared-memory single-copy module
* @param(in) reg_data registration data returned by the registration function
*
* This function deregisters a region from use by a peers copy_from and copy_to function. Once a
* region has been deregistered the data is immediately not usable by any local peer.
*/
typedef void (*mca_smsc_module_deregister_region_fn_t)(void *reg_data);
enum {
/** Module requires the local registration of any region that will be used for single-copy
* operations. It is theresponsibility of the caller to pass this data with the pointer to the
* peer. */
MCA_SMSC_FEATURE_REQUIRE_REGISTRATION = 1,
/** Module can map peer memory into the local processes' address space. */
MCA_SMSC_FEATURE_CAN_MAP = 2,
};
struct mca_smsc_module_t {
/** Module features. */
uint64_t features;
/** Ignore if MCA_SMSC_FEATURE_REQUIRES_REGISTRATION is not set. */
size_t registration_data_size;
/** Get an endpoint for a peer. This function should always return a newly-allocated endpoint.
* The base will be responsible for caching that endpoint. */
mca_smsc_module_get_endpoint_fn_t get_endpoint;
/** Delete an endpoint and clean up all resources associated with it. */
mca_smsc_module_return_endpoint_fn_t return_endpoint;
/* All components must provide an implementation of the copy functions. */
/** Copy data into a peer's memory space. */
mca_smsc_module_copy_fn_t copy_to;
/** Copy data from a peer's memory space. */
mca_smsc_module_copy_fn_t copy_from;
/* Defined if MCA_SMSC_FEATURE_CAN_MAP is set. */
/** Map a peer memory region into this processes address space. The module is allowed to cache
* the mapping and return it in subsequent calls. */
mca_smsc_module_map_peer_region_fn_t map_peer_region;
/** Delete a mapping. This is allowed to leave the mapping in place. */
mca_smsc_module_unmap_peer_region_fn_t unmap_peer_region;
/* Defined if MCA_SMSC_FEATURE_REQUIRES_REGISTRATION is set. */
/** Register a memory region for use with single-copy by a remote peer. The module may cache
* this registration for future use. */
mca_smsc_module_register_region_fn_t register_region;
/** Deregister a memory region for use with single-copy. */
mca_smsc_module_deregister_region_fn_t deregister_region;
};
typedef struct mca_smsc_module_t mca_smsc_module_t;
/**
* @brief Query if this component can run.
*
* @returns OPAL_SUCCESS if the component can run or an opal error code otherwise
*
* This function is responsible for verifying the component can run. It should do the minimum amount
* of work to run at any time during execution. This includes sending any modex message if needed.
* It should refrain from allocating resources if possible.
*/
typedef int (*mca_smsc_component_query_fn_t)(void);
/**
* @brief Enable the use of this component and return a module.
*
* @returns A module on success or NULL otherwise.
*
* This function should do any remaining work (not already done in query) to prepare the component
* for use. It should return a fully initialized module.
*/
typedef mca_smsc_module_t *(*mca_smsc_component_enable_fn_t)(void);
struct mca_smsc_component_1_0_0_t {
mca_base_component_t smsc_version;
mca_base_component_data_t smsc_data;
/** Priority of this component. Only the winning component will be used. */
int priority;
/** Check if this component can be used. */
mca_smsc_component_query_fn_t query;
/** Enable the use of this component. */
mca_smsc_component_enable_fn_t enable;
};
typedef struct mca_smsc_component_1_0_0_t mca_smsc_component_1_0_0_t;
typedef mca_smsc_component_1_0_0_t mca_smsc_component_t;
OPAL_DECLSPEC extern mca_smsc_module_t *mca_smsc;
#if MCA_opal_smsc_DIRECT_CALL
# include MCA_opal_smsc_DIRECT_CALL_HEADER
# define MCA_SMSC_CALL_STAMP(a, b, ...) mca_smsc_##a##_##b(__VA_ARGS__)
# define MCA_SMSC_CALL_EXPANDER(a, b, ...) MCA_SMSC_CALL_STAMP(a, b, __VA_ARGS__)
# define MCA_SMSC_CALL(a, ...) \
MCA_SMSC_CALL_EXPANDER(MCA_opal_smsc_DIRECT_CALL_COMPONENT, a, __VA_ARGS__)
#else
# define MCA_SMSC_CALL(a, ...) mca_smsc->a(__VA_ARGS__)
#endif /* MCA_opal_smsc_DIRECT_CALL */
/**
* @brief Check if the selected component has a feature.
*
* @param(in) feature feature to check for (see smsc.h for list of features)
*/
static inline bool mca_smsc_base_has_feature(uint64_t feature)
{
return (NULL != mca_smsc) && !!(mca_smsc->features & feature);
}
static inline ssize_t mca_smsc_base_registration_data_size(void)
{
if (NULL == mca_smsc || !mca_smsc_base_has_feature(MCA_SMSC_FEATURE_REQUIRE_REGISTRATION)) {
return OPAL_ERR_NOT_AVAILABLE;
}
return mca_smsc->registration_data_size;
}
#define MCA_SMSC_BASE_VERSION_1_0_0 \
OPAL_MCA_BASE_VERSION_2_1_0("smsc", MCA_SMSC_BASE_MAJOR_VERSION, MCA_SMSC_BASE_MINOR_VERSION, \
MCA_SMSC_BASE_PATCH_VERSION)
#define MCA_SMSC_DEFAULT_VERSION(name) \
MCA_SMSC_BASE_VERSION_1_0_0, .mca_component_name = name, \
MCA_BASE_MAKE_VERSION(component, OPAL_MAJOR_VERSION, \
OPAL_MINOR_VERSION, OPAL_RELEASE_VERSION)
#endif /* OPAL_MCA_SMSC_H */
|