Changeset 651


Ignore:
Timestamp:
Nov 14, 2019, 11:50:09 AM (2 years ago)
Author:
alain
Message:

1) Improve the VMM MMAP allocator: implement the "buddy" algorithm
to allocate only aligned blocks.
2) fix a bug in the pthread_join() / pthread_exit() mmechanism.

Location:
trunk/kernel
Files:
26 edited

Legend:

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

    r647 r651  
    937937    uint32_t       new;
    938938
    939 // check argument
     939// check arguments
    940940assert( (file_xp != XPTR_NULL) , "file_xp == XPTR_NULL" );
     941assert( (new_offset != NULL )  , "new_offset == NULL" );
    941942
    942943    // get cluster and local pointer on remote file descriptor
     
    991992
    992993    // success
    993     if ( new_offset != NULL ) *new_offset = new;
     994    *new_offset = new;
    994995    return 0;
    995996
  • trunk/kernel/kern/kernel_init.c

    r647 r651  
    929929///////////////////////////////////////////////////////////////////////////////////////////
    930930// This function is the entry point for the kernel initialisation.
    931 // It is executed by all cores in all clusters, but only core[0] initializes
     931// It is executed by all cores in all clusters, but only core[cxy][0] initializes
    932932// the shared resources such as the cluster manager, or the local peripherals.
    933933// To comply with the multi-kernels paradigm, it accesses only local cluster memory, using
     
    10171017    /////////////////////////////////////////////////////////////////////////////////
    10181018
    1019     // core[0] initialises DQDT (only core[0] in cluster 0 build the quad-tree)
     1019    // core[0] initialises DQDT (only core[0][0] build the quad-tree)
    10201020    if( core_lid == 0 ) dqdt_init();
    10211021   
  • trunk/kernel/kern/process.c

    r637 r651  
    916916            {
    917917                // mark target thread for delete and block it
    918                 thread_delete( target_xp , process->pid , false );   // not forced
     918                thread_delete( target_xp , true );                   // forced
    919919            }
    920920        }
     
    18021802    // allocates memory for process descriptor from local cluster
    18031803        process = process_alloc();
    1804 
    1805 
    18061804    if( process == NULL )
    18071805    {
  • trunk/kernel/kern/process.h

    r635 r651  
    122122typedef struct process_s
    123123{
    124         vmm_t              vmm;              /*! embedded virtual memory manager                 */
    125 
    126         fd_array_t         fd_array;         /*! embedded open file descriptors array            */
    127 
    128         xptr_t             vfs_root_xp;      /*! extended pointer on VFS root inode              */
    129         xptr_t             vfs_bin_xp;       /*! extended pointer on .elf file descriptor        */
    130         pid_t              pid;              /*! process identifier                              */
     124    vmm_t              vmm;              /*! embedded virtual memory manager                 */
     125
     126    fd_array_t         fd_array;         /*! embedded open file descriptors array            */
     127
     128    xptr_t             vfs_root_xp;      /*! extended pointer on VFS root inode              */
     129    xptr_t             vfs_bin_xp;       /*! extended pointer on .elf file descriptor        */
     130    pid_t              pid;              /*! process identifier                              */
    131131    xptr_t             ref_xp;           /*! extended pointer on reference process           */
    132132    xptr_t             owner_xp;         /*! extended pointer on owner process               */
    133133    xptr_t             parent_xp;        /*! extended pointer on parent process              */
    134134
    135         xptr_t             cwd_xp;           /*! extended pointer on current working dir inode   */
    136         remote_busylock_t  cwd_lock;         /*! lock protecting working directory changes       */
    137 
    138         xlist_entry_t      children_root;    /*! root of the children process xlist              */
     135    xptr_t             cwd_xp;           /*! extended pointer on current working dir inode   */
     136    remote_busylock_t  cwd_lock;         /*! lock protecting working directory changes       */
     137
     138    xlist_entry_t      children_root;    /*! root of the children process xlist              */
    139139    remote_queuelock_t children_lock;    /*! lock protecting children process xlist          */
    140140    uint32_t           children_nr;      /*! number of children processes                    */
    141141
    142         xlist_entry_t      children_list;    /*! member of list of children of same parent       */
     142    xlist_entry_t      children_list;    /*! member of list of children of same parent       */
    143143    xlist_entry_t      local_list;       /*! member of list of process in same cluster       */
    144144    xlist_entry_t      copies_list;      /*! member of list of copies of same process        */
    145145    xlist_entry_t      txt_list;         /*! member of list of processes sharing same TXT    */
    146146
    147         struct thread_s  * th_tbl[CONFIG_THREADS_MAX_PER_CLUSTER];       /*! local threads       */
    148 
    149         uint32_t           th_nr;            /*! number of threads in this cluster               */
     147    struct thread_s  * th_tbl[CONFIG_THREADS_MAX_PER_CLUSTER];       /*! local threads       */
     148
     149    uint32_t           th_nr;            /*! number of threads in this cluster               */
    150150    rwlock_t           th_lock;          /*! lock protecting th_tbl[]  i                     */
    151151
  • trunk/kernel/kern/scheduler.c

    r641 r651  
    493493#endif
    494494
    495 // This assert should never be false, as this check has been
     495// This assert should always be true, as this check has been
    496496// done before, by any function that can possibly deschedule...
    497497assert( (current->busylocks == 0),
    498 "unexpected descheduling of thread holding %d busylocks = %d\n", current->busylocks );
     498"current thread hold %d busylocks\n", current->busylocks );
    499499
    500500    // activate or create an RPC thread if RPC_FIFO non empty
     
    514514"kernel stack overflow for thread %x on core[%x,%d]", next, local_cxy, lid );
    515515
    516 // check next thread attached to same core as the calling thread
     516// check next thread attached to same core as the current thread
    517517assert( (next->core == current->core),
    518 "next core %x != current core %x", next->core, current->core );
    519 
     518"next_core_lid %d / current_core_lid %d", current->core->lid, next->core->lid );
     519   
    520520// check next thread not blocked when type != IDLE
    521521assert( ((next->blocked == 0) || (next->type == THREAD_IDLE)) ,
  • trunk/kernel/kern/thread.c

    r647 r651  
    673673uint32_t cycle = (uint32_t)hal_get_cycles();
    674674if( DEBUG_THREAD_USER_EXEC < cycle )
    675 printk("\n[%s] thread[%x,%x] enter / cycle %d\n",
    676 __FUNCTION__, process->pid, thread->trdid, cycle );
     675printk("\n[%s] thread[%x,%x] enter / entry %x / cycle %d\n",
     676__FUNCTION__, process->pid, thread->trdid, entry_func , cycle );
    677677#endif
    678678
     
    11051105//////////////////////////////////////
    11061106void thread_delete( xptr_t  target_xp,
    1107                     pid_t   pid,
    11081107                    bool_t  is_forced )
    11091108{
     
    11151114    cxy_t       target_cxy;             // target thread cluster     
    11161115    thread_t  * target_ptr;             // pointer on target thread
    1117     process_t * target_process;         // pointer on arget process
     1116    process_t * target_process;         // pointer on target process
    11181117    pid_t       target_pid;             // target process identifier
    11191118    xptr_t      target_flags_xp;        // extended pointer on target thread <flags>
     
    11221121    trdid_t     target_trdid;           // target thread identifier
    11231122    ltid_t      target_ltid;            // target thread local index
     1123    uint32_t    target_flags;           // target thread flags
    11241124    xptr_t      joining_xp;             // extended pointer on joining thread
     1125    thread_t  * joining_ptr;            // local pointer on joining thread
     1126    cxy_t       joining_cxy;            // joining thread cluster
    11251127
    11261128    // get target thread cluster and local pointer
     
    11281130    target_ptr      = GET_PTR( target_xp );
    11291131
    1130     // get target thread identifier, attached flag, and process PID
     1132    // get target thread trdid, ltid, flags, and process PID
    11311133    target_trdid    = hal_remote_l32( XPTR( target_cxy , &target_ptr->trdid ) );
    11321134    target_ltid     = LTID_FROM_TRDID( target_trdid );
    1133     target_flags_xp = XPTR( target_cxy , &target_ptr->flags ); 
    1134     target_attached = ( (hal_remote_l32( target_flags_xp ) & THREAD_FLAG_DETACHED) == 0 );
     1135    target_flags_xp = XPTR( target_cxy , &target_ptr->flags );
     1136    target_flags    = hal_remote_l32( target_flags_xp );
    11351137    target_process  = hal_remote_lpt( XPTR( target_cxy , &target_ptr->process ) );
    11361138    target_pid      = hal_remote_l32( XPTR( target_cxy , &target_process->pid ) );
    1137 
    1138 // check target PID
    1139 assert( (pid == target_pid),
    1140 "unconsistent pid and target_xp arguments" );
     1139    target_attached = ((target_flags & THREAD_FLAG_DETACHED) == 0);
    11411140
    11421141    // get killer thread pointers
     
    11471146uint32_t cycle  = (uint32_t)hal_get_cycles();
    11481147if( DEBUG_THREAD_DELETE < cycle )
    1149 printk("\n[%s] killer[%x,%x] enters / target[%x,%x] / cycle %d\n",
     1148printk("\n[%s] killer[%x,%x] enters / target[%x,%x] / forced %d / flags %x / cycle %d\n",
    11501149__FUNCTION__, killer_ptr->process->pid, killer_ptr->trdid, 
    1151 target_ptr->process->pid, target_ptr->trdid, cycle );
     1150target_pid, target_trdid, is_forced, target_flags, cycle );
    11521151#endif
    11531152
    11541153// check target thread is not the main thread, because the main thread
    11551154// must be deleted by the parent process sys_wait() function
    1156 assert( ((CXY_FROM_PID( pid ) != target_cxy) || (target_ltid != 0)),
     1155assert( ((CXY_FROM_PID( target_pid ) != target_cxy) || (target_ltid != 0)),
    11571156"target thread cannot be the main thread" );
    11581157
     
    11821181            // get extended pointer on joining thread
    11831182            joining_xp  = (xptr_t)hal_remote_l64( target_join_xp_xp );
     1183
     1184            // get cluster and local pointer on joining thread
     1185            joining_ptr = GET_PTR( joining_xp );
     1186            joining_cxy = GET_CXY( joining_xp );
     1187
     1188            // copy exit_status from target thread to joining thread, because
     1189            // target thread may be deleted before joining thread resume
     1190            void * status = hal_remote_lpt( XPTR( target_cxy , &target_ptr->exit_status ) );
     1191            hal_remote_spt( XPTR( joining_cxy , &joining_ptr->exit_status ) , status );
    11841192           
    11851193            // reset the join_done flag in target thread
     
    12021210
    12031211#if DEBUG_THREAD_DELETE
    1204 cycle  = (uint32_t)hal_get_cycles;
     1212cycle  = (uint32_t)hal_get_cycles();
    12051213if( DEBUG_THREAD_DELETE < cycle )
    12061214printk("\n[%s] killer[%x,%x] exit / target[%x,%x] marked after join / cycle %d\n",
    12071215__FUNCTION__, killer_ptr->process->pid, killer_ptr->trdid,
    1208 target_ptr->process->pid, target_ptr->trdid, cycle );
     1216target_pid, target_trdid, cycle );
    12091217#endif
    12101218
     
    12151223            hal_remote_atomic_or( target_flags_xp , THREAD_FLAG_KILL_DONE );
    12161224
    1217             // block this thread on BLOCKED_JOIN
     1225            // block target thread on BLOCKED_JOIN
    12181226            thread_block( killer_xp , THREAD_BLOCKED_JOIN );
    12191227
     
    12251233
    12261234#if DEBUG_THREAD_DELETE
    1227 cycle  = (uint32_t)hal_get_cycles;
     1235cycle  = (uint32_t)hal_get_cycles();
    12281236if( DEBUG_THREAD_DELETE < cycle )
    12291237printk("\n[%s] killer[%x,%x] deschedules / target[%x,%x] not completed / cycle %d\n",
    12301238__FUNCTION__, killer_ptr->process->pid, killer_ptr->trdid,
    1231 target_ptr->process->pid, target_ptr->trdid, cycle );
     1239target_pid, target_trdid, cycle );
    12321240#endif
    12331241            // deschedule
     
    12441252
    12451253#if DEBUG_THREAD_DELETE
    1246 cycle  = (uint32_t)hal_get_cycles;
     1254cycle  = (uint32_t)hal_get_cycles();
    12471255if( DEBUG_THREAD_DELETE < cycle )
    12481256printk("\n[%s] killer[%x,%x] exit / target[%x,%x] marked after join / cycle %d\n",
    12491257__FUNCTION__, killer_ptr->process->pid, killer_ptr->trdid,
    1250 target_ptr->process->pid, target_ptr->trdid, cycle );
     1258target_pid, target_trdid, cycle );
    12511259#endif
    12521260
     
    12621270
    12631271#if DEBUG_THREAD_DELETE
    1264 cycle  = (uint32_t)hal_get_cycles;
     1272cycle  = (uint32_t)hal_get_cycles();
    12651273if( DEBUG_THREAD_DELETE < cycle )
    12661274printk("\n[%s] killer[%x,%x] exit / target [%x,%x] marked / no join / cycle %d\n",
    12671275__FUNCTION__, killer_ptr->process->pid, killer_ptr->trdid,
    1268 target_ptr->process->pid, target_ptr->trdid, cycle );
     1276target_pid, target_trdid, cycle );
    12691277#endif
    12701278
  • trunk/kernel/kern/thread.h

    r647 r651  
    153153    remote_busylock_t   join_lock;       /*! lock protecting the join/exit            */
    154154    xptr_t              join_xp;         /*! joining/killer thread extended pointer   */
     155    void              * exit_status;     /*! status returned to joiniy thread        */
    155156
    156157    uint32_t          * ack_rsp_count;   /*! pointer on acknowledge response counter  */
     
    392393 ***************************************************************************************
    393394 * @ thread_xp   : extended pointer on the target thread.
    394  * @ pid         : process identifier (to get the owner cluster identifier).
    395395 * @ is_forced   : the deletion does not depends on the attached mode.
    396396 **************************************************************************************/
    397397void thread_delete( xptr_t  thread_xp,
    398                     pid_t   pid,
    399398                    bool_t  is_forced );
    400399
  • trunk/kernel/kernel_config.h

    r647 r651  
    5656#define DEBUG_DEV_NIC_RX                  0
    5757#define DEBUG_DEV_NIC_RX                  0
    58 #define DEBUG_DEV_FBF                        1
     58#define DEBUG_DEV_FBF                     0
    5959#define DEBUG_DEV_DMA                     0
    6060#define DEBUG_DEV_MMC                     0
     
    9090#define DEBUG_FATFS_UPDATE_IOC            0
    9191
    92 #define DEBUG_HAL_CONTEXT                 0
     92#define DEBUG_HAL_CONTEXT_FORK            0
     93#define DEBUG_HAL_CONTEXT_INIT            0
    9394#define DEBUG_HAL_EXCEPTIONS              0
    9495#define DEBUG_HAL_GPT_COPY                0
     
    104105#define DEBUG_HAL_TXT_RX                  0
    105106#define DEBUG_HAL_TXT_TX                  0
    106 #define DEBUG_HAL_FBF                        1
     107#define DEBUG_HAL_FBF                     0
    107108#define DEBUG_HAL_USPACE                  0
    108109#define DEBUG_HAL_VMM                     0
     
    134135#define DEBUG_PROCESS_GET_LOCAL_COPY      0
    135136#define DEBUG_PROCESS_INIT_CREATE         0
    136 #define DEBUG_PROCESS_MAKE_EXEC              1
    137 #define DEBUG_PROCESS_MAKE_FORK              1
     137#define DEBUG_PROCESS_MAKE_EXEC           0
     138#define DEBUG_PROCESS_MAKE_FORK           0
    138139#define DEBUG_PROCESS_REFERENCE_INIT      0
    139140#define DEBUG_PROCESS_SIGACTION           0
     
    177178#define DEBUG_SEM                         0
    178179
    179 #define DEBUG_SYSCALLS_ERROR                  2
     180#define DEBUG_SYSCALLS_ERROR                 2
    180181
    181182#define DEBUG_SYS_BARRIER                 0
     
    184185#define DEBUG_SYS_CONDVAR                 0
    185186#define DEBUG_SYS_DISPLAY                 0
    186 #define DEBUG_SYS_EXEC                       2
     187#define DEBUG_SYS_EXEC                    0
    187188#define DEBUG_SYS_EXIT                    0
    188189#define DEBUG_SYS_FBF                     0
    189190#define DEBUG_SYS_FG                      0
    190 #define DEBUG_SYS_FORK                       2
     191#define DEBUG_SYS_FORK                    0
    191192#define DEBUG_SYS_GET_CONFIG              0
    192193#define DEBUG_SYS_GETCWD                  0
     
    199200#define DEBUG_SYS_IS_FG                   0
    200201#define DEBUG_SYS_KILL                    0
     202#define DEBUG_SYS_LSEEK                   0
    201203#define DEBUG_SYS_MKDIR                   0
    202204#define DEBUG_SYS_MMAP                    0
     
    264266#define DEBUG_VMM_HANDLE_PAGE_FAULT       0
    265267#define DEBUG_VMM_HANDLE_COW              0
    266 #define DEBUG_VMM_MMAP_ALLOC              0
     268#define DEBUG_VMM_MMAP                    0
    267269#define DEBUG_VMM_PAGE_ALLOCATE           0
    268270#define DEBUG_VMM_REMOVE_VSEG             0
     
    326328////////////////////////////////////////////////////////////////////////////////////////////
    327329
    328 #define CONFIG_VERSION           "Version 2.2 / June 2019"
     330#define CONFIG_VERSION           "Version 2.3 / November 2019"
    329331
    330332////////////////////////////////////////////////////////////////////////////////////////////
     
    431433
    432434////////////////////////////////////////////////////////////////////////////////////////////
    433 //             32 bits  USER SPACE SEGMENTATION / all values are numbers of pages
     435//       32 bits  USER SPACE SEGMENTATION / all bases and sizes are numbers of pages
    434436////////////////////////////////////////////////////////////////////////////////////////////
    435437
     
    438440#define CONFIG_VMM_UTILS_BASE         0x000200     // UTILS zone base        : 2   Mbytes
    439441#define CONFIG_VMM_ELF_BASE           0x000400     // ELF zone base          : 4   Mbytes
    440 #define CONFIG_VMM_HEAP_BASE          0x002000     // HEAP zone base         : 32  Mbytes
     442#define CONFIG_VMM_HEAP_BASE          0x040000     // HEAP zone base         : 32  Mbytes
    441443#define CONFIG_VMM_STACK_BASE         0x0C0000     // STACK zone base        : 3   Gbytes
    442444
     
    445447#define CONFIG_VMM_STACK_SIZE         0x001000     // single stack vseg size : 16  Mbytes
    446448
     449#define CONFIG_VMM_HEAP_MAX_ORDER     18           // max size of MMAP vseg  :  1  Gbytes
    447450////////////////////////////////////////////////////////////////////////////////////////////
    448451//                      PHYSICAL MEMORY MANAGEMENT         
     
    463466
    464467#define CONFIG_INSTRUMENTATION_SYSCALLS    0
    465 #define CONFIG_INSTRUMENTATION_PGFAULTS    1
     468#define CONFIG_INSTRUMENTATION_PGFAULTS    0
    466469#define CONFIG_INSTRUMENTATION_FOOTPRINT   0
    467 #define CONFIG_INSTRUMENTATION_GPT         1
     470#define CONFIG_INSTRUMENTATION_GPT         0
    468471
    469472
  • trunk/kernel/libk/elf.c

    r635 r651  
    216216                          process_t * process )
    217217{
     218    uint32_t     new_offset;       // unused, required by vfs_lseek()
    218219        kmem_req_t   req;              // kmem request for program header
    219220        Elf_Ehdr     header;           // local buffer for .elf header
     
    274275
    275276        // set seek pointer in file descriptor to access segment descriptors array
    276         error = vfs_lseek( file_xp , header.e_phoff, SEEK_SET , NULL );
     277        error = vfs_lseek( file_xp , header.e_phoff, SEEK_SET , &new_offset );
    277278
    278279        if( error )
  • trunk/kernel/libk/list.h

    r636 r651  
    6161
    6262/***************************************************************************
    63  * This macro return an uint32_t that is the offset (number of bytes)
     63 * This macro return an intptr_t that is the offset (number of bytes)
    6464 * of a field in a structure.
     65 ***************************************************************************
    6566 * @ type   : structure type
    6667 * @ member : name of the field
  • trunk/kernel/libk/user_dir.h

    r635 r651  
    3737 * - An user process open a directory by calling the "opendir()" syscall.
    3838 *   The user_dir_create() function allocates physical memory to create in the cluster
    39  *   containing the target inode one or several physical pages to implement an array
    40  *   of "dirent", mapped in the user process space as an ANON vseg. It allocates also
    41  *   an "user_dir_t" descriptor structure defined below, registered in the xlist rooted
    42  *   in the reference user process descriptor.
     39 *   containing the directory inode one or several physical pages to implement an array
     40 *   of "dirent". This array is mapped in the user process space as an ANON vseg.
     41 *   It allocates also an "user_dir_t" descriptor structure defined below, registered
     42 *   in the xlist rooted in the reference user process descriptor.
    4343 * - This "user_dir_t" structure contains the total number of "entries", the "current"
    4444 *   pointer used by the readdir() syscall, and an "ident" field, that is actually
     
    104104 * structures rooted in the reference process descriptor, release all memory
    105105 * allocated for the user_dir_t struct in the directory inode cluster, including
    106  * the dirent array, and delete all ANON vseg copies in all process VMM copies,
     106 * the dirent array, and delete the ANON vseg copies in all process VMM copies,
    107107 * using parallel RPCs.
    108108 * It must be executed by a thread running in the cluster containing the target inode.
  • trunk/kernel/mm/mapper.c

    r637 r651  
    442442        if ( page_xp == XPTR_NULL ) return -1;
    443443
    444         // compute extended pointer in kernel mapper
     444        // compute extended pointer on kernel mapper
    445445        xptr_t     map_xp  = ppm_page2base( page_xp ) + page_offset;
    446446
     
    448448if( DEBUG_MAPPER_MOVE_USER < cycle )
    449449printk("\n[%s] thread[%x,%x] : get buffer(%x,%x) in mapper\n",
    450 __FUNCTION__, this->process->pid, this->trdid, map_cxy, map_ptr );
     450__FUNCTION__, this->process->pid, this->trdid, GET_CXY(map_xp), GET_PTR(map_xp) );
    451451#endif
    452452        // compute pointer in user buffer
  • trunk/kernel/mm/ppm.c

    r637 r651  
    296296                current_size >>= 1;
    297297
    298         // update order fiels in new free block
     298        // update order fields in new free block
    299299                current_block = found_block + current_size;
    300300                current_block->order = current_order;
  • trunk/kernel/mm/vmm.c

    r641 r651  
    5555
    5656////////////////////////////////////////////////////////////////////////////////////////////
     57// This static function is called by the vmm_user_init() function.
     58// It initialises the free lists of vsegs used by the VMM MMAP allocator.
     59// It makes the assumption that HEAP_BASE == 1 Gbytes and HEAP_SIZE == 2 Gbytes.
     60////////////////////////////////////////////////////////////////////////////////////////////
     61static void vmm_stack_init( vmm_t * vmm )
     62{
     63
     64// check STACK zone
     65assert( ((CONFIG_VMM_STACK_SIZE * CONFIG_THREADS_MAX_PER_CLUSTER) <=
     66(CONFIG_VMM_VSPACE_SIZE - CONFIG_VMM_STACK_BASE)) , "STACK zone too small\n");
     67
     68    // get pointer on STACK allocator
     69    stack_mgr_t * mgr = &vmm->stack_mgr;
     70
     71    mgr->bitmap   = 0;
     72    mgr->vpn_base = CONFIG_VMM_STACK_BASE;
     73    busylock_init( &mgr->lock , LOCK_VMM_STACK );
     74
     75}
     76
     77////////////////////////////////////////////////////////////////////////////////////////////
    5778// This static function is called by the vmm_create_vseg() function, and implements
    58 // the VMM STACK specific allocator.
     79// the VMM STACK specific allocator. Depending on the local thread index <ltid>,
     80// it ckeks availability of the corresponding slot in the process STACKS region,
     81// allocates a vseg descriptor, and initializes the "vpn_base" and "vpn_size" fields.
    5982////////////////////////////////////////////////////////////////////////////////////////////
    6083// @ vmm      : [in]  pointer on VMM.
    6184// @ ltid     : [in]  requested slot == local user thread identifier.
    62 // @ vpn_base : [out] first allocated page
    63 // @ vpn_size : [out] number of allocated pages
    6485////////////////////////////////////////////////////////////////////////////////////////////
    65 static void vmm_stack_alloc( vmm_t  * vmm,
    66                              ltid_t   ltid,
    67                              vpn_t  * vpn_base,
    68                              vpn_t  * vpn_size )
     86static vseg_t * vmm_stack_alloc( vmm_t  * vmm,
     87                                 ltid_t   ltid )
    6988{
    7089
     
    7695    stack_mgr_t * mgr = &vmm->stack_mgr;
    7796
    78     // get lock on stack allocator
     97    // get lock protecting stack allocator
    7998    busylock_acquire( &mgr->lock );
    8099
     
    83102"slot index %d already allocated", ltid );
    84103
     104    // allocate a vseg descriptor
     105    vseg_t * vseg = vseg_alloc();
     106
     107    if( vseg == NULL )
     108        {
     109        // release lock protecting free lists
     110        busylock_release( &mgr->lock );
     111
     112        printk("\n[ERROR] %s cannot allocate memory for vseg in cluster %x\n",
     113        __FUNCTION__ , local_cxy );
     114
     115        return NULL;
     116    }
     117
    85118    // update bitmap
    86119    bitmap_set( &mgr->bitmap , ltid );
     
    89122    busylock_release( &mgr->lock );
    90123
    91     // returns vpn_base, vpn_size (first page non allocated)
    92     *vpn_base = mgr->vpn_base + ltid * CONFIG_VMM_STACK_SIZE + 1;
    93     *vpn_size = CONFIG_VMM_STACK_SIZE - 1;
     124    // set "vpn_base" & "vpn_size" fields (first page non allocated)
     125    vseg->vpn_base = mgr->vpn_base + (ltid * CONFIG_VMM_STACK_SIZE) + 1;
     126    vseg->vpn_size = CONFIG_VMM_STACK_SIZE - 1;
     127
     128    return vseg;
    94129
    95130} // end vmm_stack_alloc()
     
    98133// This static function is called by the vmm_remove_vseg() function, and implements
    99134// the VMM STACK specific desallocator.
     135// It updates the bitmap to release the corresponding slot in the process STACKS region,
     136// and releases memory allocated to vseg descriptor.
    100137////////////////////////////////////////////////////////////////////////////////////////////
    101138// @ vmm      : [in] pointer on VMM.
     
    128165    busylock_release( &mgr->lock );
    129166
     167    // release memory allocated to vseg descriptor
     168    vseg_free( vseg );
     169
    130170}  // end vmm_stack_free()
     171
     172
     173
     174////////////////////////////////////////////////////////////////////////////////////////////
     175// This function display the current state of the VMM MMAP allocator of a process VMM
     176// identified by the <vmm> argument.
     177////////////////////////////////////////////////////////////////////////////////////////////
     178void vmm_mmap_display( vmm_t * vmm )
     179{
     180    uint32_t  order;
     181    xptr_t    root_xp;
     182    xptr_t    iter_xp;
     183
     184    // get pointer on process
     185    process_t * process = (process_t *)(((char*)vmm) - OFFSETOF( process_t , vmm ));
     186
     187    // get process PID
     188    pid_t pid = process->pid;
     189
     190    // get pointer on VMM MMAP allocator
     191    mmap_mgr_t * mgr = &vmm->mmap_mgr;
     192
     193    // display header
     194    printk("***** VMM MMAP allocator / process %x *****\n", pid );
     195
     196    // scan the array of free lists of vsegs
     197    for( order = 0 ; order <= CONFIG_VMM_HEAP_MAX_ORDER ; order++ )
     198    {
     199        root_xp = XPTR( local_cxy , &mgr->free_list_root[order] );
     200
     201        if( !xlist_is_empty( root_xp ) )
     202        {
     203            printk(" - %d (%x pages) : ", order , 1<<order );
     204
     205            XLIST_FOREACH( root_xp , iter_xp )
     206            {
     207                xptr_t   vseg_xp = XLIST_ELEMENT( iter_xp , vseg_t , xlist );
     208                vseg_t * vseg    = GET_PTR( vseg_xp );
     209
     210                printk("%x | ", vseg->vpn_base );
     211            }
     212
     213            printk("\n");
     214        }
     215    }
     216}  // end vmm_mmap_display()
     217
     218////////////////////////////////////////////////////////////////////////////////////////////
     219// This static function is called by the vmm_user_init() function.
     220// It initialises the free lists of vsegs used by the VMM MMAP allocator.
     221// TODO this function is only valid for 32 bits cores, and makes three assumptions:
     222// HEAP_BASE == 1 Gbytes / HEAP_SIZE == 2 Gbytes / MMAP_MAX_SIZE == 1 Gbytes
     223////////////////////////////////////////////////////////////////////////////////////////////
     224void vmm_mmap_init( vmm_t * vmm )
     225{
     226
     227// check HEAP base and size
     228assert( (CONFIG_VMM_HEAP_BASE == 0x40000) & (CONFIG_VMM_STACK_BASE == 0xc0000),
     229"CONFIG_VMM_HEAP_BASE != 0x40000 or CONFIG_VMM_STACK_BASE != 0xc0000" );
     230
     231// check  MMAP vseg max order
     232assert( (CONFIG_VMM_HEAP_MAX_ORDER == 18), "max mmap vseg size is 256K pages" );
     233
     234    // get pointer on MMAP allocator
     235    mmap_mgr_t * mgr = &vmm->mmap_mgr;
     236
     237    // initialize HEAP base and size
     238    mgr->vpn_base        = CONFIG_VMM_HEAP_BASE;
     239    mgr->vpn_size        = CONFIG_VMM_STACK_BASE - CONFIG_VMM_HEAP_BASE;
     240
     241    // initialize lock
     242    busylock_init( &mgr->lock , LOCK_VMM_MMAP );
     243
     244    // initialize free lists
     245    uint32_t   i;
     246    for( i = 0 ; i <= CONFIG_VMM_HEAP_MAX_ORDER ; i++ )
     247    {
     248        xlist_root_init( XPTR( local_cxy , &mgr->free_list_root[i] ) );
     249    }
     250
     251    // allocate and register first 1 Gbytes vseg
     252    vseg_t * vseg0 = vseg_alloc();
     253
     254assert( (vseg0 != NULL) , "cannot allocate vseg" );
     255
     256    vseg0->vpn_base = CONFIG_VMM_HEAP_BASE;
     257    vseg0->vpn_size = CONFIG_VMM_HEAP_BASE;
     258
     259    xlist_add_first( XPTR( local_cxy , &mgr->free_list_root[CONFIG_VMM_HEAP_MAX_ORDER] ),
     260                     XPTR( local_cxy , &vseg0->xlist ) );
     261
     262    // allocate and register second 1 Gbytes vseg
     263    vseg_t * vseg1 = vseg_alloc();
     264
     265assert( (vseg1 != NULL) , "cannot allocate vseg" );
     266
     267    vseg1->vpn_base = CONFIG_VMM_HEAP_BASE << 1;
     268    vseg1->vpn_size = CONFIG_VMM_HEAP_BASE;
     269
     270    xlist_add_first( XPTR( local_cxy , &mgr->free_list_root[CONFIG_VMM_HEAP_MAX_ORDER] ),
     271                     XPTR( local_cxy , &vseg1->xlist ) );
     272
     273#if DEBUG_VMM_MMAP
     274thread_t * this = CURRENT_THREAD;
     275uint32_t cycle = (uint32_t)hal_get_cycles();
     276printk("\n[%s] thread[%x,%x] / cycle %d\n",
     277__FUNCTION__, this->process->pid, this->trdid, cycle );
     278vmm_mmap_display( vmm );
     279#endif
     280
     281}  // end vmm_mmap_init()
    131282
    132283////////////////////////////////////////////////////////////////////////////////////////////
    133284// This static function is called by the vmm_create_vseg() function, and implements
    134 // the VMM MMAP specific allocator.
     285// the VMM MMAP specific allocator.  Depending on the requested number of pages <npages>,
     286// it get a free vseg from the relevant free_list, and initializes the "vpn_base" and
     287// "vpn_size" fields.
    135288////////////////////////////////////////////////////////////////////////////////////////////
    136289// @ vmm      : [in] pointer on VMM.
    137290// @ npages   : [in] requested number of pages.
    138 // @ vpn_base : [out] first allocated page.
    139 // @ vpn_size : [out] actual number of allocated pages.
     291// @ returns local pointer on vseg if success / returns NULL if failure.
    140292////////////////////////////////////////////////////////////////////////////////////////////
    141 static error_t vmm_mmap_alloc( vmm_t * vmm,
    142                                vpn_t   npages,
    143                                vpn_t * vpn_base,
    144                                vpn_t * vpn_size )
     293static vseg_t * vmm_mmap_alloc( vmm_t * vmm,
     294                                vpn_t   npages )
    145295{
    146     uint32_t   order;
    147     xptr_t     vseg_xp;
    148     vseg_t   * vseg;
    149     vpn_t      base;
    150     vpn_t      size;
    151     vpn_t      free;
    152 
    153 #if DEBUG_VMM_MMAP_ALLOC
     296
     297#if DEBUG_VMM_MMAP
    154298thread_t * this = CURRENT_THREAD;
    155299uint32_t cycle = (uint32_t)hal_get_cycles();
    156 if( DEBUG_VMM_MMAP_ALLOC < cycle )
    157 printk("\n[%s] thread[%x,%x] enter / cycle %d\n",
    158 __FUNCTION__, this->process->pid, this->trdid, cycle );
     300if( DEBUG_VMM_MMAP < cycle )
     301printk("\n[%s] thread[%x,%x] for %x pages / cycle %d\n",
     302__FUNCTION__, this->process->pid, this->trdid, npages, cycle );
    159303#endif
    160304
    161305    // number of allocated pages must be power of 2
    162306    // compute actual size and order
    163     size = POW2_ROUNDUP( npages );
    164     order = bits_log2( size );
     307    vpn_t    required_vpn_size = POW2_ROUNDUP( npages );
     308    uint32_t required_order    = bits_log2( required_vpn_size );
    165309
    166310    // get mmap allocator pointer
    167311    mmap_mgr_t * mgr = &vmm->mmap_mgr;
    168312
    169     // build extended pointer on root of zombi_list[order]
    170     xptr_t root_xp = XPTR( local_cxy , &mgr->zombi_list[order] );
    171 
    172     // take lock protecting zombi_lists
     313    // take lock protecting free lists in MMAP allocator
    173314    busylock_acquire( &mgr->lock );
    174315
    175     // get vseg from zombi_list or from mmap zone
    176     if( xlist_is_empty( root_xp ) )                   // from mmap zone
    177     {
    178         // check overflow
    179         free = mgr->first_free_vpn;
    180         if( (free + size) > mgr->vpn_size ) return -1;
    181 
    182         // update MMAP allocator
    183         mgr->first_free_vpn += size;
    184 
    185         // compute base
    186         base = free;
    187     }
    188     else                                              // from zombi_list
    189     {
    190         // get pointer on zombi vseg from zombi_list
    191         vseg_xp = XLIST_FIRST( root_xp , vseg_t , xlist );
    192         vseg    = GET_PTR( vseg_xp );
    193 
    194         // remove vseg from free-list
    195         xlist_unlink( XPTR( local_cxy , &vseg->xlist ) );
    196 
    197         // compute base
    198         base = vseg->vpn_base;
    199     }
    200 
    201     // release lock
    202     busylock_release( &mgr->lock );
    203 
    204 #if DEBUG_VMM_MMAP_ALLOC
    205 cycle = (uint32_t)hal_get_cycles();
    206 if( DEBUG_VMM_DESTROY < cycle )
    207 printk("\n[%s] thread[%x,%x] exit / vpn_base %x / vpn_size %x / cycle %d\n",
    208 __FUNCTION__, this->process->pid, this->trdid, base, size, cycle );
    209 #endif
    210 
    211     // returns vpn_base, vpn_size
    212     *vpn_base = base;
    213     *vpn_size = size;
    214     return 0;
     316    // initialises the while loop variables
     317    uint32_t   current_order = required_order;
     318    vseg_t   * current_vseg  = NULL;
     319
     320    // search a free vseg equal or larger than requested size
     321        while( current_order <= CONFIG_VMM_HEAP_MAX_ORDER )
     322        {
     323        // build extended pointer on free_pages_root[current_order]
     324        xptr_t root_xp = XPTR( local_cxy , &mgr->free_list_root[current_order] );
     325
     326                if( !xlist_is_empty( root_xp ) )
     327                {
     328            // get extended pointer on first vseg in this free_list
     329                        xptr_t current_vseg_xp = XLIST_FIRST( root_xp , vseg_t , xlist );
     330            current_vseg = GET_PTR( current_vseg_xp );
     331
     332            // build extended pointer on xlist field in vseg descriptor
     333            xptr_t list_entry_xp = XPTR( local_cxy , &current_vseg->xlist );
     334
     335            // remove this vseg from the free_list
     336                        xlist_unlink( list_entry_xp );
     337
     338                        break; 
     339                }
     340
     341        // increment loop index
     342        current_order++;
     343
     344    }  // end while loop
     345
     346    if( current_vseg == NULL )  // return failure
     347    {
     348        // release lock protecting free lists
     349        busylock_release( &mgr->lock );
     350
     351        printk("\n[ERROR] %s cannot allocate ) %d page(s) in cluster %x\n",
     352        __FUNCTION__, npages , local_cxy );
     353
     354        return NULL;
     355    }
     356
     357        // split recursively the found vseg in smaller vsegs
     358    // if required, and update the free-lists accordingly
     359        while( current_order > required_order )
     360        {
     361        // get found vseg base and size
     362        vpn_t  vpn_base = current_vseg->vpn_base;
     363        vpn_t  vpn_size = current_vseg->vpn_size;
     364       
     365        // allocate a new vseg for the upper half of current vseg
     366            vseg_t * new_vseg = vseg_alloc();
     367
     368            if( new_vseg == NULL )
     369        {
     370                // release lock protecting free lists
     371            busylock_release( &mgr->lock );
     372
     373            printk("\n[ERROR] %s cannot allocate memory for vseg in cluster %x\n",
     374            __FUNCTION__ , local_cxy );
     375
     376            return NULL;
     377            }
     378
     379        // initialise new vseg (upper half of found vseg)
     380        new_vseg->vmm      = vmm;
     381        new_vseg->vpn_base = vpn_base + (vpn_size >> 1);
     382        new_vseg->vpn_size = vpn_size >> 1;
     383
     384        // insert new vseg in relevant free_list
     385                xlist_add_first( XPTR( local_cxy , &mgr->free_list_root[current_order-1] ),
     386                         XPTR( local_cxy , &new_vseg->xlist ) );
     387
     388        // update found vseg
     389        current_vseg->vpn_size = vpn_size>>1;
     390
     391        // update order
     392                current_order --;
     393        }
     394
     395        // release lock protecting free lists
     396        busylock_release( &mgr->lock );
     397
     398#if DEBUG_VMM_MMAP
     399vmm_mmap_display( vmm );
     400#endif
     401
     402    return current_vseg;
    215403
    216404}  // end vmm_mmap_alloc()
     
    219407// This static function implements the VMM MMAP specific desallocator.
    220408// It is called by the vmm_remove_vseg() function.
     409// It releases the vseg to the relevant free_list, after trying (recursively) to
     410// merge it to the buddy vseg.
    221411////////////////////////////////////////////////////////////////////////////////////////////
    222412// @ vmm      : [in] pointer on VMM.
     
    226416                           vseg_t * vseg )
    227417{
    228     // get pointer on mmap allocator
     418
     419#if DEBUG_VMM_MMAP
     420thread_t * this = CURRENT_THREAD;
     421uint32_t cycle = (uint32_t)hal_get_cycles();
     422if( DEBUG_VMM_MMAP < cycle )
     423printk("\n[%s] thread[%x,%x] for vpn_base %x / vpn_size %x / cycle %d\n",
     424__FUNCTION__, this->process->pid, this->trdid, vseg->vpn_base, vseg->vpn_size, cycle );
     425#endif
     426
     427    vseg_t * buddy_vseg;
     428
     429    // get mmap allocator pointer
    229430    mmap_mgr_t * mgr = &vmm->mmap_mgr;
    230431
    231     // compute zombi_list order
    232     uint32_t order = bits_log2( vseg->vpn_size );
    233 
    234     // take lock protecting zombi lists
     432    // take lock protecting free lists
    235433    busylock_acquire( &mgr->lock );
    236434
    237     // update relevant zombi_list
    238     xlist_add_first( XPTR( local_cxy , &mgr->zombi_list[order] ),
    239                      XPTR( local_cxy , &vseg->xlist ) );
     435    // initialise loop variables
     436    // released_vseg is the currently released vseg
     437    vseg_t * released_vseg     = vseg;
     438    uint32_t released_order    = bits_log2( vseg->vpn_size );
     439
     440        // iteratively merge the released vseg to the buddy vseg
     441        // release the current page and exit when buddy not found
     442    while( released_order <= CONFIG_VMM_HEAP_MAX_ORDER )
     443    {
     444        // compute buddy_vseg vpn_base
     445                vpn_t buddy_vpn_base = released_vseg->vpn_base ^ (1 << released_order);
     446       
     447        // build extended pointer on free_pages_root[current_order]
     448        xptr_t root_xp = XPTR( local_cxy , &mgr->free_list_root[released_order] );
     449
     450        // scan this free list to find the buddy vseg
     451        xptr_t   iter_xp;
     452        buddy_vseg = NULL;
     453        XLIST_FOREACH( root_xp , iter_xp )
     454        {
     455            xptr_t   current_vseg_xp = XLIST_ELEMENT( iter_xp , vseg_t , xlist );
     456            vseg_t * current_vseg    = GET_PTR( current_vseg_xp );
     457
     458            if( current_vseg->vpn_base == buddy_vpn_base )
     459            {
     460                buddy_vseg = current_vseg;
     461                break;
     462            }
     463        }
     464       
     465        if( buddy_vseg != NULL )     // buddy found => merge released & buddy
     466        {
     467            // update released vseg fields
     468            released_vseg->vpn_size = buddy_vseg->vpn_size<<1;
     469            if( released_vseg->vpn_base > buddy_vseg->vpn_base)
     470                released_vseg->vpn_base = buddy_vseg->vpn_base;
     471
     472            // remove buddy vseg from free_list
     473            xlist_unlink( XPTR( local_cxy , &buddy_vseg->xlist ) );
     474
     475            // release memory allocated to buddy descriptor
     476            vseg_free( buddy_vseg );
     477        }
     478        else                         // buddy not found => register & exit
     479        {
     480            // register released vseg in free list
     481            xlist_add_first( root_xp , XPTR( local_cxy , &released_vseg->xlist ) );
     482
     483            // exit while loop
     484            break;
     485        }
     486
     487        // increment released_order
     488        released_order++;
     489    }
    240490
    241491    // release lock
    242492    busylock_release( &mgr->lock );
    243493
    244 }  // end of vmm_mmap_free()
     494#if DEBUG_VMM_MMAP
     495vmm_mmap_display( vmm );
     496#endif
     497
     498}  // end vmm_mmap_free()
    245499
    246500////////////////////////////////////////////////////////////////////////////////////////////
     
    288542error_t vmm_user_init( process_t * process )
    289543{
    290     uint32_t  i;
    291544
    292545#if DEBUG_VMM_USER_INIT
     
    306559         "UTILS zone too small\n" );
    307560
    308 // check STACK zone
    309 assert( ((CONFIG_VMM_STACK_SIZE * CONFIG_THREADS_MAX_PER_CLUSTER) <=
    310 (CONFIG_VMM_VSPACE_SIZE - CONFIG_VMM_STACK_BASE)) ,
    311 "STACK zone too small\n");
    312 
    313     // initialize the lock protecting the VSL
     561    // initialize lock protecting the VSL
    314562        remote_queuelock_init( XPTR( local_cxy , &vmm->vsl_lock ) , LOCK_VMM_VSL );
    315563
     564
     565    // initialize STACK allocator
     566    vmm_stack_init( vmm );
     567
     568    // initialize MMAP allocator
     569    vmm_mmap_init( vmm );
     570
     571    // initialize instrumentation counters
     572        vmm->false_pgfault_nr    = 0;
     573        vmm->local_pgfault_nr    = 0;
     574        vmm->global_pgfault_nr   = 0;
     575        vmm->false_pgfault_cost  = 0;
     576        vmm->local_pgfault_cost  = 0;
     577        vmm->global_pgfault_cost = 0;
    316578
    317579/*
     
    356618    vmm->envs_vpn_base = base;
    357619*/
    358     // initialize STACK allocator
    359     vmm->stack_mgr.bitmap   = 0;
    360     vmm->stack_mgr.vpn_base = CONFIG_VMM_STACK_BASE;
    361     busylock_init( &vmm->stack_mgr.lock , LOCK_VMM_STACK );
    362 
    363     // initialize MMAP allocator
    364     vmm->mmap_mgr.vpn_base        = CONFIG_VMM_HEAP_BASE;
    365     vmm->mmap_mgr.vpn_size        = CONFIG_VMM_STACK_BASE - CONFIG_VMM_HEAP_BASE;
    366     vmm->mmap_mgr.first_free_vpn  = CONFIG_VMM_HEAP_BASE;
    367     busylock_init( &vmm->mmap_mgr.lock , LOCK_VMM_MMAP );
    368     for( i = 0 ; i < 32 ; i++ )
    369     {
    370         xlist_root_init( XPTR( local_cxy , &vmm->mmap_mgr.zombi_list[i] ) );
    371     }
    372 
    373     // initialize instrumentation counters
    374         vmm->false_pgfault_nr    = 0;
    375         vmm->local_pgfault_nr    = 0;
    376         vmm->global_pgfault_nr   = 0;
    377         vmm->false_pgfault_cost  = 0;
    378         vmm->local_pgfault_cost  = 0;
    379         vmm->global_pgfault_cost = 0;
    380 
    381620    hal_fence();
    382621
     
    11581397    remote_queuelock_release( parent_lock_xp );
    11591398
     1399/* deprecated [AG] : this is already done by the vmm_user_init() funcfion
     1400
    11601401    // initialize the child VMM STACK allocator
    1161     child_vmm->stack_mgr.bitmap   = 0;
    1162     child_vmm->stack_mgr.vpn_base = CONFIG_VMM_STACK_BASE;
     1402    vmm_stack_init( child_vmm );
    11631403
    11641404    // initialize the child VMM MMAP allocator
    1165     uint32_t i;
    1166     child_vmm->mmap_mgr.vpn_base        = CONFIG_VMM_HEAP_BASE;
    1167     child_vmm->mmap_mgr.vpn_size        = CONFIG_VMM_STACK_BASE - CONFIG_VMM_HEAP_BASE;
    1168     child_vmm->mmap_mgr.first_free_vpn  = CONFIG_VMM_HEAP_BASE;
    1169     for( i = 0 ; i < 32 ; i++ )
    1170     {
    1171         xlist_root_init( XPTR( local_cxy , &child_vmm->mmap_mgr.zombi_list[i] ) );
    1172     }
     1405    vmm_mmap_init( child_vmm );
    11731406
    11741407    // initialize instrumentation counters
     
    11791412        child_vmm->local_pgfault_cost  = 0;
    11801413        child_vmm->global_pgfault_cost = 0;
    1181 
     1414*/
    11821415    // copy base addresses from parent VMM to child VMM
    11831416    child_vmm->args_vpn_base = (vpn_t)hal_remote_lpt(XPTR(parent_cxy, &parent_vmm->args_vpn_base));
     
    12601493    remote_queuelock_release( vsl_lock_xp );
    12611494
    1262     // remove all registered MMAP vsegs
    1263     // from zombi_lists in MMAP allocator
     1495    // remove all registered MMAP vsegs from free_lists in MMAP allocator
    12641496    uint32_t i;
    1265     for( i = 0 ; i<32 ; i++ )
    1266     {
    1267         // build extended pointer on zombi_list[i]
    1268         xptr_t root_xp = XPTR( local_cxy , &vmm->mmap_mgr.zombi_list[i] );
     1497    for( i = 0 ; i <= CONFIG_VMM_HEAP_MAX_ORDER ; i++ )
     1498    {
     1499        // build extended pointer on free list root
     1500        xptr_t root_xp = XPTR( local_cxy , &vmm->mmap_mgr.free_list_root[i] );
    12691501 
    12701502        // scan zombi_list[i]
     
    13431575                          cxy_t         cxy )
    13441576{
    1345     vseg_t     * vseg;          // created vseg pointer
    1346     vpn_t        vpn_base;      // first page index
    1347     vpn_t        vpn_size;      // number of pages covered by vseg
    1348         error_t      error;
     1577    vseg_t     * vseg;          // pointer on allocated vseg descriptor
    13491578
    13501579#if DEBUG_VMM_CREATE_VSEG
     
    13641593        vmm_t * vmm    = &process->vmm;
    13651594
    1366     // compute base, size, vpn_base, vpn_size, depending on vseg type
    1367     // we use the VMM specific allocators for "stack", "file", "anon", & "remote" vsegs
    1368 
     1595    // allocate a vseg descriptor and initialize it, depending on type
     1596    // we use specific allocators for "stack" and "mmap" types
     1597
     1598    /////////////////////////////
    13691599    if( type == VSEG_TYPE_STACK )
    13701600    {
    1371         // get vpn_base and vpn_size from STACK allocator
    1372         vmm_stack_alloc( vmm , base , &vpn_base , &vpn_size );
    1373 
    1374         // compute vseg base and size from vpn_base and vpn_size
    1375         base = vpn_base << CONFIG_PPM_PAGE_SHIFT;
    1376         size = vpn_size << CONFIG_PPM_PAGE_SHIFT;
    1377     }
    1378     else if( type == VSEG_TYPE_FILE )
    1379     {
    1380         // compute page index (in mapper) for first byte
    1381         vpn_t    vpn_min    = file_offset >> CONFIG_PPM_PAGE_SHIFT;
    1382 
    1383         // compute page index (in mapper) for last byte
    1384         vpn_t    vpn_max    = (file_offset + size - 1) >> CONFIG_PPM_PAGE_SHIFT;
    1385 
    1386         // compute offset in first page
    1387         uint32_t offset = file_offset & CONFIG_PPM_PAGE_MASK;
    1388 
    1389         // compute number of pages required in virtual space
    1390         vpn_t    npages      = vpn_max - vpn_min + 1;
    1391 
    1392         // get vpn_base and vpn_size from MMAP allocator
    1393         error = vmm_mmap_alloc( vmm , npages , &vpn_base , &vpn_size );
    1394         if( error )
     1601        // get vseg from STACK allocator
     1602        vseg = vmm_stack_alloc( vmm , base );    // base == ltid
     1603       
     1604        if( vseg == NULL )
    13951605        {
    1396             printk("\n[ERROR] in %s : no vspace for mmap vseg / process %x in cluster %x\n",
    1397                    __FUNCTION__ , process->pid , local_cxy );
     1606            printk("\n[ERROR] %s cannot create %s vseg for process %x in cluster %x\n",
     1607            __FUNCTION__ , vseg_type_str( type ) , process->pid , local_cxy );
    13981608            return NULL;
    13991609        }
    14001610
    1401         // set the vseg base (not always aligned for FILE)
    1402         base = (vpn_base << CONFIG_PPM_PAGE_SHIFT) + offset;
    1403     }
    1404     else if( (type == VSEG_TYPE_ANON) ||
    1405              (type == VSEG_TYPE_REMOTE) )
     1611        // initialize vseg
     1612        vseg->type = type;
     1613        vseg->vmm  = vmm;
     1614        vseg->min  = vseg->vpn_base << CONFIG_PPM_PAGE_SHIFT;
     1615        vseg->max  = vseg->min + (vseg->vpn_size << CONFIG_PPM_PAGE_SHIFT);
     1616        vseg->cxy  = cxy;
     1617
     1618        vseg_init_flags( vseg , type );
     1619    }
     1620    /////////////////////////////////
     1621    else if( type == VSEG_TYPE_FILE )
     1622    {
     1623        // compute page index (in mapper) for first and last byte
     1624        vpn_t    vpn_min    = file_offset >> CONFIG_PPM_PAGE_SHIFT;
     1625        vpn_t    vpn_max    = (file_offset + size - 1) >> CONFIG_PPM_PAGE_SHIFT;
     1626
     1627        // compute offset in first page and number of pages
     1628        uint32_t offset = file_offset & CONFIG_PPM_PAGE_MASK;
     1629        vpn_t    npages      = vpn_max - vpn_min + 1;
     1630
     1631        // get vseg from MMAP allocator
     1632        vseg = vmm_mmap_alloc( vmm , npages );
     1633
     1634        if( vseg == NULL )
     1635        {
     1636            printk("\n[ERROR] %s cannot create %s vseg for process %x in cluster %x\n",
     1637            __FUNCTION__ , vseg_type_str( type ) , process->pid , local_cxy );
     1638            return NULL;
     1639        }
     1640
     1641        // initialize vseg
     1642        vseg->type        = type;
     1643        vseg->vmm         = vmm;
     1644        vseg->min         = (vseg->vpn_base << CONFIG_PPM_PAGE_SHIFT) + offset;
     1645        vseg->max         = vseg->min + size;
     1646        vseg->file_offset = file_offset;
     1647        vseg->file_size   = file_size;
     1648        vseg->mapper_xp   = mapper_xp;
     1649        vseg->cxy         = cxy;
     1650
     1651        vseg_init_flags( vseg , type );
     1652    }
     1653    /////////////////////////////////////////////////////////////////
     1654    else if( (type == VSEG_TYPE_ANON) || (type == VSEG_TYPE_REMOTE) )
    14061655    {
    14071656        // compute number of required pages in virtual space
     
    14091658        if( size & CONFIG_PPM_PAGE_MASK) npages++;
    14101659       
    1411         // get vpn_base and vpn_size from MMAP allocator
    1412         error = vmm_mmap_alloc( vmm , npages , &vpn_base , &vpn_size );
    1413         if( error )
     1660        // allocate vseg from MMAP allocator
     1661        vseg = vmm_mmap_alloc( vmm , npages );
     1662
     1663        if( vseg == NULL )
    14141664        {
    1415             printk("\n[ERROR] in %s : no vspace for mmap vseg / process %x in cluster %x\n",
    1416                    __FUNCTION__ , process->pid , local_cxy );
     1665            printk("\n[ERROR] %s cannot create %s vseg for process %x in cluster %x\n",
     1666            __FUNCTION__ , vseg_type_str( type ) , process->pid , local_cxy );
    14171667            return NULL;
    14181668        }
    14191669
    1420         // set vseg base (always aligned for ANON or REMOTE)
    1421         base = vpn_base << CONFIG_PPM_PAGE_SHIFT;
    1422     }
     1670        // initialize vseg
     1671        vseg->type = type;
     1672        vseg->vmm  = vmm;
     1673        vseg->min  = vseg->vpn_base << CONFIG_PPM_PAGE_SHIFT;
     1674        vseg->max  = vseg->min + (vseg->vpn_size << CONFIG_PPM_PAGE_SHIFT);
     1675        vseg->cxy  = cxy;
     1676
     1677        vseg_init_flags( vseg , type );
     1678    }
     1679    /////////////////////////////////////////////////////////////////
    14231680    else    // VSEG_TYPE_DATA, VSEG_TYPE_CODE or KERNEL vseg
    14241681    {
     
    14261683        uint32_t vpn_max = (base + size - 1) >> CONFIG_PPM_PAGE_SHIFT;
    14271684
    1428         vpn_base = vpn_min;
    1429             vpn_size = vpn_max - vpn_min + 1;
     1685        // allocate vseg descriptor
     1686            vseg = vseg_alloc();
     1687
     1688            if( vseg == NULL )
     1689            {
     1690            printk("\n[ERROR] %s cannot create %s vseg for process %x in cluster %x\n",
     1691            __FUNCTION__ , vseg_type_str( type ) , process->pid , local_cxy );
     1692            return NULL;
     1693            }
     1694        // initialize vseg
     1695        vseg->type        = type;
     1696        vseg->vmm         = vmm;
     1697        vseg->min         = base;
     1698        vseg->max         = base + size;
     1699        vseg->vpn_base    = base >> CONFIG_PPM_PAGE_SHIFT;
     1700        vseg->vpn_size    = vpn_max - vpn_min + 1;
     1701        vseg->file_offset = file_offset;
     1702        vseg->file_size   = file_size;
     1703        vseg->mapper_xp   = mapper_xp;
     1704        vseg->cxy         = cxy;
     1705
     1706        vseg_init_flags( vseg , type );
    14301707    }
    14311708
    14321709    // check collisions
    1433     vseg = vmm_check_conflict( process , vpn_base , vpn_size );
    1434 
    1435     if( vseg != NULL )
    1436     {
    1437         printk("\n[ERROR] in %s for process %x : new vseg [vpn_base %x / vpn_size %x]\n"
    1438                "  overlap existing vseg [vpn_base %x / vpn_size %x]\n",
    1439         __FUNCTION__ , process->pid, vpn_base, vpn_size, vseg->vpn_base, vseg->vpn_size );
     1710    vseg_t * existing_vseg = vmm_check_conflict( process , vseg->vpn_base , vseg->vpn_size );
     1711
     1712    if( existing_vseg != NULL )
     1713    {
     1714        printk("\n[ERROR] in %s for process %x : new vseg %s [vpn_base %x / vpn_size %x]\n"
     1715               "        overlap existing vseg %s [vpn_base %x / vpn_size %x]\n",
     1716        __FUNCTION__ , process->pid, vseg_type_str(vseg->type), vseg->vpn_base, vseg->vpn_size,
     1717        vseg_type_str(existing_vseg->type), existing_vseg->vpn_base, existing_vseg->vpn_size );
     1718        vseg_free( vseg );
    14401719        return NULL;
    14411720    }
    1442 
    1443     // allocate physical memory for vseg descriptor
    1444         vseg = vseg_alloc();
    1445         if( vseg == NULL )
    1446         {
    1447             printk("\n[ERROR] in %s for process %x : cannot allocate memory for vseg\n",
    1448         __FUNCTION__ , process->pid );
    1449         return NULL;
    1450         }
    1451 
    1452 #if (DEBUG_VMM_CREATE_VSEG & 1)
    1453 if( DEBUG_VMM_CREATE_VSEG < cycle )
    1454 printk("\n[%s] thread[%x,%x] : base %x / size %x / vpn_base %x / vpn_size %x\n",
    1455 __FUNCTION__, this->process->pid, this->trdid, base, size, vpn_base, vpn_size );
    1456 #endif
    1457 
    1458     // initialize vseg descriptor
    1459         vseg_init( vseg,
    1460                type,
    1461                base,
    1462                size,
    1463                vpn_base,
    1464                vpn_size,
    1465                file_offset,
    1466                file_size,
    1467                mapper_xp,
    1468                cxy );
    14691721
    14701722    // build extended pointer on VSL lock
     
    14801732    remote_queuelock_release( lock_xp );
    14811733
    1482 #if DEBUG_VMM_CREATE_VSEG
     1734#if DEBUG_VMM_CREATE_VSEG 
    14831735cycle = (uint32_t)hal_get_cycles();
    1484 // if( DEBUG_VMM_CREATE_VSEG < cycle )
    1485 if( type == VSEG_TYPE_REMOTE )
    1486 printk("\n[%s] thread[%x,%x] exit / process %x / %s / base %x / cxy %x / cycle %d\n",
    1487 __FUNCTION__, this->process->pid, this->trdid,
    1488 process->pid, vseg_type_str(type), base, cxy, cycle );
     1736if( DEBUG_VMM_CREATE_VSEG < cycle )
     1737printk("\n[%s] thread[%x,%x] exit / %s / vpn_base %x / vpn_size %x / cycle %d\n",
     1738__FUNCTION__, this->process->pid, this->trdid,
     1739vseg_type_str(type), vseg->vpn_base, vseg->vpn_size, cycle );
    14891740#endif
    14901741
     
    16541905        // release slot to local stack allocator
    16551906        vmm_stack_free( vmm , vseg );
    1656 
    1657         // release vseg descriptor to local kmem
    1658         vseg_free( vseg );
    16591907    }
    16601908    else if( (vseg_type == VSEG_TYPE_ANON) ||
  • trunk/kernel/mm/vmm.h

    r640 r651  
    6464
    6565/*********************************************************************************************
    66  * This structure defines the MMAP allocator used by the VMM to dynamically handle 
    67  * MMAP vsegs requested or released by an user process.
    68  * This allocator should be only used in the reference cluster.
    69  * - allocation policy : all allocated vsegs occupy an integer number of pages that is
    70  *   power of 2, and are aligned on a page boundary. The requested number of pages is
    71  *   rounded if required. The first_free_vpn variable defines completely the MMAP zone state.
    72  *   It is never decremented, as the released vsegs are simply registered in a zombi_list.
    73  *   The relevant zombi_list is checked first for each allocation request.
    74  * - release policy : a released MMAP vseg is registered in an array of zombi_lists.
    75  *   This array is indexed by ln(number of pages), and each entry contains the root of
    76  *   a local list of zombi vsegs that have the same size. The physical memory allocated
    77  *   for a zombi vseg descriptor is not released, to use the "list" field.
    78  *   This physical memory allocated for MMAP vseg descriptors is actually released
    79  *   when the VMM is destroyed.
     66 * This structure defines the MMAP allocator used by the VMM to dynamically handle MMAP vsegs
     67 * requested or released by an user process. It must be called in the reference cluster.
     68 * - allocation policy :
     69 *   This allocator implements the buddy algorithm. All allocated vsegs occupy an integer
     70 *   number of pages, that is power of 2, and are aligned (vpn_base is multiple of vpn_size).
     71 *   The requested number of pages is rounded if required. The global allocator state is
     72 *   completely defined by the free_pages_root[] array indexed by the vseg order.
     73 *   These free lists are local, but are implemented as xlist because we use the existing
     74 *   vseg.xlist to register a free vseg in its free list.
     75 * - release policy :
     76 *   A released vseg is recursively merged with the "buddy" vseg when it is free, in
     77 *   order to build the largest possible aligned free vsegs. The resulting vseg.vpn_size
     78 *   field is updated.
     79 * Implementation note:
     80 * The only significant (and documented) fiels in the vsegs registered in the MMAP allocator
     81 * free lists are "xlist", "vpn_base", and "vpn_size".
    8082 ********************************************************************************************/
    8183
     
    8587    vpn_t          vpn_base;           /*! first page of MMAP zone                          */
    8688    vpn_t          vpn_size;           /*! number of pages in MMAP zone                     */
    87     vpn_t          first_free_vpn;     /*! first free page in MMAP zone                     */
    88     xlist_entry_t  zombi_list[32];     /*! array of roots of released vsegs lists           */
     89    xlist_entry_t  free_list_root[CONFIG_VMM_HEAP_MAX_ORDER + 1];  /* roots of free lists   */
    8990}
    9091mmap_mgr_t;
     
    103104 * 2. The VSL contains only local vsegs, but it is implemented as an xlist, and protected by
    104105 *    a remote_rwlock, because it can be accessed by a thread running in a remote cluster.
    105  *    An exemple is the vmm_fork_copy() function.
     106 *    An example is the vmm_fork_copy() function.
    106107 * 3. The GPT in the reference cluster can be directly accessed by remote threads to handle
    107108 *    false page-fault (page is mapped in the reference GPT, but the PTE copy is missing
     
    119120
    120121    stack_mgr_t        stack_mgr;           /*! embedded STACK vsegs allocator              */
     122
    121123    mmap_mgr_t         mmap_mgr;            /*! embedded MMAP vsegs allocator               */
    122124
     
    156158 * call to the vmm_user_init() function after an exec() syscall.
    157159 * It removes from the VMM of the process identified by the <process> argument all
    158  * non kernel vsegs (i.e. all user vsegs), by calling the vmm_remove_vseg() function.
     160 * all user vsegs, by calling the vmm_remove_vseg() function.
    159161 * - the vsegs are removed from the VSL.
    160162 * - the corresponding GPT entries are removed from the GPT.
     
    279281/*********************************************************************************************
    280282 * This function allocates memory for a vseg descriptor, initialises it, and register it
    281  * in the VSL of the local process descriptor, that must be the reference process.
    282  * - For the FILE, ANON, & REMOTE types, it does not use the <base> and <size> arguments,
    283  *   but uses the specific MMAP virtual memory allocator.
     283 * in the VSL of the local process descriptor.
     284 * - For the FILE, ANON, & REMOTE types, it does not use the <base> argument, but uses
     285 *   the specific VMM MMAP allocator.
    284286 * - For the STACK type, it does not use the <base> and <size> arguments,  but uses the
    285  *   and the <base> argument the specific STACK virtual memory allocator.
     287 *   the specific VMM STACK allocator.
    286288 * It checks collision with pre-existing vsegs.
    287289 * To comply with the "on-demand" paging policy, this function does NOT modify the GPT,
  • trunk/kernel/mm/vseg.c

    r635 r651  
    8181}
    8282
    83 ///////////////////////////////////
    84 void vseg_init( vseg_t      * vseg,
    85                 vseg_type_t   type,
    86                     intptr_t      base,
    87                 uint32_t      size,
    88                 vpn_t         vpn_base,
    89                 vpn_t         vpn_size,
    90                         uint32_t      file_offset,
    91                 uint32_t      file_size,
    92                 xptr_t        mapper_xp,
    93                 cxy_t         cxy )
     83/////////////////////////////////////////
     84void vseg_init_flags( vseg_t      * vseg,
     85                      vseg_type_t   type )
    9486{
    95     vseg->type        = type;
    96         vseg->min         = base;
    97         vseg->max         = base + size;
    98     vseg->vpn_base    = vpn_base;
    99         vseg->vpn_size    = vpn_size;
    100     vseg->file_offset = file_offset;
    101     vseg->file_size   = file_size;
    102         vseg->mapper_xp   = mapper_xp;
    103     vseg->cxy         = cxy;
    104 
    10587    // set vseg flags depending on type
    106         if     ( type == VSEG_TYPE_CODE )
     88        if( type == VSEG_TYPE_CODE )
    10789    {
    10890        vseg->flags = VSEG_USER    |
  • trunk/kernel/mm/vseg.h

    r640 r651  
    4141typedef enum
    4242{
    43     VSEG_TYPE_CODE   = 0,          /*! executable user code     / private / localized     */
    44     VSEG_TYPE_DATA   = 1,          /*! initialized user data    / public  / distributed   */
    45     VSEG_TYPE_STACK  = 2,          /*! execution user stack     / private / localized     */
    46     VSEG_TYPE_ANON   = 3,          /*! anonymous mmap           / public  / localized     */
    47     VSEG_TYPE_FILE   = 4,          /*! file mmap                / public  / localized     */
    48     VSEG_TYPE_REMOTE = 5,          /*! remote mmap              / public  / localized     */
     43    VSEG_TYPE_CODE   = 1,          /*! executable user code     / private / localized     */
     44    VSEG_TYPE_DATA   = 2,          /*! initialized user data    / public  / distributed   */
     45    VSEG_TYPE_STACK  = 3,          /*! execution user stack     / private / localized     */
     46    VSEG_TYPE_ANON   = 4,          /*! anonymous mmap           / public  / localized     */
     47    VSEG_TYPE_FILE   = 5,          /*! file mmap                / public  / localized     */
     48    VSEG_TYPE_REMOTE = 6,          /*! remote mmap              / public  / localized     */
    4949
    50     VSEG_TYPE_KCODE  = 6,          /*! executable kernel code   / private / localized     */
    51     VSEG_TYPE_KDATA  = 7,          /*! initialized kernel data  / private / localized     */
    52     VSEG_TYPE_KDEV   = 8,          /*! kernel peripheral device / public  / localized     */
     50    VSEG_TYPE_KCODE  = 7,          /*! executable kernel code   / private / localized     */
     51    VSEG_TYPE_KDATA  = 8,          /*! initialized kernel data  / private / localized     */
     52    VSEG_TYPE_KDEV   = 9,          /*! kernel peripheral device / public  / localized     */
    5353}
    5454vseg_type_t;
     
    115115
    116116/*******************************************************************************************
    117  * This function initializes a local vseg descriptor, from the arguments values.
    118  * It does NOT register the vseg in the local VMM.
     117 * This function initializes the "flags" field for a local <vseg> descriptor,
     118 * depending on the vseg <type>.
    119119 *******************************************************************************************
    120120 * @ vseg      : pointer on the vseg descriptor.
    121  * @ base      : vseg base address.
    122  * @ size      : vseg size (bytes).
    123  * @ vpn_base  : first page index.
    124  * @ vpn_size  : number of pages.
    125121 * @ type      : vseg type.
    126  * @ cxy       : target cluster for physical mapping.
    127122 ******************************************************************************************/
    128 void vseg_init( vseg_t      * vseg,
    129                     vseg_type_t   type,
    130                 intptr_t      base,
    131                     uint32_t      size,
    132                 vpn_t         vpn_base,
    133                 vpn_t         vpn_size,
    134                 uint32_t      file_offset,
    135                 uint32_t      file_size,
    136                 xptr_t        mapper_xp,
    137                 cxy_t         cxy );
     123void vseg_init_flags( vseg_t      * vseg,
     124                          vseg_type_t   type );
    138125
    139126/*******************************************************************************************
  • trunk/kernel/syscalls/sys_exit.c

    r625 r651  
    108108__FUNCTION__, pid, this->trdid );
    109109#endif
    110         thread_delete( XPTR( local_cxy , this ) , pid , true );
     110        thread_delete( XPTR( local_cxy , this ) , true );    // forced
    111111    }
    112112
  • trunk/kernel/syscalls/sys_get_nb_cores.c

    r639 r651  
    3535#include <syscalls.h>
    3636
    37 ////////////////////////////////////
     37/////////////////////////////////////
    3838int sys_get_nb_cores( uint32_t   cxy,
    3939                      uint32_t * ncores )
     
    5151#if DEBUG_SYS_GET_NB_CORES
    5252if( DEBUG_SYS_GET_NB_CORES < tm_start )
    53 printk("\n[%s] thread[%x,%x] enter / cycle %d\n",
    54 __FUNCTION__, process->pid, this->trdid, (uint32_t)tm_start );
     53printk("\n[%s] thread[%x,%x] enter  for cluster %x / cycle %d\n",
     54__FUNCTION__, process->pid, this->trdid, cxy, (uint32_t)tm_start );
    5555#endif
    5656
     
    8888#if DEBUG_SYS_GET_NB_CORES
    8989if( DEBUG_SYS_GET_NB_CORES < tm_end )
    90 printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
    91 __FUNCTION__ , process->pid, this->trdid, (uint32_t)tm_end );
     90printk("\n[%s] thread[%x,%x] exit / ncores %d / cycle %d\n",
     91__FUNCTION__ , process->pid, this->trdid, k_ncores, (uint32_t)tm_end );
    9292#endif
    9393
  • trunk/kernel/syscalls/sys_lseek.c

    r457 r651  
    11/*
    2  * kern/sys_lseek.c - set the read/write offset of an opened file
     2 * kern/sys_lseek.c - Kernel function implementing the lseek system call.
    33 *
    4  * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless
    5  * Copyright (c) 2011,2012 UPMC Sorbonne Universites
     4 * AUthor        Alain Greiner (2016,2017,2018,2019)
     5s
     6 * Copyright (c) UPMC Sorbonne Universites
    67 *
    7  * This file is part of ALMOS-kernel.
     8 * This file is part of ALMOS-MKH.
    89 *
    9  * ALMOS-kernel is free software; you can redistribute it and/or modify it
     10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
    1011 * under the terms of the GNU General Public License as published by
    1112 * the Free Software Foundation; version 2.0 of the License.
    1213 *
    13  * ALMOS-kernel is distributed in the hope that it will be useful, but
     14 * ALMOS-MKH is distributed in the hope that it will be useful, but
    1415 * WITHOUT ANY WARRANTY; without even the implied warranty of
    1516 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     
    1718 *
    1819 * You should have received a copy of the GNU General Public License
    19  * along with ALMOS-kernel; if not, write to the Free Software Foundation,
     20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
    2021 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
    2122 */
     
    3132#include <process.h>
    3233
    33 ////////////////////////////////
    34 int sys_lseek (uint32_t file_id,
    35                uint32_t offset,
    36                uint32_t whence )
     34/////////////////////////////////
     35int sys_lseek ( uint32_t file_id,
     36                uint32_t offset,
     37                uint32_t whence )
    3738{
    3839        error_t    error;
     
    4344        process_t * process = this->process;
    4445
     46#if (DEBUG_SYS_LSEEK || CONFIG_INSTRUMENTATION_SYSCALLS)
     47uint64_t     tm_start = hal_get_cycles();
     48#endif
     49
     50#if DEBUG_SYS_LSEEK
     51if( DEBUG_SYS_LSEEK < tm_start )
     52printk("\n[%s] thread[%x,%x] enter / file_id %d / offset %d / cycle %d\n",
     53__FUNCTION__, process->pid, this->trdid, file_id, offset, (uint32_t)tm_start );
     54#endif
     55
    4556    // check file_id argument
    4657        if( file_id >= CONFIG_PROCESS_FILE_MAX_NR )
    4758        {
    48         printk("\n[ERROR] in %s : illegal file descriptor index = %d\n",
    49                __FUNCTION__ , file_id );
     59
     60#if DEBUG_SYSCALLS_ERROR
     61printk("\n[ERROR] in %s : thread[%x,%x] illegal file descriptor index %d\n",
     62__FUNCTION__ , process->pid, this->trdid, file_id );
     63#endif
    5064                this->errno = EBADFD;
    5165                return -1;
     
    5771    if( file_xp == XPTR_NULL )
    5872    {
    59         printk("\n[ERROR] in %s : undefined file descriptor index = %d\n",
    60                __FUNCTION__ , file_id );
     73
     74#if DEBUG_SYSCALLS_ERROR
     75printk("\n[ERROR] in %s : thread[%x,%x] undefined fd_id %d\n",
     76__FUNCTION__, process->pid, this->trdid, file_id );
     77#endif
    6178                this->errno = EBADFD;
    6279                return -1;
    6380    }
    6481
    65         /* FIXME: file may be closed in parallel
    66          * of seek/read/write/mmap ..etc
    67          * so file may be NULL or invalid */
     82// FIXME: file may be closed in parallel of seek/read/write/mmap ..etc
    6883
    6984    // call relevant VFS function
     
    7287        if( error )
    7388        {
    74         printk("\n[ERROR] in %s : cannot seek file = %d\n",
    75                __FUNCTION__ , file_id );
     89
     90#if DEBUG_SYSCALLS_ERROR
     91printk("\n[ERROR] in %s : thread[%x,%x] cannot seek file_id %d\n",
     92__FUNCTION__, process->pid, this->trdid, file_id );
     93#endif
    7694                this->errno = error;
    7795                return -1;
    7896        }
     97
     98#if (DEBUG_SYS_LSEEK || CONFIG_INSTRUMENTATION_SYSCALLS)
     99uint64_t     tm_end = hal_get_cycles();
     100#endif
     101
     102#if DEBUG_SYS_LSEEK
     103if( DEBUG_SYS_LSEEK < tm_end )
     104printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
     105__FUNCTION__ , process->pid, this->trdid, (uint32_t)tm_end );
     106#endif
     107
     108#if CONFIG_INSTRUMENTATION_SYSCALLS
     109hal_atomic_add( &syscalls_cumul_cost[SYS_LSEEK] , tm_end - tm_start );
     110hal_atomic_add( &syscalls_occurences[SYS_LSEEK] , 1 );
     111#endif
    79112 
    80113        return new_offset;
  • trunk/kernel/syscalls/sys_mmap.c

    r637 r651  
    112112    }
    113113
    114     // FIXME handle Copy_On_Write for MAP_PRIVATE...
     114// FIXME handle Copy_On_Write for MAP_PRIVATE...
    115115
    116116    // test mmap type : can be FILE / ANON / REMOTE
     
    127127#endif
    128128
    129             // FIXME: handle concurent delete of file by another thread
     129// FIXME: handle concurent delete of file by another thread
    130130
    131131                if( fdid >= CONFIG_PROCESS_FILE_MAX_NR )
     
    164164#endif
    165165
    166         // get inode pointer & mapper pointer
    167         vfs_inode_t * inode_ptr  = hal_remote_lpt(XPTR(file_cxy , &file_ptr->inode ));
     166        // get mapper pointer
    168167        mapper_t    * mapper_ptr = hal_remote_lpt(XPTR(file_cxy , &file_ptr->mapper));
    169168
    170         // get file size
    171                 uint32_t size = hal_remote_l32( XPTR( file_cxy , &inode_ptr->size ) );
    172 
    173 #if (DEBUG_SYS_MMAP & 1)
    174 if ( DEBUG_SYS_MMAP < tm_start )
    175 printk("\n[%s] thread[%x,%x] get file size : %d bytes\n",
    176 __FUNCTION__, process->pid, this->trdid, size );
    177 #endif
    178 
    179         // chek offset and length arguments
    180                 if( (offset + length) > size)
    181                 {
    182 
    183 #if DEBUG_SYSCALLS_ERROR
    184 printk("\n[ERROR] in %s: thread[%x,%x] / offset(%d) + len(%d) >= file's size(%d)\n",
    185 __FUNCTION__, process->pid, this->trdid, k_attr.offset, k_attr.length, size );
    186 #endif
    187             this->errno = ERANGE;
    188             return -1;
    189                 }
     169#if (DEBUG_SYS_MMAP & 1)
     170if ( DEBUG_SYS_MMAP < tm_start )
     171printk("\n[%s] thread[%x,%x] get file mapper %x\n",
     172__FUNCTION__, process->pid, this->trdid, mapper_ptr );
     173#endif
    190174
    191175/* TODO
  • trunk/kernel/syscalls/sys_thread_cancel.c

    r506 r651  
    101101    {
    102102        // block target thread and mark it for delete
    103         thread_delete( target_xp , pid , false );
     103        thread_delete( target_xp , false );              // not forced
    104104    }
    105105
  • trunk/kernel/syscalls/sys_thread_create.c

    r637 r651  
    154154        else                                        // set default attributes
    155155        {
    156         kern_attr.attributes = PT_ATTR_DETACH | PT_ATTR_CLUSTER_DEFINED;
     156        kern_attr.attributes = PT_ATTR_CLUSTER_DEFINED;
    157157        child_cxy = dqdt_get_cluster_for_thread( LOCAL_CLUSTER->dqdt_root_xp );
    158158        }
  • trunk/kernel/syscalls/sys_thread_exit.c

    r635 r651  
    3333#include <syscalls.h>
    3434
    35 ////////////////////////////////////////
    36 int sys_thread_exit( void * exit_value )
     35/////////////////////////////////////////
     36int sys_thread_exit( void * exit_status )
    3737{
     38    error_t     error;
     39    vseg_t    * vseg;
     40
    3841        thread_t  * this      = CURRENT_THREAD;
    3942    trdid_t     trdid     = this->trdid;
    4043    process_t * process   = this->process;
    4144    pid_t       pid       = process->pid;
     45   
     46    // check exit_value pointer in user space if required
     47    if( exit_status != NULL )
     48    {
     49        error = vmm_get_vseg( process , (intptr_t)exit_status  , &vseg );
    4250
    43     // check exit_value argument
    44     if( exit_value != NULL )
    45     {
     51        if( error )
     52            {
    4653
    4754#if DEBUG_SYSCALLS_ERROR
    48 printk("\n[ERROR] in %s : thread[%x,%x] / exit_value argument %x must be NULL\n",
    49 __FUNCTION__ , pid, trdid , exit_value );
     55printk("\n[ERROR] in %s : exit_status buffer %x unmapped / thread[%x,%x]\n",
     56__FUNCTION__, (intptr_t)exit_status, process->pid, this->trdid );
    5057#endif
    51         this->errno = EINVAL;
    52         return -1;
     58            this->errno = EINVAL;
     59                return -1;
     60        }
     61    }
     62
     63        // check busylocks
     64    uint32_t count = this->busylocks;
     65        if( count )
     66        {
     67
     68#if DEBUG_SYSCALLS_ERROR
     69printk("\n[ERROR] in %s : busylocks count = %d  / thread[%x,%x]\n",
     70__FUNCTION__ , count, process->pid, this->trdid );
     71#endif
     72            this->errno = EINVAL;
     73                return -1;
    5374    }
    5475
    5576    // If calling thread is the main thread, the process must be deleted.
    56     // => delete all process threads and synchronise with parent process.
    57     // If calling thread is not the main thread, it must be deleted.
    58     // => block the thread and mark it for delete.
    59     if( (CXY_FROM_PID( pid ) == local_cxy) && (LTID_FROM_TRDID(trdid) == 0) )
     77    // => delete all process threads and synchronize with parent process.
     78    // If calling thread is not the main thread, only this thread must be deleted.
     79    // => register exit_status in thread descriptor, block the thread,
     80    //    mark it for delete, and synchronize with joining thread.
     81
     82    if( (CXY_FROM_PID( pid ) == local_cxy) && (LTID_FROM_TRDID(trdid) == 0) )  // main
    6083    {
    6184
     
    6992        sys_exit( 0 );
    7093    }
    71     else
     94    else                                                             // not the main
    7295    {
    7396
     
    78101__FUNCTION__ , pid , trdid , (uint32_t)tm_start );
    79102#endif
     103        // register exit_status in thread descriptor
     104        this->exit_status = exit_status;
     105
    80106        // block calling thread and mark it for delete,
    81         thread_delete( XPTR( local_cxy , this ) , pid , false );
     107        thread_delete( XPTR( local_cxy , this ) , false );   // not forced
    82108
    83109        // deschedule
  • trunk/kernel/syscalls/sys_thread_join.c

    r637 r651  
    11/*
    2  * sys_thread_join.c - passive wait on the end of a given thread.
     2 * sys_thread_join.c - wait termination of of an attached thread.
    33 *
    44 * Authors    Alain Greiner (2016,2017,2018,2019)
     
    2626#include <hal_special.h>
    2727#include <hal_irqmask.h>
     28#include <hal_uspace.h>
    2829#include <thread.h>
    2930#include <vmm.h>
     
    3738///////////////////////////////////////
    3839int sys_thread_join ( trdid_t    trdid,
    39                       void    ** exit_value )
     40                      void    ** exit_status )
    4041{
     42    error_t       error;
    4143    reg_t         save_sr;
    4244    xptr_t        target_xp;
     
    4749    xptr_t        target_flags_xp;
    4850    xptr_t        target_join_xp_xp;
     51    xptr_t        target_exit_status_xp;
    4952    xptr_t        killer_xp;
    5053    xptr_t        joining_xp;
    5154    thread_t    * joining_ptr;
    5255    process_t   * process;
     56    vseg_t      * vseg;
     57    void        * status;
    5358
    5459    // get joining thread pointers
     
    6267
    6368#if DEBUG_SYS_THREAD_JOIN
    64 uint64_t     tm_start;
    65 uint64_t     tm_end;
    66 tm_start = hal_get_cycles();
     69uint64_t  tm_start = hal_get_cycles();
    6770if( DEBUG_SYS_THREAD_JOIN < tm_start )
    68 printk("\n[DBG] %s : joining thread[%x,%x] enter / target thread[%x,%x] / cycle %d\n",
     71printk("\n[%s] joining thread[%x,%x] enter / target thread[%x,%x] / cycle %d\n",
    6972__FUNCTION__ , process->pid, joining_ptr->trdid,
    7073process->pid, trdid, (uint32_t)tm_start );
     
    7780
    7881#if DEBUG_SYSCALLS_ERROR
    79 printk("\n[ERROR] in %s : illegal trdid argument %x\n",
    80 __FUNCTION__, trdid );
     82printk("\n[ERROR] in %s : illegal trdid argument %x / joining thread[%x,%x]\n",
     83__FUNCTION__, trdid, joining_ptr->process->pid, joining_ptr-trdid );
    8184#endif
    8285                joining_ptr->errno = EINVAL;
     
    8487        }
    8588
    86     // check exit_value argument
    87         if( exit_value != NULL )
     89    // check exit_value argument in user space
     90    error = vmm_get_vseg( process , (intptr_t)exit_status  , &vseg );
     91        if( error )
    8892        {
    8993
    9094#if DEBUG_SYSCALLS_ERROR
    91 printk("\n[ERROR] in %s : exit_value argument must be NULL\n",
    92 __FUNCTION__ );
     95printk("\n[ERROR] in %s : exit_status argument %x not mapped / joining thread[%x,%x]\n",
     96__FUNCTION__, exit_status, joining_ptr->process->pid, joining_ptr-trdid );
    9397#endif
    9498                joining_ptr->errno = EINVAL;
     
    101105
    102106#if DEBUG_SYSCALLS_ERROR
    103 printk("\n[ERROR] in %s : this thread (%x) == target thread(%x)\n",
    104 __FUNCTION__, joining_ptr->trdid, trdid );
     107printk("\n[ERROR] in %s : joinig thread[%x,%x] == target thread\n",
     108__FUNCTION__, joining_ptr->process->pid, joining_ptr->trdid );
    105109#endif
    106110        joining_ptr->errno = EDEADLK;
     
    116120
    117121#if DEBUG_SYSCALLS_ERROR
    118 printk("\n[ERROR] in %s : target thread %x not found\n",
    119 __FUNCTION__, trdid );
     122printk("\n[ERROR] in %s : target thread[%x,%x] not found / joining_thread[%x,%x]\n",
     123__FUNCTION__, process->pid, trdid, joining_ptr->process->pid, joining_ptr-trdid );
    120124#endif
    121125        joining_ptr->errno = ESRCH;
     
    124128
    125129    // get extended pointers on various fields in target thread
    126     target_join_lock_xp = XPTR( target_cxy , &target_ptr->join_lock );
    127     target_flags_xp     = XPTR( target_cxy , &target_ptr->flags );
    128     target_join_xp_xp   = XPTR( target_cxy , &target_ptr->join_xp );
     130    target_join_lock_xp   = XPTR( target_cxy , &target_ptr->join_lock );
     131    target_flags_xp       = XPTR( target_cxy , &target_ptr->flags );
     132    target_join_xp_xp     = XPTR( target_cxy , &target_ptr->join_xp );
     133    target_exit_status_xp = XPTR( target_cxy , &target_ptr->exit_status );
    129134
    130135    // check target thread joinable
     
    133138
    134139#if DEBUG_SYSCALLS_ERROR
    135 printk("\n[ERROR] in %s : target thread %x not joinable\n", __FUNCTION__, trdid );
     140printk("\n[ERROR] in %s : target thread[%x,‰x] not attached / joining thread[%x,%x]\n",
     141__FUNCTION__, process->pid, trdid, joining_ptr->process->pid, joining_ptr-trdid );
    136142#endif
    137143        joining_ptr->errno = EINVAL;
     
    146152
    147153    // test the kill_done flag from the target thread
    148     if( hal_remote_l32( target_flags_xp ) & THREAD_FLAG_KILL_DONE )  // killer thread is first
    149     {
     154    if( hal_remote_l32( target_flags_xp ) & THREAD_FLAG_KILL_DONE )  // killer is first
     155    {
     156        // get exit_status from target thread
     157        status = (void*)hal_remote_lpt( target_exit_status_xp );
     158
    150159        // get pointers on killer thread
    151160        killer_xp  = (xptr_t)hal_remote_l64( target_join_xp_xp );
     
    159168        // release the lock protecting join     
    160169        remote_busylock_release( target_join_lock_xp );
    161 
    162 #if DEBUG_SYS_THREAD_JOIN
    163 tm_end = hal_get_cycles();
    164 if( DEBUG_SYS_THREAD_JOIN < tm_end )
    165 printk("\n[DBG] %s : joining thread[%x,%x] exit / target thread[%x,%x] completed / cycle %d\n",
    166 __FUNCTION__, process->pid, joining_ptr->trdid, process->pid, trdid, (uint32_t)tm_end );
    167 #endif
    168 
    169     }
    170     else                                                          // joining thread is first
     170    }
     171    else                                                          // joining is first
    171172    {
    172173        // set the join_done flag in target thread
     
    184185#if DEBUG_SYS_THREAD_JOIN
    185186if( DEBUG_SYS_THREAD_JOIN < tm_start )
    186 printk("\n[DBG] %s : joining thread[%x,%x] deschedules / target thread[%x,%x] not completed\n",
     187printk("\n[%s] joining thread[%x,%x] deschedules / target thread[%x,%x] not completed\n",
    187188__FUNCTION__ , process->pid, joining_ptr->trdid, process->pid, trdid );
    188189#endif
    189190        // deschedule
    190191        sched_yield( "joining thread waiting killer thread" );
     192
     193        // returns exit_status from joining thread
     194        status = joining_ptr->exit_status;
     195    }
    191196   
     197    // returns exit_status to user space
     198    hal_copy_to_uspace( exit_status,
     199                        XPTR( local_cxy , &status ),
     200                        sizeof( void* ) );
     201
     202    // restore IRQs
     203    hal_restore_irq( save_sr );
     204
     205    hal_fence();
     206
     207#if (DEBUG_SYS_THREAD_JOIN || CONFIG_INSTRUMENTATION_SYSCALLS)
     208uint64_t     tm_end = hal_get_cycles();
     209#endif
     210
     211#if CONFIG_INSTRUMENTATION_SYSCALLS
     212hal_atomic_add( &syscalls_cumul_cost[SYS_THREAD_JOIN] , tm_end - tm_start );
     213hal_atomic_add( &syscalls_occurences[SYS_THREAD_JOIN] , 1 );
     214#endif
     215
    192216#if DEBUG_SYS_THREAD_JOIN
    193217tm_end = hal_get_cycles();
    194218if( DEBUG_SYS_THREAD_JOIN < tm_end )
    195 printk("\n[DBG] %s : joining thread[%x,%x] exit / target thread[%x,%x] completed / cycle %d\n",
     219printk("\n[%s] joining thread[%x,%x] exit / target thread[%x,%x] completed / cycle %d\n",
    196220__FUNCTION__ , process->pid, joining_ptr->trdid, process->pid, trdid, (uint32_t)tm_end );
    197221#endif
    198222
    199     }
    200 
    201     // restore IRQs
    202     hal_restore_irq( save_sr );
    203 
    204223    return 0;
    205224
  • trunk/kernel/syscalls/syscalls.h

    r642 r651  
    3737
    3838/******************************************************************************************
    39  * [0] This function terminates the execution of the calling user thread,
    40  * and makes the exit_value pointer available to any successful pthread_join() with the
     39 * [0] This function terminates the execution of the calling user thread, and makes
     40 * the <exit_status> pointer available to any successful pthread_join() with the
    4141 * terminating thread.
    42  * It actually set the THREAD_SIG_EXIT signal, set the THREAD_BLOCKED_GLOBAL bit in the
    43  * thread descriptor and deschedule.
    44  * The thread will be detached from its process, and the memory allocated to the thread
    45  * descriptor will be released later by the scheduler.
    46  ******************************************************************************************
    47  * @ exit_vallue  : pointer to be returned to joining thread if thread is attached.
     42 * - If the calling thread is the main thread, it calls the sys_exit() function to delete
     43 *   completely the user process. 
     44 * - if the calling thread is not the main thread, it registers the <exit_status> pointer
     45 *   in the thread descriptor, and calls the thread_delete() function, that will set the
     46 *   THREAD_SIG_EXIT signal, set the THREAD_BLOCKED_GLOBAL bit in thread descriptor, and
     47 *   deschedules. All memory allocated to the thread is released later by the scheduler.
     48 *   If the thread is in "detached" mode, the thread_delete() function implements
     49 *   the synchonisation with the joining thread.
     50 ******************************************************************************************
     51 * @ exit_status  : pointer to be returned to joining thread if thread is attached.
    4852 * @ return 0 if success / return -1 if all locks not released or illegal argument.
    4953 *****************************************************************************************/
    50 int sys_thread_exit( void * exit_value );
     54int sys_thread_exit( void * exit_status );
    5155
    5256/******************************************************************************************
     
    222226 ******************************************************************************************
    223227 * @ attr       : pointer on attributes structure.
    224  * @ return 0 if success / return -1 if failure.
     228 * @ returns 0 if success / returns -1 if failure.
    225229 *****************************************************************************************/
    226230int sys_mmap( mmap_attr_t * attr );
     
    234238 * @ buf      : buffer virtual address in user space.
    235239 * @ count    : number of bytes.
    236  * @ return number of bytes actually read if success / returns -1 if failure.
     240 * @ returns number of bytes actually read if success / returns -1 if failure.
    237241 *****************************************************************************************/
    238242int sys_read( uint32_t   file_id,
     
    251255 * @ buf      : buffer virtual address in user space.
    252256 * @ count    : number of bytes.
    253  * @ return number of bytes actually written if success / returns -1 if failure.
     257 * @ returns number of bytes actually written if success / returns -1 if failure.
    254258 *****************************************************************************************/
    255259int sys_write( uint32_t   file_id,
     
    258262
    259263/******************************************************************************************
    260  * [16] This function repositions the offset of the file descriptor identified by <file_id>,
    261  * according to the operation type defined by the <whence> argument.
     264 * [16] This function repositions the offset of the file descriptor identified by the
     265 * <file_id> argument, according to the operation type defined by the <whence> argument.
    262266 ******************************************************************************************
    263267 * @ file_id  : open file index in fd_array.
    264268 * @ offset   : used to compute new offset value.
    265269 * @ whence   : operation type (see below).
    266  * @ return 0 if success / returns -1 if failure.
     270 * @ returns new offset value if success / returns -1 if failure.
    267271 *****************************************************************************************/
    268272int sys_lseek( xptr_t    file_id,
     
    276280 ******************************************************************************************
    277281  file_id   : file descriptor index in fd_array.
    278  * @ return 0 if success / returns -1 if failure.
     282 * @ returns 0 if success / returns -1 if failure.
    279283 *****************************************************************************************/
    280284int sys_close( uint32_t file_id );
     
    289293 ******************************************************************************************
    290294 * @ pathname   : pathname (can be relative or absolute).
    291  * @ return 0 if success / returns -1 if failure.
     295 * @ returns 0 if success / returns -1 if failure.
    292296 *****************************************************************************************/
    293297int sys_unlink( char * pathname );
Note: See TracChangeset for help on using the changeset viewer.