root/opal/datatype/opal_datatype_position.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. position_predefined_data
  2. position_contiguous_loop
  3. opal_convertor_generic_simple_position

   1 /* -*- Mode: C; c-basic-offset:4 ; -*- */
   2 /*
   3  * Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana
   4  *                         University Research and Technology
   5  *                         Corporation.  All rights reserved.
   6  * Copyright (c) 2004-2014 The University of Tennessee and The University
   7  *                         of Tennessee Research Foundation.  All rights
   8  *                         reserved.
   9  * Copyright (c) 2004-2006 High Performance Computing Center Stuttgart,
  10  *                         University of Stuttgart.  All rights reserved.
  11  * Copyright (c) 2004-2006 The Regents of the University of California.
  12  *                         All rights reserved.
  13  * Copyright (c) 2009      Oak Ridge National Labs.  All rights reserved.
  14  * Copyright (c) 2013      Cisco Systems, Inc.  All rights reserved.
  15  * Copyright (c) 2014-2018 Research Organization for Information Science
  16  *                         and Technology (RIST). All rights reserved.
  17  * $COPYRIGHT$
  18  *
  19  * Additional copyrights may follow
  20  *
  21  * $HEADER$
  22  */
  23 
  24 #include "opal_config.h"
  25 
  26 #include <stddef.h>
  27 #include <stdlib.h>
  28 
  29 #include "opal/datatype/opal_datatype.h"
  30 #include "opal/datatype/opal_convertor.h"
  31 #include "opal/datatype/opal_datatype_internal.h"
  32 
  33 #if OPAL_ENABLE_DEBUG
  34 #include "opal/util/output.h"
  35 
  36 #define DO_DEBUG(INST)  if( opal_position_debug ) { INST }
  37 #else
  38 #define DO_DEBUG(INST)
  39 #endif  /* OPAL_ENABLE_DEBUG */
  40 
  41 /* The pack/unpack functions need a cleanup. I have to create a proper interface to access
  42  * all basic functionalities, hence using them as basic blocks for all conversion functions.
  43  *
  44  * But first let's make some global assumptions:
  45  * - a datatype (with the flag DT_DATA set) will have the contiguous flags set if and only if
  46  *   the data is really contiguous (extent equal with size)
  47  * - for the OPAL_DATATYPE_LOOP type the DT_CONTIGUOUS flag set means that the content of the loop is
  48  *   contiguous but with a gap in the begining or at the end.
  49  * - the DT_CONTIGUOUS flag for the type OPAL_DATATYPE_END_LOOP is meaningless.
  50  */
  51 
  52 /**
  53  * Advance the current position in the convertor based using the
  54  * current element and a left-over counter. Update the head pointer
  55  * and the leftover byte space.
  56  */
  57 static inline void
  58 position_predefined_data( opal_convertor_t* CONVERTOR,
  59                           dt_elem_desc_t* ELEM,
  60                           size_t* COUNT,
  61                           unsigned char** POINTER,
  62                           size_t* SPACE )
  63 {
  64     size_t _copy_count = *(COUNT);
  65     size_t _copy_blength;
  66     ddt_elem_desc_t* _elem = &((ELEM)->elem);
  67 
  68     _copy_blength =  opal_datatype_basicDatatypes[_elem->common.type]->size;
  69     if( (_copy_count * _copy_blength) > *(SPACE) ) {
  70         _copy_count = *(SPACE) / _copy_blength;
  71         if( 0 == _copy_count ) return;  /* nothing to do */
  72     }
  73     _copy_blength *= _copy_count;
  74 
  75     OPAL_DATATYPE_SAFEGUARD_POINTER( *(POINTER) + _elem->disp, _copy_blength, (CONVERTOR)->pBaseBuf,
  76                                 (CONVERTOR)->pDesc, (CONVERTOR)->count );
  77     *(POINTER) += (_copy_count * _elem->extent);
  78     *(SPACE)   -= _copy_blength;
  79     *(COUNT)   -= _copy_count;
  80 }
  81 
  82 /**
  83  * Advance the current position in the convertor based using the
  84  * current contiguous loop and a left-over counter. Update the head
  85  * pointer and the leftover byte space.
  86  */
  87 static inline void
  88 position_contiguous_loop( opal_convertor_t* CONVERTOR,
  89                           dt_elem_desc_t* ELEM,
  90                           size_t* COUNT,
  91                           unsigned char** POINTER,
  92                           size_t* SPACE )
  93 {
  94     ddt_loop_desc_t *_loop = (ddt_loop_desc_t*)(ELEM);
  95     ddt_endloop_desc_t* _end_loop = (ddt_endloop_desc_t*)((ELEM) + (ELEM)->loop.items);
  96     size_t _copy_loops = *(COUNT);
  97 
  98     if( (_copy_loops * _end_loop->size) > *(SPACE) )
  99         _copy_loops = *(SPACE) / _end_loop->size;
 100     OPAL_DATATYPE_SAFEGUARD_POINTER( *(POINTER) + _end_loop->first_elem_disp,
 101                                 (_copy_loops - 1) * _loop->extent + _end_loop->size,
 102                                 (CONVERTOR)->pBaseBuf, (CONVERTOR)->pDesc, (CONVERTOR)->count );
 103     *(POINTER) += _copy_loops * _loop->extent;
 104     *(SPACE)   -= _copy_loops * _end_loop->size;
 105     *(COUNT)   -= _copy_loops;
 106 }
 107 
 108 #define POSITION_PREDEFINED_DATATYPE( CONVERTOR, ELEM, COUNT, POSITION, SPACE ) \
 109     position_predefined_data( (CONVERTOR), (ELEM), &(COUNT), &(POSITION), &(SPACE) )
 110 
 111 #define POSITION_CONTIGUOUS_LOOP( CONVERTOR, ELEM, COUNT, POSITION, SPACE ) \
 112     position_contiguous_loop( (CONVERTOR), (ELEM), &(COUNT), &(POSITION), &(SPACE) )
 113 
 114 int opal_convertor_generic_simple_position( opal_convertor_t* pConvertor,
 115                                             size_t* position )
 116 {
 117     dt_stack_t* pStack;       /* pointer to the position on the stack */
 118     uint32_t pos_desc;        /* actual position in the description of the derived datatype */
 119     size_t count_desc;       /* the number of items already done in the actual pos_desc */
 120     dt_elem_desc_t* description = pConvertor->use_desc->desc;
 121     dt_elem_desc_t* pElem;    /* current position */
 122     unsigned char *base_pointer = pConvertor->pBaseBuf;
 123     size_t iov_len_local;
 124     ptrdiff_t extent = pConvertor->pDesc->ub - pConvertor->pDesc->lb;
 125 
 126     DUMP( "opal_convertor_generic_simple_position( %p, &%ld )\n", (void*)pConvertor, (long)*position );
 127     assert(*position > pConvertor->bConverted);
 128 
 129     /* We dont want to have to parse the datatype multiple times. What we are interested in
 130      * here is to compute the number of completed datatypes that we can move forward, update
 131      * the  counters and finally compute the position taking in account only the remaining
 132      * elements. The only problem is that we have to modify all the elements on the stack.
 133      */
 134     iov_len_local = *position - pConvertor->bConverted;
 135     if( iov_len_local > pConvertor->pDesc->size ) {
 136         pStack = pConvertor->pStack;  /* we're working with the full stack */
 137         count_desc = iov_len_local / pConvertor->pDesc->size;
 138         DO_DEBUG( opal_output( 0, "position before %lu asked %lu data size %lu"
 139                                " iov_len_local %lu count_desc %" PRIsize_t "\n",
 140                                (unsigned long)pConvertor->bConverted, (unsigned long)*position, (unsigned long)pConvertor->pDesc->size,
 141                                (unsigned long)iov_len_local, count_desc ); );
 142         /* Update all the stack including the last one */
 143         for( pos_desc = 0; pos_desc <= pConvertor->stack_pos; pos_desc++ )
 144             pStack[pos_desc].disp += count_desc * extent;
 145         pConvertor->bConverted += count_desc * pConvertor->pDesc->size;
 146         iov_len_local = *position - pConvertor->bConverted;
 147         pStack[0].count -= count_desc;
 148         DO_DEBUG( opal_output( 0, "after bConverted %lu remaining count %lu iov_len_local %lu\n",
 149                                (unsigned long)pConvertor->bConverted, (unsigned long)pStack[0].count, (unsigned long)iov_len_local ); );
 150     }
 151 
 152     pStack = pConvertor->pStack + pConvertor->stack_pos;
 153     pos_desc      = pStack->index;
 154     base_pointer += pStack->disp;
 155     count_desc    = pStack->count;
 156     pStack--;
 157     pConvertor->stack_pos--;
 158     pElem = &(description[pos_desc]);
 159 
 160     DO_DEBUG( opal_output( 0, "position start pos_desc %d count_desc %" PRIsize_t " disp %llx\n"
 161                            "stack_pos %d pos_desc %d count_desc %" PRIsize_t " disp %llx\n",
 162                            pos_desc, count_desc, (unsigned long long)(base_pointer - pConvertor->pBaseBuf),
 163                            pConvertor->stack_pos, pStack->index, pStack->count, (unsigned long long)pStack->disp ); );
 164     /* Last data has been only partially converted. Compute the relative position */
 165     if( 0 != pConvertor->partial_length ) {
 166         size_t element_length = opal_datatype_basicDatatypes[pElem->elem.common.type]->size;
 167         size_t missing_length = element_length - pConvertor->partial_length;
 168         if( missing_length >= iov_len_local ) {
 169             pConvertor->partial_length = (pConvertor->partial_length + iov_len_local) % element_length;
 170             pConvertor->bConverted    += iov_len_local;
 171             assert(pConvertor->partial_length < element_length);
 172             return 0;
 173         }
 174         pConvertor->partial_length = (pConvertor->partial_length + missing_length) % element_length;
 175         assert(pConvertor->partial_length == 0);
 176         pConvertor->bConverted += missing_length;
 177         iov_len_local -= missing_length;
 178         count_desc--;
 179     }
 180     while( 1 ) {
 181         if( OPAL_DATATYPE_END_LOOP == pElem->elem.common.type ) { /* end of the current loop */
 182             DO_DEBUG( opal_output( 0, "position end_loop count %" PRIsize_t " stack_pos %d pos_desc %d disp %lx space %lu\n",
 183                                    pStack->count, pConvertor->stack_pos, pos_desc,
 184                                    pStack->disp, (unsigned long)iov_len_local ); );
 185             if( --(pStack->count) == 0 ) { /* end of loop */
 186                 if( pConvertor->stack_pos == 0 ) {
 187                     pConvertor->flags |= CONVERTOR_COMPLETED;
 188                     pConvertor->partial_length = 0;
 189                     goto complete_loop;  /* completed */
 190                 }
 191                 pConvertor->stack_pos--;
 192                 pStack--;
 193                 pos_desc++;
 194             } else {
 195                 if( pStack->index == -1 ) {
 196                     pStack->disp += extent;
 197                 } else {
 198                     assert( OPAL_DATATYPE_LOOP == description[pStack->index].loop.common.type );
 199                     pStack->disp += description[pStack->index].loop.extent;
 200                 }
 201                 pos_desc = pStack->index + 1;
 202             }
 203             base_pointer = pConvertor->pBaseBuf + pStack->disp;
 204             UPDATE_INTERNAL_COUNTERS( description, pos_desc, pElem, count_desc );
 205             DO_DEBUG( opal_output( 0, "position new_loop count %" PRIsize_t " stack_pos %d pos_desc %d disp %lx space %lu\n",
 206                                    pStack->count, pConvertor->stack_pos, pos_desc,
 207                                    pStack->disp, (unsigned long)iov_len_local ); );
 208         }
 209         if( OPAL_DATATYPE_LOOP == pElem->elem.common.type ) {
 210             ptrdiff_t local_disp = (ptrdiff_t)base_pointer;
 211             if( pElem->loop.common.flags & OPAL_DATATYPE_FLAG_CONTIGUOUS ) {
 212                 POSITION_CONTIGUOUS_LOOP( pConvertor, pElem, count_desc,
 213                                           base_pointer, iov_len_local );
 214                 if( 0 == count_desc ) {  /* completed */
 215                     pos_desc += pElem->loop.items + 1;
 216                     goto update_loop_description;
 217                 }
 218                 /* Save the stack with the correct last_count value. */
 219             }
 220             local_disp = (ptrdiff_t)base_pointer - local_disp;
 221             PUSH_STACK( pStack, pConvertor->stack_pos, pos_desc, OPAL_DATATYPE_LOOP, count_desc,
 222                         pStack->disp + local_disp );
 223             pos_desc++;
 224         update_loop_description:  /* update the current state */
 225             base_pointer = pConvertor->pBaseBuf + pStack->disp;
 226             UPDATE_INTERNAL_COUNTERS( description, pos_desc, pElem, count_desc );
 227             DDT_DUMP_STACK( pConvertor->pStack, pConvertor->stack_pos, pElem, "advance loop" );
 228             DO_DEBUG( opal_output( 0, "position set loop count %" PRIsize_t " stack_pos %d pos_desc %d disp %lx space %lu\n",
 229                                    pStack->count, pConvertor->stack_pos, pos_desc,
 230                                    pStack->disp, (unsigned long)iov_len_local ); );
 231             continue;
 232         }
 233         while( pElem->elem.common.flags & OPAL_DATATYPE_FLAG_DATA ) {
 234             /* now here we have a basic datatype */
 235             POSITION_PREDEFINED_DATATYPE( pConvertor, pElem, count_desc,
 236                                           base_pointer, iov_len_local );
 237             if( 0 != count_desc ) {  /* completed */
 238                 pConvertor->partial_length = iov_len_local;
 239                 goto complete_loop;
 240             }
 241             base_pointer = pConvertor->pBaseBuf + pStack->disp;
 242             pos_desc++;  /* advance to the next data */
 243             UPDATE_INTERNAL_COUNTERS( description, pos_desc, pElem, count_desc );
 244             DO_DEBUG( opal_output( 0, "position set loop count %" PRIsize_t " stack_pos %d pos_desc %d disp %lx space %lu\n",
 245                                    pStack->count, pConvertor->stack_pos, pos_desc,
 246                                    pStack->disp, (unsigned long)iov_len_local ); );
 247         }
 248     }
 249  complete_loop:
 250     pConvertor->bConverted = *position;  /* update the already converted bytes */
 251 
 252     if( !(pConvertor->flags & CONVERTOR_COMPLETED) ) {
 253         /* I complete an element, next step I should go to the next one */
 254         PUSH_STACK( pStack, pConvertor->stack_pos, pos_desc, pElem->elem.common.type, count_desc,
 255                     base_pointer - pConvertor->pBaseBuf );
 256         DO_DEBUG( opal_output( 0, "position save stack stack_pos %d pos_desc %d count_desc %" PRIsize_t " disp %llx\n",
 257                                pConvertor->stack_pos, pStack->index, pStack->count, (unsigned long long)pStack->disp ); );
 258         return 0;
 259     }
 260     return 1;
 261 }

/* [<][>][^][v][top][bottom][index][help] */