X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/3080c6b0d097d6b3b7d5b3dda0592154ce438f64..7f2b5ea49487adf6b6d075435936f060617c96ad:/src/smpi/smpi_mpi_dt.c diff --git a/src/smpi/smpi_mpi_dt.c b/src/smpi/smpi_mpi_dt.c index bfd4b03315..bb63c6bc69 100644 --- a/src/smpi/smpi_mpi_dt.c +++ b/src/smpi/smpi_mpi_dt.c @@ -1,7 +1,7 @@ /* smpi_mpi_dt.c -- MPI primitives to handle datatypes */ /* FIXME: a very incomplete implementation */ -/* Copyright (c) 2009-2014. The SimGrid Team. +/* Copyright (c) 2009-2015. The SimGrid Team. * All rights reserved. */ /* This program is free software; you can redistribute it and/or modify it @@ -10,7 +10,7 @@ #include #include #include - +#include #include "private.h" #include "smpi_mpi_dt_private.h" #include "mc/mc.h" @@ -20,27 +20,36 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_mpi_dt, smpi, "Logging specific to SMPI (datatype)"); -#define CREATE_MPI_DATATYPE(name, type) \ - static s_smpi_mpi_datatype_t mpi_##name = { \ - sizeof(type), /* size */ \ - 0, /*was 1 has_subtype*/ \ - 0, /* lb */ \ - sizeof(type), /* ub = lb + size */ \ - DT_FLAG_BASIC, /* flags */ \ - NULL /* pointer on extended struct*/ \ - }; \ -MPI_Datatype name = &mpi_##name; - -#define CREATE_MPI_DATATYPE_NULL(name) \ - static s_smpi_mpi_datatype_t mpi_##name = { \ - 0, /* size */ \ - 0, /*was 1 has_subtype*/ \ - 0, /* lb */ \ - 0, /* ub = lb + size */ \ - DT_FLAG_BASIC, /* flags */ \ - NULL /* pointer on extended struct*/ \ - }; \ -MPI_Datatype name = &mpi_##name; +xbt_dict_t smpi_type_keyvals = NULL; +int type_keyval_id=0;//avoid collisions + +#define CREATE_MPI_DATATYPE(name, type) \ + static s_smpi_mpi_datatype_t mpi_##name = { \ + (char*) # name, \ + sizeof(type), /* size */ \ + 0, /*was 1 has_subtype*/ \ + 0, /* lb */ \ + sizeof(type), /* ub = lb + size */ \ + DT_FLAG_BASIC, /* flags */ \ + NULL, /* attributes */ \ + NULL, /* pointer on extended struct*/ \ + 0 /* in_use counter */ \ + }; \ +const MPI_Datatype name = &mpi_##name; + +#define CREATE_MPI_DATATYPE_NULL(name) \ + static s_smpi_mpi_datatype_t mpi_##name = { \ + (char*) # name, \ + 0, /* size */ \ + 0, /* was 1 has_subtype*/ \ + 0, /* lb */ \ + 0, /* ub = lb + size */ \ + DT_FLAG_BASIC, /* flags */ \ + NULL, /* attributes */ \ + NULL, /* pointer on extended struct*/ \ + 0 /* in_use counter */ \ + }; \ +const MPI_Datatype name = &mpi_##name; //The following are datatypes for the MPI functions MPI_MAXLOC and MPI_MINLOC. typedef struct { @@ -51,6 +60,10 @@ typedef struct { float value; float index; } float_float; +typedef struct { + long value; + long index; +} long_long; typedef struct { double value; double index; @@ -75,7 +88,10 @@ typedef struct { long double value; int index; } long_double_int; - +typedef struct { + int64_t value; + int64_t index; +} integer128_t; // Predefined data types CREATE_MPI_DATATYPE(MPI_CHAR, char); CREATE_MPI_DATATYPE(MPI_SHORT, short); @@ -93,6 +109,7 @@ CREATE_MPI_DATATYPE(MPI_DOUBLE, double); CREATE_MPI_DATATYPE(MPI_LONG_DOUBLE, long double); CREATE_MPI_DATATYPE(MPI_WCHAR, wchar_t); CREATE_MPI_DATATYPE(MPI_C_BOOL, _Bool); +CREATE_MPI_DATATYPE(MPI_BYTE, int8_t); CREATE_MPI_DATATYPE(MPI_INT8_T, int8_t); CREATE_MPI_DATATYPE(MPI_INT16_T, int16_t); CREATE_MPI_DATATYPE(MPI_INT32_T, int32_t); @@ -114,12 +131,26 @@ CREATE_MPI_DATATYPE(MPI_SHORT_INT, short_int); CREATE_MPI_DATATYPE(MPI_2INT, int_int); CREATE_MPI_DATATYPE(MPI_2FLOAT, float_float); CREATE_MPI_DATATYPE(MPI_2DOUBLE, double_double); +CREATE_MPI_DATATYPE(MPI_2LONG, long_long); + +CREATE_MPI_DATATYPE(MPI_REAL, float); +CREATE_MPI_DATATYPE(MPI_REAL4, float); +CREATE_MPI_DATATYPE(MPI_REAL8, float); +CREATE_MPI_DATATYPE(MPI_REAL16, double); +CREATE_MPI_DATATYPE_NULL(MPI_COMPLEX8); +CREATE_MPI_DATATYPE_NULL(MPI_COMPLEX16); +CREATE_MPI_DATATYPE_NULL(MPI_COMPLEX32); +CREATE_MPI_DATATYPE(MPI_INTEGER1, int); +CREATE_MPI_DATATYPE(MPI_INTEGER2, int16_t); +CREATE_MPI_DATATYPE(MPI_INTEGER4, int32_t); +CREATE_MPI_DATATYPE(MPI_INTEGER8, int64_t); +CREATE_MPI_DATATYPE(MPI_INTEGER16, integer128_t); CREATE_MPI_DATATYPE(MPI_LONG_DOUBLE_INT, long_double_int); CREATE_MPI_DATATYPE_NULL(MPI_UB); CREATE_MPI_DATATYPE_NULL(MPI_LB); -CREATE_MPI_DATATYPE_NULL(MPI_PACKED); +CREATE_MPI_DATATYPE(MPI_PACKED, char); // Internal use only CREATE_MPI_DATATYPE(MPI_PTR, void*); @@ -145,33 +176,76 @@ MPI_Aint smpi_datatype_ub(MPI_Datatype datatype) return datatype->ub; } -MPI_Datatype smpi_datatype_dup(MPI_Datatype datatype) +int smpi_datatype_dup(MPI_Datatype datatype, MPI_Datatype* new_t) { - MPI_Datatype new_t= xbt_new(s_smpi_mpi_datatype_t,1); - memcpy(new_t, datatype, sizeof(s_smpi_mpi_datatype_t)); - if (datatype->has_subtype) - memcpy(new_t->substruct, datatype->substruct, sizeof(s_smpi_subtype_t)); - return new_t; + int ret=MPI_SUCCESS; + *new_t= xbt_new(s_smpi_mpi_datatype_t,1); + memcpy(*new_t, datatype, sizeof(s_smpi_mpi_datatype_t)); + if (datatype->has_subtype){ + //FIXME: may copy too much information. + (*new_t)->substruct=xbt_malloc(sizeof(s_smpi_mpi_struct_t)); + memcpy((*new_t)->substruct, datatype->substruct, sizeof(s_smpi_mpi_struct_t)); + } + if(datatype->name) + (*new_t)->name = xbt_strdup(datatype->name); + if(datatype->attributes !=NULL){ + (*new_t)->attributes=xbt_dict_new(); + xbt_dict_cursor_t cursor = NULL; + int *key; + int flag; + void* value_in; + void* value_out; + xbt_dict_foreach(datatype->attributes, cursor, key, value_in){ + smpi_type_key_elem elem = xbt_dict_get_or_null_ext(smpi_type_keyvals, (const char*)key, sizeof(int)); + if(elem && elem->copy_fn!=MPI_NULL_COPY_FN){ + ret = elem->copy_fn(datatype, *key, NULL, value_in, &value_out, &flag ); + if(ret!=MPI_SUCCESS){ + *new_t=MPI_DATATYPE_NULL; + return ret; + } + if(flag) + xbt_dict_set_ext((*new_t)->attributes, (const char*)key, sizeof(int),value_out, NULL); + } + } + } + return ret; } int smpi_datatype_extent(MPI_Datatype datatype, MPI_Aint * lb, MPI_Aint * extent) { + if(datatype == MPI_DATATYPE_NULL){ + *lb=0; + *extent=0; + return MPI_SUCCESS; + } *lb = datatype->lb; *extent = datatype->ub - datatype->lb; return MPI_SUCCESS; } MPI_Aint smpi_datatype_get_extent(MPI_Datatype datatype){ + if(datatype == MPI_DATATYPE_NULL){ + return 0; + } return datatype->ub - datatype->lb; } +void smpi_datatype_get_name(MPI_Datatype datatype, char* name, int* length){ + *length = strlen(datatype->name); + strcpy(name, datatype->name); +} + +void smpi_datatype_set_name(MPI_Datatype datatype, char* name){ + datatype->name = xbt_strdup(name);; +} + int smpi_datatype_copy(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype) { int count; if(smpi_privatize_global_variables){ - switch_data_segment(smpi_process_index()); + smpi_switch_data_segment(smpi_process_index()); } /* First check if we really have something to do */ if (recvcount > 0 && recvbuf != sendbuf) { @@ -181,17 +255,17 @@ int smpi_datatype_copy(void *sendbuf, int sendcount, MPI_Datatype sendtype, count = sendcount < recvcount ? sendcount : recvcount; if(sendtype->has_subtype == 0 && recvtype->has_subtype == 0) { - if(!_xbt_replay_is_active()) memcpy(recvbuf, sendbuf, count); + if(!smpi_process_get_replaying()) memcpy(recvbuf, sendbuf, count); } else if (sendtype->has_subtype == 0) { s_smpi_subtype_t *subtype = recvtype->substruct; - subtype->unserialize( sendbuf, recvbuf,1, subtype, MPI_REPLACE); + subtype->unserialize( sendbuf, recvbuf, recvcount/smpi_datatype_size(recvtype), subtype, MPI_REPLACE); } else if (recvtype->has_subtype == 0) { s_smpi_subtype_t *subtype = sendtype->substruct; - subtype->serialize(sendbuf, recvbuf,1, subtype); + subtype->serialize(sendbuf, recvbuf, sendcount/smpi_datatype_size(sendtype), subtype); }else{ s_smpi_subtype_t *subtype = sendtype->substruct; @@ -314,6 +388,7 @@ s_smpi_mpi_vector_t* smpi_datatype_vector_create( int block_stride, void smpi_datatype_create(MPI_Datatype* new_type, int size,int lb, int ub, int has_subtype, void *struct_type, int flags){ MPI_Datatype new_t= xbt_new(s_smpi_mpi_datatype_t,1); + new_t->name = NULL; new_t->size = size; new_t->has_subtype = size>0? has_subtype:0; new_t->lb = lb; @@ -321,6 +396,7 @@ void smpi_datatype_create(MPI_Datatype* new_type, int size,int lb, int ub, int h new_t->flags = flags; new_t->substruct = struct_type; new_t->in_use=0; + new_t->attributes=NULL; *new_type = new_t; #ifdef HAVE_MC @@ -330,6 +406,18 @@ void smpi_datatype_create(MPI_Datatype* new_type, int size,int lb, int ub, int h } void smpi_datatype_free(MPI_Datatype* type){ + xbt_assert((*type)->in_use >= 0); + if((*type)->attributes !=NULL){ + xbt_dict_cursor_t cursor = NULL; + int* key; + void * value; + int flag; + xbt_dict_foreach((*type)->attributes, cursor, key, value){ + smpi_type_key_elem elem = xbt_dict_get_or_null_ext(smpi_type_keyvals, (const char*)key, sizeof(int)); + if(elem && elem->delete_fn) + elem->delete_fn(*type,*key, value, &flag); + } + } if((*type)->flags & DT_FLAG_PREDEFINED)return; @@ -343,6 +431,9 @@ void smpi_datatype_free(MPI_Datatype* type){ ((s_smpi_subtype_t *)(*type)->substruct)->subtype_free(type); xbt_free((*type)->substruct); } + if ((*type)->name != NULL){ + xbt_free((*type)->name); + } xbt_free(*type); *type = MPI_DATATYPE_NULL; } @@ -358,7 +449,10 @@ void smpi_datatype_use(MPI_Datatype type){ void smpi_datatype_unuse(MPI_Datatype type){ - if(type && type->in_use-- == 0 && (type->flags & DT_FLAG_DESTROYED)) + if (type->in_use > 0) + type->in_use--; + + if(type && type->in_use == 0 && (type->flags & DT_FLAG_DESTROYED)) smpi_datatype_free(&type); #ifdef HAVE_MC @@ -1223,6 +1317,8 @@ static void max_func(void *a, void *b, int *length, APPLY_FUNC(a, b, length, unsigned int, MAX_OP); } else if (*datatype == MPI_UNSIGNED_LONG) { APPLY_FUNC(a, b, length, unsigned long, MAX_OP); + } else if (*datatype == MPI_UNSIGNED_CHAR) { + APPLY_FUNC(a, b, length, unsigned char, MAX_OP); } else if (*datatype == MPI_FLOAT) { APPLY_FUNC(a, b, length, float, MAX_OP); } else if (*datatype == MPI_DOUBLE) { @@ -1249,6 +1345,8 @@ static void min_func(void *a, void *b, int *length, APPLY_FUNC(a, b, length, unsigned int, MIN_OP); } else if (*datatype == MPI_UNSIGNED_LONG) { APPLY_FUNC(a, b, length, unsigned long, MIN_OP); + } else if (*datatype == MPI_UNSIGNED_CHAR) { + APPLY_FUNC(a, b, length, unsigned char, MIN_OP); } else if (*datatype == MPI_FLOAT) { APPLY_FUNC(a, b, length, float, MIN_OP); } else if (*datatype == MPI_DOUBLE) { @@ -1275,6 +1373,8 @@ static void sum_func(void *a, void *b, int *length, APPLY_FUNC(a, b, length, unsigned int, SUM_OP); } else if (*datatype == MPI_UNSIGNED_LONG) { APPLY_FUNC(a, b, length, unsigned long, SUM_OP); + } else if (*datatype == MPI_UNSIGNED_CHAR) { + APPLY_FUNC(a, b, length, unsigned char, SUM_OP); } else if (*datatype == MPI_FLOAT) { APPLY_FUNC(a, b, length, float, SUM_OP); } else if (*datatype == MPI_DOUBLE) { @@ -1307,6 +1407,8 @@ static void prod_func(void *a, void *b, int *length, APPLY_FUNC(a, b, length, unsigned int, PROD_OP); } else if (*datatype == MPI_UNSIGNED_LONG) { APPLY_FUNC(a, b, length, unsigned long, PROD_OP); + } else if (*datatype == MPI_UNSIGNED_CHAR) { + APPLY_FUNC(a, b, length, unsigned char, PROD_OP); } else if (*datatype == MPI_FLOAT) { APPLY_FUNC(a, b, length, float, PROD_OP); } else if (*datatype == MPI_DOUBLE) { @@ -1339,6 +1441,8 @@ static void land_func(void *a, void *b, int *length, APPLY_FUNC(a, b, length, unsigned int, LAND_OP); } else if (*datatype == MPI_UNSIGNED_LONG) { APPLY_FUNC(a, b, length, unsigned long, LAND_OP); + } else if (*datatype == MPI_UNSIGNED_CHAR) { + APPLY_FUNC(a, b, length, unsigned char, LAND_OP); } else if (*datatype == MPI_C_BOOL) { APPLY_FUNC(a, b, length, _Bool, LAND_OP); } @@ -1361,6 +1465,8 @@ static void lor_func(void *a, void *b, int *length, APPLY_FUNC(a, b, length, unsigned int, LOR_OP); } else if (*datatype == MPI_UNSIGNED_LONG) { APPLY_FUNC(a, b, length, unsigned long, LOR_OP); + } else if (*datatype == MPI_UNSIGNED_CHAR) { + APPLY_FUNC(a, b, length, unsigned char, LOR_OP); } else if (*datatype == MPI_C_BOOL) { APPLY_FUNC(a, b, length, _Bool, LOR_OP); } @@ -1383,6 +1489,8 @@ static void lxor_func(void *a, void *b, int *length, APPLY_FUNC(a, b, length, unsigned int, LXOR_OP); } else if (*datatype == MPI_UNSIGNED_LONG) { APPLY_FUNC(a, b, length, unsigned long, LXOR_OP); + } else if (*datatype == MPI_UNSIGNED_CHAR) { + APPLY_FUNC(a, b, length, unsigned char, LXOR_OP); } else if (*datatype == MPI_C_BOOL) { APPLY_FUNC(a, b, length, _Bool, LXOR_OP); } @@ -1393,8 +1501,7 @@ static void band_func(void *a, void *b, int *length, { if (*datatype == MPI_CHAR) { APPLY_FUNC(a, b, length, char, BAND_OP); - } - if (*datatype == MPI_SHORT) { + }else if (*datatype == MPI_SHORT) { APPLY_FUNC(a, b, length, short, BAND_OP); } else if (*datatype == MPI_INT) { APPLY_FUNC(a, b, length, int, BAND_OP); @@ -1406,6 +1513,8 @@ static void band_func(void *a, void *b, int *length, APPLY_FUNC(a, b, length, unsigned int, BAND_OP); } else if (*datatype == MPI_UNSIGNED_LONG) { APPLY_FUNC(a, b, length, unsigned long, BAND_OP); + } else if (*datatype == MPI_UNSIGNED_CHAR) { + APPLY_FUNC(a, b, length, unsigned char, BAND_OP); } else if (*datatype == MPI_BYTE) { APPLY_FUNC(a, b, length, uint8_t, BAND_OP); } @@ -1428,6 +1537,8 @@ static void bor_func(void *a, void *b, int *length, APPLY_FUNC(a, b, length, unsigned int, BOR_OP); } else if (*datatype == MPI_UNSIGNED_LONG) { APPLY_FUNC(a, b, length, unsigned long, BOR_OP); + } else if (*datatype == MPI_UNSIGNED_CHAR) { + APPLY_FUNC(a, b, length, unsigned char, BOR_OP); } else if (*datatype == MPI_BYTE) { APPLY_FUNC(a, b, length, uint8_t, BOR_OP); } @@ -1450,6 +1561,8 @@ static void bxor_func(void *a, void *b, int *length, APPLY_FUNC(a, b, length, unsigned int, BXOR_OP); } else if (*datatype == MPI_UNSIGNED_LONG) { APPLY_FUNC(a, b, length, unsigned long, BXOR_OP); + } else if (*datatype == MPI_UNSIGNED_CHAR) { + APPLY_FUNC(a, b, length, unsigned char, BXOR_OP); } else if (*datatype == MPI_BYTE) { APPLY_FUNC(a, b, length, uint8_t, BXOR_OP); } @@ -1466,6 +1579,8 @@ static void minloc_func(void *a, void *b, int *length, APPLY_FUNC(a, b, length, double_int, MINLOC_OP); } else if (*datatype == MPI_SHORT_INT) { APPLY_FUNC(a, b, length, short_int, MINLOC_OP); + } else if (*datatype == MPI_2LONG) { + APPLY_FUNC(a, b, length, long_long, MINLOC_OP); } else if (*datatype == MPI_2INT) { APPLY_FUNC(a, b, length, int_int, MINLOC_OP); } else if (*datatype == MPI_LONG_DOUBLE_INT) { @@ -1488,6 +1603,8 @@ static void maxloc_func(void *a, void *b, int *length, APPLY_FUNC(a, b, length, double_int, MAXLOC_OP); } else if (*datatype == MPI_SHORT_INT) { APPLY_FUNC(a, b, length, short_int, MAXLOC_OP); + } else if (*datatype == MPI_2LONG) { + APPLY_FUNC(a, b, length, long_long, MAXLOC_OP); } else if (*datatype == MPI_2INT) { APPLY_FUNC(a, b, length, int_int, MAXLOC_OP); } else if (*datatype == MPI_LONG_DOUBLE_INT) { @@ -1546,11 +1663,119 @@ void smpi_op_destroy(MPI_Op op) void smpi_op_apply(MPI_Op op, void *invec, void *inoutvec, int *len, MPI_Datatype * datatype) { + if(op==MPI_OP_NULL) + return; + if(smpi_privatize_global_variables){ //we need to switch here, as the called function may silently touch global variables - XBT_VERB("Applying operation, switch to the right data frame "); - switch_data_segment(smpi_process_index()); + XBT_DEBUG("Applying operation, switch to the right data frame "); + smpi_switch_data_segment(smpi_process_index()); } - if(!_xbt_replay_is_active()) + if(!smpi_process_get_replaying()) op->func(invec, inoutvec, len, datatype); } + +int smpi_type_attr_delete(MPI_Datatype type, int keyval){ + smpi_type_key_elem elem = xbt_dict_get_or_null_ext(smpi_type_keyvals, (const char*)&keyval, sizeof(int)); + if(!elem) + return MPI_ERR_ARG; + if(elem->delete_fn!=MPI_NULL_DELETE_FN){ + void * value; + int flag; + if(smpi_type_attr_get(type, keyval, &value, &flag)==MPI_SUCCESS){ + int ret = elem->delete_fn(type, keyval, value, &flag); + if(ret!=MPI_SUCCESS) return ret; + } + } + if(type->attributes==NULL) + return MPI_ERR_ARG; + + xbt_dict_remove_ext(type->attributes, (const char*)&keyval, sizeof(int)); + return MPI_SUCCESS; +} + +int smpi_type_attr_get(MPI_Datatype type, int keyval, void* attr_value, int* flag){ + smpi_type_key_elem elem = xbt_dict_get_or_null_ext(smpi_type_keyvals, (const char*)&keyval, sizeof(int)); + if(!elem) + return MPI_ERR_ARG; + xbt_ex_t ex; + if(type->attributes==NULL){ + *flag=0; + return MPI_SUCCESS; + } + TRY { + *(void**)attr_value = xbt_dict_get_ext(type->attributes, (const char*)&keyval, sizeof(int)); + *flag=1; + } + CATCH(ex) { + *flag=0; + xbt_ex_free(ex); + } + return MPI_SUCCESS; +} + +int smpi_type_attr_put(MPI_Datatype type, int keyval, void* attr_value){ + if(!smpi_type_keyvals) + smpi_type_keyvals = xbt_dict_new(); + smpi_type_key_elem elem = xbt_dict_get_or_null_ext(smpi_type_keyvals, (const char*)&keyval, sizeof(int)); + if(!elem ) + return MPI_ERR_ARG; + int flag; + void* value; + smpi_type_attr_get(type, keyval, &value, &flag); + if(flag && elem->delete_fn!=MPI_NULL_DELETE_FN){ + int ret = elem->delete_fn(type, keyval, value, &flag); + if(ret!=MPI_SUCCESS) return ret; + } + if(type->attributes==NULL) + type->attributes=xbt_dict_new(); + + xbt_dict_set_ext(type->attributes, (const char*)&keyval, sizeof(int), attr_value, NULL); + return MPI_SUCCESS; +} + +int smpi_type_keyval_create(MPI_Type_copy_attr_function* copy_fn, MPI_Type_delete_attr_function* delete_fn, int* keyval, void* extra_state){ + + if(!smpi_type_keyvals) + smpi_type_keyvals = xbt_dict_new(); + + smpi_type_key_elem value = (smpi_type_key_elem) xbt_new0(s_smpi_mpi_type_key_elem_t,1); + + value->copy_fn=copy_fn; + value->delete_fn=delete_fn; + + *keyval = type_keyval_id; + xbt_dict_set_ext(smpi_type_keyvals,(const char*)keyval, sizeof(int),(void*)value, NULL); + type_keyval_id++; + return MPI_SUCCESS; +} + +int smpi_type_keyval_free(int* keyval){ + smpi_type_key_elem elem = xbt_dict_get_or_null_ext(smpi_type_keyvals, (const char*)keyval, sizeof(int)); + if(!elem){ + return MPI_ERR_ARG; + } + xbt_dict_remove_ext(smpi_type_keyvals, (const char*)keyval, sizeof(int)); + xbt_free(elem); + return MPI_SUCCESS; +} + +int smpi_mpi_pack(void* inbuf, int incount, MPI_Datatype type, void* outbuf, int outcount, int* position, MPI_Comm comm){ + size_t size = smpi_datatype_size(type); + if (outcount - *position < incount*size) + return MPI_ERR_BUFFER; + smpi_datatype_copy(inbuf, incount, type, + (char*)outbuf + *position, outcount, MPI_CHAR); + *position += incount * size; + return MPI_SUCCESS; +} + +int smpi_mpi_unpack(void* inbuf, int insize, int* position, void* outbuf, int outcount, MPI_Datatype type, MPI_Comm comm){ + size_t size = smpi_datatype_size(type); + if (outcount*size> insize) + return MPI_ERR_BUFFER; + smpi_datatype_copy((char*)inbuf + *position, insize, MPI_CHAR, + outbuf, outcount, type); + *position += outcount * size; + return MPI_SUCCESS; +}