Changes in / [af4487d:29d618e]


Ignore:
Files:
5 deleted
9 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/Makefile.am

    raf4487d r29d618e  
    5353
    5454thread_headers = concurrency/coroutine.hfa concurrency/thread.hfa concurrency/kernel.hfa \
    55                 concurrency/monitor.hfa concurrency/mutex.hfa concurrency/exception.hfa
     55                concurrency/monitor.hfa concurrency/mutex.hfa
    5656
    5757thread_libsrc = concurrency/CtxSwitch-@ARCHITECTURE@.S concurrency/alarm.cfa \
  • libcfa/src/concurrency/coroutine.cfa

    raf4487d r29d618e  
    215215                return cor;
    216216        }
     217
     218        struct $coroutine * __cfactx_cor_active(void) {
     219                return active_coroutine();
     220        }
    217221}
    218222
  • libcfa/src/concurrency/invoke.c

    raf4487d r29d618e  
    2929// Called from the kernel when starting a coroutine or task so must switch back to user mode.
    3030
     31extern struct $coroutine * __cfactx_cor_active(void);
    3132extern struct $coroutine * __cfactx_cor_finish(void);
    3233extern void __cfactx_cor_leave ( struct $coroutine * );
     
    3536extern void disable_interrupts() OPTIONAL_THREAD;
    3637extern void enable_interrupts( __cfaabi_dbg_ctx_param );
     38
     39struct exception_context_t * this_exception_context() {
     40        return &__get_stack( __cfactx_cor_active() )->exception_context;
     41}
    3742
    3843void __cfactx_invoke_coroutine(
  • libcfa/src/concurrency/invoke.h

    raf4487d r29d618e  
    9898        }
    9999
     100        struct exception_context_t * this_exception_context();
     101
    100102        // struct which calls the monitor is accepting
    101103        struct __waitfor_mask_t {
  • libcfa/src/concurrency/io/setup.cfa

    raf4487d r29d618e  
    384384                        /* paranoid */ verify( is_pow2( params_in.num_ready ) || (params_in.num_ready < 8) );
    385385                        sq.ready_cnt = max( params_in.num_ready, 8 );
    386                         sq.ready = alloc( sq.ready_cnt, 64`align );
     386                        sq.ready = alloc_align( 64, sq.ready_cnt );
    387387                        for(i; sq.ready_cnt) {
    388388                                sq.ready[i] = -1ul32;
  • libcfa/src/concurrency/kernel/startup.cfa

    raf4487d r29d618e  
    579579
    580580        // Lock the RWlock so no-one pushes/pops while we are changing the queue
    581         disable_interrupts();
    582581        uint_fast32_t last_size = ready_mutate_lock();
    583582
     
    587586        // Unlock the RWlock
    588587        ready_mutate_unlock( last_size );
    589         enable_interrupts_noPoll(); // Don't poll, could be in main cluster
    590 
    591588
    592589        this.io.cnt  = num_io;
     
    604601
    605602        // Lock the RWlock so no-one pushes/pops while we are changing the queue
    606         disable_interrupts();
    607603        uint_fast32_t last_size = ready_mutate_lock();
    608604
     
    612608        // Unlock the RWlock
    613609        ready_mutate_unlock( last_size );
    614         enable_interrupts_noPoll(); // Don't poll, could be in main cluster
    615610
    616611        #if !defined(__CFA_NO_STATISTICS__)
  • libcfa/src/concurrency/ready_queue.cfa

    raf4487d r29d618e  
    215215}
    216216
    217 static inline [unsigned, bool] idx_from_r(unsigned r, unsigned preferred) {
    218         unsigned i;
    219         bool local;
    220         #if defined(BIAS)
    221                 unsigned rlow  = r % BIAS;
    222                 unsigned rhigh = r / BIAS;
    223                 if((0 != rlow) && preferred >= 0) {
    224                         // (BIAS - 1) out of BIAS chances
    225                         // Use perferred queues
    226                         i = preferred + (rhigh % 4);
    227                         local = true;
    228                 }
    229                 else {
    230                         // 1 out of BIAS chances
    231                         // Use all queues
    232                         i = rhigh;
    233                         local = false;
    234                 }
    235         #else
    236                 i = r;
    237                 local = false;
    238         #endif
    239         return [i, local];
    240 }
    241 
    242217//-----------------------------------------------------------------------
    243218__attribute__((hot)) bool push(struct cluster * cltr, struct $thread * thrd) with (cltr->ready_queue) {
     
    247222        thrd->link.ts = rdtscl();
    248223
    249         __attribute__((unused)) bool local;
    250         __attribute__((unused)) int preferred;
    251         #if defined(BIAS)
    252                 preferred =
     224        #if defined(BIAS) && !defined(__CFA_NO_STATISTICS__)
     225                bool local = false;
     226                int preferred =
    253227                        //*
    254228                        kernelTLS.this_processor ? kernelTLS.this_processor->id * 4 : -1;
     
    256230                        thrd->link.preferred * 4;
    257231                        //*/
     232
     233
    258234        #endif
    259235
     
    262238        do {
    263239                // Pick the index of a lane
    264                 // unsigned r = __tls_rand();
    265                 unsigned r = __tls_rand_fwd();
    266                 [i, local] = idx_from_r(r, preferred);
    267 
    268                 #if !defined(__CFA_NO_STATISTICS__)
    269                         if(local) {
    270                                 __tls_stats()->ready.pick.push.local++;
    271                         }
     240                #if defined(BIAS)
     241                        unsigned r = __tls_rand();
     242                        unsigned rlow  = r % BIAS;
     243                        unsigned rhigh = r / BIAS;
     244                        if((0 != rlow) && preferred >= 0) {
     245                                // (BIAS - 1) out of BIAS chances
     246                                // Use perferred queues
     247                                i = preferred + (rhigh % 4);
     248
     249                                #if !defined(__CFA_NO_STATISTICS__)
     250                                        local = true;
     251                                        __tls_stats()->ready.pick.push.local++;
     252                                #endif
     253                        }
     254                        else {
     255                                // 1 out of BIAS chances
     256                                // Use all queues
     257                                i = rhigh;
     258                                local = false;
     259                        }
     260                #else
     261                        i = __tls_rand();
    272262                #endif
    273263
     
    284274
    285275        // Actually push it
    286         #ifdef USE_SNZI
    287                 bool lane_first =
    288         #endif
    289 
    290         push(lanes.data[i], thrd);
     276        bool lane_first = push(lanes.data[i], thrd);
    291277
    292278        #ifdef USE_SNZI
     
    301287        #endif
    302288
    303         __tls_rand_advance_bck();
    304 
    305289        // Unlock and return
    306290        __atomic_unlock( &lanes.data[i].lock );
     
    327311        /* paranoid */ verify( lanes.count > 0 );
    328312        unsigned count = __atomic_load_n( &lanes.count, __ATOMIC_RELAXED );
    329         int preferred;
    330313        #if defined(BIAS)
    331314                // Don't bother trying locally too much
    332315                int local_tries = 8;
    333                 preferred = kernelTLS.this_processor->id * 4;
    334         #endif
    335 
     316        #endif
    336317
    337318        // As long as the list is not empty, try finding a lane that isn't empty and pop from it
     
    342323        #endif
    343324                // Pick two lists at random
    344                 // unsigned ri = __tls_rand();
    345                 // unsigned rj = __tls_rand();
    346                 unsigned ri = __tls_rand_bck();
    347                 unsigned rj = __tls_rand_bck();
    348 
    349                 unsigned i, j;
    350                 __attribute__((unused)) bool locali, localj;
    351                 [i, locali] = idx_from_r(ri, preferred);
    352                 [j, localj] = idx_from_r(rj, preferred);
    353 
    354                 #if !defined(__CFA_NO_STATISTICS__)
    355                         if(locali) {
    356                                 __tls_stats()->ready.pick.pop.local++;
    357                         }
    358                         if(localj) {
    359                                 __tls_stats()->ready.pick.pop.local++;
    360                         }
     325                unsigned i,j;
     326                #if defined(BIAS)
     327                        #if !defined(__CFA_NO_STATISTICS__)
     328                                bool local = false;
     329                        #endif
     330                        uint64_t r = __tls_rand();
     331                        unsigned rlow  = r % BIAS;
     332                        uint64_t rhigh = r / BIAS;
     333                        if(local_tries && 0 != rlow) {
     334                                // (BIAS - 1) out of BIAS chances
     335                                // Use perferred queues
     336                                unsigned pid = kernelTLS.this_processor->id * 4;
     337                                i = pid + (rhigh % 4);
     338                                j = pid + ((rhigh >> 32ull) % 4);
     339
     340                                // count the tries
     341                                local_tries--;
     342
     343                                #if !defined(__CFA_NO_STATISTICS__)
     344                                        local = true;
     345                                        __tls_stats()->ready.pick.pop.local++;
     346                                #endif
     347                        }
     348                        else {
     349                                // 1 out of BIAS chances
     350                                // Use all queues
     351                                i = rhigh;
     352                                j = rhigh >> 32ull;
     353                        }
     354                #else
     355                        i = __tls_rand();
     356                        j = __tls_rand();
    361357                #endif
    362358
     
    368364                if(thrd) {
    369365                        #if defined(BIAS) && !defined(__CFA_NO_STATISTICS__)
    370                                 if( locali || localj ) __tls_stats()->ready.pick.pop.lsuccess++;
     366                                if( local ) __tls_stats()->ready.pick.pop.lsuccess++;
    371367                        #endif
    372368                        return thrd;
     
    547543
    548544                // Allocate new array (uses realloc and memcpies the data)
    549                 lanes.data = alloc( ncount, lanes.data`realloc );
     545                lanes.data = alloc(lanes.data, ncount);
    550546
    551547                // Fix the moved data
     
    638634
    639635                // Allocate new array (uses realloc and memcpies the data)
    640                 lanes.data = alloc( lanes.count, lanes.data`realloc );
     636                lanes.data = alloc(lanes.data, lanes.count);
    641637
    642638                // Fix the moved data
  • libcfa/src/exception.c

    raf4487d r29d618e  
    209209                void * stop_param) {
    210210        // Verify actions follow the rules we expect.
    211         verify(actions & _UA_CLEANUP_PHASE);
    212         verify(actions & _UA_FORCE_UNWIND);
    213         verify(!(actions & _UA_SEARCH_PHASE));
    214         verify(!(actions & _UA_HANDLER_FRAME));
     211        verify((actions & _UA_CLEANUP_PHASE) && (actions & _UA_FORCE_UNWIND));
     212        verify(!(actions & (_UA_SEARCH_PHASE | _UA_HANDLER_FRAME)));
    215213
    216214        if ( actions & _UA_END_OF_STACK ) {
    217                 abort();
     215                exit(1);
    218216        } else {
    219217                return _URC_NO_REASON;
     
    221219}
    222220
    223 __attribute__((weak)) _Unwind_Reason_Code
    224 __cfaehm_cancellation_unwind( struct _Unwind_Exception * exception ) {
    225         return _Unwind_ForcedUnwind( exception, _Stop_Fn, (void*)0x22 );
    226 }
     221static struct _Unwind_Exception cancel_exception_storage;
    227222
    228223// Cancel the current stack, prefroming approprate clean-up and messaging.
    229224void __cfaehm_cancel_stack( exception_t * exception ) {
    230         __cfaehm_allocate_exception( exception );
    231 
    232         struct exception_context_t * context = this_exception_context();
    233         struct __cfaehm_node * node = EXCEPT_TO_NODE(context->current_exception);
    234 
    235         // Preform clean-up of any extra active exceptions.
    236         while ( node->next ) {
    237                 struct __cfaehm_node * to_free = node->next;
    238                 node->next = to_free->next;
    239                 exception_t * except = NODE_TO_EXCEPT( to_free );
    240                 except->virtual_table->free( except );
    241             free( to_free );
    242         }
    243 
     225        // TODO: Detect current stack and pick a particular stop-function.
    244226        _Unwind_Reason_Code ret;
    245         ret = __cfaehm_cancellation_unwind( &node->unwind_exception );
     227        ret = _Unwind_ForcedUnwind( &cancel_exception_storage, _Stop_Fn, (void*)0x22 );
    246228        printf("UNWIND ERROR %d after force unwind\n", ret);
    247229        abort();
  • libcfa/src/stdlib.hfa

    raf4487d r29d618e  
    114114} // distribution
    115115
    116 /*
    117         FIX ME : fix alloc interface after Ticker Number 214 is resolved, define and add union to S_fill. Then, modify postfix-fill functions to support T * with nmemb, char, and T object of any size. Finally, change alloc_internal.
    118         Or, just follow the instructions below for that.
    119 
    120         1. Replace the current forall-block that contains defintions of S_fill and S_realloc with following:
    121                 forall( dtype T | sized(T) ) {
    122                         union  U_fill           { char c; T * a; T t; };
    123                         struct S_fill           { char tag; char c; size_t size; T * at; char t[50]; };
    124                         struct S_realloc        { inline T *; };
    125                 }
    126 
    127         2. Replace all current postfix-fill functions with following for updated S_fill:
    128                 S_fill(T) ?`fill( char a )                                      { S_fill(T) ret = {'c'}; ret.fill.c = a; return ret; }
    129                 S_fill(T) ?`fill( T    a )                                      { S_fill(T) ret = {'t'}; memcpy(&ret.fill.t, &a, sizeof(T)); return ret; }
    130                 S_fill(T) ?`fill( T    a[], size_t nmemb )      { S_fill(T) ret = {'a', nmemb}; ret.fill.a = a; return ret; }
    131 
    132         3. Replace the $alloc_internal function which is outside ttype forall-block with following function:
    133                 T * $alloc_internal( void * Resize, T * Realloc, size_t Align, size_t Dim, S_fill(T) Fill) {
    134                         T * ptr = NULL;
    135                         size_t size = sizeof(T);
    136                         size_t copy_end = 0;
    137 
    138                         if(Resize) {
    139                                 ptr = (T*) (void *) resize( (int *)Resize, Align, Dim * size );
    140                         } else if (Realloc) {
    141                                 if (Fill.tag != '0') copy_end = min(malloc_size( Realloc ), Dim * size);
    142                                 ptr = (T*) (void *) realloc( (int *)Realloc, Align, Dim * size );
    143                         } else {
    144                                 ptr = (T*) (void *) memalign( Align, Dim * size );
    145                         }
    146 
    147                         if(Fill.tag == 'c') {
    148                                 memset( (char *)ptr + copy_end, (int)Fill.fill.c, Dim * size - copy_end );
    149                         } else if(Fill.tag == 't') {
    150                                 for ( int i = copy_end; i <= Dim * size - size ; i += size ) {
    151                                         memcpy( (char *)ptr + i, &Fill.fill.t, size );
    152                                 }
    153                         } else if(Fill.tag == 'a') {
    154                                 memcpy( (char *)ptr + copy_end, Fill.fill.a, min(Dim * size - copy_end, size * Fill.nmemb) );
    155                         }
    156 
    157                         return ptr;
    158                 } // $alloc_internal
    159 */
    160 
    161 typedef struct S_align                  { inline size_t;  } T_align;
    162 typedef struct S_resize                 { inline void *;  }     T_resize;
    163 
    164 forall( dtype T ) {
    165         struct S_fill           { char tag; char c; size_t size; T * at; char t[50]; };
    166         struct S_realloc        { inline T *; };
    167 }
    168 
    169 static inline T_align   ?`align   ( size_t a )  { return (T_align){a}; }
    170 static inline T_resize  ?`resize  ( void * a )  { return (T_resize){a}; }
    171 static inline forall( dtype T | sized(T) ) {
    172 
    173         S_fill(T) ?`fill ( T t ) {
    174                 S_fill(T) ret = { 't' };
    175                 size_t size = sizeof(T);
    176                 if(size > sizeof(ret.t)) { printf("ERROR: const object of size greater than 50 bytes given for dynamic memory fill\n"); exit(1); }
    177                 memcpy( &ret.t, &t, size );
    178                 return ret;
    179         }
    180         S_fill(T)               ?`fill ( char c )                               { return (S_fill(T)){ 'c', c }; }
    181         S_fill(T)               ?`fill ( T * a )                                { return (S_fill(T)){ 'T', '0', 0, a }; }
    182         S_fill(T)               ?`fill ( T a[], size_t nmemb )  { return (S_fill(T)){ 'a', '0', nmemb * sizeof(T), a }; }
    183 
    184         S_realloc(T)    ?`realloc ( T * a )                             { return (S_realloc(T)){a}; }
    185 
    186         T * $alloc_internal( void * Resize, T * Realloc, size_t Align, size_t Dim, S_fill(T) Fill) {
    187                 T * ptr = NULL;
    188                 size_t size = sizeof(T);
    189                 size_t copy_end = 0;
    190 
    191                 if(Resize) {
    192                         ptr = (T*) (void *) resize( (int *)Resize, Align, Dim * size );
    193                 } else if (Realloc) {
    194                         if (Fill.tag != '0') copy_end = min(malloc_size( Realloc ), Dim * size);
    195                         ptr = (T*) (void *) realloc( (int *)Realloc, Align, Dim * size );
     116static inline forall( dtype T | sized(T) ) {
     117        // Cforall safe general allocation, fill, resize, array
     118
     119        T * alloc( void ) {
     120                return malloc();
     121        } // alloc
     122
     123        T * alloc( size_t dim ) {
     124                return aalloc( dim );
     125        } // alloc
     126
     127        forall( dtype S | sized(S) )
     128        T * alloc( S ptr[], size_t dim = 1 ) {                          // singleton/array resize
     129                return resize( (T *)ptr, dim * sizeof(T) );             // CFA resize
     130        } // alloc
     131
     132        T * alloc( T ptr[], size_t dim = 1, bool copy = true ) {
     133                if ( copy ) {
     134                        return realloc( ptr, dim * sizeof(T) );         // CFA realloc
    196135                } else {
    197                         ptr = (T*) (void *) memalign( Align, Dim * size );
    198                 }
    199 
    200                 if(Fill.tag == 'c') {
    201                         memset( (char *)ptr + copy_end, (int)Fill.c, Dim * size - copy_end );
    202                 } else if(Fill.tag == 't') {
    203                         for ( int i = copy_end; i <= Dim * size - size ; i += size ) {
    204                                 memcpy( (char *)ptr + i, &Fill.t, size );
    205                         }
    206                 } else if(Fill.tag == 'a') {
    207                         memcpy( (char *)ptr + copy_end, Fill.at, min(Dim * size - copy_end, Fill.size) );
    208                 } else if(Fill.tag == 'T') {
    209                         for ( int i = copy_end; i <= Dim * size - size ; i += size ) {
    210                                 memcpy( (char *)ptr + i, Fill.at, size );
    211                         }
    212                 }
    213 
    214                 return ptr;
    215         } // $alloc_internal
    216 
    217         forall( ttype TT | { T * $alloc_internal( void *, T *, size_t, size_t, S_fill(T), TT ); } ) {
    218 
    219                 T * $alloc_internal( void *       , T * Realloc, size_t Align, size_t Dim, S_fill(T) Fill, T_resize Resize, TT rest) {
    220                 return $alloc_internal( Resize, (T*)0p, Align, Dim, Fill, rest);
    221                 }
    222 
    223                 T * $alloc_internal( void * Resize, T *        , size_t Align, size_t Dim, S_fill(T) Fill, S_realloc(T) Realloc, TT rest) {
    224                 return $alloc_internal( (void*)0p, Realloc, Align, Dim, Fill, rest);
    225                 }
    226 
    227                 T * $alloc_internal( void * Resize, T * Realloc, size_t      , size_t Dim, S_fill(T) Fill, T_align Align, TT rest) {
    228                 return $alloc_internal( Resize, Realloc, Align, Dim, Fill, rest);
    229                 }
    230 
    231                 T * $alloc_internal( void * Resize, T * Realloc, size_t Align, size_t Dim, S_fill(T)     , S_fill(T) Fill, TT rest) {
    232                 return $alloc_internal( Resize, Realloc, Align, Dim, Fill, rest);
    233                 }
    234 
    235             T * alloc( TT all ) {
    236                 return $alloc_internal( (void*)0p, (T*)0p, (_Alignof(T) > libAlign() ? _Alignof(T) : libAlign()), (size_t)1, (S_fill(T)){'0'}, all);
    237             }
    238 
    239             T * alloc( size_t dim, TT all ) {
    240                 return $alloc_internal( (void*)0p, (T*)0p, (_Alignof(T) > libAlign() ? _Alignof(T) : libAlign()), dim, (S_fill(T)){'0'}, all);
    241             }
    242 
    243         } // distribution TT
    244 
    245 } // distribution T
     136                        return resize( ptr, dim * sizeof(T) );          // CFA resize
     137                } // if
     138        } // alloc
     139
     140        T * alloc_set( char fill ) {
     141                return (T *)memset( (T *)alloc(), (int)fill, sizeof(T) ); // initialize with fill value
     142        } // alloc_set
     143
     144        T * alloc_set( const T & fill ) {
     145                return (T *)memcpy( (T *)alloc(), &fill, sizeof(T) ); // initialize with fill value
     146        } // alloc_set
     147
     148        T * alloc_set( size_t dim, char fill ) {
     149                return (T *)memset( (T *)alloc( dim ), (int)fill, dim * sizeof(T) ); // initialize with fill value
     150        } // alloc_set
     151
     152        T * alloc_set( size_t dim, const T & fill ) {
     153                T * r = (T *)alloc( dim );
     154                for ( i; dim ) { memcpy( &r[i], &fill, sizeof(T) ); } // initialize with fill value
     155                return r;
     156        } // alloc_set
     157
     158        T * alloc_set( size_t dimNew, const T fill[], size_t dimOld ) {
     159                return (T *)memcpy( (T *)alloc( dimNew ), fill, min( dimNew, dimOld ) * sizeof(T) ); // initialize with fill value
     160        } // alloc_set
     161
     162        T * alloc_set( T ptr[], size_t dim, char fill ) {       // realloc array with fill
     163                size_t osize = malloc_size( ptr );                              // current allocation
     164                size_t nsize = dim * sizeof(T);                                 // new allocation
     165                T * nptr = realloc( ptr, nsize );                               // CFA realloc
     166                if ( nsize > osize ) {                                                  // larger ?
     167                        memset( (char *)nptr + osize, (int)fill, nsize - osize ); // initialize added storage
     168                } // if
     169                return nptr;
     170        } // alloc_set
     171
     172        T * alloc_set( T ptr[], size_t dim, const T & fill ) {  // realloc array with fill
     173                size_t odim = malloc_size( ptr ) / sizeof(T);   // current dimension
     174                size_t nsize = dim * sizeof(T);                                 // new allocation
     175                size_t ndim = nsize / sizeof(T);                                // new dimension
     176                T * nptr = realloc( ptr, nsize );                               // CFA realloc
     177                if ( ndim > odim ) {                                                    // larger ?
     178                        for ( i; odim ~ ndim ) {
     179                                memcpy( &nptr[i], &fill, sizeof(T) );   // initialize with fill value
     180                        } // for
     181                } // if
     182                return nptr;
     183        } // alloc_set
     184} // distribution
     185
     186static inline forall( dtype T | sized(T) ) {
     187        T * alloc_align( size_t align ) {
     188                return (T *)memalign( align, sizeof(T) );
     189        } // alloc_align
     190
     191        T * alloc_align( size_t align, size_t dim ) {
     192                return (T *)memalign( align, dim * sizeof(T) );
     193        } // alloc_align
     194
     195        T * alloc_align( T * ptr, size_t align ) {                      // aligned realloc array
     196                return (T *)(void *)realloc( (void *)ptr, align, sizeof(T) ); // CFA C realloc
     197        } // alloc_align
     198
     199        forall( dtype S | sized(S) )
     200        T * alloc_align( S ptr[], size_t align ) {                      // aligned reuse array
     201                return (T *)(void *)resize( (void *)ptr, align, sizeof(T) ); // CFA realloc
     202        } // alloc_align
     203
     204        T * alloc_align( T ptr[], size_t align, size_t dim ) { // aligned realloc array
     205                return (T *)(void *)realloc( (void *)ptr, align, dim * sizeof(T) ); // CFA realloc
     206        } // alloc_align
     207
     208        T * alloc_align_set( size_t align, char fill ) {
     209                return (T *)memset( (T *)alloc_align( align ), (int)fill, sizeof(T) ); // initialize with fill value
     210        } // alloc_align_set
     211
     212        T * alloc_align_set( size_t align, const T & fill ) {
     213                return (T *)memcpy( (T *)alloc_align( align ), &fill, sizeof(T) ); // initialize with fill value
     214        } // alloc_align_set
     215
     216        T * alloc_align_set( size_t align, size_t dim, char fill ) {
     217                return (T *)memset( (T *)alloc_align( align, dim ), (int)fill, dim * sizeof(T) ); // initialize with fill value
     218        } // alloc_align_set
     219
     220        T * alloc_align_set( size_t align, size_t dim, const T & fill ) {
     221                T * r = (T *)alloc_align( align, dim );
     222                for ( i; dim ) { memcpy( &r[i], &fill, sizeof(T) ); } // initialize with fill value
     223                return r;
     224        } // alloc_align_set
     225
     226        T * alloc_align_set( size_t align, size_t dimNew, const T fill[], size_t dimOld ) {
     227                return (T *)memcpy( (T *)alloc_align( align, dimNew ), fill, min( dimNew, dimOld ) * sizeof(T) );
     228        } // alloc_align_set
     229
     230        T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill ) {
     231                size_t osize = malloc_size( ptr );                              // current allocation
     232                size_t nsize = dim * sizeof(T);                                 // new allocation
     233                T * nptr = alloc_align( ptr, align, nsize );
     234                if ( nsize > osize ) {                                                  // larger ?
     235                        memset( (char *)nptr + osize, (int)fill, nsize - osize ); // initialize added storage
     236                } // if
     237                return nptr;
     238        } // alloc_align_set
     239
     240        T * alloc_align_set( T ptr[], size_t align, size_t dim, const T & fill ) {
     241                size_t odim = malloc_size( ptr ) / sizeof(T);   // current dimension
     242                size_t nsize = dim * sizeof(T);                                 // new allocation
     243                size_t ndim = nsize / sizeof(T);                                // new dimension
     244                T * nptr = alloc_align( ptr, align, nsize );
     245                if ( ndim > odim ) {                                                    // larger ?
     246                        for ( i; odim ~ ndim ) {
     247                                memcpy( &nptr[i], &fill, sizeof(T) );   // initialize with fill value
     248                        } // for
     249                } // if
     250                return nptr;
     251        } // alloc_align_set
     252} // distribution
    246253
    247254static inline forall( dtype T | sized(T) ) {
Note: See TracChangeset for help on using the changeset viewer.