io/ompio and common/ompio: add initial support for cuda buffers in ompio
this commit adds the initial support for cuda buffers in ompio, for blocking and non-blocking individual read and write operations. Signed-off-by: Edgar Gabriel <egabriel@central.uh.edu>
Этот коммит содержится в:
родитель
8c2ea0ef49
Коммит
6a532101aa
@ -9,7 +9,7 @@
|
|||||||
# University of Stuttgart. All rights reserved.
|
# University of Stuttgart. All rights reserved.
|
||||||
# Copyright (c) 2004-2005 The Regents of the University of California.
|
# Copyright (c) 2004-2005 The Regents of the University of California.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
# Copyright (c) 2008-2016 University of Houston. All rights reserved.
|
# Copyright (c) 2008-2018 University of Houston. All rights reserved.
|
||||||
# Copyright (c) 2016 IBM Corporation. All rights reserved.
|
# Copyright (c) 2016 IBM Corporation. All rights reserved.
|
||||||
# Copyright (c) 2017-2018 Research Organization for Information Science
|
# Copyright (c) 2017-2018 Research Organization for Information Science
|
||||||
# and Technology (RIST). All rights reserved.
|
# and Technology (RIST). All rights reserved.
|
||||||
@ -74,6 +74,11 @@ else
|
|||||||
ompidir = $(includedir)
|
ompidir = $(includedir)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if OPAL_cuda_support
|
||||||
|
headers += common_ompio_cuda.h
|
||||||
|
sources += common_ompio_cuda.c
|
||||||
|
endif
|
||||||
|
|
||||||
# These two rules will sym link the "noinst" libtool library filename
|
# These two rules will sym link the "noinst" libtool library filename
|
||||||
# to the installable libtool library filename in the case where we are
|
# to the installable libtool library filename in the case where we are
|
||||||
# compiling this component statically (case 2), described above).
|
# compiling this component statically (case 2), described above).
|
||||||
|
69
ompi/mca/common/ompio/common_ompio_cuda.c
Обычный файл
69
ompi/mca/common/ompio/common_ompio_cuda.c
Обычный файл
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||||
|
* University Research and Technology
|
||||||
|
* Corporation. All rights reserved.
|
||||||
|
* Copyright (c) 2004-2016 The University of Tennessee and The University
|
||||||
|
* of Tennessee Research Foundation. All rights
|
||||||
|
* reserved.
|
||||||
|
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
||||||
|
* University of Stuttgart. All rights reserved.
|
||||||
|
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||||
|
* All rights reserved.
|
||||||
|
* Copyright (c) 2008-2018 University of Houston. All rights reserved.
|
||||||
|
* $COPYRIGHT$
|
||||||
|
*
|
||||||
|
* Additional copyrights may follow
|
||||||
|
*
|
||||||
|
* $HEADER$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ompi_config.h"
|
||||||
|
|
||||||
|
#include "opal/datatype/opal_convertor.h"
|
||||||
|
#include "opal/datatype/opal_datatype_cuda.h"
|
||||||
|
#include "opal/mca/common/cuda/common_cuda.h"
|
||||||
|
|
||||||
|
#include "ompi/mca/io/ompio/io_ompio.h"
|
||||||
|
#include "common_ompio.h"
|
||||||
|
#include "common_ompio_cuda.h"
|
||||||
|
|
||||||
|
void mca_common_ompio_check_gpu_buf ( ompio_file_t *fh, const void *buf, int *is_gpu,
|
||||||
|
int *is_managed)
|
||||||
|
{
|
||||||
|
opal_convertor_t convertor;
|
||||||
|
|
||||||
|
*is_gpu=0;
|
||||||
|
*is_managed=0;
|
||||||
|
|
||||||
|
convertor.flags=0;
|
||||||
|
if ( opal_cuda_check_one_buf ( (char *)buf, &convertor ) ) {
|
||||||
|
*is_gpu = 1;
|
||||||
|
if ( convertor.flags & CONVERTOR_CUDA_UNIFIED ){
|
||||||
|
*is_managed =1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mca_common_ompio_register_buf ( ompio_file_t *fh, const void *buf,
|
||||||
|
size_t bufsize )
|
||||||
|
{
|
||||||
|
mca_common_cuda_register ( ( char *)buf, bufsize, (char *) fh->f_filename );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mca_common_ompio_unregister_buf ( ompio_file_t *fh, void *buf )
|
||||||
|
{
|
||||||
|
if ( NULL != fh ) {
|
||||||
|
mca_common_cuda_unregister ( (char *)buf, (char *)fh->f_filename);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
char dummy_filename[]="dummy_ompio_filename";
|
||||||
|
mca_common_cuda_unregister ( (char *)buf, (char *)dummy_filename);
|
||||||
|
}
|
||||||
|
free (buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
51
ompi/mca/common/ompio/common_ompio_cuda.h
Обычный файл
51
ompi/mca/common/ompio/common_ompio_cuda.h
Обычный файл
@ -0,0 +1,51 @@
|
|||||||
|
/* -*- Mode: C; c-basic-offset:4 ; -*- */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||||
|
* University Research and Technology
|
||||||
|
* Corporation. All rights reserved.
|
||||||
|
* Copyright (c) 2004-2007 The University of Tennessee and The University
|
||||||
|
* of Tennessee Research Foundation. All rights
|
||||||
|
* reserved.
|
||||||
|
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
||||||
|
* University of Stuttgart. All rights reserved.
|
||||||
|
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||||
|
* All rights reserved.
|
||||||
|
* Copyright (c) 2008-2018 University of Houston. All rights reserved.
|
||||||
|
* $COPYRIGHT$
|
||||||
|
*
|
||||||
|
* Additional copyrights may follow
|
||||||
|
*
|
||||||
|
* $HEADER$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MCA_COMMON_OMPIO_CUDA_H
|
||||||
|
#define MCA_COMMON_OMPIO_CUDA_H
|
||||||
|
|
||||||
|
|
||||||
|
#define OMPIO_CUDA_PREPARE_BUF(_fh,_buf,_count,_datatype,_tbuf,_convertor,_max_data,_decoded_iov,_iov_count){ \
|
||||||
|
opal_convertor_clone ( _fh->f_convertor, _convertor, 0); \
|
||||||
|
opal_convertor_prepare_for_send ( _convertor, &(_datatype->super), _count, _buf );\
|
||||||
|
opal_convertor_get_packed_size( _convertor, &_max_data ); \
|
||||||
|
_tbuf = (char *) malloc ( _max_data ); \
|
||||||
|
if ( NULL == _tbuf ) { \
|
||||||
|
opal_output(1, "common_ompio: could not allocate memory.\n"); \
|
||||||
|
return OMPI_ERR_OUT_OF_RESOURCE; \
|
||||||
|
} \
|
||||||
|
mca_common_ompio_register_buf (_fh, _tbuf, _max_data); \
|
||||||
|
_decoded_iov = (struct iovec *) malloc ( sizeof ( struct iovec )); \
|
||||||
|
if ( NULL == _decoded_iov ) { \
|
||||||
|
opal_output(1, "common_ompio: could not allocate memory.\n"); \
|
||||||
|
return OMPI_ERR_OUT_OF_RESOURCE; \
|
||||||
|
} \
|
||||||
|
_decoded_iov->iov_base = _tbuf; \
|
||||||
|
_decoded_iov->iov_len = _max_data; \
|
||||||
|
_iov_count=1;}
|
||||||
|
|
||||||
|
|
||||||
|
void mca_common_ompio_check_gpu_buf ( ompio_file_t *fh, const void *buf,
|
||||||
|
int *is_gpu, int *is_managed);
|
||||||
|
void mca_common_ompio_register_buf ( ompio_file_t *fh, const void *buf,
|
||||||
|
size_t bufsize);
|
||||||
|
void mca_common_ompio_unregister_buf ( ompio_file_t *fh, void *buf );
|
||||||
|
|
||||||
|
#endif
|
@ -36,6 +36,10 @@
|
|||||||
#include "math.h"
|
#include "math.h"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#if OPAL_CUDA_SUPPORT
|
||||||
|
#include "common_ompio_cuda.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Read and write routines are split into two interfaces.
|
/* Read and write routines are split into two interfaces.
|
||||||
** The
|
** The
|
||||||
** mca_io_ompio_file_read/write[_at]
|
** mca_io_ompio_file_read/write[_at]
|
||||||
@ -86,6 +90,17 @@ int mca_common_ompio_file_read (ompio_file_t *fh,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if OPAL_CUDA_SUPPORT
|
||||||
|
int is_gpu=0, is_managed=0;
|
||||||
|
opal_convertor_t convertor;
|
||||||
|
mca_common_ompio_check_gpu_buf ( fh, buf, &is_gpu, &is_managed);
|
||||||
|
if ( is_gpu && !is_managed ) {
|
||||||
|
char *tbuf=NULL;
|
||||||
|
|
||||||
|
OMPIO_CUDA_PREPARE_BUF(fh,buf,count,datatype,tbuf,&convertor,max_data,decoded_iov,iov_count);
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
mca_common_ompio_decode_datatype (fh,
|
mca_common_ompio_decode_datatype (fh,
|
||||||
datatype,
|
datatype,
|
||||||
count,
|
count,
|
||||||
@ -93,8 +108,18 @@ int mca_common_ompio_file_read (ompio_file_t *fh,
|
|||||||
&max_data,
|
&max_data,
|
||||||
&decoded_iov,
|
&decoded_iov,
|
||||||
&iov_count);
|
&iov_count);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
mca_common_ompio_decode_datatype (fh,
|
||||||
|
datatype,
|
||||||
|
count,
|
||||||
|
buf,
|
||||||
|
&max_data,
|
||||||
|
&decoded_iov,
|
||||||
|
&iov_count);
|
||||||
|
#endif
|
||||||
|
|
||||||
if ( -1 == OMPIO_MCA_GET(fh, cycle_buffer_size) ) {
|
if ( -1 == OMPIO_MCA_GET(fh, cycle_buffer_size )) {
|
||||||
bytes_per_cycle = max_data;
|
bytes_per_cycle = max_data;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -136,6 +161,15 @@ int mca_common_ompio_file_read (ompio_file_t *fh,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if OPAL_CUDA_SUPPORT
|
||||||
|
if ( is_gpu && !is_managed ) {
|
||||||
|
size_t pos=0;
|
||||||
|
|
||||||
|
opal_convertor_unpack (&convertor, decoded_iov, &iov_count, &pos );
|
||||||
|
opal_convertor_cleanup (&convertor);
|
||||||
|
mca_common_ompio_unregister_buf (fh, decoded_iov->iov_base);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (NULL != decoded_iov) {
|
if (NULL != decoded_iov) {
|
||||||
free (decoded_iov);
|
free (decoded_iov);
|
||||||
decoded_iov = NULL;
|
decoded_iov = NULL;
|
||||||
@ -208,6 +242,18 @@ int mca_common_ompio_file_iread (ompio_file_t *fh,
|
|||||||
int i = 0; /* index into the decoded iovec of the buffer */
|
int i = 0; /* index into the decoded iovec of the buffer */
|
||||||
int j = 0; /* index into the file vie iovec */
|
int j = 0; /* index into the file vie iovec */
|
||||||
|
|
||||||
|
#if OPAL_CUDA_SUPPORT
|
||||||
|
int is_gpu=0, is_managed=0;
|
||||||
|
mca_common_ompio_check_gpu_buf ( fh, buf, &is_gpu, &is_managed);
|
||||||
|
if ( is_gpu && !is_managed ) {
|
||||||
|
char *tbuf=NULL;
|
||||||
|
|
||||||
|
OMPIO_CUDA_PREPARE_BUF(fh,buf,count,datatype,tbuf,&ompio_req->req_convertor,max_data,decoded_iov,iov_count);
|
||||||
|
|
||||||
|
ompio_req->req_tbuf = tbuf;
|
||||||
|
ompio_req->req_size = max_data;
|
||||||
|
}
|
||||||
|
else {
|
||||||
mca_common_ompio_decode_datatype (fh,
|
mca_common_ompio_decode_datatype (fh,
|
||||||
datatype,
|
datatype,
|
||||||
count,
|
count,
|
||||||
@ -215,7 +261,16 @@ int mca_common_ompio_file_iread (ompio_file_t *fh,
|
|||||||
&max_data,
|
&max_data,
|
||||||
&decoded_iov,
|
&decoded_iov,
|
||||||
&iov_count);
|
&iov_count);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
mca_common_ompio_decode_datatype (fh,
|
||||||
|
datatype,
|
||||||
|
count,
|
||||||
|
buf,
|
||||||
|
&max_data,
|
||||||
|
&decoded_iov,
|
||||||
|
&iov_count);
|
||||||
|
#endif
|
||||||
// Non-blocking operations have to occur in a single cycle
|
// Non-blocking operations have to occur in a single cycle
|
||||||
j = fh->f_index_in_file_view;
|
j = fh->f_index_in_file_view;
|
||||||
|
|
||||||
|
@ -34,6 +34,10 @@
|
|||||||
#include "math.h"
|
#include "math.h"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#if OPAL_CUDA_SUPPORT
|
||||||
|
#include "common_ompio_cuda.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
int mca_common_ompio_file_write (ompio_file_t *fh,
|
int mca_common_ompio_file_write (ompio_file_t *fh,
|
||||||
const void *buf,
|
const void *buf,
|
||||||
int count,
|
int count,
|
||||||
@ -61,6 +65,20 @@ int mca_common_ompio_file_write (ompio_file_t *fh,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if OPAL_CUDA_SUPPORT
|
||||||
|
int is_gpu=0, is_managed=0;
|
||||||
|
mca_common_ompio_check_gpu_buf ( fh, buf, &is_gpu, &is_managed);
|
||||||
|
if ( is_gpu && !is_managed ) {
|
||||||
|
size_t pos=0;
|
||||||
|
char *tbuf=NULL;
|
||||||
|
opal_convertor_t convertor;
|
||||||
|
|
||||||
|
OMPIO_CUDA_PREPARE_BUF(fh,buf,count,datatype,tbuf,&convertor,max_data,decoded_iov,iov_count);
|
||||||
|
|
||||||
|
opal_convertor_pack (&convertor, decoded_iov, &iov_count, &pos );
|
||||||
|
opal_convertor_cleanup ( &convertor);
|
||||||
|
}
|
||||||
|
else {
|
||||||
mca_common_ompio_decode_datatype (fh,
|
mca_common_ompio_decode_datatype (fh,
|
||||||
datatype,
|
datatype,
|
||||||
count,
|
count,
|
||||||
@ -68,8 +86,17 @@ int mca_common_ompio_file_write (ompio_file_t *fh,
|
|||||||
&max_data,
|
&max_data,
|
||||||
&decoded_iov,
|
&decoded_iov,
|
||||||
&iov_count);
|
&iov_count);
|
||||||
|
}
|
||||||
if ( -1 == OMPIO_MCA_GET(fh, cycle_buffer_size) ) {
|
#else
|
||||||
|
mca_common_ompio_decode_datatype (fh,
|
||||||
|
datatype,
|
||||||
|
count,
|
||||||
|
buf,
|
||||||
|
&max_data,
|
||||||
|
&decoded_iov,
|
||||||
|
&iov_count);
|
||||||
|
#endif
|
||||||
|
if ( -1 == OMPIO_MCA_GET(fh, cycle_buffer_size )) {
|
||||||
bytes_per_cycle = max_data;
|
bytes_per_cycle = max_data;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -108,6 +135,11 @@ int mca_common_ompio_file_write (ompio_file_t *fh,
|
|||||||
fh->f_io_array = NULL;
|
fh->f_io_array = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if OPAL_CUDA_SUPPORT
|
||||||
|
if ( is_gpu && !is_managed ) {
|
||||||
|
mca_common_ompio_unregister_buf (fh, decoded_iov->iov_base);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (NULL != decoded_iov) {
|
if (NULL != decoded_iov) {
|
||||||
free (decoded_iov);
|
free (decoded_iov);
|
||||||
@ -176,6 +208,23 @@ int mca_common_ompio_file_iwrite (ompio_file_t *fh,
|
|||||||
int i = 0; /* index into the decoded iovec of the buffer */
|
int i = 0; /* index into the decoded iovec of the buffer */
|
||||||
int j = 0; /* index into the file vie iovec */
|
int j = 0; /* index into the file vie iovec */
|
||||||
|
|
||||||
|
#if OPAL_CUDA_SUPPORT
|
||||||
|
int is_gpu=0, is_managed=0;
|
||||||
|
mca_common_ompio_check_gpu_buf ( fh, buf, &is_gpu, &is_managed);
|
||||||
|
if ( is_gpu && !is_managed ) {
|
||||||
|
size_t pos=0;
|
||||||
|
char *tbuf=NULL;
|
||||||
|
opal_convertor_t convertor;
|
||||||
|
|
||||||
|
OMPIO_CUDA_PREPARE_BUF(fh,buf,count,datatype,tbuf,&convertor,max_data,decoded_iov,iov_count);
|
||||||
|
|
||||||
|
opal_convertor_pack (&convertor, decoded_iov, &iov_count, &pos );
|
||||||
|
opal_convertor_cleanup (&convertor);
|
||||||
|
|
||||||
|
ompio_req->req_tbuf = tbuf;
|
||||||
|
ompio_req->req_size = max_data;
|
||||||
|
}
|
||||||
|
else {
|
||||||
mca_common_ompio_decode_datatype (fh,
|
mca_common_ompio_decode_datatype (fh,
|
||||||
datatype,
|
datatype,
|
||||||
count,
|
count,
|
||||||
@ -183,6 +232,16 @@ int mca_common_ompio_file_iwrite (ompio_file_t *fh,
|
|||||||
&max_data,
|
&max_data,
|
||||||
&decoded_iov,
|
&decoded_iov,
|
||||||
&iov_count);
|
&iov_count);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
mca_common_ompio_decode_datatype (fh,
|
||||||
|
datatype,
|
||||||
|
count,
|
||||||
|
buf,
|
||||||
|
&max_data,
|
||||||
|
&decoded_iov,
|
||||||
|
&iov_count);
|
||||||
|
#endif
|
||||||
j = fh->f_index_in_file_view;
|
j = fh->f_index_in_file_view;
|
||||||
|
|
||||||
/* Non blocking operations have to occur in a single cycle */
|
/* Non blocking operations have to occur in a single cycle */
|
||||||
|
@ -19,6 +19,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common_ompio_request.h"
|
#include "common_ompio_request.h"
|
||||||
|
#if OPAL_CUDA_SUPPORT
|
||||||
|
#include "common_ompio_cuda.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
static void mca_common_ompio_request_construct(mca_ompio_request_t* req);
|
static void mca_common_ompio_request_construct(mca_ompio_request_t* req);
|
||||||
static void mca_common_ompio_request_destruct(mca_ompio_request_t *req);
|
static void mca_common_ompio_request_destruct(mca_ompio_request_t *req);
|
||||||
@ -34,6 +37,20 @@ opal_list_t mca_common_ompio_pending_requests = {{0}};
|
|||||||
static int mca_common_ompio_request_free ( struct ompi_request_t **req)
|
static int mca_common_ompio_request_free ( struct ompi_request_t **req)
|
||||||
{
|
{
|
||||||
mca_ompio_request_t *ompio_req = ( mca_ompio_request_t *)*req;
|
mca_ompio_request_t *ompio_req = ( mca_ompio_request_t *)*req;
|
||||||
|
#if OPAL_CUDA_SUPPORT
|
||||||
|
if ( NULL != ompio_req->req_tbuf ) {
|
||||||
|
if ( MCA_OMPIO_REQUEST_READ == ompio_req->req_type ){
|
||||||
|
struct iovec decoded_iov;
|
||||||
|
uint32_t iov_count=1;
|
||||||
|
size_t pos=0;
|
||||||
|
|
||||||
|
decoded_iov.iov_base = ompio_req->req_tbuf;
|
||||||
|
decoded_iov.iov_len = ompio_req->req_size;
|
||||||
|
opal_convertor_unpack (&ompio_req->req_convertor, &decoded_iov, &iov_count, &pos );
|
||||||
|
}
|
||||||
|
mca_common_ompio_unregister_buf ( NULL, ompio_req->req_tbuf );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if ( NULL != ompio_req->req_free_fn ) {
|
if ( NULL != ompio_req->req_free_fn ) {
|
||||||
ompio_req->req_free_fn (ompio_req );
|
ompio_req->req_free_fn (ompio_req );
|
||||||
}
|
}
|
||||||
@ -60,6 +77,10 @@ void mca_common_ompio_request_construct(mca_ompio_request_t* req)
|
|||||||
req->req_ompi.req_cancel = mca_common_ompio_request_cancel;
|
req->req_ompi.req_cancel = mca_common_ompio_request_cancel;
|
||||||
req->req_ompi.req_type = OMPI_REQUEST_IO;
|
req->req_ompi.req_type = OMPI_REQUEST_IO;
|
||||||
req->req_data = NULL;
|
req->req_data = NULL;
|
||||||
|
#if OPAL_CUDA_SUPPORT
|
||||||
|
req->req_tbuf = NULL;
|
||||||
|
req->req_size = 0;
|
||||||
|
#endif
|
||||||
req->req_progress_fn = NULL;
|
req->req_progress_fn = NULL;
|
||||||
req->req_free_fn = NULL;
|
req->req_free_fn = NULL;
|
||||||
|
|
||||||
|
@ -52,6 +52,11 @@ struct mca_ompio_request_t {
|
|||||||
mca_ompio_request_type_t req_type;
|
mca_ompio_request_type_t req_type;
|
||||||
void *req_data;
|
void *req_data;
|
||||||
opal_list_item_t req_item;
|
opal_list_item_t req_item;
|
||||||
|
#if OPAL_CUDA_SUPPORT
|
||||||
|
void *req_tbuf;
|
||||||
|
size_t req_size;
|
||||||
|
opal_convertor_t req_convertor;
|
||||||
|
#endif
|
||||||
mca_fbtl_base_module_progress_fn_t req_progress_fn;
|
mca_fbtl_base_module_progress_fn_t req_progress_fn;
|
||||||
mca_fbtl_base_module_request_free_fn_t req_free_fn;
|
mca_fbtl_base_module_request_free_fn_t req_free_fn;
|
||||||
};
|
};
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user