Changeset 625 for trunk/kernel/kern


Ignore:
Timestamp:
Apr 10, 2019, 10:09:39 AM (5 years ago)
Author:
alain
Message:

Fix a bug in the vmm_remove_vseg() function: the physical pages
associated to an user DATA vseg were released to the kernel when
the target process descriptor was in the reference cluster.
This physical pages release should be done only when the page
forks counter value is zero.
All other modifications are cosmetic.

Location:
trunk/kernel/kern
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/kernel/kern/chdev.c

    r619 r625  
    138138    uint32_t   server_lid;    // core running the server thread local index
    139139    xptr_t     lock_xp;       // extended pointer on lock protecting the chdev state
    140     uint32_t   save_sr;       // for critical section
    141140
    142141#if (DEBUG_SYS_READ & 1)
     
    177176uint32_t rx_cycle = (uint32_t)hal_get_cycles();
    178177if( (is_rx) && (DEBUG_CHDEV_CMD_RX < rx_cycle) )
    179 printk("\n[%s] client[%x,%x] enter for RX / server[%x,%x] / cycle %d\n",
     178printk("\n[%s] client thread[%x,%x] enter for RX / server[%x,%x] / cycle %d\n",
    180179__FUNCTION__, this->process->pid, this->trdid, server_pid, server_trdid, rx_cycle );
    181180#endif
     
    184183uint32_t tx_cycle = (uint32_t)hal_get_cycles();
    185184if( (is_rx == 0) && (DEBUG_CHDEV_CMD_TX < tx_cycle) )
    186 printk("\n[%s] client[%x,%x] enter for TX / server[%x,%x] / cycle %d\n",
     185printk("\n[%s] client thread[%x,%x] enter for TX / server[%x,%x] / cycle %d\n",
    187186__FUNCTION__, this->process->pid, this->trdid, server_pid, server_trdid, tx_cycle );
    188187#endif
     
    194193    xptr_t  root_xp    = XPTR( chdev_cxy , &chdev_ptr->wait_root );
    195194
    196     // build extended pointer on server thread blocked state
    197     xptr_t  blocked_xp = XPTR( chdev_cxy , &server_ptr->blocked );
    198 
    199195    // build extended pointer on lock protecting chdev waiting queue
    200196    lock_xp            = XPTR( chdev_cxy , &chdev_ptr->wait_lock );
    201197
    202     // TODO the hal_disable_irq() / hal_restore_irq()
    203     // in the sequence below is probably useless, as it is
    204     // already done by the busylock_acquire() / busylock_release()
    205     // => remove it [AG] october 2018
    206 
    207     // critical section for the following sequence:
     198    // The following actions execute in critical section,
     199    // because the lock_acquire / lock_release :
    208200    // (1) take the lock protecting the chdev state
    209     // (2) block the client thread
    210     // (3) unblock the server thread if required
    211     // (4) register client thread in server queue
    212     // (5) send IPI to force server scheduling
    213     // (6) release the lock protecting waiting queue
    214     // (7) deschedule
    215 
    216     // enter critical section
    217     hal_disable_irq( &save_sr );
    218 
    219     // take the lock protecting chdev queue
     201    // (2) register client thread in server queue
     202    // (3) unblock the server thread and block client thread
     203    // (4) send IPI to force server scheduling
     204    // (5) release the lock protecting waiting queue
     205
     206    // 1. take the lock protecting chdev queue
    220207    remote_busylock_acquire( lock_xp );
    221208
    222     // block current thread
    223     thread_block( XPTR( local_cxy , CURRENT_THREAD ) , THREAD_BLOCKED_IO );
    224 
    225 #if (DEBUG_CHDEV_CMD_TX & 1)
    226 if( (is_rx == 0) && (DEBUG_CHDEV_CMD_TX < tx_cycle) )
    227 printk("\n[%s] client thread[%x,%x] blocked\n",
    228 __FUNCTION__, this->process->pid, this->trdid );
    229 #endif
    230 
    231 #if (DEBUG_CHDEV_CMD_RX & 1)
    232 if( (is_rx) && (DEBUG_CHDEV_CMD_RX < rx_cycle) )
    233 printk("\n[%s] client thread[%x,%x] blocked\n",
    234 __FUNCTION__, this->process_pid, this->trdid );
    235 #endif
    236 
    237     // unblock server thread if required
    238     if( hal_remote_l32( blocked_xp ) & THREAD_BLOCKED_IDLE )
    239     thread_unblock( server_xp , THREAD_BLOCKED_IDLE );
    240 
    241 #if (DEBUG_CHDEV_CMD_TX & 1)
    242 if( (is_rx == 0) && (DEBUG_CHDEV_CMD_TX < tx_cycle) )
    243 printk("\n[%s] TX server thread[%x,%x] unblocked\n",
    244 __FUNCTION__, server_pid, server_trdid );
    245 #endif
    246 
    247 #if (DEBUG_CHDEV_CMD_RX & 1)
    248 if( (is_rx) && (DEBUG_CHDEV_CMD_RX < rx_cycle) )
    249 printk("\n[%s] RX server thread[%x,%x] unblocked\n",
    250 __FUNCTION__, server_pid, server_trdid );
    251 #endif
    252 
    253     // register client thread in waiting queue
     209    // 2. register client thread in waiting queue
    254210    xlist_add_last( root_xp , list_xp );
    255211
     
    266222#endif
    267223 
    268     // send IPI to core running the server thread when server core != client core
     224    // 3. client thread unblocks server thread and blocks itself
     225    thread_unblock( server_xp , THREAD_BLOCKED_IDLE );
     226    thread_block( XPTR( local_cxy , CURRENT_THREAD ) , THREAD_BLOCKED_IO );
     227
     228#if (DEBUG_CHDEV_CMD_TX & 1)
     229if( (is_rx == 0) && (DEBUG_CHDEV_CMD_TX < tx_cycle) )
     230printk("\n[%s] client thread[%x,%x] unblock server thread[%x,%x] and block itsef\n",
     231__FUNCTION__, this->process->pid, this->trdid, server_pid, server_trdid );
     232#endif
     233
     234#if (DEBUG_CHDEV_CMD_RX & 1)
     235if( (is_rx) && (DEBUG_CHDEV_CMD_RX < rx_cycle) )
     236printk("\n[%s] client thread[%x,%x] unblock server thread[%x,%x] and block itsef\n",
     237__FUNCTION__, this->process->pid, this->trdid, server_pid, server_trdid );
     238#endif
     239
     240    // 4. send IPI to core running the server thread when server core != client core
    269241    if( (server_lid != this->core->lid) || (local_cxy != chdev_cxy) )
    270242    {
     
    285257    }
    286258 
    287     // release lock protecting chdev queue
     259    // 5. release lock protecting chdev queue
    288260    remote_busylock_release( lock_xp );
    289261
    290262    // deschedule
    291263    sched_yield("blocked on I/O");
    292 
    293     // exit critical section
    294     hal_restore_irq( save_sr );
    295264
    296265#if DEBUG_CHDEV_CMD_RX
    297266rx_cycle = (uint32_t)hal_get_cycles();
    298267if( (is_rx) && (DEBUG_CHDEV_CMD_RX < rx_cycle) )
    299 printk("\n[%s] client_thread[%x,%x] exit for RX / cycle %d\n",
     268printk("\n[%s] client thread[%x,%x] exit for RX / cycle %d\n",
    300269__FUNCTION__, this->process->pid, this->trdid, rx_cycle );
    301270#endif
     
    304273tx_cycle = (uint32_t)hal_get_cycles();
    305274if( (is_rx == 0) && (DEBUG_CHDEV_CMD_TX < tx_cycle) )
    306 printk("\n[%s] client_thread[%x,%x] exit for TX / cycle %d\n",
     275printk("\n[%s] client thread[%x,%x] exit for TX / cycle %d\n",
    307276__FUNCTION__, this->process->pid, this->trdid, tx_cycle );
    308277#endif
     
    344313uint32_t rx_cycle = (uint32_t)hal_get_cycles();
    345314if( (chdev->is_rx) && (DEBUG_CHDEV_SERVER_RX < rx_cycle) )
    346 printk("\n[%s] DEV thread[%x,%x] check TXT_RX channel %d / cycle %d\n",
     315printk("\n[%s] server thread[%x,%x] check TXT_RX channel %d / cycle %d\n",
    347316__FUNCTION__ , server->process->pid, server->trdid, chdev->channel, rx_cycle );
    348317#endif
     
    370339rx_cycle = (uint32_t)hal_get_cycles();
    371340if( (chdev->is_rx) && (DEBUG_CHDEV_SERVER_RX < rx_cycle) )
    372 printk("\n[%s] thread[%x,%x] found RX queue empty => blocks / cycle %d\n",
     341printk("\n[%s] server thread[%x,%x] found RX queue empty => blocks / cycle %d\n",
    373342__FUNCTION__ , server->process->pid, server->trdid, rx_cycle );
    374343#endif
     
    377346tx_cycle = (uint32_t)hal_get_cycles();
    378347if( (chdev->is_rx == 0) && (DEBUG_CHDEV_SERVER_TX < tx_cycle) )
    379 printk("\n[%s] thread[%x,%x] found TX queue empty => blocks / cycle %d\n",
     348printk("\n[%s] server thread[%x,%x] found TX queue empty => blocks / cycle %d\n",
    380349__FUNCTION__ , server->process->pid, server->trdid, tx_cycle );
    381350#endif
     
    407376rx_cycle = (uint32_t)hal_get_cycles();
    408377if( (chdev->is_rx) && (DEBUG_CHDEV_SERVER_RX < rx_cycle) )
    409 printk("\n[%s] thread[%x,%x] for RX get client thread[%x,%x] / cycle %d\n",
     378printk("\n[%s] server thread[%x,%x] get command from client thread[%x,%x] / cycle %d\n",
    410379__FUNCTION__, server->process->pid, server->trdid, client_pid, client_trdid, rx_cycle );
    411380#endif
     
    414383tx_cycle = (uint32_t)hal_get_cycles();
    415384if( (chdev->is_rx == 0) && (DEBUG_CHDEV_SERVER_TX < tx_cycle) )
    416 printk("\n[%s] thread[%x,%x] for TX get client thread[%x,%x] / cycle %d\n",
     385printk("\n[%s] server thread[%x,%x] get command from client thread[%x,%x] / cycle %d\n",
    417386__FUNCTION__, server->process->pid, server->trdid, client_pid, client_trdid, tx_cycle );
    418387#endif
     
    445414rx_cycle = (uint32_t)hal_get_cycles();
    446415if( (chdev->is_rx) && (DEBUG_CHDEV_SERVER_RX < rx_cycle) )
    447 printk("\n[%s] thread[%x,%x] completes RX for client thread[%x,%x] / cycle %d\n",
     416printk("\n[%s] thread[%x,%x] completes command for client thread[%x,%x] / cycle %d\n",
    448417__FUNCTION__, server->process->pid, server->trdid, client_pid, client_trdid, rx_cycle );
    449418#endif
     
    452421tx_cycle = (uint32_t)hal_get_cycles();
    453422if( (chdev->is_rx == 0) && (DEBUG_CHDEV_SERVER_TX < tx_cycle) )
    454 printk("\n[%s] thread[%x,%x] completes TX for client thread[%x,%x] / cycle %d\n",
     423printk("\n[%s] thread[%x,%x] completes command for client thread[%x,%x] / cycle %d\n",
    455424__FUNCTION__, server->process->pid, server->trdid, client_pid, client_trdid, tX_cycle );
    456425#endif
  • trunk/kernel/kern/chdev.h

    r619 r625  
    111111/******************************************************************************************
    112112 * This structure defines a chdev descriptor.
    113  * For multi-channels device, there is one chdev descriptor per channel.
    114113 * This structure is NOT replicated, and can be located in any cluster.
    115114 * One kernel thread, in charge of handling the commands registered in the waiting queue
  • trunk/kernel/kern/printk.c

    r623 r625  
    253253                break;
    254254            }
    255             case ('b'):             // excactly 2 digits hexadecimal
     255            case ('b'):             /* exactly 2 digits hexadecimal */
    256256            {
    257257                int  val = va_arg( *args, int );
     
    426426
    427427    // print generic infos
    428     nolock_printk("\n[PANIC] in %s: line %d | cycle %d\n"
     428    nolock_printk("\n\n[PANIC] in %s: line %d | cycle %d\n"
    429429                  "core[%x,%d] | thread %x (%x) | process %x (%x)\n",
    430430                  function_name, line, (uint32_t)cycle,
     
    502502    remote_busylock_acquire( lock_xp );
    503503
    504     // display string on TTY0
     504    // display buf on TTY0
    505505    dev_txt_sync_write( buf , 10 );
     506
     507    // release TXT0 lock
     508    remote_busylock_release( lock_xp );
     509}
     510
     511////////////////////////
     512void putd( int32_t val )
     513{
     514    static const char HexaTab[] = "0123456789ABCDEF";
     515
     516    char      buf[10];
     517    uint32_t  i;
     518
     519    // get pointers on TXT0 chdev
     520    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
     521    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
     522    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
     523
     524    // get extended pointer on remote TXT0 chdev lock
     525    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
     526
     527    // get TXT0 lock
     528    remote_busylock_acquire( lock_xp );
     529
     530    if (val < 0)
     531    {
     532        val = -val;
     533        dev_txt_sync_write( "-" , 1 );
     534    }
     535
     536    for(i = 0; i < 10 ; i++)
     537    {
     538        buf[9 - i] = HexaTab[val % 10];
     539        if (!(val /= 10)) break;
     540    }
     541
     542    // display buf on TTY0
     543    dev_txt_sync_write( &buf[9-i] , i+1 );
    506544
    507545    // release TXT0 lock
  • trunk/kernel/kern/printk.h

    r623 r625  
    123123
    124124/**********************************************************************************
    125  * This function displays a non-formated message on kernel TXT0 terminal.
     125 * This function displays a non-formated message on TXT0 terminal.
    126126 * This function is actually used to debug the assembly level kernel functions.
    127127 **********************************************************************************
     
    131131
    132132/**********************************************************************************
    133  * This function displays a 32 bits value in hexadecimal on kernel TXT0 terminal.
     133 * This function displays a 32 bits value in hexadecimal on TXT0 terminal.
    134134 * This function is actually used to debug the assembly level kernel functions.
    135135 **********************************************************************************
     
    139139
    140140/**********************************************************************************
    141  * This function displays a 64 bits value in hexadecimal on kernel TXT0 terminal.
     141 * This function displays a 32 bits signed value in decimal on TXT0 terminal.
     142 * This function is actually used to debug the assembly level kernel functions.
     143 **********************************************************************************
     144 * @ val   : 32 bits signed value.
     145 *********************************************************************************/
     146void putd( int32_t val );
     147
     148/**********************************************************************************
     149 * This function displays a 64 bits value in hexadecimal on TXT0 terminal.
    142150 * This function is actually used to debug the assembly level kernel functions.
    143151 **********************************************************************************
     
    147155
    148156/**********************************************************************************
    149  * This debug function displays on the kernel TXT0 terminal the content of an
     157 * This debug function displays on the TXT0 terminal the content of an
    150158 * array of bytes defined by <buffer> and <size> arguments (16 bytes per line).
    151159 * The <string> argument is displayed before the buffer content.
  • trunk/kernel/kern/process.c

    r624 r625  
    9191}
    9292
    93 /////////////////////////////////////////////////
    94 void process_reference_init( process_t * process,
    95                              pid_t       pid,
    96                              xptr_t      parent_xp )
    97 {
     93////////////////////////////////////////////////////
     94error_t process_reference_init( process_t * process,
     95                                pid_t       pid,
     96                                xptr_t      parent_xp )
     97{
     98    error_t     error;
    9899    xptr_t      process_xp;
    99100    cxy_t       parent_cxy;
     
    105106    uint32_t    stdout_id;
    106107    uint32_t    stderr_id;
    107     error_t     error;
    108108    uint32_t    txt_id;
    109109    char        rx_path[40];
     
    111111    xptr_t      file_xp;
    112112    xptr_t      chdev_xp;
    113     chdev_t chdev_ptr;
     113    chdev_t   * chdev_ptr;
    114114    cxy_t       chdev_cxy;
    115115    pid_t       parent_pid;
     116    vmm_t     * vmm;
    116117
    117118    // build extended pointer on this reference process
    118119    process_xp = XPTR( local_cxy , process );
     120
     121    // get pointer on process vmm
     122    vmm = &process->vmm;
    119123
    120124    // get parent process cluster and local pointer
     
    129133uint32_t cycle = (uint32_t)hal_get_cycles();
    130134if( DEBUG_PROCESS_REFERENCE_INIT < cycle )
    131 printk("\n[%s] thread[%x,%x] enter to initalialize process %x / cycle %d\n",
    132 __FUNCTION__, parent_pid, this->trdid, pid, cycle );
     135printk("\n[%s] thread[%x,%x] enter to initialize process %x / cycle %d\n",
     136__FUNCTION__, this->process->pid, this->trdid, pid, cycle );
    133137#endif
    134138
     
    144148    process->cwd_xp      = hal_remote_l64( XPTR( parent_cxy, &parent_ptr->cwd_xp ) );
    145149
    146     // initialize vmm as empty
    147     error = vmm_init( process );
    148 
    149 assert( (error == 0) , "cannot initialize VMM\n" );
     150    // initialize VSL as empty
     151    vmm->vsegs_nr = 0;
     152        xlist_root_init( XPTR( local_cxy , &vmm->vsegs_root ) );
     153
     154    // create an empty GPT as required by the architecture
     155    error = hal_gpt_create( &vmm->gpt );
     156    if( error )
     157    {
     158        printk("\n[ERROR] in %s : cannot create empty GPT\n", __FUNCTION__ );
     159        return -1;
     160    }
     161
     162#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
     163if( DEBUG_PROCESS_REFERENCE_INIT < cycle )
     164printk("\n[%s] thread[%x,%x] created empty GPT for process %x\n",
     165__FUNCTION__, parent_pid, this->trdid, pid );
     166#endif
     167
     168    // initialize GPT and VSL locks
     169    remote_rwlock_init( XPTR( local_cxy , &vmm->gpt_lock ) , LOCK_VMM_GPT );
     170        remote_rwlock_init( XPTR( local_cxy , &vmm->vsl_lock ) , LOCK_VMM_VSL );
     171
     172    // register kernel vsegs in VMM as required by the architecture
     173    error = hal_vmm_kernel_update( process );
     174    if( error )
     175    {
     176        printk("\n[ERROR] in %s : cannot register kernel vsegs in VMM\n", __FUNCTION__ );
     177        return -1;
     178    }
     179
     180#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
     181if( DEBUG_PROCESS_REFERENCE_INIT < cycle )
     182printk("\n[%s] thread[%x,%x] registered kernel vsegs for process %x\n",
     183__FUNCTION__, parent_pid, this->trdid, pid );
     184#endif
     185
     186    // create "args" and "envs" vsegs
     187    // create "stacks" and "mmap" vsegs allocators
     188    // initialize locks protecting GPT and VSL
     189    error = vmm_user_init( process );
     190    if( error )
     191    {
     192        printk("\n[ERROR] in %s : cannot register user vsegs in VMM\n", __FUNCTION__ );
     193        return -1;
     194    }
    150195 
    151196#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
    152197cycle = (uint32_t)hal_get_cycles();
    153198if( DEBUG_PROCESS_REFERENCE_INIT < cycle )
    154 printk("\n[%s] thread[%x,%x] / vmm empty for process %x / cycle %d\n",
    155 __FUNCTION__, parent_pid, this->trdid, pid, cycle );
     199printk("\n[%s] thread[%x,%x] initialized vmm for process %x\n",
     200__FUNCTION__, parent_pid, this->trdid, pid );
    156201#endif
    157202
     
    187232                           &stdin_xp,
    188233                           &stdin_id );
    189 
    190 assert( (error == 0) , "cannot open stdin pseudo file" );
     234        if( error )
     235        {
     236            printk("\n[ERROR] in %s : cannot open stdout pseudo-file\n", __FUNCTION__ );
     237            return -1;
     238        }
     239
    191240assert( (stdin_id == 0) , "stdin index must be 0" );
    192241
     
    206255                           &stdout_xp,
    207256                           &stdout_id );
    208 
    209         assert( (error == 0) , "cannot open stdout pseudo file" );
    210         assert( (stdout_id == 1) , "stdout index must be 1" );
     257        if( error )
     258        {
     259            printk("\n[ERROR] in %s : cannot open stdout pseudo-file\n", __FUNCTION__ );
     260            return -1;
     261        }
     262
     263assert( (stdout_id == 1) , "stdout index must be 1" );
    211264
    212265#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
     
    225278                           &stderr_xp,
    226279                           &stderr_id );
    227 
    228         assert( (error == 0) , "cannot open stderr pseudo file" );
    229         assert( (stderr_id == 2) , "stderr index must be 2" );
     280        if( error )
     281        {
     282            printk("\n[ERROR] in %s : cannot open stderr pseudo-file\n", __FUNCTION__ );
     283            return -1;
     284        }
     285
     286assert( (stderr_id == 2) , "stderr index must be 2" );
    230287
    231288#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
     
    240297    {
    241298        // get extended pointer on stdin pseudo file in parent process
    242         file_xp = (xptr_t)hal_remote_l64( XPTR( parent_cxy , &parent_ptr->fd_array.array[0] ) );
     299        file_xp = (xptr_t)hal_remote_l64( XPTR( parent_cxy,
     300                                                &parent_ptr->fd_array.array[0] ) );
    243301
    244302        // get extended pointer on parent process TXT chdev
     
    261319
    262320    // initialize lock protecting CWD changes
    263     remote_busylock_init( XPTR( local_cxy , &process->cwd_lock ), LOCK_PROCESS_CWD );
     321    remote_busylock_init( XPTR( local_cxy ,
     322                                &process->cwd_lock ), LOCK_PROCESS_CWD );
    264323
    265324#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
     
    273332    xlist_root_init( XPTR( local_cxy , &process->children_root ) );
    274333    process->children_nr     = 0;
    275     remote_queuelock_init( XPTR( local_cxy , &process->children_lock ), LOCK_PROCESS_CHILDREN );
     334    remote_queuelock_init( XPTR( local_cxy,
     335                                 &process->children_lock ), LOCK_PROCESS_CHILDREN );
    276336
    277337    // reset semaphore / mutex / barrier / condvar list roots and lock
     
    280340    xlist_root_init( XPTR( local_cxy , &process->barrier_root ) );
    281341    xlist_root_init( XPTR( local_cxy , &process->condvar_root ) );
    282     remote_queuelock_init( XPTR( local_cxy , &process->sync_lock ), LOCK_PROCESS_USERSYNC );
     342    remote_queuelock_init( XPTR( local_cxy ,
     343                                 &process->sync_lock ), LOCK_PROCESS_USERSYNC );
    283344
    284345    // reset open directories root and lock
    285346    xlist_root_init( XPTR( local_cxy , &process->dir_root ) );
    286     remote_queuelock_init( XPTR( local_cxy , &process->dir_lock ), LOCK_PROCESS_DIR );
     347    remote_queuelock_init( XPTR( local_cxy ,
     348                                 &process->dir_lock ), LOCK_PROCESS_DIR );
    287349
    288350    // register new process in the local cluster manager pref_tbl[]
     
    315377#endif
    316378
     379    return 0;
     380
    317381}  // process_reference_init()
    318382
     
    321385                           xptr_t      reference_process_xp )
    322386{
    323     error_t error;
     387    error_t   error;
     388    vmm_t   * vmm;
    324389
    325390    // get reference process cluster and local pointer
    326391    cxy_t       ref_cxy = GET_CXY( reference_process_xp );
    327392    process_t * ref_ptr = GET_PTR( reference_process_xp );
     393
     394    // get pointer on process vmm
     395    vmm = &local_process->vmm;
    328396
    329397    // initialize PID, REF_XP, PARENT_XP, and STATE
     
    343411
    344412// check user process
    345 assert( (local_process->pid != 0), "PID cannot be 0" );
    346 
    347     // reset local process vmm
    348     error = vmm_init( local_process );
    349     assert( (error == 0) , "cannot initialize VMM\n");
    350 
    351     // reset process file descriptors array
     413assert( (local_process->pid != 0), "LPID cannot be 0" );
     414
     415    // initialize VSL as empty
     416    vmm->vsegs_nr = 0;
     417        xlist_root_init( XPTR( local_cxy , &vmm->vsegs_root ) );
     418
     419    // create an empty GPT as required by the architecture
     420    error = hal_gpt_create( &vmm->gpt );
     421    if( error )
     422    {
     423        printk("\n[ERROR] in %s : cannot create empty GPT\n", __FUNCTION__ );
     424        return -1;
     425    }
     426
     427    // initialize GPT and VSL locks
     428    remote_rwlock_init( XPTR( local_cxy , &vmm->gpt_lock ) , LOCK_VMM_GPT );
     429        remote_rwlock_init( XPTR( local_cxy , &vmm->vsl_lock ) , LOCK_VMM_VSL );
     430
     431    // register kernel vsegs in VMM as required by the architecture
     432    error = hal_vmm_kernel_update( local_process );
     433    if( error )
     434    {
     435        printk("\n[ERROR] in %s : cannot register kernel vsegs in VMM\n", __FUNCTION__ );
     436        return -1;
     437    }
     438
     439    // create "args" and "envs" vsegs
     440    // create "stacks" and "mmap" vsegs allocators
     441    // initialize locks protecting GPT and VSL
     442    error = vmm_user_init( local_process );
     443    if( error )
     444    {
     445        printk("\n[ERROR] in %s : cannot register user vsegs in VMM\n", __FUNCTION__ );
     446        return -1;
     447    }
     448 
     449#if (DEBUG_PROCESS_COPY_INIT & 1)
     450cycle = (uint32_t)hal_get_cycles();
     451if( DEBUG_PROCESS_COPY_INIT < cycle )
     452printk("\n[%s] thread[%x,%x] initialized vmm for process %x / cycle %d\n",
     453__FUNCTION__, parent_pid, this->trdid, pid, cycle );
     454#endif
     455
     456    // set process file descriptors array
    352457        process_fd_init( local_process );
    353458
    354     // reset vfs_root_xp / vfs_bin_xp / cwd_xp fields
     459    // set vfs_root_xp / vfs_bin_xp / cwd_xp fields
    355460    local_process->vfs_root_xp = hal_remote_l64( XPTR( ref_cxy , &ref_ptr->vfs_root_xp ) );
    356461    local_process->vfs_bin_xp  = hal_remote_l64( XPTR( ref_cxy , &ref_ptr->vfs_bin_xp ) );
     
    380485    local_process->th_nr  = 0;
    381486    rwlock_init( &local_process->th_lock , LOCK_PROCESS_THTBL );
    382 
    383487
    384488    // register new process descriptor in local cluster manager local_list
     
    451555#endif
    452556
    453     // remove process from children_list
    454     // and release PID if owner cluster
     557    // when target process cluster is the owner cluster
     558    // - remove process from TXT list and transfer ownership
     559    // - remove process from children_list
     560    // - release PID
    455561    if( CXY_FROM_PID( pid ) == local_cxy )
    456562    {
     563        process_txt_detach( XPTR( local_cxy , process ) );
     564
     565#if (DEBUG_PROCESS_DESTROY & 1)
     566if( DEBUG_PROCESS_DESTROY < cycle )
     567printk("\n[%s] thread[%x,%x] removed process %x from TXT list\n",
     568__FUNCTION__, this->process->pid, this->trdid, pid );
     569#endif
     570
    457571        // get pointers on parent process
    458572        parent_xp  = process->parent_xp;
     
    472586#if (DEBUG_PROCESS_DESTROY & 1)
    473587if( DEBUG_PROCESS_DESTROY < cycle )
    474 printk("\n[%s] thread[%x,%x] removed process %x in cluster %x from children list\n",
    475 __FUNCTION__, this->process->pid, this->trdid, pid, local_cxy );
     588printk("\n[%s] thread[%x,%x] removed process %x from parent process children list\n",
     589__FUNCTION__, this->process->pid, this->trdid, pid );
    476590#endif
    477591
     
    777891uint32_t cycle = (uint32_t)hal_get_cycles();
    778892if( DEBUG_PROCESS_SIGACTION < cycle )
    779 printk("\n[%s] thread[%x,%x] enter in cluster %x for process %x / cycle %d\n",
    780 __FUNCTION__, this->process->pid, this->trdid, local_cxy, process->pid, cycle );
     893printk("\n[%s] thread[%x,%x] enter for process %x n cluster %x / cycle %d\n",
     894__FUNCTION__, this->process->pid, this->trdid, process->pid, local_cxy, cycle );
    781895#endif
    782896
     
    11891303}  // end process_register_thread()
    11901304
    1191 /////////////////////////////////////////////////
    1192 bool_t process_remove_thread( thread_t * thread )
     1305///////////////////////////////////////////////////
     1306uint32_t process_remove_thread( thread_t * thread )
    11931307{
    11941308    uint32_t count;  // number of threads in local process descriptor
     1309
     1310// check thread
     1311assert( (thread != NULL) , "thread argument is NULL" );
    11951312
    11961313    process_t * process = thread->process;
     
    12051322    count = process->th_nr;
    12061323
    1207 // check thread
    1208 assert( (thread != NULL) , "thread argument is NULL" );
    1209 
    12101324// check th_nr value
    12111325assert( (count > 0) , "process th_nr cannot be 0" );
     
    12181332    rwlock_wr_release( &process->th_lock );
    12191333
    1220     return (count == 1);
     1334    return count;
    12211335
    12221336}  // end process_remove_thread()
     
    12831397cycle = (uint32_t)hal_get_cycles();
    12841398if( DEBUG_PROCESS_MAKE_FORK < cycle )
    1285 printk("\n[%s] thread[%x,%x] allocated process %x / cycle %d\n",
     1399printk("\n[%s] thread[%x,%x] allocated child_process %x / cycle %d\n",
    12861400__FUNCTION__, pid, trdid, new_pid, cycle );
    12871401#endif
    12881402
    12891403    // initializes child process descriptor from parent process descriptor
    1290     process_reference_init( process,
    1291                             new_pid,
    1292                             parent_process_xp );
     1404    error = process_reference_init( process,
     1405                                    new_pid,
     1406                                    parent_process_xp );
     1407    if( error )
     1408    {
     1409        printk("\n[ERROR] in %s : cannot initialize child process in cluster %x\n",
     1410        __FUNCTION__, local_cxy );
     1411        process_free( process );
     1412        return -1;
     1413    }
    12931414
    12941415#if( DEBUG_PROCESS_MAKE_FORK & 1 )
     
    12981419__FUNCTION__, pid, trdid, new_pid, cycle );
    12991420#endif
    1300 
    13011421
    13021422    // copy VMM from parent descriptor to child descriptor
     
    13611481#endif
    13621482
    1363     // set Copy_On_Write flag in parent process GPT
    1364     // this includes all replicated GPT copies
     1483    // set COW flag in DATA, ANON, REMOTE vsegs for parent process VMM
     1484    // this includes all parnet process copies in all clusters
    13651485    if( parent_process_cxy == local_cxy )   // reference is local
    13661486    {
     
    13731493    }
    13741494
    1375     // set Copy_On_Write flag in child process GPT
     1495    // set COW flag in DATA, ANON, REMOTE vsegs for child process VMM
    13761496    vmm_set_cow( process );
    13771497 
     
    14231543    char          ** args_pointers;           // array of pointers on main thread arguments
    14241544
    1425     // get thread, process, pid and ref_xp
     1545    // get calling thread, process, pid and ref_xp
    14261546    thread  = CURRENT_THREAD;
    14271547    process = thread->process;
     
    14701590cycle = (uint32_t)hal_get_cycles();
    14711591if( DEBUG_PROCESS_MAKE_EXEC < cycle )
    1472 printk("\n[%s] thread[%x,%x] deleted all threads / cycle %d\n",
     1592printk("\n[%s] thread[%x,%x] deleted existing threads / cycle %d\n",
    14731593__FUNCTION__, pid, thread->trdid, cycle );
    14741594#endif
    14751595
    1476     // reset local process VMM
    1477     vmm_destroy( process );
     1596    // reset calling process VMM
     1597    vmm_user_reset( process );
    14781598
    14791599#if( DEBUG_PROCESS_MAKE_EXEC & 1 )
    14801600cycle = (uint32_t)hal_get_cycles();
    14811601if( DEBUG_PROCESS_MAKE_EXEC < cycle )
    1482 printk("\n[%s] thread[%x,%x] reset VMM / cycle %d\n",
     1602printk("\n[%s] thread[%x,%x] completed VMM reset / cycle %d\n",
    14831603__FUNCTION__, pid, thread->trdid, cycle );
    14841604#endif
    14851605
    1486     // re-initialize the VMM (kentry/args/envs vsegs registration)
    1487     error = vmm_init( process );
     1606    // re-initialize the VMM (args/envs vsegs registration)
     1607    error = vmm_user_init( process );
    14881608    if( error )
    14891609    {
     
    14971617cycle = (uint32_t)hal_get_cycles();
    14981618if( DEBUG_PROCESS_MAKE_EXEC < cycle )
    1499 printk("\n[%s] thread[%x,%x] / kentry/args/envs vsegs registered / cycle %d\n",
     1619printk("\n[%s] thread[%x,%x] registered args/envs vsegs / cycle %d\n",
    15001620__FUNCTION__, pid, thread->trdid, cycle );
    15011621#endif
     
    15151635cycle = (uint32_t)hal_get_cycles();
    15161636if( DEBUG_PROCESS_MAKE_EXEC < cycle )
    1517 printk("\n[%s] thread[%x,%x] / code/data vsegs registered / cycle %d\n",
     1637printk("\n[%s] thread[%x,%x] registered code/data vsegs / cycle %d\n",
    15181638__FUNCTION__, pid, thread->trdid, cycle );
    15191639#endif
     
    15771697    vmm->vsegs_nr = 0;
    15781698        xlist_root_init( XPTR( local_cxy , &vmm->vsegs_root ) );
    1579         remote_rwlock_init( XPTR( local_cxy , &vmm->vsegs_lock ) , LOCK_VMM_VSL );
    15801699
    15811700    // initialise GPT as empty
    15821701    error = hal_gpt_create( &vmm->gpt );
    1583 
    15841702    if( error )
    15851703    {
     
    15881706    }
    15891707
    1590     // initialize GPT lock
     1708    // initialize VSL and GPT locks
     1709        remote_rwlock_init( XPTR( local_cxy , &vmm->vsl_lock ) , LOCK_VMM_VSL );
    15911710    remote_rwlock_init( XPTR( local_cxy , &vmm->gpt_lock ) , LOCK_VMM_GPT );
    15921711   
    15931712    // create kernel vsegs in GPT and VSL, as required by the hardware architecture
    15941713    error = hal_vmm_kernel_init( info );
    1595 
    15961714    if( error )
    15971715    {
     
    16521770    // allocates memory for process descriptor from local cluster
    16531771        process = process_alloc();
    1654        
    1655 // check memory allocator
    1656 assert( (process != NULL),
    1657 "no memory for process descriptor in cluster %x", local_cxy  );
     1772    if( process == NULL )
     1773    {
     1774        printk("\n[PANIC] in %s : cannot allocate process\n", __FUNCTION__ );
     1775        hal_core_sleep();
     1776    }
    16581777
    16591778    // set the CWD and VFS_ROOT fields in process descriptor
     
    16631782    // get PID from local cluster
    16641783    error = cluster_pid_alloc( process , &pid );
    1665 
    1666 // check PID allocator
    1667 assert( (error == 0),
    1668 "cannot allocate PID in cluster %x", local_cxy );
    1669 
    1670 // check PID value
    1671 assert( (pid == 1) ,
    1672 "process INIT must be first process in cluster 0" );
     1784    if( error )
     1785    {
     1786        printk("\n[PANIC] in %s : cannot allocate PID\n", __FUNCTION__ );
     1787        hal_core_sleep();
     1788    }
     1789    if( pid != 1 )
     1790    {
     1791        printk("\n[PANIC] in %s : process PID must be 0x1\n", __FUNCTION__ );
     1792        hal_core_sleep();
     1793    }
    16731794
    16741795    // initialize process descriptor / parent is local process_zero
    1675     process_reference_init( process,
    1676                             pid,
    1677                             XPTR( local_cxy , &process_zero ) ); 
     1796    error = process_reference_init( process,
     1797                                    pid,
     1798                                    XPTR( local_cxy , &process_zero ) ); 
     1799    if( error )
     1800    {
     1801        printk("\n[PANIC] in %s : cannot initialize process\n", __FUNCTION__ );
     1802        hal_core_sleep();
     1803    }
    16781804
    16791805#if(DEBUG_PROCESS_INIT_CREATE & 1)
     
    16931819                            &file_xp,
    16941820                            &file_id );
    1695 
    1696 assert( (error == 0),
    1697 "failed to open file <%s>", CONFIG_PROCESS_INIT_PATH );
     1821    if( error )
     1822    {
     1823        printk("\n[PANIC] in %s : cannot open file <%s>\n",
     1824         __FUNCTION__, CONFIG_PROCESS_INIT_PATH  );
     1825        hal_core_sleep();
     1826    }
    16981827
    16991828#if(DEBUG_PROCESS_INIT_CREATE & 1)
     
    17031832#endif
    17041833
    1705    // register "code" and "data" vsegs as well as entry-point
     1834    // register "code" and "data" vsegs as well as entry-point
    17061835    // in process VMM, using information contained in the elf file.
    17071836        error = elf_load_process( file_xp , process );
    17081837
    1709 assert( (error == 0),
    1710 "cannot access .elf file <%s>", CONFIG_PROCESS_INIT_PATH );
     1838    if( error )
     1839    {
     1840        printk("\n[PANIC] in %s : cannot access file <%s>\n",
     1841         __FUNCTION__, CONFIG_PROCESS_INIT_PATH  );
     1842        hal_core_sleep();
     1843    }
     1844
    17111845
    17121846#if(DEBUG_PROCESS_INIT_CREATE & 1)
     
    17141848printk("\n[%s] thread[%x,%x] registered code/data vsegs in VMM\n",
    17151849__FUNCTION__, this->process->pid, this->trdid );
     1850#endif
     1851
     1852#if (DEBUG_PROCESS_INIT_CREATE & 1)
     1853hal_vmm_display( process , true );
    17161854#endif
    17171855
     
    17511889                                &thread );
    17521890
    1753 assert( (error == 0),
    1754 "cannot create main thread for <%s>", CONFIG_PROCESS_INIT_PATH );
    1755 
    1756 assert( (thread->trdid == 0),
    1757 "main thread must have index 0 for <%s>", CONFIG_PROCESS_INIT_PATH );
     1891    if( error )
     1892    {
     1893        printk("\n[PANIC] in %s : cannot create main thread\n", __FUNCTION__  );
     1894        hal_core_sleep();
     1895    }
     1896    if( thread->trdid != 0 )
     1897    {
     1898        printk("\n[PANIC] in %s : bad main thread trdid\n", __FUNCTION__  );
     1899        hal_core_sleep();
     1900    }
    17581901
    17591902#if(DEBUG_PROCESS_INIT_CREATE & 1)
     
    19892132    process_txt_transfer_ownership( process_xp );
    19902133
    1991     // get extended pointer on process stdin file
     2134    // get extended pointer on process stdin pseudo file
    19922135    file_xp = (xptr_t)hal_remote_l64( XPTR( process_cxy , &process_ptr->fd_array.array[0] ) );
    19932136
     
    20142157uint32_t txt_id = hal_remote_l32( XPTR( chdev_cxy , &chdev_ptr->channel ) );
    20152158if( DEBUG_PROCESS_TXT < cycle )
    2016 printk("\n[%s] thread[%x,%x] detached process %x from TXT %d / cycle %d\n",
     2159printk("\n[%s] thread[%x,%x] detached process %x from TXT%d / cycle %d\n",
    20172160__FUNCTION__, this->process->pid, this->trdid, process_pid, txt_id, cycle );
    20182161#endif
     
    20562199uint32_t txt_id = hal_remote_l32( XPTR( txt_cxy , &txt_ptr->channel ) );
    20572200if( DEBUG_PROCESS_TXT < cycle )
    2058 printk("\n[%s] thread[%x,%x] give TXT %d to process %x / cycle %d\n",
     2201printk("\n[%s] thread[%x,%x] give TXT%d ownership to process %x / cycle %d\n",
    20592202__FUNCTION__, this->process->pid, this->trdid, txt_id, process_pid, cycle );
    20602203#endif
     
    20782221    xptr_t      iter_xp;         // iterator for xlist
    20792222    xptr_t      current_xp;      // extended pointer on current process
    2080     process_t * current_ptr;     // local pointer on current process
    2081     cxy_t       current_cxy;     // cluster for current process
     2223    bool_t      found;
    20822224
    20832225#if DEBUG_PROCESS_TXT
     
    20862228#endif
    20872229
    2088     // get pointers on process in owner cluster
     2230    // get pointers on target process
    20892231    process_cxy = GET_CXY( process_xp );
    20902232    process_ptr = GET_PTR( process_xp );
    20912233    process_pid = hal_remote_l32( XPTR( process_cxy , &process_ptr->pid ) );
    20922234
    2093     // check owner cluster
    2094     assert( (process_cxy == CXY_FROM_PID( process_pid )) ,
    2095     "process descriptor not in owner cluster" );
     2235// check owner cluster
     2236assert( (process_cxy == CXY_FROM_PID( process_pid )) ,
     2237"process descriptor not in owner cluster" );
    20962238
    20972239    // get extended pointer on stdin pseudo file
     
    21032245    txt_ptr = GET_PTR( txt_xp );
    21042246
    2105     // get extended pointer on TXT_RX owner and TXT channel
     2247    // get relevant infos from chdev descriptor
    21062248    owner_xp = hal_remote_l64( XPTR( txt_cxy , &txt_ptr->ext.txt.owner_xp ) );
    2107     txt_id   = hal_remote_l32 ( XPTR( txt_cxy , &txt_ptr->channel ) );
    2108 
    2109     // transfer ownership only if process is the TXT owner
     2249    txt_id   = hal_remote_l32( XPTR( txt_cxy , &txt_ptr->channel ) );
     2250
     2251    // transfer ownership only if target process is the TXT owner
    21102252    if( (owner_xp == process_xp) && (txt_id > 0) ) 
    21112253    {
     
    21142256        lock_xp = XPTR( txt_cxy , &txt_ptr->ext.txt.lock );
    21152257
    2116         // get lock
    2117         remote_busylock_acquire( lock_xp );
    2118 
    2119         if( process_get_ppid( process_xp ) != 1 )           // process is not KSH
     2258        if( process_get_ppid( process_xp ) != 1 )       // target process is not KSH
    21202259        {
     2260            // get lock
     2261            remote_busylock_acquire( lock_xp );
     2262
    21212263            // scan attached process list to find KSH process
    2122             XLIST_FOREACH( root_xp , iter_xp )
     2264            found = false;
     2265            for( iter_xp = hal_remote_l64( root_xp ) ;
     2266                 (iter_xp != root_xp) && (found == false) ;
     2267                 iter_xp = hal_remote_l64( iter_xp ) )
     2268            {
     2269                current_xp = XLIST_ELEMENT( iter_xp , process_t , txt_list );
     2270
     2271                if( process_get_ppid( current_xp ) == 1 )  // current is KSH
     2272                {
     2273                    // set owner field in TXT chdev
     2274                    hal_remote_s64( XPTR( txt_cxy , &txt_ptr->ext.txt.owner_xp ) , current_xp );
     2275
     2276#if DEBUG_PROCESS_TXT
     2277cycle = (uint32_t)hal_get_cycles();
     2278if( DEBUG_PROCESS_TXT < cycle )
     2279printk("\n[%s] thread[%x,%x] transfered TXT%d ownership to KSH / cycle %d\n",
     2280__FUNCTION__, this->process->pid, this->trdid, txt_id, cycle );
     2281#endif
     2282                    found = true;
     2283                }
     2284            }
     2285
     2286            // release lock
     2287            remote_busylock_release( lock_xp );
     2288
     2289// It must exist a KSH process for each user TXT channel
     2290assert( (found == true), "KSH process not found for TXT%d", txt_id );
     2291
     2292        }
     2293        else                                           // target process is KSH
     2294        {
     2295            // get lock
     2296            remote_busylock_acquire( lock_xp );
     2297
     2298            // scan attached process list to find another process
     2299            found = false;
     2300            for( iter_xp = hal_remote_l64( root_xp ) ;
     2301                 (iter_xp != root_xp) && (found == false) ;
     2302                 iter_xp = hal_remote_l64( iter_xp ) )
    21232303            {
    21242304                current_xp  = XLIST_ELEMENT( iter_xp , process_t , txt_list );
    2125                 current_cxy = GET_CXY( current_xp );
    2126                 current_ptr = GET_PTR( current_xp );
    2127 
    2128                 if( process_get_ppid( current_xp ) == 1 )  // current is KSH
     2305
     2306                if( current_xp != process_xp )            // current is not KSH
    21292307                {
    2130                     // release lock
    2131                     remote_busylock_release( lock_xp );
    2132 
    21332308                    // set owner field in TXT chdev
    21342309                    hal_remote_s64( XPTR( txt_cxy , &txt_ptr->ext.txt.owner_xp ) , current_xp );
    21352310
    21362311#if DEBUG_PROCESS_TXT
    2137 cycle = (uint32_t)hal_get_cycles();
    2138 uint32_t ksh_pid = hal_remote_l32( XPTR( current_cxy , &current_ptr->pid ) );
     2312cycle  = (uint32_t)hal_get_cycles();
     2313cxy_t       current_cxy = GET_CXY( current_xp );
     2314process_t * current_ptr = GET_PTR( current_xp );
     2315uint32_t    new_pid     = hal_remote_l32( XPTR( current_cxy , &current_ptr->pid ) );
    21392316if( DEBUG_PROCESS_TXT < cycle )
    2140 printk("\n[%s] thread[%x,%x] release TXT %d to KSH %x / cycle %d\n",
    2141 __FUNCTION__, this->process->pid, this->trdid, txt_id, ksh_pid, cycle );
    2142 process_txt_display( txt_id );
    2143 #endif
    2144                      return;
     2317printk("\n[%s] thread[%x,%x] transfered TXT%d ownership to process %x / cycle %d\n",
     2318__FUNCTION__,this->process->pid, this->trdid, txt_id, new_pid, cycle );
     2319#endif
     2320                    found = true;
    21452321                }
    21462322            }
    2147  
     2323
    21482324            // release lock
    21492325            remote_busylock_release( lock_xp );
    21502326
    2151             // PANIC if KSH not found
    2152             assert( false , "KSH process not found for TXT %d" );
    2153 
    2154             return;
     2327            // no more owner for TXT if no other process found
     2328            if( found == false )
     2329            {
     2330                // set owner field in TXT chdev
     2331                hal_remote_s64( XPTR( txt_cxy , &txt_ptr->ext.txt.owner_xp ) , XPTR_NULL );
     2332
     2333#if DEBUG_PROCESS_TXT
     2334cycle = (uint32_t)hal_get_cycles();
     2335if( DEBUG_PROCESS_TXT < cycle )
     2336printk("\n[%s] thread[%x,%x] released TXT%d (no attached process) / cycle %d\n",
     2337__FUNCTION__, this->process->pid, this->trdid, txt_id, cycle );
     2338#endif
     2339            }
    21552340        }
    2156         else                                               // process is KSH
    2157         {
    2158             // scan attached process list to find another process
    2159             XLIST_FOREACH( root_xp , iter_xp )
    2160             {
    2161                 current_xp  = XLIST_ELEMENT( iter_xp , process_t , txt_list );
    2162                 current_cxy = GET_CXY( current_xp );
    2163                 current_ptr = GET_PTR( current_xp );
    2164 
    2165                 if( current_xp != process_xp )            // current is not KSH
    2166                 {
    2167                     // release lock
    2168                     remote_busylock_release( lock_xp );
    2169 
    2170                     // set owner field in TXT chdev
    2171                     hal_remote_s64( XPTR( txt_cxy , &txt_ptr->ext.txt.owner_xp ) , current_xp );
     2341    }
     2342    else
     2343    {
    21722344
    21732345#if DEBUG_PROCESS_TXT
    2174 cycle  = (uint32_t)hal_get_cycles();
    2175 uint32_t new_pid = hal_remote_l32( XPTR( current_cxy , &current_ptr->pid ) );
     2346cycle = (uint32_t)hal_get_cycles();
    21762347if( DEBUG_PROCESS_TXT < cycle )
    2177 printk("\n[%s] thread[%x,%x] release TXT %d to process %x / cycle %d\n",
    2178 __FUNCTION__,this->process->pid, this->trdid, txt_id, new_pid, cycle );
    2179 process_txt_display( txt_id );
    2180 #endif
    2181                      return;
    2182                 }
    2183             }
    2184 
    2185             // release lock
    2186             remote_busylock_release( lock_xp );
    2187 
    2188             // no more owner for TXT if no other process found
    2189             hal_remote_s64( XPTR( txt_cxy , &txt_ptr->ext.txt.owner_xp ) , XPTR_NULL );
    2190 
    2191 #if DEBUG_PROCESS_TXT
    2192 cycle = (uint32_t)hal_get_cycles();
    2193 if( DEBUG_PROCESS_TXT < cycle )
    2194 printk("\n[%s] thread[%x,%x] release TXT %d to nobody / cycle %d\n",
    2195 __FUNCTION__, this->process->pid, this->trdid, txt_id, cycle );
    2196 process_txt_display( txt_id );
    2197 #endif
    2198             return;
    2199         }
    2200     }
    2201     else
    2202     {
    2203 
    2204 #if DEBUG_PROCESS_TXT
    2205 cycle = (uint32_t)hal_get_cycles();
    2206 if( DEBUG_PROCESS_TXT < cycle )
    2207 printk("\n[%s] thread %x in process %d does nothing (not TXT owner) / cycle %d\n",
    2208 __FUNCTION__, this->trdid, process_pid, cycle );
    2209 process_txt_display( txt_id );
    2210 #endif
    2211 
    2212     }
     2348printk("\n[%s] thread[%x,%x] does nothing for process %x (not TXT owner) / cycle %d\n",
     2349__FUNCTION__, this->process->pid, this->trdid, process_pid, cycle );
     2350#endif
     2351
     2352    }
     2353
    22132354}  // end process_txt_transfer_ownership()
    22142355
  • trunk/kernel/kern/process.h

    r623 r625  
    228228
    229229/*********************************************************************************************
    230  * This function initializes a reference, user process descriptor from another process
     230 * This function initializes a reference user process descriptor from another process
    231231 * descriptor, defined by the <parent_xp> argument. The <process> and <pid> arguments
    232232 * are previously allocated by the caller. This function can be called by two functions:
    233  * 1) process_init_create() : process is the INIT process; parent is process-zero.
     233 * 1) process_init_create() : process is the INIT process, and parent is process-zero.
    234234 * 2) process_make_fork() : the parent process descriptor is generally remote.
    235235 * The following fields are initialised :
    236236 * - It set the pid / ppid / ref_xp / parent_xp / state fields.
    237  * - It initializes the VMM (register the kentry, args, envs vsegs in VSL)
     237 * - It creates an empty GPT and an empty VSL.
     238 * - It initializes the locks protecting the GPT and the VSL.
     239 * - It registers the "kernel" vsegs in VSL, using the hal_vmm_kernel_update() function.
     240 * - It registers the "args" and "envs" vsegs in VSL, using the vmm_user_init() function.
     241 * - The "code and "data" must be registered later, using the elf_load_process() function.
    238242 * - It initializes the FDT, defining the three pseudo files STDIN / STDOUT / STDERR.
    239243 *   . if INIT process     => link to kernel TXT[0].
    240  *   . if KSH[i] process   => allocate a free TXT[i] and give TXT ownership.
    241  *   . if USER process     => same TXT[i] as parent process and give TXT ownership.
     244 *   . if KSH[i] process   => allocate a free TXT[i].
     245 *   . if USER process     => link to parent process TXT[i].
    242246 * - It set the root_xp, bin_xp, cwd_xp fields.
    243247 * - It reset the children list as empty, but does NOT register it in parent children list.
     
    251255 * @ pid          : [in] process identifier.
    252256 * @ parent_xp    : [in] extended pointer on parent process descriptor.
    253  ********************************************************************************************/
    254 void process_reference_init( process_t * process,
    255                              pid_t       pid,
    256                              xptr_t      parent_xp );
     257 * @ return 0 if success / return -1 if failure
     258 ********************************************************************************************/
     259error_t process_reference_init( process_t * process,
     260                                pid_t       pid,
     261                                xptr_t      parent_xp );
    257262
    258263/*********************************************************************************************
    259264 * This function initializes a copy process descriptor, in the local cluster,
    260265 * from information defined in the reference remote process descriptor.
     266 * As the VSL and the GPT of a process copy are handled as local caches, the GPT copy is
     267 * created empty, and the VSL copy contains only the "kernel", "args", and "envs" vsegs.
    261268 *********************************************************************************************
    262269 * @ process              : [in] local pointer on process descriptor to initialize.
    263270 * @ reference_process_xp : [in] extended pointer on reference process descriptor.
    264  * @ return 0 if success / return ENOMEM if failure
     271 * @ return 0 if success / return -1 if failure
    265272 ********************************************************************************************/
    266273error_t process_copy_init( process_t * local_process,
     
    272279 * The local th_tbl[] array must be empty.
    273280 *********************************************************************************************
    274  * @ process     : pointer on the process descriptor.
     281 * @ process     : [in] pointer on the process descriptor.
    275282 ********************************************************************************************/
    276283void process_destroy( process_t * process );
     
    283290 * taken by the caller function.
    284291 *********************************************************************************************
    285  * @ process_xp : extended pointer on process descriptor.
     292 * @ process_xp    : [in] extended pointer on process descriptor.
    286293 ********************************************************************************************/
    287294void process_display( xptr_t process_xp );
     
    396403/*********************************************************************************************
    397404 * This function implements the "fork" system call, and is called by the sys_fork() function,
    398  * likely throuch the RPC_PROCESS_MAKE_FORK.
    399  * It allocates memory and initializes a new "child" process descriptor, and the associated
    400  * "child" thread descriptor in local cluster. It involves up to three different clusters :
     405 * likely through the RPC_PROCESS_MAKE_FORK.
     406 * It allocates memory and initializes a new child process descriptor, and the associated
     407 * child thread descriptor in local cluster. It involves up to three different clusters:
    401408 * - the child (local) cluster can be any cluster selected by the sys_fork function.
    402409 * - the parent cluster must be the reference cluster for the parent process.
    403410 * - the client cluster containing the thread requesting the fork can be any cluster.
    404  * The new "child" process descriptor is initialised from informations found in the "parent"
     411 * The new child process descriptor is initialised from informations found in the parent
    405412 * reference process descriptor, containing the complete process description.
    406  * The new "child" thread descriptor is initialised from informations found in the "parent"
     413 * The new child thread descriptor is initialised from informations found in the parent
    407414 * thread descriptor.
    408415 *********************************************************************************************
     
    504511
    505512/*********************************************************************************************
    506  * This function atomically registers a new thread in the local process descriptor.
    507  * It checks that there is an available slot in the local th_tbl[] array, and allocates
    508  * a new LTID using the relevant lock depending on the kernel/user type.
    509  *********************************************************************************************
    510  * @ process  : pointer on the local process descriptor.
    511  * @ thread   : pointer on new thread to be registered.
     513 * This function atomically registers a new thread identified by the <thread> argument
     514 * in the th_tbl[] array of the local process descriptor identified by the <process>
     515 * argument. It checks that there is an available slot in the local th_tbl[] array,
     516 * and allocates a new LTID using the relevant lock depending on the kernel/user type,
     517 * and returns the global thread identifier in the <trdid> buffer.
     518 *********************************************************************************************
     519 * @ process  : [in]  pointer on the local process descriptor.
     520 * @ thread   : [in]  pointer on new thread to be registered.
    512521 * @ trdid    : [out] buffer for allocated trdid.
    513522 * @ returns 0 if success / returns non zero if no slot available.
     
    516525                                 struct thread_s * thread,
    517526                                 trdid_t         * trdid );
     527
     528/*********************************************************************************************
     529 * This function atomically removes a thread identified by the <thread> argument from
     530 * the local process descriptor th_tbl[] array, and returns the number of thread currently
     531 * registered in th_tbl[] array before this remove.
     532 *********************************************************************************************
     533 * @ thread   : pointer on thread to be removed.
     534 * @ returns number of threads registered in th_tbl before thread remove.
     535 ********************************************************************************************/
     536uint32_t process_remove_thread( struct thread_s * thread );
    518537
    519538
     
    556575
    557576/*********************************************************************************************
    558  * This function gives a process identified by the <process_xp> argument the exclusive
     577 * This function gives a process identified by the <process_xp> argument the
    559578 * ownership of its attached TXT_RX terminal (i.e. put the process in foreground).
    560  * It can be called by a thread running in any cluster, but the <process_xp> must be the
    561  * owner cluster process descriptor.
     579 * It can be called by a thread running in any cluster, but the target process descriptor
     580 * must be the process owner.
    562581 *********************************************************************************************
    563582 * @ owner_xp  : extended pointer on process descriptor in owner cluster.
     
    566585
    567586/*********************************************************************************************
    568  * When the process identified by the <owner_xp> argument has the exclusive ownership of
    569  * the TXT_RX terminal, this function transfer this ownership to another attached process.
    570  * The process descriptor must be the process owner.
    571  * This function does nothing if the process identified by the <process_xp> is not
    572  * the TXT owner.
     587 * When the target process identified by the <owner_xp> argument has the exclusive ownership
     588 * of the TXT_RX terminal, this function transfer this ownership to another process attached
     589 * to the same terminal. The target process descriptor must be the process owner.
     590 * This function does nothing if the target process is not the TXT owner.
    573591 * - If the current owner is not the KSH process, the new owner is the KSH process.
    574592 * - If the current owner is the KSH process, the new owner is another attached process.
  • trunk/kernel/kern/rpc.c

    r624 r625  
    2424#include <kernel_config.h>
    2525#include <hal_kernel_types.h>
     26#include <hal_vmm.h>
    2627#include <hal_atomic.h>
    2728#include <hal_remote.h>
     
    5253    &rpc_pmem_get_pages_server,            // 0
    5354    &rpc_pmem_release_pages_server,        // 1
    54     &rpc_undefined,                        // 2    unused slot
     55    &rpc_ppm_display_server,               // 2
    5556    &rpc_process_make_fork_server,         // 3
    5657    &rpc_user_dir_create_server,           // 4
     
    8182    &rpc_vmm_create_vseg_server,           // 27
    8283    &rpc_vmm_set_cow_server,               // 28
    83     &rpc_hal_vmm_display_server,               // 29
     84    &rpc_hal_vmm_display_server,           // 29
    8485};
    8586
     
    8889    "PMEM_GET_PAGES",            // 0
    8990    "PMEM_RELEASE_PAGES",        // 1
    90     "undefined",                 // 2
     91    "PPM_DISPLAY",               // 2
    9192    "PROCESS_MAKE_FORK",         // 3
    9293    "USER_DIR_CREATE",           // 4
     
    566567
    567568/////////////////////////////////////////////////////////////////////////////////////////
    568 // [2]      undefined slot
    569 /////////////////////////////////////////////////////////////////////////////////////////
     569// [2]            Marshaling functions attached to RPC_PPM_DISPLAY   
     570/////////////////////////////////////////////////////////////////////////////////////////
     571
     572/////////////////////////////////////////
     573void rpc_ppm_display_client( cxy_t  cxy )
     574{
     575#if DEBUG_RPC_PPM_DISPLAY
     576thread_t * this = CURRENT_THREAD;
     577uint32_t cycle = (uint32_t)hal_get_cycles();
     578if( cycle > DEBUG_RPC_PPM_DISPLAY )
     579printk("\n[%s] thread[%x,%x] on core %d enter / cycle %d\n",
     580__FUNCTION__, this->process->pid, this->trdid, this->core->lid , cycle );
     581#endif
     582
     583    uint32_t responses = 1;
     584
     585    // initialise RPC descriptor header
     586    rpc_desc_t  rpc;
     587    rpc.index    = RPC_PPM_DISPLAY;
     588    rpc.blocking = true;
     589    rpc.rsp      = &responses;
     590
     591    // register RPC request in remote RPC fifo
     592    rpc_send( cxy , &rpc );
     593
     594#if DEBUG_RPC_PPM_DISPLAY
     595cycle = (uint32_t)hal_get_cycles();
     596if( cycle > DEBUG_RPC_PPM_DISPLAY )
     597printk("\n[%s] thread[%x,%x] on core %d exit / cycle %d\n",
     598__FUNCTION__, this->process->pid, this->trdid, this->core->lid, cycle );
     599#endif
     600}
     601
     602////////////////////////////////////////////////////////////////////
     603void rpc_ppm_display_server( xptr_t __attribute__((__unused__)) xp )
     604{
     605#if DEBUG_RPC_PPM_DISPLAY
     606thread_t * this = CURRENT_THREAD;
     607uint32_t cycle = (uint32_t)hal_get_cycles();
     608if( cycle > DEBUG_RPC_PPM_DISPLAY )
     609printk("\n[%s] thread[%x,%x] on core %d enter / cycle %d\n",
     610__FUNCTION__, this->process->pid, this->trdid, this->core->lid , cycle );
     611#endif
     612
     613    // call local kernel function
     614    ppm_display();
     615
     616#if DEBUG_RPC_PPM_DISPLAY
     617cycle = (uint32_t)hal_get_cycles();
     618if( cycle > DEBUG_RPC_PPM_DISPLAY )
     619printk("\n[%s] thread[%x,%x] on core %d exit / cycle %d\n",
     620__FUNCTION__, this->process->pid, this->trdid, this->core->lid, cycle );
     621#endif
     622}
    570623
    571624/////////////////////////////////////////////////////////////////////////////////////////
  • trunk/kernel/kern/rpc.h

    r624 r625  
    6262    RPC_PMEM_GET_PAGES            = 0,
    6363    RPC_PMEM_RELEASE_PAGES        = 1,
    64     RPC_UNDEFINED_2               = 2,     
     64    RPC_PPM_DISPLAY               = 2,     
    6565    RPC_PROCESS_MAKE_FORK         = 3,
    6666    RPC_USER_DIR_CREATE           = 4,
     
    200200
    201201/***********************************************************************************
    202  * [2] undefined slot
    203  **********************************************************************************/
     202 * [2] The RPC_PPM_DISPLAY allows any client thread to require any remote cluster
     203 * identified by the <cxy> argumentto display the physical memory allocator state.
     204 **********************************************************************************/
     205void rpc_ppm_display_client( cxy_t  cxy );
     206
     207void rpc_ppm_display_server( xptr_t xp );
    204208
    205209/***********************************************************************************
  • trunk/kernel/kern/scheduler.c

    r624 r625  
    180180    sched = &core->scheduler;
    181181
    182     /////////////// scan user threads to handle both ACK and DELETE requests
     182    ////////////////// scan user threads to handle both ACK and DELETE requests
    183183    root = &sched->u_root;
    184184    iter = root->next;
     
    240240            busylock_release( &sched->lock );
    241241
    242 // check th_nr value
    243 assert( (process->th_nr > 0) , "process th_nr cannot be 0\n" );
    244 
    245             // remove thread from process th_tbl[]
    246             process->th_tbl[ltid] = NULL;
    247             count = hal_atomic_add( &process->th_nr , - 1 );
    248  
    249             // release memory allocated for thread descriptor
    250             thread_destroy( thread );
     242            // release memory allocated for thread
     243            count = thread_destroy( thread );
    251244
    252245            hal_fence();
     
    255248uint32_t cycle = (uint32_t)hal_get_cycles();
    256249if( DEBUG_SCHED_HANDLE_SIGNALS < cycle )
    257 printk("\n[%s] thread[%x,%x] on core[%x,%d] deleted / cycle %d\n",
    258 __FUNCTION__ , process->pid , thread->trdid , local_cxy , thread->core->lid , cycle );
     250printk("\n[%s] thread[%x,%x] on core[%x,%d] deleted / %d threads / cycle %d\n",
     251__FUNCTION__, process->pid, thread->trdid, local_cxy, thread->core->lid, count, cycle );
    259252#endif
    260253            // destroy process descriptor if last thread
     
    274267    }  // end user threads
    275268
    276     ////// scan kernel threads for DELETE only
     269    ///////////// scan kernel threads for DELETE only
    277270    root = &sched->k_root;
    278271    iter = root->next;
     
    290283
    291284// check process descriptor is local kernel process
    292 assert( ( thread->process == &process_zero ) , "illegal process descriptor\n");
     285assert( ( thread->process == &process_zero ) , "illegal process descriptor");
    293286
    294287            // get thread ltid
     
    325318
    326319// check th_nr value
    327 assert( (process_zero.th_nr > 0) , "kernel process th_nr cannot be 0\n" );
     320assert( (process_zero.th_nr > 0) , "kernel process th_nr cannot be 0" );
    328321
    329322            // remove thread from process th_tbl[]
     
    477470}  // end sched_register_thread()
    478471
    479 //////////////////////////////////////
    480 void sched_yield( const char * cause )
     472//////////////////////////////////////////////////////////////////
     473void sched_yield( const char * cause __attribute__((__unused__)) )
    481474{
    482475    thread_t      * next;
     
    512505// check next thread kernel_stack overflow
    513506assert( (next->signature == THREAD_SIGNATURE),
    514 "kernel stack overflow for thread %x on core[%x,%d] \n", next, local_cxy, lid );
     507"kernel stack overflow for thread %x on core[%x,%d]", next, local_cxy, lid );
    515508
    516509// check next thread attached to same core as the calling thread
    517510assert( (next->core == current->core),
    518 "next core %x != current core %x\n", next->core, current->core );
     511"next core %x != current core %x", next->core, current->core );
    519512
    520513// check next thread not blocked when type != IDLE
    521514assert( ((next->blocked == 0) || (next->type == THREAD_IDLE)) ,
    522 "next thread %x (%s) is blocked on core[%x,%d]\n",
     515"next thread %x (%s) is blocked on core[%x,%d]",
    523516next->trdid , thread_type_str(next->type) , local_cxy , lid );
    524517
     
    561554#if (DEBUG_SCHED_YIELD & 1)
    562555// if( sched->trace )
    563 if(uint32_t)hal_get_cycles() > DEBUG_SCHED_YIELD )
     556if( (uint32_t)hal_get_cycles() > DEBUG_SCHED_YIELD )
    564557printk("\n[%s] core[%x,%d] / cause = %s\n"
    565558"      thread %x (%s) (%x,%x) continue / cycle %d\n",
     
    584577    list_entry_t * iter;
    585578    thread_t     * thread;
    586 
    587 // check lid
    588 assert( (lid < LOCAL_CLUSTER->cores_nr),
    589 "illegal core index %d\n", lid);
    590579
    591580    core_t       * core    = &LOCAL_CLUSTER->core_tbl[lid];
     
    644633{
    645634    thread_t     * thread;
    646 
    647 // check cxy
    648 assert( (cluster_is_undefined( cxy ) == false),
    649 "illegal cluster %x\n", cxy );
    650 
    651 assert( (lid < hal_remote_l32( XPTR( cxy , &LOCAL_CLUSTER->cores_nr ) ) ),
    652 "illegal core index %d\n", lid );
    653635
    654636    // get local pointer on target scheduler
  • trunk/kernel/kern/thread.c

    r624 r625  
    33 *
    44 * Author  Ghassan Almaless (2008,2009,2010,2011,2012)
    5  *         Alain Greiner (2016,2017,2018)
     5 *         Alain Greiner (2016,2017,2018,2019)
    66 *
    77 * Copyright (c) UPMC Sorbonne Universites
     
    2929#include <hal_special.h>
    3030#include <hal_remote.h>
     31#include <hal_vmm.h>
    3132#include <memcpy.h>
    3233#include <printk.h>
     
    9697
    9798/////////////////////////////////////////////////////////////////////////////////////
    98 // This static function releases the physical memory for a thread descriptor.
    99 // It is called by the three functions:
    100 // - thread_user_create()
    101 // - thread_user_fork()
    102 // - thread_kernel_create()
    103 /////////////////////////////////////////////////////////////////////////////////////
    104 // @ thread  : pointer on thread descriptor.
    105 /////////////////////////////////////////////////////////////////////////////////////
    106 static void thread_release( thread_t * thread )
    107 {
    108     kmem_req_t   req;
    109 
    110     xptr_t base_xp = ppm_base2page( XPTR(local_cxy , thread ) );
    111 
    112     req.type  = KMEM_PAGE;
    113     req.ptr   = GET_PTR( base_xp );
    114     kmem_free( &req );
    115 }
    116 
    117 /////////////////////////////////////////////////////////////////////////////////////
    11899// This static function initializes a thread descriptor (kernel or user).
    119100// It can be called by the four functions:
     
    122103// - thread_kernel_create()
    123104// - thread_idle_init()
     105// The "type" and "trdid" fields must have been previously set.
    124106// It updates the local DQDT.
    125107/////////////////////////////////////////////////////////////////////////////////////
    126 // @ thread       : pointer on local thread descriptor
    127 // @ process      : pointer on local process descriptor.
    128 // @ type         : thread type.
    129 // @ func         : pointer on thread entry function.
    130 // @ args         : pointer on thread entry function arguments.
    131 // @ core_lid     : target core local index.
    132 // @ u_stack_base : stack base (user thread only)
    133 // @ u_stack_size : stack base (user thread only)
     108// @ thread          : pointer on local thread descriptor
     109// @ process         : pointer on local process descriptor.
     110// @ type            : thread type.
     111// @ trdid           : thread identifier
     112// @ func            : pointer on thread entry function.
     113// @ args            : pointer on thread entry function arguments.
     114// @ core_lid        : target core local index.
     115// @ user_stack_vseg : local pointer on user stack vseg (user thread only)
    134116/////////////////////////////////////////////////////////////////////////////////////
    135117static error_t thread_init( thread_t      * thread,
    136118                            process_t     * process,
    137119                            thread_type_t   type,
     120                            trdid_t         trdid,
    138121                            void          * func,
    139122                            void          * args,
    140123                            lid_t           core_lid,
    141                             intptr_t        u_stack_base,
    142                             uint32_t        u_stack_size )
    143 {
    144     error_t        error;
    145     trdid_t        trdid;      // allocated thread identifier
    146 
    147         cluster_t    * local_cluster = LOCAL_CLUSTER;
     124                            vseg_t        * user_stack_vseg )
     125{
     126
     127// check type and trdid fields initialized
     128assert( (thread->type == type)   , "bad type argument" );
     129assert( (thread->trdid == trdid) , "bad trdid argument" );
    148130
    149131#if DEBUG_THREAD_INIT
     
    152134if( DEBUG_THREAD_INIT < cycle )
    153135printk("\n[%s] thread[%x,%x] enter for thread %x in process %x / cycle %d\n",
    154 __FUNCTION__, this->process->pid, this->trdid, thread, process->pid , cycle );
     136__FUNCTION__, this->process->pid, this->trdid, thread->trdid, process->pid , cycle );
    155137#endif
    156138
     
    159141
    160142        // Initialize new thread descriptor
    161         thread->type            = type;
    162143    thread->quantum         = 0;            // TODO
    163144    thread->ticks_nr        = 0;            // TODO
    164145    thread->time_last_check = 0;            // TODO
    165         thread->core            = &local_cluster->core_tbl[core_lid];
     146        thread->core            = &LOCAL_CLUSTER->core_tbl[core_lid];
    166147        thread->process         = process;
    167 
    168148    thread->busylocks       = 0;
    169149
     
    172152#endif
    173153
    174     thread->u_stack_base    = u_stack_base;
    175     thread->u_stack_size    = u_stack_size;
     154    thread->user_stack_vseg = user_stack_vseg;
    176155    thread->k_stack_base    = (intptr_t)thread + desc_size;
    177156    thread->k_stack_size    = CONFIG_THREAD_DESC_SIZE - desc_size;
    178 
    179157    thread->entry_func      = func;         // thread entry point
    180158    thread->entry_args      = args;         // thread function arguments
     
    185163    thread->blocked         = THREAD_BLOCKED_GLOBAL;
    186164
    187     // register new thread in process descriptor, and get a TRDID
    188     error = process_register_thread( process, thread , &trdid );
    189 
    190     if( error )
    191     {
    192         printk("\n[ERROR] in %s : thread %x in process %x cannot get TRDID in cluster %x\n"
    193         "    for thread %s in process %x / cycle %d\n",
    194         __FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid,
    195         local_cxy, thread_type_str(type), process->pid, (uint32_t)hal_get_cycles() );
    196         return EINVAL;
    197     }
    198 
    199     // initialize trdid
    200     thread->trdid           = trdid;
    201 
    202165    // initialize sched list
    203166    list_entry_init( &thread->sched_list );
     
    237200} // end thread_init()
    238201
    239 /////////////////////////////////////////////////////////
     202//////////////////////////////////////////////////
    240203error_t thread_user_create( pid_t             pid,
    241204                            void            * start_func,
     
    246209    error_t        error;
    247210        thread_t     * thread;       // pointer on created thread descriptor
     211    trdid_t        trdid;        // created thred identifier
    248212    process_t    * process;      // pointer to local process descriptor
    249213    lid_t          core_lid;     // selected core local index
    250     vseg_t       * vseg;         // stack vseg
     214    vseg_t       * us_vseg;      // user stack vseg
    251215
    252216assert( (attr != NULL) , "pthread attributes must be defined" );
     
    266230    {
    267231                printk("\n[ERROR] in %s : cannot get process descriptor %x\n",
    268                __FUNCTION__ , pid );
    269         return ENOMEM;
     232        __FUNCTION__ , pid );
     233        return -1;
    270234    }
    271235
     
    284248                printk("\n[ERROR] in %s : illegal core index attribute = %d\n",
    285249            __FUNCTION__ , core_lid );
    286             return EINVAL;
     250            return -1;
    287251        }
    288252    }
     
    298262#endif
    299263
    300     // allocate a stack from local VMM
    301     vseg = vmm_create_vseg( process,
    302                             VSEG_TYPE_STACK,
    303                             0,                 // size unused
    304                             0,                 // length unused
    305                             0,                 // file_offset unused
    306                             0,                 // file_size unused
    307                             XPTR_NULL,         // mapper_xp unused
    308                             local_cxy );
    309 
    310     if( vseg == NULL )
    311     {
    312             printk("\n[ERROR] in %s : cannot create stack vseg\n", __FUNCTION__ );
    313                 return ENOMEM;
    314     }
    315 
    316 #if( DEBUG_THREAD_USER_CREATE & 1)
    317 if( DEBUG_THREAD_USER_CREATE < cycle )
    318 printk("\n[%s] stack vseg created / vpn_base %x / %d pages\n",
    319 __FUNCTION__, vseg->vpn_base, vseg->vpn_size );
    320 #endif
    321 
    322264    // allocate memory for thread descriptor
    323265    thread = thread_alloc();
     
    325267    if( thread == NULL )
    326268    {
    327             printk("\n[ERROR] in %s : cannot create new thread\n", __FUNCTION__ );
    328         vmm_delete_vseg( process->pid , vseg->min );
    329         return ENOMEM;
     269            printk("\n[ERROR] in %s : cannot create new thread in cluster %x\n",
     270        __FUNCTION__, local_cxy );
     271        return -1;
    330272    }
    331273
     
    336278#endif
    337279
     280    // set type in thread descriptor
     281    thread->type = THREAD_USER;
     282
     283    // register new thread in process descriptor, and get a TRDID
     284    error = process_register_thread( process, thread , &trdid );
     285
     286    if( error )
     287    {
     288        printk("\n[ERROR] in %s : cannot register new thread in process %x\n",
     289        __FUNCTION__, pid );
     290        thread_destroy( thread );
     291        return -1;
     292    }
     293
     294    // set trdid in thread descriptor
     295    thread->trdid = trdid;
     296
     297#if( DEBUG_THREAD_USER_CREATE & 1)
     298if( DEBUG_THREAD_USER_CREATE < cycle )
     299printk("\n[%s] new thread %x registered in process %x\n",
     300__FUNCTION__, trdid, pid );
     301#endif
     302
     303    // allocate a stack from local VMM
     304    us_vseg = vmm_create_vseg( process,
     305                               VSEG_TYPE_STACK,
     306                               LTID_FROM_TRDID( trdid ),
     307                               0,                         // size unused
     308                               0,                         // file_offset unused
     309                               0,                         // file_size unused
     310                               XPTR_NULL,                 // mapper_xp unused
     311                               local_cxy );
     312
     313    if( us_vseg == NULL )
     314    {
     315            printk("\n[ERROR] in %s : cannot create stack vseg\n", __FUNCTION__ );
     316        process_remove_thread( thread );
     317        thread_destroy( thread );
     318                return -1;
     319    }
     320
     321#if( DEBUG_THREAD_USER_CREATE & 1)
     322if( DEBUG_THREAD_USER_CREATE < cycle )
     323printk("\n[%s] stack vseg created / vpn_base %x / %d pages\n",
     324__FUNCTION__, us_vseg->vpn_base, us_vseg->vpn_size );
     325#endif
     326
    338327    // initialize thread descriptor
    339328    error = thread_init( thread,
    340329                         process,
    341330                         THREAD_USER,
     331                         trdid,
    342332                         start_func,
    343333                         start_arg,
    344334                         core_lid,
    345                          vseg->min,
    346                          vseg->max - vseg->min );
     335                         us_vseg );
    347336    if( error )
    348337    {
    349338            printk("\n[ERROR] in %s : cannot initialize new thread\n", __FUNCTION__ );
    350         vmm_delete_vseg( process->pid , vseg->min );
    351         thread_release( thread );
    352         return EINVAL;
     339        vmm_remove_vseg( process , us_vseg );
     340        process_remove_thread( thread );
     341        thread_destroy( thread );
     342        return -1;
    353343    }
    354344
    355345#if( DEBUG_THREAD_USER_CREATE & 1)
    356346if( DEBUG_THREAD_USER_CREATE < cycle )
    357 printk("\n[%s] new thread descriptor initialised / trdid %x\n",
    358 __FUNCTION__, thread->trdid );
     347printk("\n[%s] new thread %x in process %x initialised\n",
     348__FUNCTION__, thread->trdid, process->pid );
    359349#endif
    360350
     
    369359    {
    370360            printk("\n[ERROR] in %s : cannot create CPU context\n", __FUNCTION__ );
    371         vmm_delete_vseg( process->pid , vseg->min );
    372         thread_release( thread );
    373         return ENOMEM;
     361        vmm_remove_vseg( process , us_vseg );
     362        process_remove_thread( thread );
     363        thread_destroy( thread );
     364        return -1;
    374365    }
    375366    hal_cpu_context_init( thread );
     
    379370    {
    380371            printk("\n[ERROR] in %s : cannot create FPU context\n", __FUNCTION__ );
    381         vmm_delete_vseg( process->pid , vseg->min );
    382         thread_release( thread );
    383         return ENOMEM;
     372        vmm_remove_vseg( process , us_vseg );
     373        process_remove_thread( thread );
     374        thread_destroy( thread );
     375        return -1;
    384376    }
    385377    hal_fpu_context_init( thread );
     
    410402{
    411403    error_t        error;
    412         thread_t     * child_ptr;        // local pointer on local child thread
     404        thread_t     * child_ptr;        // local pointer on child thread
     405    trdid_t        child_trdid;      // child thread identifier
    413406    lid_t          core_lid;         // selected core local index
    414 
    415407    thread_t     * parent_ptr;       // local pointer on remote parent thread
    416408    cxy_t          parent_cxy;       // parent thread cluster
    417409    process_t    * parent_process;   // local pointer on parent process
    418410    xptr_t         parent_gpt_xp;    // extended pointer on parent thread GPT
    419 
    420     void         * func;             // parent thread entry_func
    421     void         * args;             // parent thread entry_args
    422     intptr_t       base;             // parent thread u_stack_base
    423     uint32_t       size;             // parent thread u_stack_size
    424     uint32_t       flags;            // parent_thread flags
    425     vpn_t          vpn_base;         // parent thread stack vpn_base
    426     vpn_t          vpn_size;         // parent thread stack vpn_size
    427     reg_t        * uzone;            // parent thread pointer on uzone 
    428 
    429     vseg_t       * vseg;             // child thread STACK vseg
     411    void         * parent_func;      // parent thread entry_func
     412    void         * parent_args;      // parent thread entry_args
     413    uint32_t       parent_flags;     // parent_thread flags
     414    vseg_t       * parent_us_vseg;   // parent thread user stack vseg
     415    vseg_t       * child_us_vseg;    // child thread user stack vseg
    430416
    431417#if DEBUG_THREAD_USER_FORK
     
    433419thread_t * this  = CURRENT_THREAD;
    434420if( DEBUG_THREAD_USER_FORK < cycle )
    435 printk("\n[%s] thread[%x,%x] enter / child_process %x / cycle %d\n",
     421printk("\n[%s] thread[%x,%x] enter for child_process %x / cycle %d\n",
    436422__FUNCTION__, this->process->pid, this->trdid, child_process->pid, cycle );
    437423#endif
     
    439425    // select a target core in local cluster
    440426    core_lid = cluster_select_local_core();
     427
     428#if (DEBUG_THREAD_USER_FORK & 1)
     429if( DEBUG_THREAD_USER_FORK < cycle )
     430printk("\n[%s] thread[%x,%x] selected core [%x,%d]\n",
     431__FUNCTION__, this->process->pid, this->trdid, local_cxy, core_lid );
     432#endif
    441433
    442434    // get cluster and local pointer on parent thread descriptor
     
    444436    parent_ptr = GET_PTR( parent_thread_xp );
    445437
    446     // get relevant fields from parent thread
    447     func  = (void *)  hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->entry_func    ));
    448     args  = (void *)  hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->entry_args    ));
    449     base  = (intptr_t)hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->u_stack_base  ));
    450     size  = (uint32_t)hal_remote_l32 ( XPTR( parent_cxy , &parent_ptr->u_stack_size  ));
    451     flags =           hal_remote_l32 ( XPTR( parent_cxy , &parent_ptr->flags         ));
    452     uzone = (reg_t *) hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->uzone_current ));
    453 
    454     vpn_base = base >> CONFIG_PPM_PAGE_SHIFT;
    455     vpn_size = size >> CONFIG_PPM_PAGE_SHIFT;
     438    // get relevant infos from parent thread
     439    parent_func    = (void *)  hal_remote_lpt( XPTR(parent_cxy,&parent_ptr->entry_func ));
     440    parent_args    = (void *)  hal_remote_lpt( XPTR(parent_cxy,&parent_ptr->entry_args ));
     441    parent_flags   = (uint32_t)hal_remote_l32( XPTR(parent_cxy,&parent_ptr->flags ));
     442    parent_us_vseg = (vseg_t *)hal_remote_lpt( XPTR(parent_cxy,&parent_ptr->user_stack_vseg ));
    456443
    457444    // get pointer on parent process in parent thread cluster
     
    459446                                                        &parent_ptr->process ) );
    460447 
    461     // get extended pointer on parent GPT in parent thread cluster
     448    // build extended pointer on parent GPT in parent thread cluster
    462449    parent_gpt_xp = XPTR( parent_cxy , &parent_process->vmm.gpt );
     450
     451#if (DEBUG_THREAD_USER_FORK & 1)
     452if( DEBUG_THREAD_USER_FORK < cycle )
     453printk("\n[%s] thread[%x,%x] get parent GPT\n",
     454__FUNCTION__, this->process->pid, this->trdid );
     455#endif
    463456
    464457    // allocate memory for child thread descriptor
    465458    child_ptr = thread_alloc();
     459
    466460    if( child_ptr == NULL )
    467461    {
    468         printk("\n[ERROR] in %s : cannot allocate new thread\n", __FUNCTION__ );
     462        printk("\n[ERROR] in %s : cannot allocate new thread\n",
     463        __FUNCTION__ );
    469464        return -1;
    470465    }
     466
     467#if (DEBUG_THREAD_USER_FORK & 1)
     468if( DEBUG_THREAD_USER_FORK < cycle )
     469printk("\n[%s] thread[%x,%x] allocated new thread descriptor %x\n",
     470__FUNCTION__, this->process->pid, this->trdid, child_ptr );
     471#endif
     472
     473    // set type in thread descriptor
     474    child_ptr->type = THREAD_USER;
     475
     476    // register new thread in process descriptor, and get a TRDID
     477    error = process_register_thread( child_process, child_ptr , &child_trdid );
     478
     479    if( error )
     480    {
     481        printk("\n[ERROR] in %s : cannot register new thread in process %x\n",
     482        __FUNCTION__, child_process->pid );
     483        thread_destroy( child_ptr );
     484        return -1;
     485    }
     486
     487    // set trdid in thread descriptor
     488    child_ptr->trdid = child_trdid;
     489
     490#if (DEBUG_THREAD_USER_FORK & 1)
     491if( DEBUG_THREAD_USER_FORK < cycle )
     492printk("\n[%s] thread[%x,%x] registered child thread %x in child process %x\n",
     493__FUNCTION__, this->process->pid, this->trdid, child_trdid, child_process->pid );
     494#endif
     495
     496    // get an user stack vseg from local VMM allocator
     497    child_us_vseg = vmm_create_vseg( child_process,
     498                                     VSEG_TYPE_STACK,
     499                                     LTID_FROM_TRDID( child_trdid ), 
     500                                     0,                               // size unused
     501                                     0,                               // file_offset unused
     502                                     0,                               // file_size unused
     503                                     XPTR_NULL,                       // mapper_xp unused
     504                                     local_cxy );
     505    if( child_us_vseg == NULL )
     506    {
     507            printk("\n[ERROR] in %s : cannot create stack vseg\n", __FUNCTION__ );
     508        process_remove_thread( child_ptr );
     509        thread_destroy( child_ptr );
     510        return -1;
     511    }
     512
     513#if (DEBUG_THREAD_USER_FORK & 1)
     514if( DEBUG_THREAD_USER_FORK < cycle )
     515printk("\n[%s] thread[%x,%x] created an user stack vseg / vpn_base %x / %d pages\n",
     516__FUNCTION__, this->process->pid, this->trdid,
     517child_us_vseg->vpn_base, child_us_vseg->vpn_size );
     518#endif
    471519
    472520    // initialize thread descriptor
     
    474522                         child_process,
    475523                         THREAD_USER,
    476                          func,
    477                          args,
     524                         child_trdid,
     525                         parent_func,
     526                         parent_args,
    478527                         core_lid,
    479                          base,
    480                          size );
     528                         child_us_vseg );
    481529    if( error )
    482530    {
    483531            printk("\n[ERROR] in %s : cannot initialize child thread\n", __FUNCTION__ );
    484         thread_release( child_ptr );
    485         return EINVAL;
     532        vmm_remove_vseg( child_process , child_us_vseg );
     533        process_remove_thread( child_ptr );
     534        thread_destroy( child_ptr );
     535        return -1;
    486536    }
    487537
     
    492542#endif
    493543
    494     // return child pointer
    495     *child_thread = child_ptr;
    496 
    497544    // set detached flag if required
    498     if( flags & THREAD_FLAG_DETACHED ) child_ptr->flags = THREAD_FLAG_DETACHED;
    499 
    500     // update uzone pointer in child thread descriptor
    501     child_ptr->uzone_current = (char *)((intptr_t)uzone +
    502                                         (intptr_t)child_ptr -
    503                                         (intptr_t)parent_ptr );
    504  
    505 
    506     // allocate CPU context for child thread
     545    if( parent_flags & THREAD_FLAG_DETACHED ) child_ptr->flags = THREAD_FLAG_DETACHED;
     546
     547    // allocate a CPU context for child thread
    507548        if( hal_cpu_context_alloc( child_ptr ) )
    508549    {
    509550            printk("\n[ERROR] in %s : cannot allocate CPU context\n", __FUNCTION__ );
    510         thread_release( child_ptr );
     551        vmm_remove_vseg( child_process , child_us_vseg );
     552        process_remove_thread( child_ptr );
     553        thread_destroy( child_ptr );
    511554        return -1;
    512555    }
    513556
    514     // allocate FPU context for child thread
     557    // allocate a FPU context for child thread
    515558        if( hal_fpu_context_alloc( child_ptr ) )
    516559    {
    517560            printk("\n[ERROR] in %s : cannot allocate FPU context\n", __FUNCTION__ );
    518         thread_release( child_ptr );
     561        vmm_remove_vseg( child_process , child_us_vseg );
     562        process_remove_thread( child_ptr );
     563        thread_destroy( child_ptr );
    519564        return -1;
    520565    }
     
    526571#endif
    527572
    528    // create and initialize STACK vseg
    529     vseg = vseg_alloc();
    530     vseg_init( vseg,
    531                VSEG_TYPE_STACK,
    532                base,
    533                size,
    534                vpn_base,
    535                vpn_size,
    536                0, 0, XPTR_NULL,                         // not a file vseg
    537                local_cxy );
    538 
    539     // register STACK vseg in local child VSL
    540     vmm_attach_vseg_to_vsl( &child_process->vmm , vseg );
    541 
    542 #if (DEBUG_THREAD_USER_FORK & 1)
    543 if( DEBUG_THREAD_USER_FORK < cycle )
    544 printk("\n[%s] thread[%x,%x] created stack vseg for thread %x in process %x\n",
    545 __FUNCTION__, this->process->pid, this->trdid, child_ptr->trdid, child_process->pid );
    546 #endif
    547 
    548     // copy all valid STACK GPT entries   
    549     vpn_t          vpn;
    550     bool_t         mapped;
    551     ppn_t          ppn;
    552     for( vpn = vpn_base ; vpn < (vpn_base + vpn_size) ; vpn++ )
     573    // scan parent GPT, and copy all valid entries
     574    // associated to user stack vseg into child GPT
     575    vpn_t  parent_vpn;
     576    vpn_t  child_vpn;
     577    bool_t mapped;
     578    ppn_t  ppn;
     579    vpn_t  parent_vpn_base = hal_remote_l32( XPTR( parent_cxy, &parent_us_vseg->vpn_base ) );
     580    vpn_t  parent_vpn_size = hal_remote_l32( XPTR( parent_cxy, &parent_us_vseg->vpn_size ) );
     581    vpn_t  child_vpn_base  = child_us_vseg->vpn_base;
     582    for( parent_vpn = parent_vpn_base , child_vpn = child_vpn_base ;
     583         parent_vpn < (parent_vpn_base + parent_vpn_size) ;
     584         parent_vpn++ , child_vpn++ )
    553585    {
    554586        error = hal_gpt_pte_copy( &child_process->vmm.gpt,
     587                                  child_vpn,
    555588                                  parent_gpt_xp,
    556                                   vpn,
     589                                  parent_vpn,
    557590                                  true,                 // set cow
    558591                                  &ppn,
     
    560593        if( error )
    561594        {
    562             vmm_detach_vseg_from_vsl( &child_process->vmm , vseg );
    563             thread_release( child_ptr );
    564595            printk("\n[ERROR] in %s : cannot update child GPT\n", __FUNCTION__ );
     596            vmm_remove_vseg( child_process , child_us_vseg );
     597            process_remove_thread( child_ptr );
     598            thread_destroy( child_ptr );
    565599            return -1;
    566600        }
    567601
    568         // increment pending forks counter for the page if mapped
     602        // increment pending forks counter for a mapped page
    569603        if( mapped )
    570604        {
     
    574608            page_t * page_ptr = GET_PTR( page_xp );
    575609
    576             // get extended pointers on forks and lock fields
     610            // build extended pointers on forks and lock fields
    577611            xptr_t forks_xp = XPTR( page_cxy , &page_ptr->forks );
    578612            xptr_t lock_xp  = XPTR( page_cxy , &page_ptr->lock );
     
    586620            // release lock protecting page
    587621            remote_busylock_release( lock_xp ); 
     622        }
     623    }
    588624
    589625#if (DEBUG_THREAD_USER_FORK & 1)
    590 cycle = (uint32_t)hal_get_cycles();
    591626if( DEBUG_THREAD_USER_FORK < cycle )
    592 printk("\n[%s] thread[%x,%x] copied one PTE to child GPT : vpn %x / forks %d\n",
    593 __FUNCTION__, this->process->pid, this->trdid,
    594 vpn, hal_remote_l32( XPTR( page_cxy , &page_ptr->forks) ) );
    595 #endif
    596 
    597         }
    598     }
    599 
    600     // set COW flag for all mapped entries of STAK vseg in parent thread GPT
     627printk("\n[%s] thread[%x,%x] copied all stack vseg PTEs to child GPT\n",
     628__FUNCTION__, this->process->pid, this->trdid );
     629#endif
     630
     631    // set COW flag for all mapped entries of user stack vseg in parent GPT
    601632    hal_gpt_set_cow( parent_gpt_xp,
    602                      vpn_base,
    603                      vpn_size );
    604  
     633                     parent_vpn_base,
     634                     parent_vpn_size );
     635
     636#if (DEBUG_THREAD_USER_FORK & 1)
     637if( DEBUG_THREAD_USER_FORK < cycle )
     638printk("\n[%s] thread[%x,%x] set the COW flag for stack vseg in parent GPT\n",
     639__FUNCTION__, this->process->pid, this->trdid );
     640#endif
     641
     642    // return child pointer
     643    *child_thread = child_ptr;
     644
    605645#if DEBUG_THREAD_USER_FORK
    606646cycle = (uint32_t)hal_get_cycles();
    607647if( DEBUG_THREAD_USER_FORK < cycle )
    608 printk("\n[%s] thread[%x,%x] exit / child_thread %x / cycle %d\n",
    609 __FUNCTION__, this->process->pid, this->trdid, child_ptr, cycle );
     648printk("\n[%s] thread[%x,%x] exit / created thread[%x,%x] / cycle %d\n",
     649__FUNCTION__, this->process->pid, this->trdid,
     650child_ptr->process->pid, child_ptr->trdid, cycle );
    610651#endif
    611652
     
    660701
    661702    // allocate an user stack vseg for main thread
    662     vseg_t * vseg = vmm_create_vseg( process,
    663                                      VSEG_TYPE_STACK,
    664                                      0,                 // size unused
    665                                      0,                 // length unused
    666                                      0,                 // file_offset unused
    667                                      0,                 // file_size unused
    668                                      XPTR_NULL,         // mapper_xp unused
    669                                      local_cxy );
    670     if( vseg == NULL )
     703    vseg_t * us_vseg = vmm_create_vseg( process,
     704                                        VSEG_TYPE_STACK,
     705                                        LTID_FROM_TRDID( thread->trdid ),
     706                                        0,                 // length unused
     707                                        0,                 // file_offset unused
     708                                        0,                 // file_size unused
     709                                        XPTR_NULL,         // mapper_xp unused
     710                                        local_cxy );
     711    if( us_vseg == NULL )
    671712    {
    672713            printk("\n[ERROR] in %s : cannot create stack vseg for main thread\n", __FUNCTION__ );
     
    675716
    676717    // update user stack in thread descriptor
    677     thread->u_stack_base = vseg->min;
    678     thread->u_stack_size = vseg->max - vseg->min;
     718    thread->user_stack_vseg = us_vseg;
    679719   
    680720    // release FPU ownership if required
     
    710750    error_t        error;
    711751        thread_t     * thread;       // pointer on new thread descriptor
     752    trdid_t        trdid;        // new thread identifier
    712753
    713754    thread_t * this = CURRENT_THREAD;
     
    737778    }
    738779
     780    // set type in thread descriptor
     781    thread->type = type;
     782
     783    // register new thread in local kernel process descriptor, and get a TRDID
     784    error = process_register_thread( &process_zero , thread , &trdid );
     785
     786    if( error )
     787    {
     788        printk("\n[ERROR] in %s : cannot register thread in kernel process\n", __FUNCTION__ );
     789        return -1;
     790    }
     791
     792    // set trdid in thread descriptor
     793    thread->trdid = trdid;
     794
    739795    // initialize thread descriptor
    740796    error = thread_init( thread,
    741797                         &process_zero,
    742798                         type,
     799                         trdid,
    743800                         func,
    744801                         args,
    745802                         core_lid,
    746                          0 , 0 );  // no user stack for a kernel thread
     803                         NULL );  // no user stack for a kernel thread
    747804
    748805    if( error ) // release allocated memory for thread descriptor
    749806    {
    750         printk("\n[ERROR] in %s : thread %x in process %x\n"
    751         "   cannot initialize thread descriptor\n",
    752         __FUNCTION__, this->trdid, this->process->pid );
    753         thread_release( thread );
     807        printk("\n[ERROR] in %s : cannot initialize thread descriptor\n", __FUNCTION__ );
     808        thread_destroy( thread );
    754809        return ENOMEM;
    755810    }
     
    763818        "    cannot create CPU context\n",
    764819        __FUNCTION__, this->trdid, this->process->pid );
    765         thread_release( thread );
     820        thread_destroy( thread );
    766821        return EINVAL;
    767822    }
     
    791846                           lid_t           core_lid )
    792847{
     848    trdid_t trdid;   
     849    error_t error;
    793850
    794851// check arguments
     
    796853assert( (core_lid < LOCAL_CLUSTER->cores_nr) , "illegal core index" );
    797854
     855    // set type in thread descriptor
     856    thread->type = THREAD_IDLE;
     857
     858    // register idle thread in local kernel process descriptor, and get a TRDID
     859    error = process_register_thread( &process_zero , thread , &trdid );
     860
     861assert( (error == 0), "cannot register idle_thread in kernel process" );
     862
     863    // set trdid in thread descriptor
     864    thread->trdid = trdid;
     865
    798866    // initialize thread descriptor
    799     error_t  error = thread_init( thread,
    800                                   &process_zero,
    801                                   type,
    802                                   func,
    803                                   args,
    804                                   core_lid,
    805                                   0 , 0 );   // no user stack for a kernel thread
    806 
    807     assert( (error == 0), "cannot create thread idle" );
     867    error = thread_init( thread,
     868                         &process_zero,
     869                         THREAD_IDLE,
     870                         trdid,
     871                         func,
     872                         args,
     873                         core_lid,
     874                         NULL );   // no user stack for a kernel thread
     875
     876assert( (error == 0), "cannot initialize idle_thread" );
    808877
    809878    // allocate & initialize CPU context if success
    810879    error = hal_cpu_context_alloc( thread );
    811880
    812     assert( (error == 0), "cannot allocate CPU context" );
     881assert( (error == 0), "cannot allocate CPU context" );
    813882
    814883    hal_cpu_context_init( thread );
     
    816885}  // end thread_idle_init()
    817886
    818 ///////////////////////////////////////////////////////////////////////////////////////
    819 // TODO: check that all memory dynamically allocated during thread execution
    820 // has been released => check vmm destroy for MMAP vsegs  [AG]
    821 ///////////////////////////////////////////////////////////////////////////////////////
    822 void thread_destroy( thread_t * thread )
    823 {
    824     reg_t        save_sr;
    825 
    826     process_t  * process    = thread->process;
    827     core_t     * core       = thread->core;
     887////////////////////////////////////////////
     888uint32_t thread_destroy( thread_t * thread )
     889{
     890    reg_t           save_sr;
     891    uint32_t        count;
     892
     893    thread_type_t   type    = thread->type;
     894    process_t     * process = thread->process;
     895    core_t        * core    = thread->core;
    828896
    829897#if DEBUG_THREAD_DESTROY
     
    835903#endif
    836904
    837     // check busylocks counter
     905    // check calling thread busylocks counter
    838906    thread_assert_can_yield( thread , __FUNCTION__ );
    839907
    840     // update intrumentation values
     908    // update target process instrumentation counter
    841909        process->vmm.pgfault_nr += thread->info.pgfault_nr;
    842910
    843     // release memory allocated for CPU context and FPU context
     911    // remove thread from process th_tbl[]
     912    count = process_remove_thread( thread );
     913
     914    // release memory allocated for CPU context and FPU context if required
    844915        hal_cpu_context_destroy( thread );
    845         if ( thread->type == THREAD_USER ) hal_fpu_context_destroy( thread );
     916        hal_fpu_context_destroy( thread );
    846917       
     918    // release user stack vseg (for an user thread only)
     919    if( type == THREAD_USER )  vmm_remove_vseg( process , thread->user_stack_vseg );
     920
    847921    // release FPU ownership if required
    848922        hal_disable_irq( &save_sr );
     
    857931        thread->signature = 0;
    858932
    859     // release memory for thread descriptor
    860     thread_release( thread );
     933    // release memory for thread descriptor (including kernel stack)
     934    kmem_req_t   req;
     935    xptr_t       base_xp = ppm_base2page( XPTR(local_cxy , thread ) );
     936
     937    req.type  = KMEM_PAGE;
     938    req.ptr   = GET_PTR( base_xp );
     939    kmem_free( &req );
    861940
    862941#if DEBUG_THREAD_DESTROY
     
    866945__FUNCTION__, this->process->pid, this->trdid, process->pid, thread->trdid, cycle );
    867946#endif
     947
     948    return count;
    868949
    869950}   // end thread_destroy()
     
    9931074    cxy_t       target_cxy;             // target thread cluster     
    9941075    thread_t  * target_ptr;             // pointer on target thread
     1076    process_t * target_process;         // pointer on arget process
     1077    pid_t       target_pid;             // target process identifier
    9951078    xptr_t      target_flags_xp;        // extended pointer on target thread <flags>
    9961079    xptr_t      target_join_lock_xp;    // extended pointer on target thread <join_lock>
     
    10061089    target_ptr      = GET_PTR( target_xp );
    10071090
    1008     // get target thread identifiers, and attached flag
     1091    // get target thread identifier, attached flag, and process PID
    10091092    target_trdid    = hal_remote_l32( XPTR( target_cxy , &target_ptr->trdid ) );
    10101093    target_ltid     = LTID_FROM_TRDID( target_trdid );
    10111094    target_flags_xp = XPTR( target_cxy , &target_ptr->flags );
    10121095    target_attached = ( (hal_remote_l32( target_flags_xp ) & THREAD_FLAG_DETACHED) == 0 );
     1096    target_process  = hal_remote_lpt( XPTR( target_cxy , &target_ptr->process ) );
     1097    target_pid      = hal_remote_l32( XPTR( target_cxy , &target_process->pid ) );
     1098
     1099// check target PID
     1100assert( (pid == target_pid),
     1101"unconsistent pid and target_xp arguments" );
    10131102
    10141103    // get killer thread pointers
     
    10271116// must be deleted by the parent process sys_wait() function
    10281117assert( ((CXY_FROM_PID( pid ) != target_cxy) || (target_ltid != 0)),
    1029 "tharget thread cannot be the main thread\n" );
     1118"target thread cannot be the main thread" );
    10301119
    10311120    // check killer thread can yield
     
    11511240void thread_idle_func( void )
    11521241{
     1242
     1243#if DEBUG_THREAD_IDLE
     1244uint32_t cycle;
     1245#endif
     1246
    11531247    while( 1 )
    11541248    {
     
    11611255
    11621256#if DEBUG_THREAD_IDLE
    1163 {
    1164 uint32_t cycle = (uint32_t)hal_get_cycles();
     1257cycle = (uint32_t)hal_get_cycles();
    11651258if( DEBUG_THREAD_IDLE < cycle )
    11661259printk("\n[%s] idle thread on core[%x,%d] goes to sleep / cycle %d\n",
    11671260__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, cycle );
    1168 }
    11691261#endif
    11701262
     
    11721264
    11731265#if DEBUG_THREAD_IDLE
    1174 {
    1175 uint32_t cycle = (uint32_t)hal_get_cycles();
     1266cycle = (uint32_t)hal_get_cycles();
    11761267if( DEBUG_THREAD_IDLE < cycle )
    11771268printk("\n[%s] idle thread on core[%x,%d] wake up / cycle %d\n",
    11781269__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, cycle );
    1179 }
    11801270#endif
    11811271
     
    11831273
    11841274#if DEBUG_THREAD_IDLE
    1185 {
    1186 uint32_t cycle = (uint32_t)hal_get_cycles();
     1275cycle = (uint32_t)hal_get_cycles();
    11871276if( DEBUG_THREAD_IDLE < cycle )
    11881277sched_display( CURRENT_THREAD->core->lid );
    1189 }
    11901278#endif     
    11911279        // search a runable thread
  • trunk/kernel/kern/thread.h

    r619 r625  
    33 *
    44 * Author  Ghassan Almaless (2008,2009,2010,2011,2012)
    5  *         Alain Greiner (2016,2017,2018)
     5 *         Alain Greiner (2016,2017,2018,2019)
    66 *
    77 * Copyright (c) UPMC Sorbonne Universites
     
    2929#include <shared_syscalls.h>
    3030#include <hal_special.h>
     31#include <hal_kentry.h>
    3132#include <xlist.h>
    3233#include <list.h>
     
    100101{
    101102        uint32_t              pgfault_nr;    /*! cumulated number of page fault           */
    102         uint32_t              sched_nr;      /*! TODO ???  [AG]                           */
    103         uint32_t              u_err_nr;      /*! TODO ???  [AG]                           */
    104         uint32_t              m_err_nr;      /*! TODO ???  [AG]                           */
    105103        cycle_t               last_cycle;    /*! last cycle counter value (date)          */
    106104        cycle_t               usr_cycles;    /*! user execution duration (cycles)         */
     
    121119 *
    122120 * WARNING (1) Don't modify the first 4 fields order, as this order is used by the
    123  *             hal_kentry assembly code for some architectures (TSAR).
     121 *             hal_kentry assembly code for the TSAR architectures.
    124122 *
    125123 * WARNING (2) Most of the thread state is private and accessed only by this thread,
     
    165163    uint32_t          * ack_rsp_count;   /*! pointer on acknowledge response counter  */
    166164
    167         intptr_t            u_stack_base;    /*! user stack base address                  */
    168         uint32_t            u_stack_size;    /*! user stack size (bytes)                  */
     165        vseg_t            * user_stack_vseg; /*! local pointer on user stack vseg         */
    169166
    170167    void              * entry_func;      /*! pointer on entry function                */
     
    248245
    249246/***************************************************************************************
    250  * This function is used by the sys_fork() system call to create the "child" thread
    251  * in the local cluster. It allocates memory for a thread descriptor, and initializes
    252  * it from the "parent" thread descriptor defined by the <parent_thread_xp> argument.
     247 * This function is used by the sys_fork() syscall to create the "child" main thread
     248 * in the local cluster. It is called, generally through the RPC_PROCESS_MAKE_FORK,
     249 * by the process_make_fork() function. It allocates memory from the local cluster
     250 * for a "child" thread descriptor, and initializes it from the "parent" thread
     251 * descriptor defined by the <parent_thread_xp> argument.
    253252 * The new thread is attached to the core that has the lowest load in local cluster.
    254253 * It is registered in the "child" process defined by the <child_process> argument.
     
    259258 * uses physical addressing on some architectures).
    260259 * The CPU and FPU execution contexts are created and linked to the new thread.
    261  * but the actual context copy is NOT done, and must be done by by the sys_fork().
     260 * but the actual context copy is NOT done, and is done by the sys_fork() function.
    262261 * The THREAD_BLOCKED_GLOBAL bit is set => the thread must be activated to start.
    263262 ***************************************************************************************
     
    273272/***************************************************************************************
    274273 * This function is called by the process_make_exec() function to re-initialise the
    275  * thread descriptor of the calling thread (that will become the new process main
    276  * thread), and immediately jump to user code without returning to kentry!!!
     274 * calling thread descriptor, that will become the new process main thread.
    277275 * It must be called by the main thread of the calling process.
     276 * - The calling thread TRDID is not modified.
     277 * - The kernel stack (currently in use) is not modified. 
    278278 * - A new user stack vseg is created and initialised.
    279  * - The kernel stack (currently in use) is not modified. 
    280279 * - The function calls the hal_cpu_context_exec() to re-initialize the CPU context
    281  *   an jump to user code. 
     280 *   and the uzone registered in kernel stack, an jump to user code. 
    282281 ***************************************************************************************
    283282 * @ entry_func : main thread entry point.
     
    329328
    330329/***************************************************************************************
    331  * This low-level function is called by the sched_handle_signals() function to releases
    332  * the physical memory allocated for a thread in a given cluster, when this thread
    333  * is marked for delete. This include the thread descriptor itself, the associated
    334  * CPU and FPU context, and the physical memory allocated for an user thread local stack.
     330 * This low-level function is called by the sched_handle_signals() function when a
     331 * thread is marked for delete. It removes the thread identified by the <thread>
     332 * argument from the process th_tbl[], and releases all physical memory allocated for
     333 * this. This includes the thread descriptor itself, the associated CPU and FPU context,
     334 * and the physical memory allocated for an user thread stack.
    335335 ***************************************************************************************
    336336 * @ thread  : pointer on the thread descriptor to release.
    337  * @ return true, if the thread was the last registerd thread in local process.
    338  **************************************************************************************/
    339 void thread_destroy( thread_t * thread );
     337 * @ return the number of threads registered in the process th_tbl[] before deletion.
     338 **************************************************************************************/
     339uint32_t thread_destroy( thread_t * thread );
    340340
    341341/***************************************************************************************
     
    383383 * This function is used by the four sys_thread_cancel(), sys_thread_exit(),
    384384 * sys_kill() and sys_exit() system calls to mark for delete a given thread.
    385  * It set the THREAD_BLOCKED_GLOBAL bit and set the the THREAD_FLAG_REQ_DELETE bit
    386  * in the thread descriptor identified by the <thread_xp> argument, to ask the scheduler
     385 * It set the THREAD_BLOCKED_GLOBAL bit and set the THREAD_FLAG_REQ_DELETE bit in the
     386 * thread descriptor identified by the <thread_xp> argument, to ask the scheduler
    387387 * to asynchronously delete the target thread, at the next scheduling point.
    388  * The calling thread can run in any cluster, as it uses remote accesses, but
    389  * the target thread cannot be the main thread of the process identified by the <pid>
    390  * argument, because the main thread must be deleted by the parent process argument.
     388 * The calling thread can run in any cluster, as it uses remote accesses.
     389 * This function makes a kernel panic if the target thread is the main thread,
     390 * because * the main thread deletion will cause the process deletion, and a process
     391 * must be deleted by the parent process, running the wait function.
    391392 * If the target thread is running in "attached" mode, and the <is_forced> argument
    392393 * is false, this function implements the required sychronisation with the joining
Note: See TracChangeset for help on using the changeset viewer.