Changeset 628


Ignore:
Timestamp:
May 6, 2019, 1:28:01 PM (5 months ago)
Author:
alain
Message:

Introduce teh page_min / page_max mechanism in the fatfs_release_inode()
function, to avoid to scan all pages in FAT mapper.

Location:
trunk
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/kernel/fs/fatfs.c

    r627 r628  
    442442
    443443//////////////////////////////////////////////////////////////////////////////////////////
    444 // This static function is called by both the fatfs_free_clusters_increment(),
    445 // and the fatfs_free_cluster_decrement() functions defined below.
    446 // It synchronously updates the  "free_clusters" and "free_cluster_hint" variables
    447 // in FS_INFO sector on the IOC device, each times these variables are modified.
    448 //////////////////////////////////////////////////////////////////////////////////////////
    449 // @ fatfs_ctx_xp      : extended pointer on fatfs context in FAT cluster.
    450 // @ free_clusters     : new free_clusters value.
    451 // @ free_cluster_hint : new free_cluster_hint value.
     444// This static function synchronously updates the FAT on IOC device.
     445// It scan the FAT mapper to copy on IOC device all dirty pages in the interval
     446// defined by the <page_min> & <page_max> arguments.
     447// It can be called by a thread running in any cluster.
     448// WARNING : We don't take the lock protecting the FAT mapper, because the FAT lock
     449// (in FATFS context) must be taken by the calling function.
     450//////////////////////////////////////////////////////////////////////////////////////////
     451// @ fatfs_ctx_xp  : extended pointer on FATFS context in FAT cluster.
     452// @ page_min      : first page to be checked.
     453// @ page_max      : last page to be checked
    452454// @ return 0 if success, return -1 if the FS_INFO sector cannot be updated.
    453455//////////////////////////////////////////////////////////////////////////////////////////
    454 static error_t fatfs_free_clusters_update_ioc( xptr_t    fatfs_ctx_xp,
    455                                                uint32_t  free_clusters,
    456                                                uint32_t  free_cluster_hint )
     456static error_t fatfs_update_ioc_fat( xptr_t   fatfs_ctx_xp,
     457                                     uint32_t page_min,
     458                                     uint32_t page_max )
     459{
     460
     461#if DEBUG_FATFS_UPDATE_IOC
     462uint32_t   cycle = (uint32_t)hal_get_cycles();
     463thread_t * this  = CURRENT_THREAD;
     464if( DEBUG_FATFS_UPDATE_IOC < cycle )
     465printk("\n[%s] thread[%x,%x] enter / page_min %d / page_max %d / cycle %d\n",
     466__FUNCTION__ , this->process->pid, this->trdid, page_min, page_max, cycle );
     467#endif
     468
     469    error_t       error;
     470    cxy_t         fat_cxy;         // FAT cluster identifier
     471    fatfs_ctx_t * fatfs_ctx;       // local pointer on FATFS context in FAT cluster
     472    xptr_t        fat_mapper_xp;   // extended pointer on FAT mapper
     473    mapper_t    * fat_mapper_ptr;  // local pointer on FAT mapper
     474    uint32_t      page_id;         // current page index in FAT mapper
     475    xptr_t        rt_xp;           // extended pointer on FAT mapper radix tree
     476    xptr_t        page_xp;         // extended pointer on current page in FAT mapper
     477    page_t      * page_ptr;        // local pointer on current page
     478    uint32_t      flags;           // current page flags
     479
     480    // get pointer and cluster on FATFS context in FAT cluster
     481    fat_cxy   = GET_CXY( fatfs_ctx_xp );
     482    fatfs_ctx = GET_PTR( fatfs_ctx_xp );
     483 
     484    // get FAT mapper pointers from FATFS context
     485    fat_mapper_xp  = hal_remote_l64( XPTR( fat_cxy , &fatfs_ctx->fat_mapper_xp ) );
     486    fat_mapper_ptr = GET_PTR( fat_mapper_xp );
     487
     488// check FAT cluster
     489assert( (fat_cxy == GET_CXY( fat_mapper_xp )) , "unconsistent FAT cluster" );
     490
     491    // build extended pointer on FAT mapper radix tree
     492    rt_xp   = XPTR( fat_cxy , &fat_mapper_ptr->rt );
     493
     494    // scan all pages in [min,max] interval
     495    for( page_id = page_min ; page_id <= page_max ; page_id++ )
     496    {
     497        // get extended pointer on page descriptor from FAT mapper
     498        page_xp = grdxt_remote_lookup( rt_xp , page_id );
     499
     500        // check only existing pages
     501        if ( page_xp != XPTR_NULL )
     502        {
     503            page_ptr = GET_PTR( page_xp );
     504            flags    = hal_remote_l32( XPTR( fat_cxy , &page_ptr->flags ) );
     505
     506            // copy only dirty pages
     507            if ( flags & PG_DIRTY )
     508            {
     509
     510#if (DEBUG_FATFS_UPDATE_IOC & 1)
     511if( DEBUG_FATFS_UPDATE_IOC < cycle )
     512printk("\n[%s] thread[%x,%x] copy page %d from FAT mapper to IOC device\n",
     513__FUNCTION__, page_id );
     514#endif
     515                // move page from mapper to device
     516                error = fatfs_move_page( page_xp , IOC_SYNC_WRITE );
     517
     518                if ( error )  return -1;
     519
     520                // reset page dirty flag
     521                ppm_page_undo_dirty( page_xp );
     522            }
     523        }
     524    }  // end loop on pages
     525
     526#if DEBUG_FATFS_UPDATE_IOC
     527cycle = (uint32_t)hal_get_cycles();
     528if( DEBUG_FATFS_UPDATE_IOC < cycle )
     529printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
     530__FUNCTION__ , this->process->pid, this->trdid, cycle );
     531#endif
     532
     533    return 0;
     534
     535}  // end fatfs_update_ioc_fat()
     536
     537//////////////////////////////////////////////////////////////////////////////////////////
     538// This static function synchronously updates the FS_INFO sector on IOC device,
     539// from values contained in the FATFS context in FAT cluster.
     540// It uses and updates the FS_INFO buffer allocated in the FAT cluster.
     541// It can be called by a thread running in any cluster.
     542//////////////////////////////////////////////////////////////////////////////////////////
     543// @ fatfs_ctx_xp  : extended pointer on FATFS context in FAT cluster.
     544// @ return 0 if success, return -1 if the FS_INFO sector cannot be updated.
     545//////////////////////////////////////////////////////////////////////////////////////////
     546static error_t fatfs_update_ioc_fsinfo( xptr_t fatfs_ctx_xp )
    457547{
    458548    cxy_t         fat_cxy;             // FAT cluster identifier
    459549    fatfs_ctx_t * fatfs_ctx_ptr;       // local pointer on fatfs context in FAT cluster
     550    uint32_t      free_clusters;       // current vale of "free_clusters" in fatfs context
     551    uint32_t      free_cluster_hint;   // current vale of "free_cluster_hint" in fatfs context
    460552    uint8_t     * fs_info_buffer_ptr;  // local pointer on FS_INFO buffer in FAT cluster
    461553    xptr_t        fs_info_buffer_xp;   // extended pointer on FS_INFO buffer in FAT cluster
     
    466558    fatfs_ctx_ptr = GET_PTR( fatfs_ctx_xp );
    467559
    468     // get pointers on FS_INFO buffer in FAT cluster
     560    // force FATFS context update
     561    hal_fence();
     562
     563    // get relevant info from fatfs context in FAT cluster
     564    fs_info_lba        = hal_remote_l32( XPTR( fat_cxy , &fatfs_ctx_ptr->fs_info_lba ) );
     565    free_clusters      = hal_remote_l32( XPTR( fat_cxy , &fatfs_ctx_ptr->free_clusters ) );
     566    free_cluster_hint  = hal_remote_l32( XPTR( fat_cxy , &fatfs_ctx_ptr->free_cluster_hint ) );
    469567    fs_info_buffer_ptr = hal_remote_lpt( XPTR( fat_cxy , &fatfs_ctx_ptr->fs_info_buffer ) );
     568
     569    // build extended pointer on FS_INFO buffer in FAT cluster
    470570    fs_info_buffer_xp  = XPTR( fat_cxy , fs_info_buffer_ptr );
    471 
    472     // get lba of FS_INFO sector on IOC device from fatfs context
    473     fs_info_lba = hal_remote_l32( XPTR( fat_cxy , &fatfs_ctx_ptr->fs_info_lba ) );
    474 
     571   
    475572    // update the FS_INFO buffer in FAT cluster
    476573    fatfs_set_remote_record( FS_FREE_CLUSTERS     , fs_info_buffer_xp , free_clusters );
     
    480577    return dev_ioc_sync_write( fs_info_buffer_xp , fs_info_lba , 1 );
    481578 
    482 }  // fatfs_free_clusters_update_ioc()
     579}  // end fatfs_update_ioc_fsinfo()
    483580
    484581//////////////////////////////////////////////////////////////////////////////////////////
     
    488585// It scan all slots in the FAT mapper seen as an array of 32 bits words, looking for the
    489586// first free slot larger than the <cluster> argument, to update "free_cluster_hint".
    490 // It calls the fatfs_free_clusters_update_ioc() function to synchronously update the
    491 // FS_INFO sector on the IOC device. It can be called by a thead running in any cluster.
    492 //
    493 // WARNING : The lock protecting exclusive access to these variables
    494 //           must be taken by the calling function.
     587// It synchronously updates the FS_INFO sector on the IOC device.
     588// It can be called by a thead running in any cluster.
     589// The lock protecting exclusive access to the FAT must be taken by the calling function.
    495590//////////////////////////////////////////////////////////////////////////////////////////
    496591// @ fatfs_ctx_xp  : extended pointer on FATFS context in FAT cluster.
     
    502597{
    503598    error_t       error;
    504     cxy_t         fat_cxy;      // FAT cluster identifier
    505     fatfs_ctx_t * fat_ctx_ptr;  // local pointer on fatfs context in FAT cluster
    506     xptr_t        mapper_xp;    // extended pointer on FAT mapper
    507     xptr_t        hint_xp;      // extended pointer on "free_cluster_hint" shared variable
    508     xptr_t        numb_xp;      // extended pointer on "free_clusters" shared variable
    509     uint32_t      numb;         // "free_clusters" variable current value
    510     uint32_t      hint;         // "free_cluster_hint" variable current value
    511     uint32_t      page_id;      // page index in FAT mapper
    512     uint32_t      slot_id;      // slot index in one page of FAT (1024 slots per page)
    513     uint32_t      page_max;     // max number of pages in FAT mapper
    514     xptr_t        page_xp;      // extended pointer on current page in FAT mapper
    515     xptr_t        base_xp;      // extended pointer on current page base
    516     xptr_t        slot_xp;      // extended pointer on current slot in FAT mapper
     599    cxy_t         fat_cxy;        // FAT cluster identifier
     600    fatfs_ctx_t * fat_ctx_ptr;    // local pointer on fatfs context in FAT cluster
     601    xptr_t        fat_mapper_xp;  // extended pointer on FAT mapper
     602    xptr_t        hint_xp;        // extended pointer on "free_cluster_hint" shared variable
     603    xptr_t        numb_xp;        // extended pointer on "free_clusters" shared variable
     604    uint32_t      numb;           // "free_clusters" variable current value
     605    uint32_t      hint;           // "free_cluster_hint" variable current value
     606    uint32_t      page_id;        // page index in FAT mapper
     607    uint32_t      slot_id;        // slot index in one page of FAT (1024 slots per page)
     608    uint32_t      page_max;       // max number of pages in FAT mapper
     609    xptr_t        page_xp;        // extended pointer on current page in FAT mapper
     610    xptr_t        base_xp;        // extended pointer on current page base
     611    xptr_t        slot_xp;        // extended pointer on current slot in FAT mapper
    517612
    518613#if DEBUG_FATFS_FREE_CLUSTERS
     
    537632
    538633    // get extended pointer on FAT mapper
    539     mapper_xp = hal_remote_l64( XPTR( fat_cxy , &fat_ctx_ptr->fat_mapper_xp ) );
     634    fat_mapper_xp = hal_remote_l64( XPTR( fat_cxy , &fat_ctx_ptr->fat_mapper_xp ) );
    540635
    541636    // initialise variables to scan the FAT mapper
     
    549644    {
    550645        // get current page from mapper
    551         page_xp = mapper_remote_get_page( mapper_xp , page_id );
     646        page_xp = mapper_remote_get_page( fat_mapper_xp , page_id );
    552647
    553648        if( page_xp == XPTR_NULL )
     
    574669
    575670                // update FS_INFO sector on IOC device
    576                 error = fatfs_free_clusters_update_ioc( fatfs_ctx_xp , numb , hint );
     671                error = fatfs_update_ioc_fat( fatfs_ctx_xp,
     672                                              page_id,
     673                                              page_id );
    577674
    578675                if( error )
     
    585682cycle = (uint32_t)hal_get_cycles();
    586683if( DEBUG_FATFS_FREE_CLUSTERS < (uint32_t)hal_get_cycles() )
    587 printk("\n[%s] thread[%x,%x] updated free cluster info  / hint %x / number %x\n",
     684printk("\n[%s] thread[%x,%x] exit / hint %x / free %x / cycle %d\n",
    588685__FUNCTION__, this->process->pid, this->trdid,
    589 hal_remote_l32(hint_xp), hal_remote_l32(numb_xp) );
     686hal_remote_l32(hint_xp), hal_remote_l32(numb_xp), cycle );
    590687#endif
    591688                return 0;
     
    612709// This static function increments the "free_clusters" variable, and updates the
    613710// "free_cluster_hint" variables in the FATFS context in FAT cluster, identified
    614 // by the <fat_ctx_xp> argument, when a cluster is released to FAT.
     711// by the <fat_ctx_xp> argument, when a FATFS cluster is released.
    615712// If the released cluster index is smaller than the current (hint) value,
    616713// it set "free_cluster_hint" <= cluster.
    617 // It calls the fatfs_free_clusters_update_ioc() function to synchronously update the
    618 // FS_INFO sector on the IOC device. It can be called by a thead running in any cluster.
    619 //
    620 // WARNING : The lock protecting exclusive access to these variables
    621 //           must be taken by the calling function.
     714// It does NOT update the  FS_INFO sector on the IOC device.
     715// It can be called by a thead running in any cluster.
     716// The lock protecting exclusive access to the FAT must be taken by the calling function.
    622717//////////////////////////////////////////////////////////////////////////////////////////
    623718// @ fatfs_ctx_xp  : extended pointer on FATFS context in FAT cluster.
     
    665760
    666761    // update FS_INFO sector on IOC device
    667     error = fatfs_free_clusters_update_ioc( fatfs_ctx_xp , numb , hint );
     762    error = fatfs_update_ioc_fsinfo( fatfs_ctx_xp );
    668763
    669764    if( error )
     
    674769
    675770#if DEBUG_FATFS_FREE_CLUSTERS
    676 thread_t * this = CURRENT_THREAD;
     771cycle = (uint32_t)hal_get_cycles();
    677772if( DEBUG_FATFS_FREE_CLUSTERS < (uint32_t)hal_get_cycles() )
    678 printk("\n[%s] thread[%x,%x] updated free cluster info : hint %x / number %x\n",
     773printk("\n[%s] thread[%x,%x] exit / hint %x / free %x / cycle %d\n",
    679774__FUNCTION__, this->process->pid, this->trdid,
    680 hal_remote_l32( hint_xp ), hal_remote_l32( numb_xp ) );
     775hal_remote_l32( hint_xp ), hal_remote_l32( numb_xp ), cycle );
    681776#endif
    682777
     
    686781
    687782//////////////////////////////////////////////////////////////////////////////////////////
    688 // This recursive function is called by the generic function fatfs_release_all_clusters()
    689 // It release all clusters allocated to a given inode in the FAT mapper.
    690 // The removal is done in reverse order of the linked list (from last to first).
    691 // It does NOT update the FS on the IOC device.
    692 //////////////////////////////////////////////////////////////////////////////////////////
    693 // @ mapper_cxy : FAT mapper cluster identifier.
    694 // @ mapper_ptr : local pointer on FAT mapper.
    695 // @ fatfs_ctx  : local pointer on FATFS context in FAT cluster.
    696 // @ cluster    : index of cluster to be released from FAT mapper.
    697 // @ return 0 if success / return -1 if error (cannot access FAT)
    698 //////////////////////////////////////////////////////////////////////////////////////////
    699 static error_t fatfs_recursive_release( cxy_t         mapper_cxy,
    700                                         mapper_t    * mapper_ptr,
    701                                         fatfs_ctx_t * fatfs_ctx,
    702                                         uint32_t      cluster )
    703 {
    704     uint32_t next;
    705 
    706     // build extended pointer on FAT mapper
    707     xptr_t mapper_xp = XPTR( mapper_cxy , mapper_ptr );
     783// This recursive function is called by the generic function fatfs_release_inode().
     784// It release all FATFS clusters allocated to a given inode to the FAT mapper.
     785// It can be called by a thread running in any cluster, as it use remote pointers
     786// to access both the FAT mapper and the FATFS context in the FAT cluster, defined
     787// by the <fat_mapper_xp> and <fatfs_ctx_xp> arguments.
     788// The removal is done in reverse order of the linked list (from last cluster to first).
     789// It returns in the <dirty_page_min> and <dirty_page_max> buffers the indexes of the
     790// modified pages in the FAT mapper.
     791// It updates the FAT mapper and the free_cluster info in the FATFS context, but does NOT
     792// update the FAT and the FS_INFO on IOC device.
     793//////////////////////////////////////////////////////////////////////////////////////////
     794// @ fat_mapper_xp  : [in]  extended pointer on FAT mapper.
     795// @ fatfs_ctx_xp   : [in]  extended pointer on FATFS context in FAT cluster.
     796// @ cluster        : [in]  index of cluster to be released from FAT mapper.
     797// @ dirty_page_min : [out] pointer on buffer for min dirty page index.
     798// @ dirty_page_max : [out] pointer on buffer for max dirty page index.
     799// @ return 0 if success / return -1 if error.
     800//////////////////////////////////////////////////////////////////////////////////////////
     801static error_t fatfs_recursive_release( xptr_t      fat_mapper_xp,
     802                                        xptr_t      fatfs_ctx_xp,
     803                                        uint32_t    cluster,
     804                                        uint32_t  * dirty_page_min,
     805                                        uint32_t  * dirty_page_max )
     806{
     807    uint32_t next;       // next cluster index
     808    uint32_t page_id;    // page index in FAT mapper
     809    uint32_t word_id;    // word index in page
     810
     811    // get page index and word index from cluster
     812    page_id = cluster >> 10;
     813    word_id = cluster & 0x3FF;
    708814
    709815    // get next cluster index from FAT mapper
    710     if ( mapper_remote_get_32( mapper_xp,
    711                                cluster,
     816    if ( mapper_remote_get_32( fat_mapper_xp,
     817                               page_id,
     818                               word_id,
    712819                               &next ) ) return -1;
    713820
     
    722829    {
    723830        // call fatfs_recursive_release() on next cluster
    724         if ( fatfs_recursive_release( mapper_cxy,
    725                                       mapper_ptr,
    726                                       fatfs_ctx,
    727                                       next ) ) return -1;
     831        if ( fatfs_recursive_release( fat_mapper_xp,
     832                                      fatfs_ctx_xp,
     833                                      next,
     834                                      dirty_page_min,
     835                                      dirty_page_max ) ) return -1;
    728836    }       
    729837
    730     // update current cluster in FAT mapper
    731     if ( mapper_remote_set_32( mapper_xp,
    732                                cluster,
     838    // update FAT mapper
     839    if ( mapper_remote_set_32( fat_mapper_xp,
     840                               page_id,
     841                               word_id,
    733842                               FREE_CLUSTER ) ) return -1;
    734843
    735     // Update free_cluster info in FATFS context and in FS_INFO sector
    736     return fatfs_free_clusters_increment( XPTR( mapper_cxy , fatfs_ctx ) , cluster );
     844    // update dirty_page_min / dirty_page_max buffers
     845    if( page_id < *dirty_page_min ) *dirty_page_min = page_id;
     846    if( page_id > *dirty_page_max ) *dirty_page_max = page_id;
     847
     848    // Update free_cluster info in FATFS context
     849    return fatfs_free_clusters_increment( fatfs_ctx_xp , cluster );
    737850
    738851}  // end fatfs_recursive_release()
     
    11091222    fatfs_ctx->fs_info_buffer        = buffer;
    11101223
    1111     remote_rwlock_init( XPTR( local_cxy , &fatfs_ctx->lock ) , LOCK_FATFS_FREE );
     1224    remote_rwlock_init( XPTR( local_cxy , &fatfs_ctx->lock ) , LOCK_FATFS_FAT );
    11121225
    11131226#if (DEBUG_FATFS_CTX_INIT & 0x1)
     
    17601873    error_t        error;
    17611874
    1762     char       dir_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1875    char           dir_name[CONFIG_VFS_MAX_NAME_LENGTH];
    17631876
    17641877// check arguments
     
    21582271}  // end fatfs_sync_inode()
    21592272
     2273
     2274
     2275
     2276
     2277
    21602278//////////////////////////////
    21612279error_t fatfs_sync_fat( void )
     
    22782396    ioc_free_cluster_hint = fatfs_get_remote_record( FS_FREE_CLUSTER_HINT , tmp_buf_xp );
    22792397
     2398#if DEBUG_FATFS_SYNC_FSINFO
     2399if( DEBUG_FATFS_SYNC_FSINFO < cycle )
     2400printk("\n[%s] thread[%x,%x] / ctx_free %x / ioc_free %x / ctx_hint %x / ioc_hint %x\n",
     2401__FUNCTION__ , this->process->pid, this->trdid,
     2402ctx_free_clusters, ioc_free_clusters, ctx_free_cluster_hint, ioc_free_cluster_hint );
     2403#endif
     2404
    22802405    // check values
    22812406    if( (ioc_free_clusters     != ctx_free_clusters) ||
     
    23272452    fatfs_ctx_t * loc_fatfs_ctx;  // local pointer on local FATFS context
    23282453    fatfs_ctx_t * fat_fatfs_ctx;  // local pointer on FATFS context in FAT cluster
    2329     xptr_t        mapper_xp;      // extended pointer on FAT mapper
     2454    xptr_t        fat_mapper_xp;  // extended pointer on FAT mapper
    23302455    cxy_t         fat_cxy;        // Fat mapper cluster identifier
    23312456    xptr_t        page_xp;        // extended pointer on current page descriptor in mapper
     
    23502475
    23512476    // get extended pointer on FAT mapper
    2352     mapper_xp  = loc_fatfs_ctx->fat_mapper_xp;
     2477    fat_mapper_xp  = loc_fatfs_ctx->fat_mapper_xp;
    23532478
    23542479    // get FAT cluster
    2355     fat_cxy = GET_CXY( mapper_xp );
     2480    fat_cxy = GET_CXY( fat_mapper_xp );
    23562481   
    23572482    // get local pointer on FATFS context in FAT cluster
     
    23942519
    23952520    // get relevant page descriptor from FAT mapper
    2396     page_xp = mapper_remote_get_page( mapper_xp , page_id );
     2521    page_xp = mapper_remote_get_page( fat_mapper_xp , page_id );
    23972522
    23982523    if( page_xp == XPTR_NULL )
     
    24272552    hal_remote_s32( slot_xp , END_OF_CHAIN_CLUSTER_MAX );
    24282553
    2429     // synchronously update FAT on device
     2554    // we don't mark the FAT mapper page as dirty,
     2555    // because we synchronously update FAT on IOC device
    24302556    error = fatfs_move_page( page_xp , IOC_SYNC_WRITE );
    24312557
     
    24572583    vfs_ctx_t   * vfs_ctx;        // local pointer on VFS context (same in all clusters).
    24582584    fatfs_ctx_t * loc_fatfs_ctx;  // local pointer on local FATFS context
    2459     fatfs_ctx_t * fat_fatfs_ctx;  // local pointer on FATFS context in FAT cluster
    2460     xptr_t        mapper_xp;      // extended pointer on FAT mapper
    2461     cxy_t         mapper_cxy;     // Fat mapper cluster identifier
    2462     mapper_t    * mapper_ptr;     // local pointer on FAT mapper
    2463     xptr_t        lock_xp;        // extended pointer on lock protecting free clusters info.
     2585    cxy_t         fat_cxy;        // FAT cluster identifier
     2586    xptr_t        fatfs_ctx_xp;   // extended pointer on FATFS context in FAT cluster
     2587    fatfs_ctx_t * fatfs_ctx_ptr;  // local pointer on FATFS context in FAT cluster
     2588    xptr_t        fat_mapper_xp;  // extended pointer on FAT mapper
     2589    mapper_t    * fat_mapper_ptr; // local pointer on FAT mapper
     2590    xptr_t        lock_xp;        // extended pointer on lock protecting FAT.
    24642591    xptr_t        first_xp;       // extended pointer on inode extension
    24652592    uint32_t      first_cluster;  // first cluster index for released inode
    24662593    vfs_inode_t * inode_ptr;      // local pointer on target inode
    24672594    cxy_t         inode_cxy;      // target inode cluster identifier
     2595    error_t       error;
    24682596
    24692597// check inode pointer
     
    24912619#endif
    24922620
    2493 #if (DEBUG_FATFS_RELEASE_INODE & 1)
    2494 fatfs_display_fat( 0 , 512 );
    2495 #endif
    2496 
    24972621    // get local pointer on VFS context (same in all clusters)
    24982622    vfs_ctx = &fs_context[FS_TYPE_FATFS];
     
    25012625    loc_fatfs_ctx = vfs_ctx->extend;
    25022626
    2503     // get pointers and cluster on FAT mapper
    2504     mapper_xp  = loc_fatfs_ctx->fat_mapper_xp;
    2505     mapper_cxy = GET_CXY( mapper_xp );
    2506     mapper_ptr = GET_PTR( mapper_xp );
     2627    // get pointers on FAT mapper
     2628    fat_mapper_xp  = loc_fatfs_ctx->fat_mapper_xp;
     2629    fat_cxy        = GET_CXY( fat_mapper_xp );
     2630    fat_mapper_ptr = GET_PTR( fat_mapper_xp );
    25072631   
    2508     // get local pointer on FATFS context in FAT cluster
    2509     fat_fatfs_ctx = hal_remote_lpt( XPTR( mapper_cxy , &vfs_ctx->extend ) );
     2632    // get pointers on FATFS context in FAT cluster
     2633    fatfs_ctx_ptr  = hal_remote_lpt( XPTR( fat_cxy , &vfs_ctx->extend ) );
     2634    fatfs_ctx_xp   = XPTR( fat_cxy , fatfs_ctx_ptr );
    25102635
    25112636    // get extended pointer on FAT lock in FAT cluster
    2512     lock_xp = XPTR( mapper_cxy , &fat_fatfs_ctx->lock );
     2637    lock_xp = XPTR( fat_cxy , &fatfs_ctx_ptr->lock );
    25132638
    25142639    // take FAT lock in write mode
    25152640    remote_rwlock_wr_acquire( lock_xp );
    25162641
     2642#if (DEBUG_FATFS_RELEASE_INODE & 0x11 == 0x11)
     2643mapper_display_page( fat_mapper_xp , 0 , 4096 );
     2644#endif
     2645
    25172646    // call the recursive function to release all clusters from FAT mapper
    2518     if ( fatfs_recursive_release( mapper_cxy,
    2519                                   mapper_ptr,
    2520                                   fat_fatfs_ctx,
    2521                                   first_cluster ) )
     2647    uint32_t dirty_page_min = 0xFFFFFFFF;
     2648    uint32_t dirty_page_max = 0;
     2649
     2650    if ( fatfs_recursive_release( fat_mapper_xp,
     2651                                  fatfs_ctx_xp,
     2652                                  first_cluster,
     2653                                  &dirty_page_min,
     2654                                  &dirty_page_max ) )
    25222655    {
    25232656        printk("\n[ERROR] in %s : cannot update FAT mapper\n", __FUNCTION__ );
     
    25312664#endif
    25322665
     2666#if (DEBUG_FATFS_RELEASE_INODE & 0x11 == 0x11)
     2667mapper_display_page( fat_mapper_xp , 0 , 4096 );
     2668#endif
     2669
    25332670    // update FAT on IOC device (from FAT mapper)
    2534     if ( fatfs_sync_fat() )
    2535     {
    2536         printk("\n[ERROR] in %s : cannot update FAT on device\n", __FUNCTION__ );
     2671    error = fatfs_update_ioc_fat( fatfs_ctx_xp,
     2672                                  dirty_page_min,
     2673                                  dirty_page_max );
     2674
     2675    if( error )
     2676    {
     2677        printk("\n[ERROR] in %s : cannot update FAT on IOC device\n", __FUNCTION__ );
    25372678        remote_rwlock_wr_release( lock_xp );
    25382679        return -1;
     
    25442685#endif
    25452686
    2546     // update FS-INFO sector on IOC device (from FATFS context)
    2547     if ( fatfs_sync_free_info() )
    2548     {
    2549         printk("\n[ERROR] in %s: cannot update FS_INFO on device\n", __FUNCTION__ );
     2687    // update FS-INFO on IOC device (from FATFS context)
     2688    error = fatfs_update_ioc_fsinfo( fatfs_ctx_xp );
     2689
     2690    if( error )
     2691    {
     2692        printk("\n[ERROR] in %s: cannot update FSINFO on IOC device\n", __FUNCTION__ );
    25502693        remote_rwlock_wr_release( lock_xp );
    25512694        return -1;
    25522695    }
     2696
     2697#if (DEBUG_FATFS_RELEASE_INODE & 1)
     2698if( DEBUG_FATFS_RELEASE_INODE < cycle )
     2699printk("\n[%s] updated FS_INFO on IOC device for >%s>\n", __FUNCTION__, name );
     2700#endif
    25532701
    25542702    // release FAT lock
  • trunk/kernel/fs/fatfs.h

    r627 r628  
    180180 *   functions to modify the FAT in both the FAT mapper and on IOC device.
    181181 *
    182  * WARNING é : Almost all fields are constant values, but the <free_cluster_hint>,
    183  * <free_clusters> and <lock> are shared variables. The <fs_info_buffer>, only
    184  * allocated in cluster 0, contains a copy of the FS_INFO sector. It is used by all
    185  * kernel instances to synchronously update the free clusters info on IOC device.
    186  * For these four variables, all kernel instances must use the values in cluster 0,
    187  * containing the FAT mapper.
     182 * WARNING 2 : Most fields are constant values, but the <free_cluster_hint>,
     183 * <free_clusters>, <dirty_page_min>, <dirty_page_max>, <lock>, and the <fs_info_buffer>
     184 * are shared variables, that can be modified by any thread running in any cluster.
     185 * The <fs_info_buffer> contains a copy of the FS_INFO sector, and is only allocated in
     186 * the FAT cluster (i.e. in cluster 0). It is used by all to synchronously update the
     187 * free clusters info on IOC device.
     188 *  => For all these variables, only the values stored in the FAT cluster must be used.
    188189 ****************************************************************************************/
    189190
     
    201202
    202203    /* shared variables (only the copy in FAT cluster must be used)                     */
     204    uint32_t            dirty_page_min;        /*! min dirty page index in FAT mapper   */
     205    uint32_t            dirty_page_max;        /*! max dirty page index in FAT mapper   */
    203206    uint32_t            free_cluster_hint;     /*! cluster[hint+1] is the first free    */
    204207    uint32_t            free_clusters;         /*! free clusters number                 */
  • trunk/kernel/fs/vfs.c

    r626 r628  
    815815assert( (inode_type == INODE_TYPE_FILE), "bad inode type" );
    816816
     817    // get mapper pointer and file offset from file descriptor
     818    file_offset = hal_remote_l32( XPTR( file_cxy , &file_ptr->offset ) );
     819    mapper      = hal_remote_lpt( XPTR( file_cxy , &file_ptr->mapper ) );
     820
    817821#if DEBUG_VFS_USER_MOVE
    818822char          name[CONFIG_VFS_MAX_NAME_LENGTH];
     
    824828{
    825829    if( to_buffer )
    826     printk("\n[%s] thread[%x,%x] enter / %d bytes / mapper(%s) -> buffer(%x) / cycle %d\n",
    827     __FUNCTION__ , this->process->pid, this->trdid, size, name, buffer, cycle );
     830    printk("\n[%s] thread[%x,%x] enter / %d bytes / map(%s) -> buf(%x) / offset %d / cycle %d\n",
     831    __FUNCTION__ , this->process->pid, this->trdid, size, name, buffer, file_offset, cycle );
    828832    else           
    829     printk("\n[%s] thread[%x,%x] enter / %d bytes / buffer(%x) -> mapper(%s) / cycle %d\n",
    830     __FUNCTION__ , this->process->pid, this->trdid, size, buffer, name, cycle );
     833    printk("\n[%s] thread[%x,%x] enter / %d bytes / buf(%x) -> map(%s) / offset %d / cycle %d\n",
     834    __FUNCTION__ , this->process->pid, this->trdid, size, buffer, name, file_offset, cycle );
    831835}
    832836#endif
    833 
    834     // get mapper pointer and file offset from file descriptor
    835     file_offset = hal_remote_l32( XPTR( file_cxy , &file_ptr->offset ) );
    836     mapper      = hal_remote_lpt( XPTR( file_cxy , &file_ptr->mapper ) );
    837837
    838838    // move data between mapper and buffer
     
    856856{
    857857    if( to_buffer )
    858     printk("\n[%s] thread[%x,%x] exit / %d bytes / mapper(%s) -> buffer(%x) / cycle %d\n",
    859     __FUNCTION__ , this->process->pid, this->trdid, size, name, buffer, cycle );
     858    printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
     859    __FUNCTION__ , this->process->pid, cycle );
    860860    else           
    861     printk("\n[%s] thread[%x,%x] exit / %d bytes / buffer(%x) -> mapper(%s) / cycle %d\n",
    862     __FUNCTION__ , this->process->pid, this->trdid, size, buffer, name, cycle );
     861    printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
     862    __FUNCTION__ , this->process->pid, cycle );
    863863}
    864864#endif
     
    25382538#if (DEBUG_VFS_LOOKUP & 1)
    25392539if( DEBUG_VFS_LOOKUP < cycle )
    2540 printk("\n[%s] thread[%x,%x] look for <%s> in <%s> / last = %d\n",
     2540printk("\n[%s] thread[%x,%x] search <%s> in <%s> / last = %d\n",
    25412541__FUNCTION__, process->pid, this->trdid, name, pathname, last );
    25422542#endif
  • trunk/kernel/kern/kernel_init.c

    r626 r628  
    162162    "PROCESS_USERSYNC",      // 26
    163163    "PROCESS_FDARRAY",       // 27
    164     "FATFS_FREE",            // 28
    165     "PROCESS_DIR",           // 29
     164    "PROCESS_DIR",           // 28
     165    "unused_29",             // 29
    166166
    167167    "PROCESS_THTBL",         // 30
     
    173173    "VMM_GPT",               // 35
    174174    "VFS_MAIN",              // 36
     175    "FATFS_FAT",             // 37
    175176};       
    176177
  • trunk/kernel/kern/rpc.c

    r625 r628  
    17351735                                   error_t     * error )          // out
    17361736{
    1737 #if DEBUG_RPC_VFS_FS_GET_DENTRY
    1738 thread_t * this = CURRENT_THREAD;
    1739 uint32_t cycle = (uint32_t)hal_get_cycles();
    1740 if( cycle > DEBUG_RPC_VFS_FS_GET_DENTRY )
     1737#if DEBUG_RPC_VFS_FS_NEW_DENTRY
     1738thread_t * this = CURRENT_THREAD;
     1739uint32_t cycle = (uint32_t)hal_get_cycles();
     1740if( cycle > DEBUG_RPC_VFS_FS_NEW_DENTRY )
    17411741printk("\n[%s] thread[%x,%x] on core %d enter / cycle %d\n",
    17421742__FUNCTION__, this->process->pid, this->trdid, this->core->lid , cycle );
     
    17471747    // initialise RPC descriptor header
    17481748    rpc_desc_t  rpc;
    1749     rpc.index    = RPC_VFS_FS_GET_DENTRY;
     1749    rpc.index    = RPC_VFS_FS_NEW_DENTRY;
    17501750    rpc.blocking = true;
    17511751    rpc.rsp      = &responses;
     
    17621762    *error   = (error_t)rpc.args[3];
    17631763
    1764 #if DEBUG_RPC_VFS_FS_GET_DENTRY
    1765 cycle = (uint32_t)hal_get_cycles();
    1766 if( cycle > DEBUG_RPC_VFS_FS_GET_DENTRY )
     1764#if DEBUG_RPC_VFS_FS_NEW_DENTRY
     1765cycle = (uint32_t)hal_get_cycles();
     1766if( cycle > DEBUG_RPC_VFS_FS_NEW_DENTRY )
    17671767printk("\n[%s] thread[%x,%x] on core %d exit / cycle %d\n",
    17681768__FUNCTION__, this->process->pid, this->trdid, this->core->lid , cycle );
     
    17731773void rpc_vfs_fs_new_dentry_server( xptr_t xp )
    17741774{
    1775 #if DEBUG_RPC_VFS_FS_GET_DENTRY
    1776 thread_t * this = CURRENT_THREAD;
    1777 uint32_t cycle = (uint32_t)hal_get_cycles();
    1778 if( cycle > DEBUG_RPC_VFS_FS_GET_DENTRY )
     1775#if DEBUG_RPC_VFS_FS_NEW_DENTRY
     1776thread_t * this = CURRENT_THREAD;
     1777uint32_t cycle = (uint32_t)hal_get_cycles();
     1778if( cycle > DEBUG_RPC_VFS_FS_NEW_DENTRY )
    17791779printk("\n[%s] thread[%x,%x] on core %d enter / cycle %d\n",
    17801780__FUNCTION__, this->process->pid, this->trdid, this->core->lid , cycle );
     
    18071807    hal_remote_s64( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)error );
    18081808
    1809 #if DEBUG_RPC_VFS_FS_GET_DENTRY
    1810 cycle = (uint32_t)hal_get_cycles();
    1811 if( cycle > DEBUG_RPC_VFS_FS_GET_DENTRY )
     1809#if DEBUG_RPC_VFS_FS_NEW_DENTRY
     1810cycle = (uint32_t)hal_get_cycles();
     1811if( cycle > DEBUG_RPC_VFS_FS_NEW_DENTRY )
    18121812printk("\n[%s] thread[%x,%x] on core %d exit / cycle %d\n",
    18131813__FUNCTION__, this->process->pid, this->trdid, this->core->lid , cycle );
  • trunk/kernel/kern/rpc.h

    r625 r628  
    7777    RPC_VFS_FILE_CREATE           = 14,
    7878    RPC_VFS_FILE_DESTROY          = 15,
    79     RPC_VFS_FS_GET_DENTRY         = 16,
     79    RPC_VFS_FS_NEW_DENTRY         = 16,
    8080    RPC_VFS_FS_ADD_DENTRY         = 17,
    8181    RPC_VFS_FS_REMOVE_DENTRY      = 18,
  • trunk/kernel/kernel_config.h

    r625 r628  
    9191#define DEBUG_FATFS_SYNC_INODE            0
    9292#define DEBUG_FATFS_UPDATE_DENTRY         0
     93#define DEBUG_FATFS_UPDATE_IOC            0
    9394
    9495#define DEBUG_HAL_CONTEXT                 0
     
    150151#define DEBUG_RPC_THREAD_USER_CREATE      0
    151152#define DEBUG_RPC_THREAD_KERNEL_CREATE    0
     153#define DEBUG_RPC_VFS_DENTRY_CREATE       0
     154#define DEBUG_RPC_VFS_DENTRY_DESTROY      0
     155#define DEBUG_RPC_VFS_DEVICE_GET_DENTRY   0
     156#define DEBUG_RPC_VFS_FILE_CREATE         0
     157#define DEBUG_RPC_VFS_FILE_DESTROY        0
     158#define DEBUG_RPC_VFS_FS_NEW_DENTRY       0
     159#define DEBUG_RPC_VFS_FS_ADD_DENTRY       0
    152160#define DEBUG_RPC_VFS_INODE_CREATE        0
    153161#define DEBUG_RPC_VFS_INODE_DESTROY       0
    154 #define DEBUG_RPC_VFS_DENTRY_CREATE       0
    155 #define DEBUG_RPC_VFS_DENTRY_DESTROY      0
    156 #define DEBUG_RPC_VFS_FILE_CREATE         0
    157 #define DEBUG_RPC_VFS_FILE_DESTROY        0
    158 #define DEBUG_RPC_VFS_DEVICE_GET_DENTRY   0
    159162#define DEBUG_RPC_VMM_CREATE_VSEG         0
    160163#define DEBUG_RPC_VMM_GET_PTE             0
     
    298301#define LOCK_PROCESS_USERSYNC 26   // remote (Q)  protect lists of user synchros in process
    299302#define LOCK_PROCESS_FDARRAY  27   // remote (Q)  protect array of open files in owner process
    300 #define LOCK_FATFS_FREE       28   // remote (Q)  protect the FATFS context (free clusters)
    301 #define LOCK_PROCESS_DIR      29   // remote (Q)  protect xlist of open directories in process
     303#define LOCK_PROCESS_DIR      28   // remote (Q)  protect xlist of open directories in process
    302304
    303305#define LOCK_PROCESS_THTBL    30   // local  (RW) protect local array of threads in a process
     
    309311#define LOCK_VMM_GPT          35   // remote (RW) protect GPT (local page table)
    310312#define LOCK_VFS_MAIN         36   // remote (RW) protect vfs traversal (in root inode)
     313#define LOCK_FATFS_FAT        37   // remote (RW) protect exclusive access to the FATFS FAT
    311314
    312315
  • trunk/kernel/mm/mapper.c

    r626 r628  
    395395{
    396396    uint32_t   page_offset;    // first byte to move to/from a mapper page
    397     uint32_t   page_count;     // number of bytes to move to/from a mapper page
     397    uint32_t   page_bytes;     // number of bytes to move to/from a mapper page
    398398    uint32_t   page_id;        // current mapper page index
    399399    uint32_t   done;           // number of moved bytes
     
    420420#endif
    421421
    422     // compute offsets of first and last bytes in file
     422    // compute indexes of first and last bytes in file
    423423    uint32_t min_byte = file_offset;
    424424    uint32_t max_byte = file_offset + size - 1;
     
    444444
    445445        // compute number of bytes in page
    446         if      ( first   == last  ) page_count = size;
    447         else if ( page_id == first ) page_count = CONFIG_PPM_PAGE_SIZE - page_offset;
    448         else if ( page_id == last  ) page_count = (max_byte & CONFIG_PPM_PAGE_MASK) + 1;
    449         else                         page_count = CONFIG_PPM_PAGE_SIZE;
     446        if      ( first   == last  ) page_bytes = size;
     447        else if ( page_id == first ) page_bytes = CONFIG_PPM_PAGE_SIZE - page_offset;
     448        else if ( page_id == last  ) page_bytes = (max_byte & CONFIG_PPM_PAGE_MASK) + 1;
     449        else                         page_bytes = CONFIG_PPM_PAGE_SIZE;
    450450
    451451#if (DEBUG_MAPPER_MOVE_USER & 1)
    452452if( DEBUG_MAPPER_MOVE_USER < cycle )
    453453printk("\n[%s] thread[%x,%x] : page_id %d / page_offset %d / bytes %d\n",
    454 __FUNCTION__, this->process->pid, this->trdid, page_id , page_offset , page_count );
    455 #endif
    456 
    457         // get extended pointer on page descriptor
     454__FUNCTION__, this->process->pid, this->trdid, page_id , page_offset , page_bytes );
     455#endif
     456
     457        // get extended pointer on page descriptor in mapper
    458458        page_xp = mapper_remote_get_page( mapper_xp , page_id );
    459459
     
    476476        if( to_buffer )
    477477        {
    478             hal_copy_to_uspace( map_cxy , map_ptr , buf_ptr , page_count );
     478            hal_copy_to_uspace( map_cxy , map_ptr + page_offset , buf_ptr , page_bytes );
    479479
    480480#if DEBUG_MAPPER_MOVE_USER & 1
    481481if( DEBUG_MAPPER_MOVE_USER < cycle )
    482482printk("\n[%s] thread[%x,%x] moved %d bytes / mapper %s (%x,%x) -> user buffer(%x,%x)\n",
    483 __FUNCTION__, this->process->pid, this->trdid, page_count,
    484 name, map_cxy, map_ptr, local_cxy, buf_ptr );
     483__FUNCTION__, this->process->pid, this->trdid, page_bytes,
     484name, map_cxy, map_ptr + page_offset, local_cxy, buf_ptr );
    485485#endif
    486486
     
    489489        {
    490490            ppm_page_do_dirty( page_xp );
    491             hal_copy_from_uspace( map_cxy , map_ptr , buf_ptr , page_count );
     491            hal_copy_from_uspace( map_cxy , map_ptr + page_offset , buf_ptr , page_bytes );
    492492
    493493#if DEBUG_MAPPER_MOVE_USER & 1
    494494if( DEBUG_MAPPER_MOVE_USER < cycle )
    495495printk("\n[%s] thread[%x,%x] moved %d bytes / user buffer(%x,%x) -> mapper %s (%x,%x)\n",
    496 __FUNCTION__, this->process->pid, this->trdid, page_count,
    497 local_cxy, buf_ptr, name, map_cxy, map_ptr );
     496__FUNCTION__, this->process->pid, this->trdid, page_bytes,
     497local_cxy, buf_ptr, name, map_cxy, map_ptr + page_offset );
    498498mapper_display_page(  mapper_xp , page_id, 128 );
    499499#endif
     
    501501        }
    502502
    503         done += page_count;
     503        done += page_bytes;
    504504    }
    505505
     
    529529{
    530530    uint32_t   page_offset;    // first byte to move to/from a mapper page
    531     uint32_t   page_count;     // number of bytes to move to/from a mapper page
     531    uint32_t   page_bytes;     // number of bytes to move to/from a mapper page
    532532    uint32_t   page_id;        // current mapper page index
    533533    uint32_t   done;           // number of moved bytes
     
    588588
    589589        // compute number of bytes to move in page
    590         if      ( first == last  )   page_count = size;
    591         else if ( page_id == first ) page_count = CONFIG_PPM_PAGE_SIZE - page_offset;
    592         else if ( page_id == last  ) page_count = (max_byte & CONFIG_PPM_PAGE_MASK) + 1;
    593         else                         page_count = CONFIG_PPM_PAGE_SIZE;
     590        if      ( first == last  )   page_bytes = size;
     591        else if ( page_id == first ) page_bytes = CONFIG_PPM_PAGE_SIZE - page_offset;
     592        else if ( page_id == last  ) page_bytes = (max_byte & CONFIG_PPM_PAGE_MASK) + 1;
     593        else                         page_bytes = CONFIG_PPM_PAGE_SIZE;
    594594
    595595        // get extended pointer on page descriptor
     
    621621    if( to_buffer )
    622622    printk("\n[%s] mapper <%s> page %d => buffer(%x,%x) / %d bytes\n",
    623     __FUNCTION__, name, page_id, dst_cxy, dst_ptr, page_count );
     623    __FUNCTION__, name, page_id, dst_cxy, dst_ptr, page_bytes );
    624624    else
    625625    printk("\n[%s] buffer(%x,%x) => mapper <%s> page %d / %d bytes\n",
    626     __FUNCTION__, src_cxy, src_ptr, name, page_id, page_count );
     626    __FUNCTION__, src_cxy, src_ptr, name, page_id, page_bytes );
    627627}
    628628#endif
    629629
    630630        // move fragment
    631         hal_remote_memcpy( XPTR( dst_cxy , dst_ptr ), XPTR( src_cxy , src_ptr ), page_count );
    632 
    633         done += page_count;
     631        hal_remote_memcpy( XPTR( dst_cxy , dst_ptr ), XPTR( src_cxy , src_ptr ), page_bytes );
     632
     633        done += page_bytes;
    634634    }
    635635
     
    647647///////////////////////////////////////////////////
    648648error_t mapper_remote_get_32( xptr_t     mapper_xp,
     649                              uint32_t   page_id,
    649650                              uint32_t   word_id,
    650                               uint32_t * p_value )
    651 {
    652     uint32_t   page_id;      // page index in file
    653     uint32_t   local_id;     // word index in page
     651                              uint32_t * value )
     652{
    654653    xptr_t     page_xp;      // extended pointer on searched page descriptor
    655654    xptr_t     base_xp;      // extended pointer on searched page base
    656 
    657655   
    658     // get page index and local word index
    659     page_id  = word_id >> 10;
    660     local_id = word_id & 0x3FF;
    661 
    662656    // get page containing the searched word
    663657    page_xp  = mapper_remote_get_page( mapper_xp , page_id );
     
    669663
    670664    // get the value from mapper
    671     *p_value = hal_remote_l32( base_xp + (local_id<<2) );
     665    *value = hal_remote_l32( base_xp + (word_id<<2) );
    672666
    673667    return 0;
     
    677671///////////////////////////////////////////////////
    678672error_t mapper_remote_set_32( xptr_t     mapper_xp,
     673                              uint32_t   page_id,
    679674                              uint32_t   word_id,
    680675                              uint32_t   value )
    681676{
    682    
    683     uint32_t   page_id;      // page index in file
    684     uint32_t   local_id;     // word index in page
    685677    xptr_t     page_xp;      // extended pointer on searched page descriptor
    686678    xptr_t     base_xp;      // extended pointer on searched page base
    687679
    688     // get page index and local vord index
    689     page_id  = word_id >> 10;
    690     local_id = word_id & 0x3FF;
    691 
    692680    // get page containing the searched word
    693681    page_xp  = mapper_remote_get_page( mapper_xp , page_id );
     
    699687
    700688    // set value to mapper
    701     hal_remote_s32( (base_xp + (local_id << 2)) , value );
    702 
    703     // set the dirty flag
     689    hal_remote_s32( (base_xp + (word_id << 2)) , value );
     690
     691    // set the dirty flag in page descriptor
    704692    ppm_page_do_dirty( page_xp );
    705693
  • trunk/kernel/mm/mapper.h

    r626 r628  
    206206 *******************************************************************************************
    207207 * @ mapper_xp  : [in]  extended pointer on the mapper.
    208  * @ word_id    : [in]  32 bits word index in file.
    209  * @ p_value    : [out] local pointer on destination buffer.
     208 * @ page_id    : [in]  page index in mapper.
     209 * @ word_id    : [in]  32 bits word index in page.
     210 * @ value      : [out] local pointer on destination buffer.
    210211 * @ returns 0 if success / return -1 if error.
    211212 ******************************************************************************************/
    212213error_t mapper_remote_get_32( xptr_t     mapper_xp,
     214                              uint32_t   page_id,
    213215                              uint32_t   word_id,
    214                               uint32_t * p_value );
     216                              uint32_t * value );
    215217
    216218/*******************************************************************************************
     
    220222 * In case of miss, it takes the mapper lock in WRITE_MODE, load the missing
    221223 * page from device to mapper, and release the mapper lock.
     224 * It does not update the FAT on IOC device.
    222225 *******************************************************************************************
    223226 * @ mapper_xp  : [in]  extended pointer on the mapper.
    224  * @ word_id    : [in]  32 bits word index in file.
     227 * @ page_id    : [in]  page index in mapper.
     228 * @ word_id    : [in]  32 bits word index in page.
    225229 * @ value      : [in]  value to be written.
    226230 * @ returns 0 if success / return -1 if error.
    227231 ******************************************************************************************/
    228232error_t mapper_remote_set_32( xptr_t     mapper_xp,
     233                              uint32_t   page_id,
    229234                              uint32_t   word_id,
    230235                              uint32_t   value );
  • trunk/libs/mini-libc/stdio.c

    r625 r628  
    5151}
    5252
    53 ///////////////////////////////////////////////////
     53////////////////////////////////////////////////////////////////////////////////////////
     54// This static function analyses the <format> and the <args> to build a formated
     55// string in the buffer defined by <string> and <length>.
     56// It does NOT add a terminating NUL character in the <string buffer>.
     57// If success, it returns the number of bytes actually copied in the string buffer.
     58// It returns -1 in case of illegal format, or if the formated string exceeds the
     59// the length argument.
     60////////////////////////////////////////////////////////////////////////////////////////
    5461static int xprintf( char         * string,
    5562                    int            length,
     
    5764                    va_list      * args )
    5865{
    59     int ps = 0;    // write index to the string buffer
     66    int ps = 0;    // index in the string buffer
    6067
    6168#define TO_STREAM(x) do { string[ps] = (x); ps++; if(ps==length) return -1; } while(0);
     
    8390
    8491    {
    85         char              buf[30];    // buffer to display one number
     92        char              buf[30];    // buffer to store the string for one number
    8693        char *            pbuf;       // pointer on first char to display
    8794        unsigned int      len = 0;    // number of char to display
  • trunk/params-hard.mk

    r627 r628  
    22
    33ARCH      = /users/alain/soc/tsar-trunk-svn-2013/platforms/tsar_generic_iob
    4 X_SIZE    = 4
    5 Y_SIZE    = 4
    6 NB_PROCS  = 1
     4X_SIZE    = 2
     5Y_SIZE    = 2
     6NB_PROCS  = 4
    77NB_TTYS   = 3
    88IOC_TYPE  = IOC_BDV
  • trunk/user/fft/fft.c

    r596 r628  
    2828// - RANDOM   : data points have pseudo random values
    2929//
    30 // This application uses 4 shared data arrays, that are distributed
    31 // in all clusters (one buffer per cluster):
     30// The main parameters for this generic application are the following:     
     31//  - M : N = 2**M = number of data points / M must be an even number.
     32//  - T : nthreads = ncores defined by the hardware / must be power of 2.
     33//
     34// This application uses 4 shared data arrays, that are dynamically
     35// allocated an distributed, using the remote_malloc() function, with
     36// one sub-buffer per cluster:
    3237// - data[N] contains N input data points, with 2 double per point.
    3338// - trans[N] contains N intermediate data points, 2 double per point.
     
    3641// For data, trans, twid, each sub-buffer contains (N/nclusters) points.
    3742// For umain, each sub-buffer contains (rootN/nclusters) points.
    38 //
    39 // The main parameters for this generic application are the following:     
    40 //  - M : N = 2**M = number of data points / M must be an even number.
    41 //  - T : nthreads = ncores defined by the hardware / must be power of 2.
    4243//
    4344// There is one thread per core.
     
    5051//  - DEBUG_MAIN  : Display intermediate results in main()
    5152//  - DEBUG_FFT1D : Display intermediate results in FFT1D()
    52 //  - DEBUG_ROW  :
     53//  - DEBUG_ROW   : Display intermedite results in FFTrow()
    5354//
    5455// Regarding final instrumentation:
     
    8788
    8889#define DEFAULT_M               12              // 4096 data points
    89 #define MODE                    COSIN
    90 #define CHECK                   0
    91 #define DEBUG_MAIN              2               // trace main() function (detailed if odd)
    92 #define DEBUG_SLAVE             2               // trace slave() function (detailed if odd)
    93 #define DEBUG_FFT1D             2               // trace FFT1D() function (detailed if odd)
     90#define USE_DQT_BARRIER         0               // use DDT barrier if non zero
     91#define MODE                    COSIN           // DATA array initialisation mode
     92#define CHECK                   0               
     93#define DEBUG_MAIN              1               // trace main() function (detailed if odd)
     94#define DEBUG_SLAVE             0               // trace slave() function (detailed if odd)
     95#define DEBUG_FFT1D             0               // trace FFT1D() function (detailed if odd)
    9496#define DEBUG_ROW               0               // trace FFTRow() function (detailed if odd)
    9597#define PRINT_ARRAY             0
     
    138140// synchronisation barrier (all threads)
    139141pthread_barrier_t      barrier;
    140 pthread_barrierattr_t  barrierattr;
     142pthread_barrierattr_t  barrier_attr;
    141143
    142144// threads identifiers, attributes, and arguments
     
    213215void main ( void )
    214216{
     217    int                 error;
     218
    215219    unsigned int        main_cxy;          // main thread cluster
    216220    unsigned int        main_x;            // main thread X coordinate
     
    240244    if( get_config( &x_size , &y_size , &ncores ) )
    241245    {
    242         printf("\n[FFT ERROR] cannot get hardware configuration\n");
     246        printf("\n[fft error] cannot get hardware configuration\n");
    243247        exit( 0 );
    244248    }
     
    247251    if( (ncores != 1) && (ncores != 2) && (ncores != 4) )
    248252    {
    249         printf("\n[FFT ERROR] number of cores per cluster must be 1/2/4\n");
     253        printf("\n[fft error] number of cores per cluster must be 1/2/4\n");
    250254        exit( 0 );
    251255    }
     
    254258    if( (x_size != 1) && (x_size != 2) && (x_size != 4) && (x_size != 8) && (x_size != 16) )
    255259    {
    256         printf("\n[FFT ERROR] x_size must be 1/2/4/8/16\n");
     260        printf("\n[fft error] x_size must be 1/2/4/8/16\n");
    257261        exit( 0 );
    258262    }
     
    261265    if( (y_size != 1) && (y_size != 2) && (y_size != 4) && (y_size != 8) && (y_size != 16) )
    262266    {
    263         printf("\n[FFT ERROR] y_size must be 1/2/4/8/16\n");
     267        printf("\n[fft error] y_size must be 1/2/4/8/16\n");
    264268        exit( 0 );
    265269    }
     
    277281    if( rootN < nthreads )
    278282    {
    279         printf("\n[FFT ERROR] sqrt(N) must be larger than T\n");
     283        printf("\n[fft error] sqrt(N) must be larger than T\n");
    280284        exit( 0 );
    281285    }
     
    287291    main_tid = (((main_x * y_size) + main_y) * ncores) + main_lid;
    288292
    289     printf("\n[FFT] starts on core[%x,%d] / %d complex points / %d thread(s) / PID %x\n",
     293    printf("\n[fft] starts on core[%x,%d] / %d complex points / %d thread(s) / PID %x\n",
    290294    main_cxy, main_lid, N, nthreads, getpid() );
    291295
     
    308312    }
    309313
    310     printf("\n[FFT] main completes remote_malloc\n");
     314    printf("\n[fft] main completes remote_malloc\n");
    311315
    312316    // arrays initialisation
     
    315319    InitT( twid );
    316320
    317     printf("\n[FFT] main completes arrays init\n");
     321    printf("\n[fft] main completes arrays init\n");
    318322
    319323#if CHECK
     
    335339
    336340    // initialise barrier
    337     barrierattr.x_size   = x_size;
    338     barrierattr.y_size   = y_size;
    339     barrierattr.nthreads = ncores;
    340     if( pthread_barrier_init( &barrier, &barrierattr , nthreads) )
    341     {
    342         printf("\n[FFT ERROR] cannot initialize barrier\n");
     341    if( USE_DQT_BARRIER )
     342    {
     343        barrier_attr.x_size   = x_size;
     344        barrier_attr.y_size   = y_size;
     345        barrier_attr.nthreads = ncores;
     346        error = pthread_barrier_init( &barrier, &barrier_attr , nthreads );
     347    }
     348    else
     349    {
     350        error = pthread_barrier_init( &barrier, NULL , nthreads );
     351    }
     352
     353    if( error )
     354    {
     355        printf("\n[fft error] cannot initialize barrier\n");
    343356        exit( 0 );
    344357    }
    345358
    346     printf("\n[FFT] main completes barrier init\n");
     359    printf("\n[fft] main completes barrier init\n");
    347360
    348361    // launch other threads to execute the slave() function
     
    377390                                         &args[tid]) ) // pointer on function arguments
    378391                    {
    379                         printf("\n[FFT ERROR] creating thread %x\n", tid );
     392                        printf("\n[fft error] creating thread %x\n", tid );
    380393                        exit( 0 );
    381394                    }
    382 #if DEBUG_MAIN
     395#if (DEBUG_MAIN & 1)
    383396unsigned long long debug_cycle;
    384397get_cycle( &debug_cycle );
    385 printf("\n[FFT] main created thread %x on core[%x,%d] / cycle %d\n",
     398printf("\n[fft] main created thread %d on core[%x,%d] / cycle %d\n",
    386399tid, cxy, lid, (unsigned int)debug_cycle );
    387400#endif
     
    390403        }
    391404    }
     405
    392406
    393407    // register sequencial initalisation completion cycle
     
    395409    init_time = (unsigned int)(end_init_cycle - start_init_cycle);
    396410
    397     printf("\n[FFT] main enters parallel execution\n");
     411    printf("\n[fft] main completes threads creation\n");
    398412   
    399413    // main itself executes the slave() function
     
    414428                    if( pthread_join( trdid[tid] , NULL ) )
    415429                    {
    416                         printf("\n[FFT ERROR] in main thread joining thread %x\n", tid );
     430                        printf("\n[fft error] in main thread joining thread %x\n", tid );
    417431                        exit( 0 );
    418432                    }
    419433                   
    420 #if DEBUG_MAIN
    421 printf("\n[FFT] main thread %d joined thread %d\n", main_tid, tid );
     434#if (DEBUG_MAIN & 1)
     435printf("\n[fft] main thread %d joined thread %d\n", main_tid, tid );
    422436#endif
    423437
     
    441455
    442456    // instrumentation
     457    char name[64];
     458    char path[128];
    443459    char string[256];
    444 
    445     snprintf( string , 256 , "/home/fft_%d_%d_%d_%d", x_size , y_size , ncores , N );
     460    int  ret;
     461
     462    // build file name
     463    if( USE_DQT_BARRIER )
     464    snprintf( name , 64 , "fft_dqt_%d_%d_%d_%d", x_size , y_size , ncores , N );
     465    else
     466    snprintf( name , 64 , "fft_smp_%d_%d_%d_%d", x_size , y_size , ncores , N );
     467
     468    // build pathname
     469    snprintf( path , 128 , "/home/%s", name );
    446470
    447471    // open instrumentation file
    448 //  FILE * f = fopen( string , NULL );
    449 //  if ( f == NULL )
    450 //  {
    451 //      printf("\n[FFT ERROR] cannot open instrumentation file %s\n", string );
    452 //      exit( 0 );
    453 //  }
    454 
    455     snprintf( string , 256 , "\n[FFT] instrumentation : (%dx%dx%d) threads / %d points\n",
    456     x_size, y_size, ncores , N );
    457 
    458     // display on terminal, and save to instrumentation file
    459     printf( "%s" , string );
    460 //  fprintf( f , string );
    461 
     472    FILE * f = fopen( path , NULL );
     473    if ( f == NULL )
     474    {
     475        printf("\n[fft error] cannot open instrumentation file <%s>\n", path );
     476        exit( 0 );
     477    }
     478    printf("\n[fft] file <%s> open\n", path );
     479
     480    // display header on terminal, and save to file
     481    printf("\n----- %s -----\n", name );
     482
     483    ret = fprintf( f , "\n----- %s -----\n", name );
     484    if( ret < 0 )
     485    {
     486        printf("\n[fft error] cannot write header to file <%s>\n", path );
     487        exit(0);
     488    }
     489
     490    // display results for each thread on terminal, and save to file
    462491    for (tid = 0 ; tid < nthreads ; tid++)
    463492    {
    464         snprintf( string , 256 , "\ntid %d : Init %d / Parallel %d / Sync %d\n",
     493        snprintf( string , 256 , "- tid %d : Sequencial %d / Parallel %d / Barrier %d\n",
    465494        tid, init_time, parallel_time[tid], sync_time[tid] );
    466495
    467496        // display on terminal, and save to instrumentation file
    468497        printf("%s" , string );
    469 //      fprintf( f , string );
    470     }
    471 
    472     // close instrumentation file and exit
    473 //  fclose( f );
    474                              
    475 
    476 /*
    477     long min_para = parallel_time[0];
    478     long max_para = parallel_time[0];
    479     long min_sync = sync_time[0];
    480     long max_sync = sync_time[0];
     498        fprintf( f , "%s" , string );
     499        if( ret < 0 )
     500        {
     501            printf("\n[fft error] cannot write thread %d to file <%s>\n", tid, path );
     502            exit(0);
     503        }
     504    }
     505
     506    // display MIN/MAX values on terminal and save to file
     507    unsigned int min_para = parallel_time[0];
     508    unsigned int max_para = parallel_time[0];
     509    unsigned int min_sync = sync_time[0];
     510    unsigned int max_sync = sync_time[0];
    481511
    482512    for (tid = 1 ; tid < nthreads ; tid++)
     
    488518    }
    489519
    490     snprintf( string , 256 , "\n      Init       Parallel   Barrier\n"
     520    snprintf( string , 256 , "\n      Sequencial  Parallel       Barrier\n"
    491521                             "MIN : %d\t | %d\t | %d\t   (cycles)\n"
    492522                             "MAX : %d\t | %d\t | %d\t   (cycles)\n",
    493523                             (int)init_time, (int)min_para, (int)min_sync,
    494524                             (int)init_time, (int)max_para, (int)max_sync );
    495 */
    496 
    497     pthread_exit( NULL );
     525    printf("%s", string );
     526    ret = fprintf( f , "%s", string );
     527    if( ret < 0 )
     528    {
     529        printf("\n[fft error] cannot write MIN/MAX to file <%s>\n", path );
     530        exit(0);
     531    }
     532
     533    // close instrumentation file
     534    ret = fclose( f );
     535    if( ret )
     536    {
     537        printf("\n[fft error] cannot close file <%s>\n", path );
     538        exit(0);
     539    }
     540    printf("\n[sort] file <%s> closed\n", path );
     541
     542    exit( 0 );
    498543
    499544} // end main()
     
    525570
    526571#if DEBUG_SLAVE
    527 printf("\n[FFT] %s : thread %x enter / cycle %d\n",
     572printf("\n[fft] %s : thread %x enter / cycle %d\n",
    528573__FUNCTION__, MyNum, (unsigned int)parallel_start );
    529574#endif
     
    569614
    570615#if DEBUG_SLAVE
    571 printf("\n[FFT] %s : thread %x exit / parallel_time %d / sync_time %d / cycle %d\n",
    572 __FUNCTION__, MyNum, parallel_time[MyNum], sync_time[MyNum], (unsigned int)parallel_stop );
     616printf("\n[fft] %s : thread %x exit / cycle %d\n", __FUNCTION__, MyNum, parallel_stop );
    573617#endif
    574618
     
    805849unsigned long long cycle;
    806850get_cycle( &cycle );
    807 printf("\n[FFT] %s : thread %x enter / first %d / last %d / cycle %d\n",
     851printf("\n[fft] %s : thread %x enter / first %d / last %d / cycle %d\n",
    808852__FUNCTION__, MyNum, MyFirst, MyLast, (unsigned int)cycle );
    809853#endif
     
    814858#if( DEBUG_FFT1D & 1 )
    815859get_cycle( &cycle );
    816 printf("\n[FFT] %s : thread %x after first transpose / cycle %d\n",
     860printf("\n[fft] %s : thread %x after first transpose / cycle %d\n",
    817861__FUNCTION__, MyNum, (unsigned int)cycle );
    818862if( PRINT_ARRAY ) PrintArray( tmp , N );
     
    827871#if( DEBUG_FFT1D & 1 )
    828872get_cycle( &cycle );
    829 printf("\n[FFT] %s : thread %x exit barrier after first transpose / cycle %d\n",
     873printf("\n[fft] %s : thread %x exit barrier after first transpose / cycle %d\n",
    830874__FUNCTION__, MyNum, (unsigned int)cycle );
    831875#endif
     
    840884
    841885#if( DEBUG_FFT1D & 1 )
    842 printf("\n[FFT] %s : thread %x after first twiddle\n", __FUNCTION__, MyNum);
     886printf("\n[fft] %s : thread %x after first twiddle\n", __FUNCTION__, MyNum);
    843887if( PRINT_ARRAY ) PrintArray( tmp , N );
    844888#endif
     
    850894
    851895#if( DEBUG_FFT1D & 1 )
    852 printf("\n[FFT] %s : thread %x exit barrier after first twiddle\n", __FUNCTION__, MyNum);
     896printf("\n[fft] %s : thread %x exit barrier after first twiddle\n", __FUNCTION__, MyNum);
    853897#endif
    854898
     
    859903
    860904#if( DEBUG_FFT1D & 1 )
    861 printf("\n[FFT] %s : thread %x after second transpose\n", __FUNCTION__, MyNum);
     905printf("\n[fft] %s : thread %x after second transpose\n", __FUNCTION__, MyNum);
    862906if( PRINT_ARRAY ) PrintArray( x , N );
    863907#endif
     
    869913
    870914#if( DEBUG_FFT1D & 1 )
    871 printf("\n[FFT] %s : thread %x exit barrier after second transpose\n", __FUNCTION__, MyNum);
     915printf("\n[fft] %s : thread %x exit barrier after second transpose\n", __FUNCTION__, MyNum);
    872916#endif
    873917
     
    882926
    883927#if( DEBUG_FFT1D & 1 )
    884 printf("\n[FFT] %s : thread %x after FFT on rows\n", __FUNCTION__, MyNum);
     928printf("\n[fft] %s : thread %x after FFT on rows\n", __FUNCTION__, MyNum);
    885929if( PRINT_ARRAY ) PrintArray( x , N );
    886930#endif
     
    892936
    893937#if( DEBUG_FFT1D & 1 )
    894 printf("\n[FFT] %s : thread %x exit barrier after FFT on rows\n", __FUNCTION__, MyNum);
     938printf("\n[fft] %s : thread %x exit barrier after FFT on rows\n", __FUNCTION__, MyNum);
    895939#endif
    896940    sync_time[MyNum] += (long)(barrier_stop - barrier_start);
     
    900944
    901945#if( DEBUG_FFT1D & 1 )
    902 printf("\n[FFT] %s : thread %x after third transpose\n", __FUNCTION__, MyNum);
     946printf("\n[fft] %s : thread %x after third transpose\n", __FUNCTION__, MyNum);
    903947if( PRINT_ARRAY ) PrintArray( x , N );
    904948#endif
     
    910954
    911955#if( DEBUG_FFT1D & 1 )
    912 printf("\n[FFT] %s : thread %x exit barrier after third transpose\n", __FUNCTION__, MyNum);
     956printf("\n[fft] %s : thread %x exit barrier after third transpose\n", __FUNCTION__, MyNum);
    913957#endif
    914958
     
    920964
    921965#if DEBUG_FFT1D
    922 printf("\n[FFT] %s : thread %x completed\n", __FUNCTION__, MyNum);
     966printf("\n[fft] %s : thread %x completed\n", __FUNCTION__, MyNum);
    923967if( PRINT_ARRAY ) PrintArray( x , N );
    924968#endif
     
    11111155#if DEBUG_ROW
    11121156unsigned int p;
    1113 printf("\n[FFT] ROW data in / %d points / offset = %d\n", rootN , offset_x );
     1157printf("\n[fft] ROW data in / %d points / offset = %d\n", rootN , offset_x );
    11141158
    11151159for ( p = 0 ; p < rootN ; p++ )
     
    11271171
    11281172#if DEBUG_ROW
    1129 printf("\n[FFT] ROW data after reverse / %d points / offset = %d\n", rootN , offset_x );
     1173printf("\n[fft] ROW data after reverse / %d points / offset = %d\n", rootN , offset_x );
    11301174
    11311175for ( p = 0 ; p < rootN ; p++ )
     
    11981242
    11991243#if DEBUG_ROW
    1200 printf("\n[FFT] ROW data out / %d points / offset = %d\n", rootN , offset_x );
     1244printf("\n[fft] ROW data out / %d points / offset = %d\n", rootN , offset_x );
    12011245for ( p = 0 ; p < rootN ; p++ )
    12021246{
  • trunk/user/ksh/ksh.c

    r626 r628  
    11781178#endif
    11791179
    1180 /*
    1181 // Lauch one or several commands without interactive mode
    1182 
    1183 // 1. first command
     1180
     1181/* 1. first direct command
    11841182if( sem_wait( &semaphore ) )
    11851183{
     
    11891187else
    11901188{
    1191     printf("\n[ksh] display fat 0 32\n");
     1189    printf("\n[ksh] load bin/user/sort.elf\n");
    11921190}
    11931191
    1194 strcpy( cmd , "display fat 0 32" );
     1192strcpy( cmd , "load bin/user/sort.elf" );
    11951193execute( cmd );
    1196 
    1197 // 2. second command
     1194*/
     1195
     1196
     1197
     1198/* 2. second direct command
    11981199if( sem_wait( &semaphore ) )
    11991200{
     
    12031204else
    12041205{
    1205     printf("\n[ksh] load bin/user/pgcd.elf\n");
     1206    printf("\n[ksh] rm home/fft_1_2_1_4096\n");
    12061207}
    12071208
    1208 strcpy( cmd , "load bin/user/pgcd.elf" );
     1209strcpy( cmd , "rm home/fft_1_2_1_4096" );
    12091210execute( cmd );
    1210 
    1211 // end non-interactive mode
    12121211*/
     1212
     1213
    12131214
    12141215        enum fsm_states
  • trunk/user/sort/sort.c

    r627 r628  
    2929#include <hal_macros.h>
    3030
    31 #define ARRAY_LENGTH        4096       // number of items
     31#define ARRAY_LENGTH        1024       // number of items
    3232#define MAX_THREADS         1024       // 16 * 16 * 4
    3333
     
    3535#define DISPLAY_ARRAY       0          // display items values before and after
    3636#define DEBUG_MAIN          1          // trace main function
    37 #define DEBUG_SORT          0          // trace sort function
     37#define DEBUG_SORT          1          // trace sort function
    3838#define INTERACTIVE_MODE    0          // activate idbg() during instrumentation
    3939#define CHECK_RESULT        0          // for debug
     
    337337
    338338#if DEBUG_MAIN
    339 printf("\n[sort] main completes barrier init\n");
     339if( USE_DQT_BARRIER ) printf("\n[sort] main completes DQT barrier init\n");
     340else                  printf("\n[sort] main completes simple barrier init\n");
    340341#endif
    341342
Note: See TracChangeset for help on using the changeset viewer.