Changeset 683 for trunk/kernel/kern


Ignore:
Timestamp:
Jan 13, 2021, 12:36:17 AM (3 years ago)
Author:
alain
Message:

All modifications required to support the <tcp_chat> application
including error recovery in case of packet loss.A

Location:
trunk/kernel/kern
Files:
21 edited

Legend:

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

    r669 r683  
    3131
    3232////////////////////////////////////////////////////////////////////////////////////////////
    33 // This static function registers the alarm identified ny the <new_alarm> argument
     33// This static function registers the alarm identified by the <alarm> & <cxy> arguments
    3434// in the list of alarms rooted in the core identified by the <core> argument.
    3535// When the existing list of alarms is not empty, it scan the list to insert the new
    3636// alarm in the right place to respect the absolute dates ordering.
    3737////////////////////////////////////////////////////////////////////////////////////////////
    38 // @ new_alarm  : local pointer on the new alarm.
    39 // @ core       : local pointer on the target core.
     38// @ cxy    : cluster containing both the new alarm and the core.
     39// @ alarm  : local pointer on the alarm.
     40// @ core   : local pointer on the core.
    4041////////////////////////////////////////////////////////////////////////////////////////////
    41 static void alarm_register( alarm_t * new_alarm,
     42static void alarm_register( cxy_t     cxy,
     43                            alarm_t * alarm,
    4244                            core_t  * core )
    4345{
    44     list_entry_t * current;          // pointer on current list_entry in existing list
    45     list_entry_t * previous;         // pointer on previous list_entry in existing list
    46     alarm_t      * current_alarm;    // pointer on current alarm in existing list
    47     cycle_t        current_date;     // date of current alarm in existing list
    48 
    49     bool_t         done = false;
    50 
    51     // get pointers on root of alarms and lock
     46    // get alarm date
     47    cycle_t new_date = hal_remote_l64( XPTR( cxy , &alarm->date ) );
     48
     49    // build local pointer on root of alarms list
    5250    list_entry_t * root = &core->alarms_root;
    53     busylock_t   * lock = &core->alarms_lock;
    54 
    55     // get pointer on new_alarm list_entry
    56     list_entry_t * new_entry = &new_alarm->list;
    57 
    58     // get new_alarm date
    59     cycle_t        new_date = new_alarm->date;
    60 
    61     // take the lock
    62     busylock_acquire( lock );
     51
     52    // build local pointer on new alarm list_entry
     53    list_entry_t * new  = &alarm->list;
    6354
    6455    // insert new alarm to respect dates order
    65     if( list_is_empty( root ) )                     // list empty
     56    if( list_remote_is_empty( cxy , &core->alarms_root ) )  // list empty
    6657    {
    67         list_add_first( root , new_entry );
     58        list_remote_add_first( cxy , root , new );
    6859    }
    69     else                                            // list non empty
     60    else                                                   // list non empty
    7061    {
    71         for( current = root->next ;
    72              (current != root) && (done == false) ;
    73              current = current->next )
     62        list_entry_t * iter;        // local pointer on current list_entry in existing list
     63        alarm_t      * iter_alarm;  // local pointer on current alarm in existing list
     64        cycle_t        iter_date;   // date of current alarm in existing list
     65        bool_t         done = false;
     66
     67        for( iter = hal_remote_lpt( XPTR( cxy , &root->next ) ) ;
     68             (iter != root) && (done == false) ;
     69             iter = hal_remote_lpt( XPTR( cxy , &iter->next ) ) )
    7470        {
    75             // get pointer on previous entry in existing list
    76             previous = current->pred;
    77 
    78             // get pointer on current alarm
    79             current_alarm = LIST_ELEMENT( current , alarm_t , list );
     71            // get local pointer on pred and next for iter
     72            list_entry_t * prev = hal_remote_lpt( XPTR( cxy , &iter->pred ) );
     73
     74            // get local pointer on current alarm
     75            iter_alarm = LIST_ELEMENT( iter , alarm_t , list );
    8076
    8177            // get date for current alarm
    82             current_date  = current_alarm->date;
    83 
    84             if( current_date > new_date )  // insert new alarm just before current
     78            iter_date = hal_remote_l64( XPTR( cxy , &iter_alarm->date ) );
     79
     80            // insert new alarm just before current when required
     81            if( iter_date > new_date ) 
    8582            {
    86                 new_entry->next = current;
    87                 new_entry->pred = previous;
    88 
    89                 current->pred  = new_entry;
    90                 previous->next = new_entry;
     83                hal_remote_spt( XPTR( cxy , &new->next ) , iter );
     84                hal_remote_spt( XPTR( cxy , &new->pred ) , prev );
     85
     86                hal_remote_spt( XPTR( cxy , &iter->pred ) , new );
     87                hal_remote_spt( XPTR( cxy , &prev->next ) , new );
    9188               
    9289                done = true;
     
    9693        if( done == false ) // new_date is larger than all registered dates
    9794        {
    98             list_add_last( root , new_entry );
     95            list_remote_add_last( cxy, root , new );
    9996        }
    10097    }
    101 
     98}  // end alarm_register()
     99           
     100
     101///////////////////////////////////
     102void alarm_init( alarm_t *  alarm )
     103{
     104    alarm->linked   = false;
     105    list_entry_init( &alarm->list );
     106}
     107
     108///////////////////////////////////////
     109void alarm_start( xptr_t     thread_xp,
     110                  cycle_t    date,
     111                  void     * func_ptr,
     112                  xptr_t     args_xp )
     113{
     114    // get cluster and local pointer on target thread
     115    thread_t * tgt_ptr = GET_PTR( thread_xp );
     116    cxy_t      tgt_cxy = GET_CXY( thread_xp );
     117
     118// check alarm state
     119assert( __FUNCTION__ , (hal_remote_l32( XPTR(tgt_cxy,&tgt_ptr->alarm.linked)) == false ),
     120"alarm already started");
     121
     122    // get local pointer on core running target thread
     123    core_t * core = hal_remote_lpt( XPTR( tgt_cxy , &tgt_ptr->core ) );
     124
     125    // build extended pointer on lock protecting alarms list
     126    xptr_t lock_xp = XPTR( tgt_cxy , &core->alarms_lock );
     127 
     128    // initialize alarm descriptor
     129    hal_remote_s64( XPTR( tgt_cxy , &tgt_ptr->alarm.date     ) , date );
     130    hal_remote_spt( XPTR( tgt_cxy , &tgt_ptr->alarm.func_ptr ) , func_ptr );
     131    hal_remote_s64( XPTR( tgt_cxy , &tgt_ptr->alarm.args_xp  ) , args_xp );
     132    hal_remote_s32( XPTR( tgt_cxy , &tgt_ptr->alarm.linked   ) , true );
     133
     134    // take the lock
     135    remote_busylock_acquire( lock_xp );
     136
     137    // register alarm in core list
     138    alarm_register( tgt_cxy , &tgt_ptr->alarm , core );
     139
     140    //release the lock
     141    remote_busylock_release( lock_xp );
     142
     143}  // end alarm_start()
     144
     145
     146/////////////////////////////////////
     147void alarm_stop( xptr_t   thread_xp )
     148{
     149    // get cluster and local pointer on target thread
     150    thread_t * tgt_ptr = GET_PTR( thread_xp );
     151    cxy_t      tgt_cxy = GET_CXY( thread_xp );
     152
     153    // get local pointer on core running target thread
     154    core_t * core = hal_remote_lpt( XPTR( tgt_cxy , &tgt_ptr->core ) );
     155
     156    // build extended pointer on lock protecting alarms list
     157    xptr_t lock_xp = XPTR( tgt_cxy , &core->alarms_lock );
     158 
     159    // take the lock
     160    remote_busylock_acquire( lock_xp );
     161
     162    // unlink the alarm from the list rooted in core
     163    list_remote_unlink( tgt_cxy , &tgt_ptr->alarm.list );
     164
     165    // update alarm state
     166    hal_remote_s32( XPTR( tgt_cxy , &tgt_ptr->alarm.linked ) , false );
     167
     168    //release the lock
     169    remote_busylock_release( lock_xp );
     170
     171}  // end alarm_stop()
     172
     173
     174//////////////////////////////////////
     175void alarm_update( xptr_t   thread_xp,
     176                   cycle_t  new_date )
     177{
     178    // get cluster and local pointer on target thread
     179    thread_t * tgt_ptr = GET_PTR( thread_xp );
     180    cxy_t      tgt_cxy = GET_CXY( thread_xp );
     181
     182    // get local pointer on core running target thread
     183    core_t * core = hal_remote_lpt( XPTR( tgt_cxy , &tgt_ptr->core ) );
     184
     185    // build extended pointer on lock protecting alarms list
     186    xptr_t lock_xp = XPTR( tgt_cxy , &core->alarms_lock );
     187 
     188    // take the lock
     189    remote_busylock_acquire( lock_xp );
     190
     191    // unlink the alarm from the core list
     192    list_remote_unlink( tgt_cxy , &tgt_ptr->alarm.list );
     193
     194    // update the alarm date and state
     195    hal_remote_s64( XPTR( tgt_cxy , &tgt_ptr->alarm.date   ) , new_date );
     196    hal_remote_s32( XPTR( tgt_cxy , &tgt_ptr->alarm.linked ) , true );
     197
     198    // register alarm in core list
     199    alarm_register( tgt_cxy , &tgt_ptr->alarm , core );
     200   
    102201    // release the lock
    103     busylock_release( lock );
    104 
    105 }  // end alarm_register()
    106 
    107 //////////////////////////////////////
    108 void alarm_start( cycle_t    date,
    109                   void     * func_ptr,
    110                   xptr_t     args_xp,
    111                   thread_t * thread )
    112 {
    113     // get pointer on alarm
    114     alarm_t * alarm = &thread->alarm;
    115 
    116     // initialize alarm descriptor
    117     alarm->date     = date;
    118     alarm->func_ptr = func_ptr;
    119     alarm->args_xp = args_xp;
    120    
    121     // register alarm in core list
    122     alarm_register( alarm , thread->core );
    123 
    124 }  // end alarm_start()
    125 
    126 /////////////////////////////////////
    127 void alarm_update( thread_t * thread,
    128                    cycle_t    new_date )
    129 {
    130     // get pointer on alarm
    131     alarm_t * alarm = &thread->alarm;
    132 
    133     // get pointer on core
    134     core_t   * core = thread->core;
    135 
    136     // get pointer on lock protecting the alarms list
    137     busylock_t   * lock = &core->alarms_lock;
    138 
    139     // unlink the alarm from the core list
    140     busylock_acquire( lock );
    141     list_unlink( &alarm->list );
    142     busylock_release( lock );
    143 
    144     // update the alarm date
    145     alarm->date = new_date;
    146 
    147     // register alarm in core list
    148     alarm_register( alarm , core );
    149    
     202    remote_busylock_release( lock_xp );
     203
    150204}  // end alarm_update()
    151205
    152 ////////////////////////////////////
    153 void alarm_stop( thread_t * thread )
    154 {
    155     // get pointer on alarm
    156     alarm_t * alarm = &thread->alarm;
    157 
    158     // get pointer on core
    159     core_t * core = thread->core;
    160 
    161     // get pointer on lock protecting the alarms list
    162     busylock_t * lock = &core->alarms_lock;
    163 
    164     // unlink the alarm from the list rooted in core
    165     busylock_acquire( lock );
    166     list_unlink( &alarm->list );
    167     busylock_release( lock );
    168 
    169 }  // end alarm_stop()
    170 
     206
  • trunk/kernel/kern/alarm.h

    r669 r683  
    3636 *   This structure defines a generic, timer based, kernel alarm.
    3737 *
    38  * - An alarm being attached to a given thread, the alarm descriptor is embedded in the
     38 * - An alarm is attached to a given thread, and the alarm descriptor is embedded in the
    3939 *   thread descriptor. A client thread can use the alarm_start() function to dynamically
    4040 *   activate the alarm. It can use the alarm_stop() function to desactivate this alarm.
    4141 * - This kernel alarm is generic, as the alarm handler (executed when the alarm rings),
    42  *   and the handler arguments are defined by two pointers <func_ptr> and <args_xp>.
     42 *   and the handler arguments are defined by two pointers: <func_ptr> and <args_xp>.
    4343 * - When an alarm is created by a client thread, it is registered in the list of alarms
    4444 *   rooted in the core running the client thread. When it is stopped, the alarm is simply
    4545 *   removed from this list.
    46  * - When creating an alarm, the client thread must define an absolute date (in cycles),
    47  *   the func_ptr local pointer, and the args_xp extended pointer.
     46 * - When creating an alarm with the alarm_start() function, the client thread must define
     47 *   an absolute date (in cycles), the func_ptr pointer, and the args_xp extended pointer.
    4848 * - The list of alarms is ordered by increasing dates. At each TICK received by a core,
    4949 *   the date of the first registered alarm is compared to the current date (in the
    5050 *   core_clock() function). The alarm handler is executed when current_date >= alarm_date.
    51  * - It is the handler responsability to stop a ringing alarm, or update the date. 
     51 * - It is the handler responsability to stop and delete a ringing alarm using the
     52 *   alarm_stop() function, or update the alarm date using the alarm_update() function. 
     53 * - The three alarm_start(), alarm_stop(), and alarm_update() access functions use
     54 *   the lock protecting the alarms list to handle concurrent accesses. These functions
     55 *   use extended pointers to access the alarm list, and can be called by a thread
     56 *   running in any cluster.
    5257 *
    53  * This mechanism is used bi the almos_mkh implementation of the TCP protocoL.
     58 * This embedded alarm mechanism is used by:
     59 * 1. the socket_accept(), socket_connect(), socket_send(), socket_close() functions,
     60 *    to implement the TCP retransmission machanism.
     61 * 2. the sys_thread_sleep() function, to implement the "sleep" mechanism.
    5462 ******************************************************************************************/
    5563
    5664typedef struct alarm_s
    5765{
     66    bool_t         linked;         /*! active when true (i.e linked to the core list)     */
    5867    cycle_t        date;           /*! absolute date for handler execution                */
    5968    void         * func_ptr;       /*! local pointer on alarm handler function            */
    6069    xptr_t         args_xp;        /*! local pointer on handler arguments                 */
    61     list_entry_t   list;           /*! all alarms attached to the same core               */
     70    list_entry_t   list;           /*! set of active alarms attached to the same core     */
    6271}
    6372alarm_t;
     
    7079
    7180/*******************************************************************************************
     81 * This function initialises the alarm state to "inactive".
     82 *******************************************************************************************
     83 * @ alarm     : local pointer on alarm.
     84 ******************************************************************************************/
     85void alarm_init( alarm_t *  alarm );
     86
     87/*******************************************************************************************
    7288 * This function initializes the alarm descriptor embedded in the thread identified by the
    73  * <thread> argument from the <date>, <func_ptr>, <args_ptr> arguments, and registers it
    74  * in the ordered list rooted in the core running this <thread>.
     89 * <thread_xp> argument from the <date>, <func_ptr>, <args_ptr> arguments, and registers
     90 * this alarm in the ordered list rooted in the core running this thread.
     91 * It takes the lock protecting the alarms list against concurrent accesses.
    7592 *******************************************************************************************
     93 * @ thread_xp  : extended pointer on the target thread.
    7694 * @ date       : absolute date (in cycles).
    7795 * @ func_ptr   : local pointer on the handler to execute when the alarm rings.
    7896 * @ args_xp    : extended pointer on the handler arguments.
    79  * @ thread     : local pointer on the client thread.
    8097 ******************************************************************************************/
    81 void alarm_start( cycle_t           date,
    82                   void            * func_ptr,
    83                   xptr_t            args_xp,
    84                   struct thread_s * thread );
     98void alarm_start( xptr_t    thread_xp,
     99                  cycle_t   date,
     100                  void    * func_ptr,
     101                  xptr_t    args_xp );
    85102
    86103/*******************************************************************************************
     
    88105 * <thread> argument. The list of alarms rooted in the core running the client thread
    89106 * is modified to respect the absolute dates ordering.
     107 * It takes the lock protecting the alarms list against concurrent accesses.
    90108 *******************************************************************************************
    91  * @ thread     : local pointer on the client thread.
     109 * @ thread_xp  : extended pointer on the target thread.
    92110 * @ new_date   : absolute new date (in cycles).
    93111 ******************************************************************************************/
    94 void alarm_update( struct thread_s * thread,
    95                    cycle_t           new_date );
     112void alarm_update( xptr_t     thread_xp,
     113                   cycle_t    new_date );
    96114
    97115/*******************************************************************************************
    98116 * This function unlink an alarm identified by the <thread> argument from the list of
    99117 * alarms rooted in the core descriptor.
     118 * It takes the lock protecting the alarms list against concurrent accesses.
    100119 *******************************************************************************************
    101  * @ thread     : local pointer on the client thread.
     120 * @ thread_xp  : extended pointer on the target thread.
    102121 ******************************************************************************************/
    103 void alarm_stop( struct thread_s * thread );
     122void alarm_stop( xptr_t    thread_xp );
    104123
    105124
  • trunk/kernel/kern/chdev.c

    r669 r683  
    8787{
    8888    chdev_t    * chdev;
    89     kmem_req_t   req;
    9089
    9190    // allocate memory for chdev
    92     req.type   = KMEM_KCM;
    93     req.order  = bits_log2( sizeof(chdev_t) );
    94     req.flags  = AF_ZERO | AF_KERNEL;
    95     chdev      = kmem_alloc( &req );
     91    chdev = kmem_alloc( bits_log2(sizeof(chdev_t)) , AF_ZERO | AF_KERNEL );
    9692
    9793    if( chdev == NULL ) return NULL;
     
    114110}  // end chdev_create()
    115111
    116 ///////////////////////////////////
    117 void chdev_print( chdev_t * chdev )
    118 {
    119     printk("\n - func      = %s"
    120            "\n - channel   = %d"
    121            "\n - base      = %l"
     112/////////////////////////////////////
     113void chdev_display( xptr_t chdev_xp )
     114{
     115    chdev_t * chdev = GET_PTR( chdev_xp );
     116    cxy_t     cxy   = GET_CXY( chdev_xp );
     117
     118    char      name[16];
     119
     120    hal_remote_memcpy( XPTR( local_cxy, name ),
     121                       XPTR( cxy , &chdev->name ), 16 );
     122
     123    printk("\n - chdev     = [%x,%x]"
     124           "\n - name      = %s"
     125           "\n - base      = [%x,%x]"
    122126           "\n - cmd       = %x"
    123            "\n - isr       = %x"
    124            "\n - chdev     = %x\n",
    125            chdev_func_str(chdev->func),
    126            chdev->channel,
    127            chdev->base,
    128            chdev->cmd,
    129            chdev->isr,
    130            chdev );
    131 }
     127           "\n - isr       = %x\n",
     128           cxy,
     129           chdev,
     130           name,
     131           GET_CXY( hal_remote_l64( XPTR( cxy , &chdev->base ))),
     132           GET_PTR( hal_remote_l64( XPTR( cxy , &chdev->base ))),
     133           hal_remote_lpt( XPTR( cxy , &chdev->cmd )),
     134           hal_remote_lpt( XPTR( cxy , &chdev->isr )) );
     135
     136}  // end chdev_display()
    132137
    133138//////////////////////////////////////////////////
     
    450455    chdev_t     * chdev_ptr;
    451456
    452     assert( __FUNCTION__, (file_xp != XPTR_NULL) ,
    453     "file_xp == XPTR_NULL\n" );
     457assert( __FUNCTION__, (file_xp != XPTR_NULL) ,
     458"file_xp == XPTR_NULL" );
    454459
    455460    // get cluster and local pointer on remote file descriptor
     
    462467    inode_ptr  = (vfs_inode_t *)hal_remote_lpt( XPTR( file_cxy , &file_ptr->inode ) );
    463468
    464     assert( __FUNCTION__, (inode_type == FILE_TYPE_DEV) ,
    465     "inode type %d is not FILE_TYPE_DEV\n", inode_type );
     469assert( __FUNCTION__, (inode_type == FILE_TYPE_DEV) ,
     470"inode type %d is not FILE_TYPE_DEV", inode_type );
    466471
    467472    // get chdev local pointer from inode extension
  • trunk/kernel/kern/chdev.h

    r669 r683  
    121121 *      . This busylock is also used to protect direct access to the shared
    122122 *        kernel TXT0 terminal, that does not use the waiting queue.
    123  *      . For mostd chdevs, the client waiting queue is an xlist of threads, but it is
     123 *      . For most chdevs, the client waiting queue is a list of threads, but it is
    124124 *        a list of sockets for the NIC chdevs. It is unused for ICU, PIC, and IOB.
    125125 *****************************************************************************************/
     
    190190
    191191/****************************************************************************************
    192  * This function display relevant values for a chdev descriptor.
    193  ****************************************************************************************
    194  * @ chdev   : pointer on chdev.
    195  ***************************************************************************************/
    196 void chdev_print( chdev_t * chdev );
    197 
    198 /****************************************************************************************
    199192 * This function returns a printable string for a device functionnal types.
    200193 ****************************************************************************************
     
    223216
    224217/****************************************************************************************
    225  * This generid function is executed by an user thread requesting an IOC or TXT chdev
     218 * This generic function is executed by an user thread requesting an IOC or TXT chdev
    226219 * service. It registers the calling thread in the waiting queue of a the remote
    227220 * chdev descriptor identified by the <chdev_xp> argument.
     
    282275
    283276/****************************************************************************************
     277 * This function display relevant values for a remote chdev descriptor.
     278 ****************************************************************************************
     279 * @ chdev_xp   : pointer on chdev.
     280 ***************************************************************************************/
     281void chdev_display( xptr_t chdev_xp );
     282
     283/****************************************************************************************
    284284 * This function displays the local copy of the external chdevs directory.
    285285 * (global variable replicated in all clusters)
  • trunk/kernel/kern/cluster.c

    r669 r683  
    22 * cluster.c - Cluster-Manager related operations
    33 *
    4  * Author  Ghassan Almaless (2008,2009,2010,2011,2012)
     4 * Author  Ghassan Almaless       (2008,2009,2010,2011,2012)
    55 *         Mohamed Lamine Karaoui (2015)
    6  *         Alain Greiner (2016,2017,2018,2019,2020)
     6 *         Alain Greiner          (2016,2017,2018,2019,2020)
    77 *
    88 * Copyright (c) UPMC Sorbonne Universites
     
    7474        cluster->y_size          = info->y_size;
    7575        cluster->io_cxy          = info->io_cxy;
     76        cluster->sys_clk         = info->sys_clk;
    7677
    7778    // initialize the cluster_info[][] array
     
    177178printk("\n[%s] PPM initialized in cluster %x / cycle %d\n",
    178179__FUNCTION__ , local_cxy , cycle );
    179 #endif
    180 
    181     // initialises embedded KHM
    182         khm_init( &cluster->khm );
    183 
    184 #if( DEBUG_CLUSTER_INIT & 1 )
    185 cycle = (uint32_t)hal_get_cycles();
    186 if( DEBUG_CLUSTER_INIT < cycle )
    187 printk("\n[%s] KHM initialized in cluster %x at cycle %d\n",
    188 __FUNCTION__ , local_cxy , hal_get_cycles() );
    189180#endif
    190181
  • trunk/kernel/kern/cluster.h

    r657 r683  
    22 * cluster.h - Cluster-Manager definition
    33 *
    4  * authors  Ghassan Almaless (2008,2009,2010,2011,2012)
     4 * authors  Ghassan Almaless       (2008,2009,2010,2011,2012)
    55 *          Mohamed Lamine Karaoui (2015)
    6  *          Alain Greiner (2016,2017,2018,2019,2019,2020)
     6 *          Alain Greiner          (2016,2017,2018,2019,2020)
    77 *
    88 * Copyright (c) UPMC Sorbonne Universites
     
    3939#include <ppm.h>
    4040#include <kcm.h>
    41 #include <khm.h>
    4241#include <rpc.h>
    4342#include <core.h>
     
    105104    uint32_t        x_size;            /*! number of clusters in a row    (can be 1)      */
    106105    uint32_t        y_size;            /*! number of clusters in a column (can be 1)      */
    107     cxy_t           io_cxy;            /*! io cluster identifier                          */
     106    uint32_t        io_cxy;            /*! io cluster identifier                          */
     107    uint32_t        sys_clk;           /*! system_clock frequency (in Hertz)              */
    108108    uint32_t        dqdt_root_level;   /*! index of root node in dqdt_tbl[]               */
    109109    uint32_t        nb_txt_channels;   /*! number of TXT channels                         */
     
    124124    list_entry_t    dev_root;          /*! root of list of devices in cluster             */
    125125
    126     // memory allocators
    127     ppm_t           ppm;               /*! embedded kernel page manager                   */
    128     khm_t           khm;               /*! embedded kernel heap manager                   */
    129     kcm_t           kcm[6];            /*! embedded kernel cache managers [6:11]          */
     126    // physical memory allocators: one PPM and severa KCM
     127    ppm_t           ppm;
     128    kcm_t           kcm[CONFIG_PPM_PAGE_ORDER - CONFIG_CACHE_LINE_ORDER];
    130129
    131130    // RPC
  • trunk/kernel/kern/core.c

    r669 r683  
    33 *
    44 * Author  Ghassan Almaless (2008,2009,2010,2011,2012)
    5  *         Alain Greiner (2016,2017,2018)
     5 *         Alain Greiner    (2016,2017,2018,2019,2020)
    66 *
    77 * Copyright (c) UPMC Sorbonne Universites
     
    4747        core->ticks_nr          = 0;
    4848        core->usage             = 0;
    49         core->spurious_irqs     = 0;
    5049        core->fpu_owner         = NULL;
    5150        core->rand_last         = hal_time_stamp() & 0xFFF;
     
    5554
    5655    // initialise the alarms lock
    57     busylock_init( &core->alarms_lock , LOCK_CORE_ALARMS );
     56    remote_busylock_init( XPTR( local_cxy , &core->alarms_lock ) , LOCK_CORE_ALARMS );
    5857
    5958    // initialise the alarms list
     
    6160}
    6261
    63 ///////////////////////////////////////
    64 void core_check_alarms( core_t * core )
     62////////////////////////////////////////////////////////////////////////////////////
     63// This static function checks the alarms registered in the core, and calls the
     64// relevant alarm handler for all alarms whose time is elapded.
     65// It does not take the lock protecting the alarm list, because it access only
     66// the first alarm in the list, and all modifications in he list are done
     67// the low level access functions called by the handler(s).
     68////////////////////////////////////////////////////////////////////////////////////
     69static void core_check_alarms( core_t * core )
    6570{
    6671    alarm_handler_t * handler;
     
    7277    if( list_is_empty( root ) ) return;
    7378
    74     // get pointer on first alarm when list non empty
    75     alarm_t * alarm = LIST_FIRST( root , alarm_t , list );
    76 
    77     // get first alarm date
    78     cycle_t alarm_date = alarm->date;
    79 
    80     // get current date
    81     cycle_t current_date = hal_get_cycles();
    82 
    83     if( current_date >= alarm_date )
     79    while( 1 )
    8480    {
    85         // get pointer on registered alarm handler
    86         handler = (alarm_handler_t *)alarm->func_ptr;
    87 
    88         // call alarm handler
    89         handler( alarm->args_xp );
     81        // get pointer on first alarm
     82        alarm_t * alarm = LIST_FIRST( root , alarm_t , list );
     83
     84        // get first alarm date
     85        cycle_t alarm_date = alarm->date;
     86
     87        // get current date
     88        cycle_t current_date = hal_get_cycles();
     89
     90        // call handler if delay elapsed, and retry
     91        if( current_date >= alarm_date )
     92        {
     93            // get pointer on registered alarm handler
     94            handler = (alarm_handler_t *)alarm->func_ptr;
     95
     96            // call alarm handler
     97            handler( alarm->args_xp );
     98        }
     99        else   // exit loop when first alarm delay not elapsed
     100        {
     101            break;
     102        }
    90103    }
    91104}   // end core_check_alarms()
     
    127140                    uint32_t * tm_us )
    128141{
    129         *tm_s  = (core->ticks_nr*CONFIG_SCHED_TICK_MS_PERIOD)/1000;
    130         *tm_us = (core->ticks_nr*CONFIG_SCHED_TICK_MS_PERIOD*1000)%1000000;
     142    // get number of cycles
     143    uint64_t cycles = core->cycles;
     144
     145    // get number of cycles per second
     146    uint32_t cycles_per_second = LOCAL_CLUSTER->sys_clk;
     147
     148    *tm_s  = cycles / cycles_per_second;
     149    *tm_us = (cycles * 1000000) % cycles_per_second;
    131150}
    132151
     
    139158        ticks = core->ticks_nr++;
    140159
     160    // handle alarms
     161    core_check_alarms( core );
     162
    141163        // handle scheduler
    142164        if( (ticks % CONFIG_SCHED_TICKS_PER_QUANTUM) == 0 ) sched_yield( "TICK");
    143 
    144     // handle alarms
    145     core_check_alarms( core );
    146165}
    147166
  • trunk/kernel/kern/core.h

    r669 r683  
    3939
    4040/****************************************************************************************
    41  * This structure defines the core descriptor.
    42  * Besides the core identifiers (gid,lid), it contains an embedded private scheduler.
     41 * This structure defines a core descriptor.
     42 * Besides the core identifiers (gid,lid), it contains an embedded private scheduler
     43 * and a software cycles counter on 64 bits.
     44 * It contains also the root of local list of alarms, dynamically registered by the
     45 * threads running on this core. This local list is protected by a remote_busylock,
     46 * because it can be accessed by any thread, running in any cluster, and using the
     47 * access functions defined in the <alarm.c> & <alarm.h> files.
    4348 * It contains an architecture specific extension to store the interrupt vector(s).
    4449 * The core_init()function must allocate memory for this extension, depending on the
     
    5156        gid_t               gid;            /*! core global identifier (hardware index)    */
    5257
     58        scheduler_t         scheduler;      /*! embedded private scheduler                 */
     59
    5360        uint64_t            cycles;         /*! total number of cycles (from hard reset)   */
    5461        uint32_t            time_stamp;     /*! previous time stamp (read from register)   */
    5562
    5663    list_entry_t        alarms_root;    /*! root of list of attached alarms            */
    57     busylock_t          alarms_lock;    /*! lock protecting the list of alarms         */
     64    remote_busylock_t   alarms_lock;    /*! lock protecting the list of alarms         */
    5865
    5966        uint32_t            ticks_nr;       /*! number of elapsed ticks                    */
    6067        uint32_t            usage;          /*! cumulated busy_percent (idle / total)      */
    61         uint32_t            spurious_irqs;  /*! for instrumentation...                     */
    6268        struct thread_s   * fpu_owner;      /*! pointer on current FPU owner thread        */
    6369    uint32_t            rand_last;      /*! last computed random value                 */
    64 
    65         scheduler_t         scheduler;      /*! embedded private scheduler                 */
    6670
    6771    void              * pic_extend;     /*! PIC implementation specific extension      */
  • trunk/kernel/kern/do_syscall.c

    r669 r683  
    22 * do_syscall.c - architecture independant entry-point for system calls.
    33 *
    4  * Author    Alain Greiner (2016,2017,2018, 2019)
     4 * Author    Alain Greiner (2016,2017,2018,2019,2020)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    4343///////////////////////////////////////////////////////////////////////////////////////
    4444// This array of pointers define the kernel functions implementing the syscalls.
    45 // It must be kept consistent with the enum in "syscalls_numbers.h" file.
     45// It must be kept consistent with the enum in <syscalls_numbers.h> file,
     46// and with the SYS_OBJs defined in the kernel <Makefile>.
    4647///////////////////////////////////////////////////////////////////////////////////////
    4748
     
    9495    sys_wait,               // 39
    9596
    96     sys_get_config,         // 40
    97     sys_get_core_id,        // 41
    98     sys_get_cycle,          // 42
    99     sys_display,            // 43
    100     sys_place_fork,         // 44
    101     sys_thread_sleep,       // 45
    102     sys_thread_wakeup,      // 46
    103     sys_trace,              // 47
    104     sys_fg,                 // 48
    105     sys_is_fg,              // 49
     97    sys_get,                // 40
     98    sys_display,            // 41
     99    sys_place_fork,         // 42
     100    sys_thread_sleep,       // 43
     101    sys_thread_wakeup,      // 44
     102    sys_trace,              // 45
     103    sys_fg,                 // 46
     104    sys_is_fg,              // 47
     105    sys_fbf,                // 48
     106    sys_undefined,          // 49   //
    106107
    107108    sys_exit,               // 50
    108109    sys_sync,               // 51
    109110    sys_fsync,              // 52
    110     sys_get_best_core,      // 53
    111     sys_get_nb_cores,       // 54
    112     sys_get_thread_info,    // 55
    113     sys_fbf,                // 56
    114     sys_socket,             // 57
     111    sys_socket,             // 53
    115112};
    116113
     
    164161    case SYS_WAIT:                         return "WAIT";             // 39
    165162
    166     case SYS_GET_CONFIG:                   return "GET_CONFIG";       // 40
    167     case SYS_GET_CORE_ID:                  return "GET_CORE_ID";      // 41
    168     case SYS_GET_CYCLE:                    return "GET_CYCLE";        // 42
    169     case SYS_DISPLAY:                      return "DISPLAY";          // 43
    170     case SYS_PLACE_FORK:                   return "PLACE_FORK";       // 44
    171     case SYS_THREAD_SLEEP:                 return "THREAD_SLEEP";     // 45
    172     case SYS_THREAD_WAKEUP:                return "THREAD_WAKEUP";    // 46
    173     case SYS_TRACE:                        return "TRACE";            // 47
    174     case SYS_FG:                           return "FG";               // 48
    175     case SYS_IS_FG:                        return "IS_FG";            // 49
     163    case SYS_GET:                          return "GET";              // 40
     164    case SYS_DISPLAY:                      return "DISPLAY";          // 41
     165    case SYS_PLACE_FORK:                   return "PLACE_FORK";       // 42
     166    case SYS_THREAD_SLEEP:                 return "THREAD_SLEEP";     // 43
     167    case SYS_THREAD_WAKEUP:                return "THREAD_WAKEUP";    // 44
     168    case SYS_TRACE:                        return "TRACE";            // 45
     169    case SYS_FG:                           return "FG";               // 46
     170    case SYS_IS_FG:                        return "IS_FG";            // 47
     171    case SYS_FBF:                          return "FBF";              // 48
    176172
    177173    case SYS_EXIT:                         return "EXIT";             // 50
    178174    case SYS_SYNC:                         return "SYNC";             // 51
    179175    case SYS_FSYNC:                        return "FSYNC";            // 52
    180     case SYS_GET_BEST_CORE:                return "GET_BEST_CORE";    // 53
    181     case SYS_GET_NB_CORES:                 return "GET_NB_CORES";     // 54
    182     case SYS_GET_THREAD_INFO:              return "GET_THREAD_INFO";  // 55
    183     case SYS_FBF:                          return "FBF";              // 56
    184     case SYS_SOCKET:                       return "SOCKET";           // 57
     176    case SYS_SOCKET:                       return "SOCKET";           // 53
    185177
    186178    default:                               return "undefined";
  • trunk/kernel/kern/kernel_init.c

    r669 r683  
    33 *
    44 * Authors :  Mohamed Lamine Karaoui (2015)
    5  *            Alain Greiner  (2016,2017,2018,2019,2020)
     5 *            Alain Greiner          (2016,2017,2018,2019,2020)
    66 *
    77 * Copyright (c) Sorbonne Universites
     
    4646#include <memcpy.h>
    4747#include <ppm.h>
     48#include <kcm.h>
    4849#include <page.h>
    4950#include <chdev.h>
     
    379380        if( func == DEV_FUNC_MMC ) 
    380381        {
    381 
    382             // check channels
    383             if( channels != 1 )
    384             {
    385                 printk("\n[PANIC] in %s : MMC device must be single channel\n",
    386                 __FUNCTION__ );
    387                 hal_core_sleep();
    388             }
    389 
    390382            // create chdev in local cluster
    391383            chdev_ptr = chdev_create( func,
     
    394386                                      false,      // direction
    395387                                      base );
    396 
    397             // check memory
    398388            if( chdev_ptr == NULL )
    399389            {
     
    403393            }
    404394           
     395#if (DEBUG_KERNEL_INIT & 0x1)
     396if( hal_time_stamp() > DEBUG_KERNEL_INIT )
     397printk("\n[%s] created chdev[%x,%x] for MMC\n",
     398__FUNCTION__ , local_cxy , chdev_ptr );
     399#endif
    405400            // make MMC specific initialisation
    406401            dev_mmc_init( chdev_ptr );
     
    423418#if( DEBUG_KERNEL_INIT & 0x1 )
    424419if( hal_time_stamp() > DEBUG_KERNEL_INIT )
    425 printk("\n[%s] : created MMC in cluster %x / chdev = %x\n",
     420printk("\n[%s] initialised chdev[%x,%x] for MMC\n",
    426421__FUNCTION__ , local_cxy , chdev_ptr );
    427422#endif
     
    439434                                          false,     // direction
    440435                                          base );
    441 
    442                 // check memory
    443436                if( chdev_ptr == NULL )
    444437                {
     
    448441                }
    449442           
     443#if (DEBUG_KERNEL_INIT & 0x1)
     444if( hal_time_stamp() > DEBUG_KERNEL_INIT )
     445printk("\n[%s] cxy %x : created chdev[%x,%x] for DMA[%d]\n",
     446__FUNCTION__ , local_cxy , chdev_ptr , channel );
     447#endif
    450448                // make DMA specific initialisation
    451449                dev_dma_init( chdev_ptr );     
     
    457455#if( DEBUG_KERNEL_INIT & 0x1 )
    458456if( hal_time_stamp() > DEBUG_KERNEL_INIT )
    459 printk("\n[%s] : created DMA[%d] in cluster %x / chdev = %x\n",
    460 __FUNCTION__ , channel , local_cxy , chdev_ptr );
     457printk("\n[%s] initialised chdev[%x,%x] for DMA[%d]\n",
     458__FUNCTION__ , local_cxy , chdev_ptr , channel );
    461459#endif
    462460            }
     
    471469// These chdev descriptors are distributed on all clusters, using a modulo on a global
    472470// index, identically computed in all clusters.
    473 // This function is executed in all clusters by the core[0] core, that computes a global index
    474 // for all external chdevs. Each core[0] core creates only the chdevs that must be placed in
    475 // the local cluster, because the global index matches the local index.
     471// This function is executed in all clusters by the core[0], that computes a global index
     472// for all external chdevs. Each core[0] core creates only the chdevs that must be placed
     473// in the local cluster, because the global index matches the local index.
    476474// The relevant entries in all copies of the devices directory are initialised.
    477475///////////////////////////////////////////////////////////////////////////////////////////
     
    499497    dev_tbl     = info->ext_dev;
    500498
    501     // initializes global index (PIC is already placed in cluster 0
     499    // initializes global index (PIC is already placed in cluster 0)
    502500    ext_chdev_gid = 1;
    503501
     
    529527
    530528        // check external device functionnal type
    531         if( (func != DEV_FUNC_IOB) && (func != DEV_FUNC_IOC) && (func != DEV_FUNC_TXT) &&
    532             (func != DEV_FUNC_NIC) && (func != DEV_FUNC_FBF) )
     529        if( (func != DEV_FUNC_IOB) &&
     530            (func != DEV_FUNC_IOC) &&
     531            (func != DEV_FUNC_TXT) &&
     532            (func != DEV_FUNC_NIC) &&
     533            (func != DEV_FUNC_FBF) )
    533534        {
    534535            printk("\n[PANIC] in %s : undefined peripheral type\n",
     
    537538        }
    538539
    539         // loops on channels
     540        // loop on channels
    540541        for( channel = 0 ; channel < channels ; channel++ )
    541542        {
     
    547548
    548549                // all kernel instances compute the target cluster for all chdevs,
    549                 // computing the global index ext_chdev_gid[func,channel,direction]
     550                // and the global index ext_chdev_gid[func,channel,direction]
    550551                cxy_t target_cxy;
    551552                while( 1 )
     
    568569                if( target_cxy == local_cxy )
    569570                {
    570 
    571 #if( DEBUG_KERNEL_INIT & 0x3 )
    572 if( hal_time_stamp() > DEBUG_KERNEL_INIT )
    573 printk("\n[%s] : found chdev %s / channel = %d / rx = %d / cluster %x\n",
    574 __FUNCTION__ , chdev_func_str( func ), channel , rx , local_cxy );
    575 #endif
    576571                    chdev = chdev_create( func,
    577572                                          impl,
     
    587582                    }
    588583
     584#if (DEBUG_KERNEL_INIT & 0x1)
     585if( hal_time_stamp() > DEBUG_KERNEL_INIT )
     586printk("\n[%s] created chdev[%x,%x] for %s[%d] / is_rx %d\n",
     587__FUNCTION__ , local_cxy , chdev , chdev_func_str(func) , channel , rx );
     588#endif
    589589                    // make device type specific initialisation
    590590                    if     ( func == DEV_FUNC_IOB ) dev_iob_init( chdev );
     
    621621                    }
    622622
    623 #if( DEBUG_KERNEL_INIT & 0x3 )
     623#if( DEBUG_KERNEL_INIT & 1 )
    624624if( hal_time_stamp() > DEBUG_KERNEL_INIT )
    625 printk("\n[%s] : created chdev %s / channel = %d / rx = %d / cluster %x / chdev = %x\n",
    626 __FUNCTION__ , chdev_func_str( func ), channel , rx , local_cxy , chdev );
    627 #endif
     625printk("\n[%s] initialised chdev[%x,%x] for %s\n",
     626__FUNCTION__ , local_cxy, chdev , chdev->name );
     627#endif
     628
    628629                }  // end if match
    629630
     
    637638
    638639///////////////////////////////////////////////////////////////////////////////////////////
    639 // This function is called by core[0] in cluster 0 to allocate memory and initialize the PIC
     640// This function is called by core[0][0] to allocate memory and initialize the PIC
    640641// device, namely the informations attached to the external IOPIC controller, that
    641642// must be replicated in all clusters (struct iopic_input).
     
    11021103    // and allocates memory for the corresponding chdev descriptors.
    11031104    if( core_lid == 0 ) internal_devices_init( info );
    1104        
    11051105
    11061106    // All core[0]s contribute to initialise external peripheral chdev descriptors.
     
    14941494                   " - core descriptor    : %d bytes\n"
    14951495                   " - scheduler          : %d bytes\n"
    1496                    " - socket             : %d bytes\n"
     1496                   " - socket descriptor  : %d bytes\n"
    14971497                   " - rpc fifo           : %d bytes\n"
    14981498                   " - page descriptor    : %d bytes\n"
     
    15011501                   " - ppm manager        : %d bytes\n"
    15021502                   " - kcm manager        : %d bytes\n"
    1503                    " - khm manager        : %d bytes\n"
    15041503                   " - vmm manager        : %d bytes\n"
    15051504                   " - vfs inode          : %d bytes\n"
     
    15291528                   sizeof( ppm_t              ),
    15301529                   sizeof( kcm_t              ),
    1531                    sizeof( khm_t              ),
    15321530                   sizeof( vmm_t              ),
    15331531                   sizeof( vfs_inode_t        ),
     
    15461544#endif
    15471545
     1546    // number of cycles per TICK (depends on the actual system clock frequency
     1547    uint32_t cycles_per_tick = cluster->sys_clk / CONFIG_SCHED_TICKS_PER_SECOND;
     1548
    15481549    // each core activates its private TICK IRQ
    1549     dev_pic_enable_timer( CONFIG_SCHED_TICK_MS_PERIOD );
     1550    dev_pic_enable_timer( cycles_per_tick );
    15501551
    15511552    /////////////////////////////////////////////////////////////////////////////////
  • trunk/kernel/kern/ksocket.c

    r669 r683  
    11/*
    2  * ksocket.c - kernel socket API implementation.
     2 * ksocket.c - kernel socket implementation.
    33 *
    4  * Authors  Alain Greiner   (2016,2017,2018,2019,2020)
     4 * Authors  Alain Greiner        (2016,2017,2018,2019,2020)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    117117    switch( sts )
    118118    {
    119         case CMD_STS_SUCCESS  : return "TX_CONNECT";
     119        case CMD_STS_SUCCESS  : return "SUCCESS";
    120120        case CMD_STS_EOF      : return "EOF";
    121121        case CMD_STS_RST      : return "RST";
     
    135135// and request the NIC_TX server thread to re-send the unacknowledged segment.
    136136///////////////////////////////////////////////////////////////////////////////////////////
    137 // @ args_xp    : extended pointer on the involved socket.
     137// @ sock_xp    : extended pointer on the involved socket.
    138138///////////////////////////////////////////////////////////////////////////////////////////
    139 static void __attribute__((noinline)) socket_alarm_handler( xptr_t args_xp )
     139static void __attribute__((noinline)) socket_alarm_handler( xptr_t sock_xp )
    140140{
    141141    // get cluster and local pointer on socket descriptor
    142     socket_t * sock_ptr = GET_PTR( args_xp );
    143     cxy_t      sock_cxy = GET_CXY( args_xp );
     142    socket_t * sock_ptr = GET_PTR( sock_xp );
     143    cxy_t      sock_cxy = GET_CXY( sock_xp );
     144
     145#if DEBUG_SOCKET_ALARM
     146uint32_t cycle = (uint32_t)hal_get_cycles();
     147#endif
     148
     149   // build extended pointer on lock protecting socket
     150    xptr_t socket_lock_xp = XPTR( sock_cxy , &sock_ptr->lock );
     151
     152    // take the socket lock
     153    remote_queuelock_acquire( socket_lock_xp );
    144154
    145155    // get relevant infos from socket descriptor
     
    151161"illegal tx_client field for a retransmission timeout" );
    152162
    153     // get TX client thread cluster and local pointer
    154     thread_t * thread_ptr = GET_PTR( thread_xp );
     163    // get TX client thread cluster
    155164    cxy_t      thread_cxy = GET_CXY( thread_xp );
    156165
     
    168177
    169178    // update the date in alarm
    170     alarm_update( thread_ptr , hal_get_cycles() + TCP_RETRANSMISSION_TIMEOUT );
     179    alarm_update( thread_xp , hal_get_cycles() + CONFIG_SOCK_RETRY_TIMEOUT );
    171180   
    172181    //////////////////////////////
     
    175184
    176185#if DEBUG_SOCKET_ALARM
    177 uint32_t cycle = (uint32_t)hal_get_cycles();
    178 printk("\n[%s] rings for TX_CONNECT : request a new SYN segment / cycle %d\n",
     186if( DEBUG_SOCKET_ALARM < cycle )
     187printk("\n[%s] rings for CONNECT : request a new SYN segment / cycle %d\n",
    179188__FUNCTION__ , cycle );
    180189#endif
     
    193202
    194203#if DEBUG_SOCKET_ALARM
    195 uint32_t cycle = (uint32_t)hal_get_cycles();
    196 printk("\n[%s] rings for TX_ACCEPT : request a new SYN-ACK segment / cycle %d\n",
     204if( DEBUG_SOCKET_ALARM < cycle )
     205printk("\n[%s] rings for ACCEPT : request a new SYN-ACK segment / cycle %d\n",
    197206__FUNCTION__ , cycle );
    198207#endif
     
    211220
    212221#if DEBUG_SOCKET_ALARM
    213 uint32_t cycle = (uint32_t)hal_get_cycles();
    214 printk("\n[%s] rings for TX_CLOSE : request a new FIN-ACK segment / cycle %d\n",
     222if( DEBUG_SOCKET_ALARM < cycle )
     223printk("\n[%s] rings for CLOSE : request a new FIN-ACK segment / cycle %d\n",
    215224__FUNCTION__ , cycle );
    216225#endif
     
    227236    if( tx_cmd == CMD_TX_SEND )
    228237    {
    229         // TODO build a new TX_SEND command
    230     }
     238        // get get relevant infos from socket pointer
     239        uint32_t  tx_una = hal_remote_l32( XPTR( sock_cxy , &sock_ptr->tx_una ));
     240        uint32_t  tx_ack = hal_remote_l32( XPTR( sock_cxy , &sock_ptr->tx_ack ));
     241        uint32_t  tx_len = hal_remote_l32( XPTR( sock_cxy , &sock_ptr->tx_len ));
     242
     243#if DEBUG_SOCKET_ALARM       
     244if( DEBUG_SOCKET_ALARM < cycle )
     245printk("\n[%s] rings for SEND : request %d bytes / cycle %d\n",
     246__FUNCTION__ , tx_len , cycle );
     247#endif
     248        // update command fields in socket
     249        hal_remote_s32( XPTR( sock_cxy , &sock_ptr->tx_nxt    ) , tx_una );
     250        hal_remote_s32( XPTR( sock_cxy , &sock_ptr->tx_todo   ) , tx_len - tx_ack );
     251        hal_remote_s32( XPTR( sock_cxy , &sock_ptr->tx_valid  ) , true );
     252
     253        // unblock the NIC_TX server thread
     254        thread_unblock( tx_server_xp , THREAD_BLOCKED_CLIENT );
     255    }
     256
     257    // release the socket lock
     258    remote_queuelock_release( socket_lock_xp );
     259
    231260}   // end socket_alarm_handler()
    232 
    233 ///////////////////////////////////////////////////////////////////////////////////////////
    234 // This static function activates the alarm embedded in the calling thread descriptor,
    235 // using the <date> argument.
    236 ///////////////////////////////////////////////////////////////////////////////////////////
    237 // @ delay   : number of cycles (from the current absolute date).
    238 ///////////////////////////////////////////////////////////////////////////////////////////
    239 static void socket_alarm_start( xptr_t   socket_xp,
    240                                 uint32_t delay )
    241 {
    242     // compute absolute date
    243     cycle_t date = hal_get_cycles() + delay;
    244 
    245     // get pointer on calling threadf
    246     thread_t * this = CURRENT_THREAD;
    247 
    248     // start the alarm
    249     alarm_start( date,
    250                  &socket_alarm_handler,   // func_ptr
    251                  socket_xp,               // args_xp
    252                  this );
    253 }
    254 
    255 ///////////////////////////////////////////////////////////////////////////////////////////
    256 // This static function activates the alarm embedded in the calling thread descriptor,
    257 // using the <date> argument.
    258 ///////////////////////////////////////////////////////////////////////////////////////////
    259 // @ date   : absolute date for this alarm.
    260 ///////////////////////////////////////////////////////////////////////////////////////////
    261 static void socket_alarm_stop( void )
    262 {
    263     // get pointer on calling threadf
    264     thread_t * this = CURRENT_THREAD;
    265 
    266     // stop the alarm
    267     alarm_stop( this );
    268 }
    269261
    270262/////////////////////////////////////////////////////////////////////////////////////////
     
    470462// associated to a socket: file descriptor, socket descriptor, RX buffer, R2T queue,
    471463// and CRQ queue. It allocates an fdid, and register it in the process fd_array.
    472 // It initialise the  the socket desccriptor static fields, other than local_addr,
     464// It initialise the socket desccriptor static fields, other than local_addr,
    473465// local_port, remote_addr, remote_port), and set the socket state to UNBOUND.
    474466// It returns the local pointer on socket descriptor and the fdid value in buffers
     
    489481{
    490482    uint32_t       fdid;
    491     kmem_req_t     req;
    492483    socket_t     * socket;
    493484    vfs_file_t   * file;
    494485    uint32_t       state;
     486    void         * tx_buf;
    495487    error_t        error;
     488
    496489
    497490    thread_t  * this    = CURRENT_THREAD;
    498491    process_t * process = this->process;
    499492
     493#if DEBUG_SOCKET_CREATE || DEBUG_SOCKET_ERROR
     494uint32_t cycle = (uint32_t)hal_get_cycles();
     495#endif
     496
    500497#if DEBUG_SOCKET_CREATE
    501 uint32_t cycle = (uint32_t)hal_get_cycles();
    502498if( DEBUG_SOCKET_CREATE < cycle )
    503499printk("\n[%s] thread[%x,%x] enter / cycle %d\n",
     
    506502   
    507503    // 1. allocate memory for socket descriptor
    508     req.type   = KMEM_KCM;
    509     req.order  = bits_log2( sizeof(socket_t) );
    510     req.flags  = AF_ZERO;
    511     socket     = kmem_remote_alloc( cxy , &req );
     504    socket = kmem_remote_alloc( cxy , bits_log2(sizeof(socket_t)) , AF_ZERO );
    512505
    513506    if( socket == NULL )
    514507    {
    515         printk("\n[ERROR] in %s : cannot allocate socket descriptor / thread[%x,%x]\n",
    516         __FUNCTION__, process->pid, this->trdid );
    517         return -1;
    518     }
    519 
    520     // 2. allocate memory for rx_buf buffer
     508
     509#if DEBUG_SOCKET_ERROR
     510printk("\n[ERROR] in %s : cannot allocate socket descriptor / thread[%x,%x] / cycle %d\n",
     511__FUNCTION__, process->pid, this->trdid, cycle );
     512#endif
     513        return -1;
     514    }
     515
     516    // 2. allocate memory for rx_buf data buffer
    521517    error = remote_buf_init( XPTR( cxy , &socket->rx_buf ),
    522                              bits_log2( CONFIG_SOCK_RX_BUF_SIZE ) );
     518                             CONFIG_SOCK_RX_BUF_ORDER );
    523519
    524520    if( error )
    525521    {
    526         printk("\n[ERROR] in %s : cannot allocate rx_buf / thread[%x,%x]\n",
    527         __FUNCTION__, process->pid, this->trdid );
    528         req.type = KMEM_KCM;
    529         req.ptr  = socket;
    530         kmem_remote_free( cxy , &req );
    531         return -1;
    532     }
    533 
    534     // 3. allocate memory for r2tq queue
     522
     523#if DEBUG_SOCKET_ERROR
     524printk("\n[ERROR] in %s : no memory for rx_buf / thread[%x,%x] / cycle %d\n",
     525__FUNCTION__, process->pid, this->trdid, cycle );
     526#endif
     527        kmem_remote_free( cxy , socket , bits_log2(sizeof(socket_t)) );  // 1
     528        return -1;
     529    }
     530
     531    // 3. allocate memory for tx_buf
     532    tx_buf = kmem_remote_alloc( cxy , CONFIG_SOCK_TX_BUF_ORDER , AF_NONE );
     533
     534    if( tx_buf == NULL )
     535    {
     536
     537#if DEBUG_SOCKET_ERROR
     538printk("\n[ERROR] in %s : no memory for tx_buf / thread[%x,%x] / cycle %d\n",
     539__FUNCTION__, process->pid, this->trdid, cycle );
     540#endif
     541        remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) );        // 2
     542        kmem_remote_free( cxy , socket , bits_log2(sizeof(socket_t)) );  // 1
     543        return -1;
     544    }
     545
     546    // 4. allocate memory for r2tq queue
    535547    error = remote_buf_init( XPTR( cxy , &socket->r2tq ),
    536548                             bits_log2( CONFIG_SOCK_R2T_BUF_SIZE ) );
    537549    if( error )
    538550    {
    539         printk("\n[ERROR] in %s : cannot allocate R2T queue / thread[%x,%x]\n",
    540         __FUNCTION__, process->pid, this->trdid );
    541         remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) );
    542         req.type = KMEM_KCM;
    543         req.ptr  = socket;
    544         kmem_remote_free( cxy , &req );
    545         return -1;
    546     }
    547 
    548     // don't allocate memory for crqq queue, as it is done by the socket_listen function
    549 
    550     //  4. allocate memory for file descriptor
    551         req.type  = KMEM_KCM;
    552         req.order = bits_log2( sizeof(vfs_file_t) );
    553     req.flags = AF_ZERO;
    554         file      = kmem_remote_alloc( cxy , &req );
     551
     552#if DEBUG_SOCKET_ERROR
     553printk("\n[ERROR] in %s : cannot allocate R2T queue / thread[%x,%x] / cycle %d\n",
     554__FUNCTION__, process->pid, this->trdid, cycle );
     555#endif
     556        kmem_remote_free( cxy , tx_buf , CONFIG_SOCK_TX_BUF_ORDER );     // 3
     557        remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) );        // 2
     558        kmem_remote_free( cxy , socket , bits_log2(sizeof(socket_t)) );  // 1
     559        return -1;
     560    }
     561
     562    // don't allocate memory for CRQ queue / done by the socket_listen function
     563
     564    // 5. allocate memory for file descriptor
     565        file = kmem_remote_alloc( cxy , bits_log2(sizeof(vfs_file_t)) , AF_ZERO );
    555566
    556567    if( file == NULL )
    557568    {
    558         printk("\n[ERROR] in %s : cannot allocate file descriptor / thread[%x,%x]\n",
    559         __FUNCTION__, process->pid, this->trdid );
    560         remote_buf_release_data( XPTR( cxy , &socket->r2tq ) );
    561         remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) );
    562         req.type = KMEM_KCM;
    563         req.ptr  = socket;
    564         kmem_remote_free( cxy , &req );
     569
     570#if DEBUG_SOCKET_ERROR
     571printk("\n[ERROR] in %s : cannot allocate file descriptor / thread[%x,%x] / cycle %d\n",
     572__FUNCTION__, process->pid, this->trdid, cycle );
     573#endif
     574        remote_buf_release_data( XPTR( cxy , &socket->r2tq ) );          // 4
     575        kmem_remote_free( cxy , tx_buf , CONFIG_SOCK_TX_BUF_ORDER );     // 3
     576        remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) );        // 2
     577        kmem_remote_free( cxy , socket , bits_log2(sizeof(socket_t)) );  // 1
    565578        return -1;
    566579    }
    567580   
    568     // 5. get an fdid value, and register file descriptor in fd_array[]
     581    // 6. get an fdid value, and register file descriptor in fd_array[]
    569582    error = process_fd_register( process->ref_xp,
    570583                                 XPTR( cxy , file ),
     
    572585    if ( error )
    573586    {
    574         printk("\n[ERROR] in %s : cannot register file descriptor / thread[%x,%x]\n",
    575         __FUNCTION__, process->pid, this->trdid );
    576         req.type = KMEM_KCM;
    577         req.ptr  = file;
    578         kmem_free( &req );
    579         remote_buf_release_data( XPTR( cxy , &socket->r2tq ) );
    580         remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) );
    581         req.ptr  = socket;
    582         kmem_free( &req );
     587
     588#if DEBUG_SOCKET_ERROR
     589if( DEBUG_SOCKET_ERROR < cycle )
     590printk("\n[ERROR] in %s : cannot register file descriptor / thread[%x,%x] / cycle %d\n",
     591__FUNCTION__, process->pid, this->trdid, cycle );
     592#endif
     593        kmem_remote_free( cxy , file , bits_log2(sizeof(vfs_file_t)) );  // 5
     594        remote_buf_release_data( XPTR( cxy , &socket->r2tq ) );          // 4
     595        kmem_remote_free( cxy , tx_buf , CONFIG_SOCK_TX_BUF_ORDER );     // 3
     596        remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) );        // 2
     597        kmem_remote_free( cxy , socket , bits_log2(sizeof(socket_t)) );  // 1
    583598        return -1;
    584599    }
     
    597612    hal_remote_s32( XPTR( cxy , &socket->rx_valid    ) , false );
    598613    hal_remote_s32( XPTR( cxy , &socket->nic_channel ) , 0 );
     614    hal_remote_spt( XPTR( cxy , &socket->tx_buf      ) , tx_buf );
    599615
    600616    // initialize file descriptor
     
    606622
    607623#if DEBUG_SOCKET_CREATE
     624cycle = (uint32_t)hal_get_cycles();
    608625if( DEBUG_SOCKET_CREATE < cycle )
    609626printk("\n[%s] thread[%x,%x] exit / socket[%x,%d] / xptr[%x,%x] / cycle %d\n",
     
    631648static void socket_destroy( xptr_t file_xp )
    632649{
    633     kmem_req_t          req;
    634 
    635650    thread_t  * this    = CURRENT_THREAD;
    636651    process_t * process = this->process;
     
    677692
    678693    // release memory allocated for file descriptor
    679     req.type = KMEM_KCM;
    680     req.ptr  = file_ptr;
    681     kmem_remote_free( file_cxy , &req );
     694    kmem_remote_free( file_cxy , file_ptr , bits_log2(sizeof(vfs_file_t)) );
    682695
    683696    // release memory allocated for buffers attached to socket descriptor
     
    687700
    688701    // release memory allocated for socket descriptor
    689     req.type = KMEM_KCM;
    690     req.ptr  = socket_ptr;
    691     kmem_remote_free( file_cxy , &req );
     702    kmem_remote_free( file_cxy , socket_ptr , bits_log2(sizeof(socket_t)) );
    692703
    693704#if DEBUG_SOCKET_DESTROY
     
    702713////////////////////////////////////////////////
    703714void socket_put_r2t_request( xptr_t    queue_xp,
    704                              uint32_t  flags,
     715                             uint8_t   flags,
    705716                             uint32_t  channel )
    706717{
     
    715726        // try to register R2T request
    716727        error_t error = remote_buf_put_from_kernel( queue_xp,
    717                                                     (uint8_t *)(&flags),
     728                                                    &flags,
    718729                                                    1 );
    719730        if( error )
     
    740751    }
    741752}  // end socket_put_r2t_request()
     753
     754///////////////////////////////////////////////////
     755error_t socket_get_r2t_request( xptr_t    queue_xp,
     756                                uint8_t * flags )
     757{
     758    // get one request from R2T queue
     759    return remote_buf_get_to_kernel( queue_xp,
     760                                     flags,
     761                                     1 );
     762}  // end socket_get_r2T_request()
    742763 
    743764///////////////////////////////////////////////////
     
    843864    process_t * process = this->process;
    844865
     866#if DEBUG_SOCKET_BIND || DEBUG_SOCKET_ERROR
     867uint32_t cycle = (uint32_t)hal_get_cycles();
     868#endif
     869
    845870#if DEBUG_SOCKET_BIND
    846 uint32_t cycle = (uint32_t)hal_get_cycles();
    847871if( DEBUG_SOCKET_BIND < cycle )
    848872printk("\n[%s] thread[%x,%x] enter / socket[%x,%d] / addr %x / port %x / cycle %d\n",
     
    858882    if( file_xp == XPTR_NULL )
    859883    {
    860         printk("\n[ERROR] in %s : undefined fdid %d / thread[%x,%x]\n",
    861         __FUNCTION__, fdid, process->pid, this->trdid );
     884
     885#if DEBUG_SOCKET_ERROR
     886printk("\n[ERROR] in %s : undefined fdid %d / thread[%x,%x] / cycle %d\n",
     887__FUNCTION__, fdid, process->pid, this->trdid, cycle );
     888#endif
    862889        return -1;
    863890    }
     
    869896    if( file_type != FILE_TYPE_SOCK )
    870897    {
    871         printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x]",
    872         __FUNCTION__, vfs_inode_type_str( file_type ), process->pid, this->trdid );
     898
     899#if DEBUG_SOCKET_ERROR
     900printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x] / cycle %d",
     901__FUNCTION__, vfs_inode_type_str( file_type ), process->pid, this->trdid, cycle );
     902#endif
    873903        return -1;
    874904    }
     
    918948    process_t * process = this->process;
    919949
     950#if DEBUG_SOCKET_LISTEN || DEBUG_SOCKET_ERROR
     951uint32_t cycle = (uint32_t)hal_get_cycles();
     952#endif
     953
    920954#if DEBUG_SOCKET_LISTEN
    921 uint32_t cycle = (uint32_t)hal_get_cycles();
    922955if( DEBUG_SOCKET_LISTEN < cycle )
    923956printk("\n[%s] thread[%x,%x] enter / socket[%x,%d] / crq_depth %x / cycle %d\n",
     
    933966    if( file_xp == XPTR_NULL )
    934967    {
    935         printk("\n[ERROR] in %s : undefined fdid %d / thread[%x,%x]\n",
    936         __FUNCTION__, fdid, process->pid, this->trdid );
     968
     969#if DEBUG_SOCKET_ERROR
     970printk("\n[ERROR] in %s : undefined fdid %d / thread[%x,%x] / cycle %d\n",
     971__FUNCTION__, fdid, process->pid, this->trdid, cycle );
     972#endif
    937973        return -1;
    938974    }
     
    944980    if( file_type != FILE_TYPE_SOCK )
    945981    {
    946         printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x]\n",
    947         __FUNCTION__, vfs_inode_type_str(file_type), process->pid, this->trdid );
     982
     983#if DEBUG_SOCKET_ERROR
     984printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x] / cycle %d\n",
     985__FUNCTION__, vfs_inode_type_str(file_type), process->pid, this->trdid, cycle );
     986#endif
    948987        return -1;
    949988    }
     
    958997    if( socket_type != SOCK_STREAM )
    959998    {
    960         printk("\n[ERROR] in %s : illegal socket type %s / thread[%x,%x]\n",
    961         __FUNCTION__, socket_type_str(socket_type), process->pid, this->trdid );
     999
     1000#if DEBUG_SOCKET_ERROR
     1001printk("\n[ERROR] in %s : illegal socket type %s / thread[%x,%x] / cycle %d\n",
     1002__FUNCTION__, socket_type_str(socket_type), process->pid, this->trdid, cycle );
     1003#endif
    9621004        return -1;
    9631005    }
     
    9661008    if( socket_state != TCP_STATE_BOUND )
    9671009    {
    968         printk("\n[ERROR] in %s : illegal socket state %s / thread[%x,%x]\n",
    969         __FUNCTION__, socket_state_str(socket_state), process->pid, this->trdid );
     1010
     1011#if DEBUG_SOCKET_ERROR
     1012printk("\n[ERROR] in %s : illegal socket state %s / thread[%x,%x] / cycle %d\n",
     1013__FUNCTION__, socket_state_str(socket_state), process->pid, this->trdid, cycle );
     1014#endif
    9701015        return -1;
    9711016    }
     
    9801025    if( error )
    9811026    {
    982         printk("\n[ERROR] in %s : cannot allocate CRQ queue / thread[%x,%x]\n",
    983         __FUNCTION__, process->pid, this->trdid );
     1027
     1028#if DEBUG_SOCKET_ERROR
     1029printk("\n[ERROR] in %s : cannot allocate CRQ queue / thread[%x,%x] / cycle %d\n",
     1030__FUNCTION__, process->pid, this->trdid, cycle );
     1031#endif
    9841032        return -1;
    9851033    }
     
    10111059    vfs_file_t        * file_ptr;
    10121060    cxy_t               file_cxy;
    1013     vfs_file_type_t    file_type;           // file descriptor type
     1061    vfs_file_type_t     file_type;           // file descriptor type
    10141062    socket_t          * socket_ptr;          // local pointer on remote waiting socket
    10151063    uint32_t            socket_type;         // listening socket type   
     
    10451093    process_t * process   = this->process;
    10461094
    1047 #if DEBUG_SOCKET_ACCEPT
     1095#if DEBUG_SOCKET_ACCEPT || DEBUG_SOCKET_ERROR
    10481096uint32_t cycle = (uint32_t)hal_get_cycles();
     1097#endif
     1098
     1099#if DEBUG_SOCKET_ACCEPT
    10491100if( DEBUG_SOCKET_ACCEPT < cycle )
    10501101printk("\n[%s] thread[%x,%x] enter for socket[%x,%d] / cycle %d\n",
     
    10601111    if( file_xp == XPTR_NULL )
    10611112    {
    1062         printk("\n[ERROR] in %s : undefined fdid %d",
    1063         __FUNCTION__, fdid );
     1113
     1114#if DEBUG_SOCKET_ERROR
     1115printk("\n[ERROR] in %s : undefined fdid %d / thead[%x,%x] / cycle %d",
     1116__FUNCTION__, fdid, process->pid, this->trdid, cycle );
     1117#endif
    10641118        return -1;
    10651119    }
     
    10711125    if( file_type != FILE_TYPE_SOCK )
    10721126    {
    1073         printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x]\n",
    1074         __FUNCTION__, vfs_inode_type_str(file_type), process->pid, this->trdid );
     1127
     1128#if DEBUG_SOCKET_ERROR
     1129printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x] / cycle %d\n",
     1130__FUNCTION__, vfs_inode_type_str(file_type), process->pid, this->trdid, cycle );
     1131#endif
    10751132        return -1;
    10761133    }
     
    10971154    if( socket_type != SOCK_STREAM )
    10981155    {
    1099         // release listening socket lock
     1156                   
     1157#if DEBUG_SOCKET_ERROR
     1158printk("\n[ERROR] in %s : illegal socket type %s / thread[%x,%x] / cycle %d\n",
     1159__FUNCTION__, socket_type_str(socket_type), process->pid , this->trdid, cycle );
     1160#endif
    11001161        remote_queuelock_release( socket_lock_xp );
    1101                    
    1102         printk("\n[ERROR] in %s : illegal socket type %s / thread[%x,%x]\n",
    1103         __FUNCTION__, socket_type_str(socket_type), process->pid , this->trdid );
    11041162        return -1;
    11051163    }
     
    11081166    if( socket_state != TCP_STATE_LISTEN )
    11091167    {
    1110         // release listening socket lock
     1168
     1169#if DEBUG_SOCKET_ERROR
     1170printk("\n[ERROR] in %s : illegal socket state %s / thread[%x,%x] / cycle %d\n",
     1171__FUNCTION__, socket_state_str(socket_state), process->pid, this->trdid, cycle );
     1172#endif
    11111173        remote_queuelock_release( socket_lock_xp );
    1112                    
    1113         printk("\n[ERROR] in %s : illegal socket state %s / thread[%x,%x]\n",
    1114         __FUNCTION__, socket_state_str(socket_state), process->pid, this->trdid );
    11151174        return -1;
    11161175    }
     
    11191178    if( (socket_rx_valid == true) || (socket_rx_client != XPTR_NULL) )
    11201179    {
    1121         // release listening socket lock
     1180
     1181#if DEBUG_SOCKET_ERROR
     1182printk("\n[ERROR] in %s : previous RX cmd on socket[%x,%d] / thread[%x,%x] / cycle %d\n",
     1183__FUNCTION__, process->pid, fdid, process->pid, this->trdid, cycle );
     1184#endif
    11221185        remote_queuelock_release( socket_lock_xp );
    1123                    
    1124         printk("\n[ERROR] in %s : previous RX cmd on socket[%x,%d] / thread[%x,%x]\n",
    1125         __FUNCTION__, process->pid, fdid, process->pid, this->trdid );
    11261186        return -1;
    11271187    }
     
    11301190    if( (socket_tx_valid == true) || (socket_tx_client != XPTR_NULL) )
    11311191    {
    1132         // release socket lock
     1192                   
     1193#if DEBUG_SOCKET_ERROR
     1194printk("\n[ERROR] in %s : previous TX cmd on socket[%x,%d] / thread[%x,%x] / cycle %d\n",
     1195__FUNCTION__, process->pid, fdid, process->pid, this->trdid, cycle );
     1196#endif
    11331197        remote_queuelock_release( socket_lock_xp );
    1134                    
    1135         printk("\n[ERROR] in %s : previous TX cmd on socket[%x,%d] / thread[%x,%x]\n",
    1136         __FUNCTION__, process->pid, fdid, process->pid, this->trdid );
    1137         return -1;
    1138     }
    1139 
    1140     // 2) build extended pointer on listening socket.crq
     1198        return -1;
     1199    }
     1200
     1201    // 2) check the listenig socket CRQ
    11411202    crq_xp  = XPTR( file_cxy , &socket_ptr->crqq );
    11421203
     
    11441205    crq_status = remote_buf_status( crq_xp );
    11451206
    1146     // block & deschedule when CRQ empty
     1207    // block & deschedule to wait a client request when CRQ empty
    11471208    if( crq_status == 0 )
    11481209    {
    1149         // register command arguments in listening socket
     1210        // register command arguments for NIC_RX server in listening socket
    11501211        hal_remote_s32( XPTR( file_cxy , &socket_ptr->rx_cmd    ), CMD_RX_ACCEPT );
    11511212        hal_remote_s64( XPTR( file_cxy , &socket_ptr->rx_client ), client_xp );
     
    11791240        crq_status   = remote_buf_status( crq_xp );
    11801241
    1181 assert( __FUNCTION__, (((crq_status > 0) || (cmd_status!= CMD_STS_SUCCESS)) && (cmd_valid == false)),
     1242assert( __FUNCTION__,
     1243(((crq_status > 0) || (cmd_status!= CMD_STS_SUCCESS)) && (cmd_valid == false)),
    11821244"illegal socket state when client thread resumes after RX_ACCEPT" );
    11831245
     
    11871249        if( cmd_status != CMD_STS_SUCCESS )
    11881250        {
    1189             // release socket lock
     1251
     1252#if DEBUG_SOCKET_ERROR
     1253printk("\n[ERROR] in %s : reported for RX / socket[%x,%d] / thread[%x,%x] / cycle %d\n",
     1254__FUNCTION__, process->pid, fdid, process->pid, this->trdid, cycle );
     1255#endif
    11901256            remote_queuelock_release( socket_lock_xp );
    1191 
    1192             printk("\n[ERROR] in %s for RX_ACCEPT command / socket[%x,%d] / thread[%x,%x]\n",
    1193             __FUNCTION__, process->pid, fdid, process->pid, this->trdid );
    11941257            return -1;
    11951258        }
    1196 
    1197         // extract first request from the listening socket CRQ
    1198         error = socket_get_crq_request( crq_xp,
     1259    }  // end blocking on CRQ empty
     1260
     1261    // from this point, we can extract a request from listening socket CRQ
     1262    error = socket_get_crq_request( crq_xp,
    11991263                                    &new_remote_addr,
    12001264                                    &new_remote_port,
    12011265                                    &new_remote_iss,
    12021266                                    &new_remote_window );
    1203 
    12041267assert( __FUNCTION__, (error == 0),
    12051268"cannot get a connection request from a non-empty CRQ" );
    12061269
    1207         // reset listening socket rx_client
    1208         hal_remote_s32( XPTR( file_cxy , &socket_ptr->rx_client ) , XPTR_NULL );
    1209 
    1210         // release socket lock
    1211         remote_queuelock_release( socket_lock_xp );
    1212 
    1213     }  // end blocking on CRQ status
    1214 
    1215     // from this point, we can create a new socket
    1216     // and ask the NIC_TX to send a SYN-ACK segment
     1270    // release listening socket lock
     1271    remote_queuelock_release( socket_lock_xp );
    12171272
    12181273#if DEBUG_SOCKET_ACCEPT
    12191274cycle = (uint32_t)hal_get_cycles();
    12201275if( DEBUG_SOCKET_ACCEPT < cycle )
    1221 printk("\n[%s] thread[%x,%x] socket[%x,%d] / got a CRQ request / cycle %d\n",
    1222 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle );
     1276printk("\n[%s] thread[%x,%x] socket[%x,%d] / CRQ request [addr %x / port %x] / cycle %d\n",
     1277__FUNCTION__, process->pid, this->trdid, process->pid, fdid,
     1278new_remote_addr, new_remote_port, cycle );
    12231279#endif
    12241280
     
    12341290    if( error )
    12351291    {
    1236         printk("\n[ERROR] in %s : cannot allocate new socket / thread[%x,%x]\n",
    1237         __FUNCTION__, process->pid, this->trdid );
     1292
     1293#if DEBUG_SOCKET_ERROR
     1294printk("\n[ERROR] in %s : cannot create new socket / thread[%x,%x] / cycle %d\n",
     1295__FUNCTION__, process->pid, this->trdid, cycle );
     1296#endif
    12381297        return -1;
    12391298    }
     
    12871346 
    12881347    // start retransmission timer
    1289     socket_alarm_start( new_socket_xp , TCP_RETRANSMISSION_TIMEOUT );
     1348    alarm_start( client_xp,
     1349                 hal_get_cycles() + CONFIG_SOCK_RETRY_TIMEOUT,
     1350                 &socket_alarm_handler,
     1351                 new_socket_xp );
    12901352
    12911353#if DEBUG_SOCKET_ACCEPT
    12921354cycle = (uint32_t)hal_get_cycles();
    12931355if( DEBUG_SOCKET_ACCEPT < cycle )
    1294 printk("\n[%s] thread[%x,%x] new_socket[%x,%d] blocks on <IO> waiting ESTAB / cycle %d\n",
     1356printk("\n[%s] thread[%x,%x] for socket[%x,%d] request SYN-ACK & blocks on <IO> / cycle %d\n",
    12951357__FUNCTION__, process->pid, this->trdid, process->pid, new_fdid, cycle );
    12961358#endif
     
    13071369#endif
    13081370
    1309     // stop retransmission timer
    1310     socket_alarm_stop();
     1371    // stop retransmission timer in thread descriptor
     1372    alarm_stop( client_xp );
    13111373
    13121374    // get new socket state, tx_valid and tx_sts
     
    13151377    cmd_status = hal_remote_l32( XPTR( new_socket_cxy , &new_socket_ptr->tx_sts ));
    13161378
    1317 assert( __FUNCTION__, (((new_state == TCP_STATE_ESTAB) || (cmd_status != CMD_STS_SUCCESS))
    1318         && (cmd_valid == false)),
     1379assert( __FUNCTION__,
     1380(((new_state == TCP_STATE_ESTAB) || (cmd_status != CMD_STS_SUCCESS)) && (cmd_valid == false)),
    13191381"illegal socket state when client thread resumes after TX_ACCEPT" );
    13201382
     
    13241386    if( cmd_status != CMD_STS_SUCCESS )
    13251387    {
    1326         printk("\n[ERROR] in %s for TX_ACCEPT command / socket[%x,%d] / thread[%x,%x]\n",
    1327         __FUNCTION__, process->pid, new_fdid, process->pid, this->trdid );
     1388
     1389#if DEBUG_SOCKET_ERROR
     1390printk("\n[ERROR] in %s reported for TX / socket[%x,%d] / thread[%x,%x] / cycle %d\n",
     1391__FUNCTION__, process->pid, new_fdid, process->pid, this->trdid, cycle );
     1392#endif
    13281393        return -1;
    13291394    }
     
    13701435    trdid_t     trdid     = this->trdid;
    13711436
     1437#if DEBUG_SOCKET_CONNECT || DEBUG_SOCKET_ERROR
     1438uint32_t cycle = (uint32_t)hal_get_cycles();
     1439#endif
     1440
    13721441    // get pointers on file descriptor
    13731442    xptr_t       file_xp  = process_fd_get_xptr_from_local( this->process , fdid );
     
    13781447    if( file_xp == XPTR_NULL )
    13791448    {
    1380         printk("\n[ERROR] in %s : undefined fdid %d",
    1381         __FUNCTION__, fdid );
     1449
     1450#if DEBUG_SOCKET_ERROR
     1451printk("\n[ERROR] in %s : undefined fdid %d / thread[%x,%x] / cycle %d",
     1452__FUNCTION__, fdid, pid, trdid, cycle );
     1453#endif
    13821454        return -1;
    13831455    }
     
    13881460
    13891461#if DEBUG_SOCKET_CONNECT
    1390 uint32_t cycle = (uint32_t)hal_get_cycles();
    13911462if( DEBUG_SOCKET_CONNECT < cycle )
    1392 printk("\n[%s] thread[%x,%x] enter for socket[%x,%d] / addr %x / port %d / cycle %d\n",
     1463printk("\n[%s] thread[%x,%x] enter for socket[%x,%d] / addr %x / port %x / cycle %d\n",
    13931464__FUNCTION__,  pid, trdid, pid, fdid, remote_addr, remote_port, cycle );
    13941465#endif
     
    13971468    if( file_type != FILE_TYPE_SOCK )
    13981469    {
    1399         printk("\n[ERROR] in %s : illegal file type %s",
    1400         __FUNCTION__, vfs_inode_type_str( file_type ) );
     1470
     1471#if DEBUG_SOCKET_ERROR
     1472printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x] / cycle %d",
     1473__FUNCTION__, vfs_inode_type_str( file_type ), pid, trdid, cycle );
     1474#endif
    14011475        return -1;
    14021476    }
     
    14121486        if( socket_state != UDP_STATE_BOUND )
    14131487        {
    1414             printk("\n[ERROR] in %s : illegal socket state %s for type %s",
    1415             __FUNCTION__, socket_state_str(socket_state), socket_type_str(socket_type) );
     1488
     1489#if DEBUG_SOCKET_ERROR
     1490printk("\n[ERROR] in %s : illegal socket state %s for type %s / thread[%x,%x] / cycle %d",
     1491__FUNCTION__, socket_state_str(socket_state), socket_type_str(socket_type), pid, trdid, cycle );
     1492#endif
    14161493            return -1;
    14171494        }
     
    14211498        if( socket_state != TCP_STATE_BOUND )
    14221499        {
    1423             printk("\n[ERROR] in %s : illegal socket state %s for type %s",
    1424             __FUNCTION__, socket_state_str(socket_state), socket_type_str(socket_type) );
     1500
     1501#if DEBUG_SOCKET_ERROR
     1502printk("\n[ERROR] in %s : illegal socket state %s for type %s / thread[%x,%x] / cycle %d",
     1503__FUNCTION__, socket_state_str(socket_state), socket_type_str(socket_type), pid, trdid, cycle );
     1504#endif
    14251505            return -1;
    14261506        }
     
    14281508    else
    14291509    {
    1430         printk("\n[ERROR] in %s : illegal socket type %s",
    1431         __FUNCTION__,  socket_type_str(socket_type) );
     1510
     1511#if DEBUG_SOCKET_ERROR
     1512printk("\n[ERROR] in %s : illegal socket type / thread[%x,%x] / cycle %d",
     1513__FUNCTION__, pid, trdid, cycle );
     1514#endif
    14321515        return -1;
    14331516    }
     
    14751558 
    14761559        // start retransmission timer
    1477         socket_alarm_start( socket_xp , TCP_RETRANSMISSION_TIMEOUT );
     1560        alarm_start( client_xp,
     1561                     hal_get_cycles() + CONFIG_SOCK_RETRY_TIMEOUT,
     1562                     &socket_alarm_handler,
     1563                     socket_xp );
    14781564
    14791565#if DEBUG_SOCKET_CONNECT
     
    14941580#endif
    14951581
    1496         // stop retransmission timer
    1497         socket_alarm_stop();
     1582        // stop retransmission timer in thread descriptor
     1583        alarm_stop( client_xp );
    14981584
    14991585        // get socket state, tx_valid and tx_sts
     
    15071593
    15081594        // reset socket.tx_client
    1509         hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_client ) , XPTR_NULL );
     1595        hal_remote_s64( XPTR( file_cxy , &socket_ptr->tx_client ) , XPTR_NULL );
    15101596
    15111597        if( cmd_status != CMD_STS_SUCCESS )
    15121598        {
    1513             printk("\n[ERROR] in %s : for command TX_CONNECT / socket[%x,%d] / thread[%x,%x]\n",
    1514             __FUNCTION__, pid, fdid, pid, trdid );
     1599
     1600#if DEBUG_SOCKET_ERROR
     1601printk("\n[ERROR] in %s reported by server / socket[%x,%d] / thread[%x,%x] / cycle %d\n",
     1602__FUNCTION__, pid, fdid, pid, trdid, cycle );
     1603#endif
    15151604            return -1;
    15161605        }
     
    15481637    trdid_t      trdid     = this->trdid;
    15491638
     1639#if DEBUG_SOCKET_CLOSE || DEBUG_SOCKET_ERROR
     1640uint32_t cycle = (uint32_t)hal_get_cycles();
     1641#endif
     1642
    15501643    // get pointers on socket descriptor
    15511644    cxy_t        file_cxy   = GET_CXY( file_xp );
     
    15581651
    15591652#if DEBUG_SOCKET_CLOSE
    1560 uint32_t cycle = (uint32_t)hal_get_cycles();
    15611653if (DEBUG_SOCKET_CLOSE < cycle )
    15621654printk("\n[%s] thread[%x,%x] enters for socket[%x,%d] / cycle %d\n",
     
    15741666        (hal_remote_l64( XPTR( file_cxy , &socket_ptr->tx_client)) != XPTR_NULL) )
    15751667    {
    1576         // release socket lock
     1668                   
     1669#if DEBUG_SOCKET_ERROR
     1670printk("\n[ERROR] in %s : previous TX cmd on socket[%x,%d] / thread[%x,%x] / cycle %d\n",
     1671__FUNCTION__, pid, fdid, pid, trdid, cycle );
     1672#endif
    15771673        remote_queuelock_release( socket_lock_xp );
    1578                    
    1579         printk("\n[ERROR] in %s : previous TX cmd on socket[%x,%d] / thread[%x,%x]\n",
    1580         __FUNCTION__, pid, fdid, pid, trdid );
    15811674        return -1;
    15821675    }
     
    16451738
    16461739        // start retransmission timer
    1647         socket_alarm_start( socket_xp , TCP_RETRANSMISSION_TIMEOUT );
     1740        alarm_start( client_xp,
     1741                     hal_get_cycles() + CONFIG_SOCK_RETRY_TIMEOUT,
     1742                     &socket_alarm_handler,
     1743                     socket_xp );
    16481744
    16491745#if DEBUG_SOCKET_CLOSE
     
    16631759__FUNCTION__, pid, trdid, pid, fdid, cycle );
    16641760#endif
    1665         // stop retransmission timer
    1666         socket_alarm_stop();
     1761        // stop retransmission timer in thread descriptor
     1762        alarm_stop( client_xp );
    16671763
    16681764        // take socket lock
     
    16741770        cmd_valid    = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_valid ) );
    16751771
    1676 assert( __FUNCTION__, (((socket_state == TCP_STATE_CLOSED) || (cmd_status != CMD_STS_SUCCESS))
    1677          && (cmd_valid == false)),
    1678 "illegal socket state when client thread resumes after TX_CLOSE\n"
    1679 " socket_state = %s / cmd_status = %d / cmd_valid = %d\n",
     1772assert( __FUNCTION__,
     1773(((socket_state == TCP_STATE_CLOSED) || (cmd_status != CMD_STS_SUCCESS)) && (cmd_valid == false)),
     1774" socket_state = %s / cmd_status = %d / cmd_valid = %d",
    16801775socket_state_str(socket_state), cmd_status, cmd_valid );
    16811776
    16821777        // reset socket.tx_client
    1683         hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_client ) , XPTR_NULL );
     1778        hal_remote_s64( XPTR( file_cxy , &socket_ptr->tx_client ) , XPTR_NULL );
    16841779
    16851780        if( cmd_status != CMD_STS_SUCCESS )  // error reported
    16861781        {
    1687             printk("\n[ERROR] in %s for command TX_CLOSE / socket[%x,%d] / thread[%x,%x]\n",
    1688             __FUNCTION__, pid, fdid, pid, this->trdid );
     1782
     1783#if DEBUG_SOCKET_ERROR
     1784printk("\n[ERROR] in %s for command TX_CLOSE / socket[%x,%d] / thread[%x,%x] / cycle %d\n",
     1785__FUNCTION__, pid, fdid, pid, this->trdid, cycle );
     1786#endif
    16891787            return -1;
    16901788        }
     
    17081806////////////////////////////////////////////////////////////////////////////////////////
    17091807// This static function is called by the two functions socket_send() & socket_recv().
    1710 // It can be used for both UDP and TCP sockets.
     1808// It is used for both UDP and TCP sockets.
    17111809////////////////////////////////////////////////////////////////////////////////////////
    17121810// @ is_send   : send when true / receive when false.
    17131811// @ fdid      : socket identifier.
    17141812// @ u_buf     : pointer on user buffer in user space.
    1715 // @ length    : number of bytes.
     1813// @ length    : number of bytes in buffer.
    17161814////////////////////////////////////////////////////////////////////////////////////////
    17171815// Implementation note : The behavior is different for SEND & RECV
     
    17491847    chdev_t           * chdev_ptr;
    17501848    cxy_t               chdev_cxy;
    1751     uint32_t            buf_status;      // number of bytes in rx_buf
    17521849    int32_t             moved_bytes;     // total number of moved bytes (fot return)
    1753     xptr_t              server_xp;       // extended pointer on NIC_TX / NIC_RX server thread
    1754     thread_t          * server_ptr;      // local pointer on NIC_TX / NIC_RX server thread
    1755     kmem_req_t          req;             // KCM request for TX kernel buffer
    1756     uint8_t           * tx_buf;          // kernel buffer for TX transfer
    1757     bool_t              cmd_valid;       // from socket descriptor
    1758     uint32_t            cmd_status;      // from socket descriptor
    1759     uint32_t            tx_todo;         // from socket descriptor
     1850    xptr_t              server_xp;       // ext pointer on NIC_TX / NIC_RX thread
     1851    thread_t          * server_ptr;      // local pointer on NIC_TX / NIC_RX thread
     1852    uint8_t           * tx_buf;          // pointer on kernel buffer for TX transfer
     1853    bool_t              cmd_valid;       // RX or TX command from socket descriptor
     1854    uint32_t            cmd_sts;         // RX or TX command from socket descriptor
     1855    uint32_t            tx_todo;         // number of bytes still to send
     1856    xptr_t              rx_buf_xp;       // extended pointer on socket rx_buf
     1857    uint32_t            rx_buf_sts;      // current status of socket rx_buf
    17601858
    17611859    thread_t  * this    = CURRENT_THREAD;
    17621860    process_t * process = this->process;
     1861
     1862#if DEBUG_SOCKET_SEND || DEBUG_SOCKET_RECV || DEBUG_SOCKET_ERROR
     1863uint32_t cycle = (uint32_t)hal_get_cycles();
     1864#endif
     1865
     1866#if DEBUG_SOCKET_SEND || DEBUG_SOCKET_RECV
     1867if( is_send )
     1868printk("\n[%s] thread[%x,%x] socket[%x,%d] enter : SEND / buf %x / length %d / cycle %d\n",
     1869__FUNCTION__, process->pid, this->trdid, process->pid, fdid, u_buf, length, cycle );
     1870else
     1871printk("\n[%s] thread[%x,%x] socket[%x,%d] enter : RECV / buf %x / length %d / cycle %d\n",
     1872__FUNCTION__, process->pid, this->trdid, process->pid, fdid, u_buf, length, cycle );
     1873#endif
    17631874
    17641875    // build extended pointer on client thread
     
    17721883    if( file_xp == XPTR_NULL )
    17731884    {
    1774         printk("\n[ERROR] in %s : undefined fdid %d / thread%x,%x]\n",
    1775         __FUNCTION__, fdid , process->pid, this->trdid );
     1885
     1886#if DEBUG_SOCKET_ERROR
     1887printk("\n[ERROR] in %s : undefined fdid %d / thread%x,%x] / cycle %d\n",
     1888__FUNCTION__, fdid , process->pid, this->trdid, cycle );
     1889#endif
    17761890        return -1;
    17771891    }
     
    17871901    if( file_type != FILE_TYPE_SOCK )
    17881902    {
    1789         printk("\n[ERROR] in %s : illegal file type %s / socket[%x,%d]\n",
    1790         __FUNCTION__, vfs_inode_type_str(file_type), process->pid, fdid );
     1903
     1904#if DEBUG_SOCKET_ERROR
     1905printk("\n[ERROR] in %s : illegal file type thread[%x,%x] / cycle %d\n",
     1906__FUNCTION__, process->pid, this->trdid, cycle );
     1907#endif
    17911908        return -1;
    17921909    }
     
    18031920    nic_channel  = hal_remote_l32( XPTR( file_cxy , &socket_ptr->nic_channel ));
    18041921
    1805     /////////////
     1922    //////////////////////////////////////////////////////
    18061923    if( is_send )                       // SEND command
    18071924    {
    18081925
    18091926#if DEBUG_SOCKET_SEND
    1810 uint32_t    cycle = (uint32_t)hal_get_cycles();
     1927cycle = (uint32_t)hal_get_cycles();
    18111928if (DEBUG_SOCKET_SEND < cycle )
    1812 printk("\n[%s] thread[%x,%x] received SEND command for socket[%x,%d] / length %d / cycle %d\n",
     1929printk("\n[%s] thread[%x,%x] / socket[%x,%d] get SEND / length %d / cycle %d\n",
    18131930__FUNCTION__, process->pid, this->trdid, process->pid, fdid, length, cycle );
    18141931#endif
     1932
    18151933        // check no previous TX command
    1816         if( (hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_valid )) == true) ||
    1817             (hal_remote_l64( XPTR( file_cxy , &socket_ptr->tx_client)) != XPTR_NULL) )
     1934        if( hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_valid )) == true )
    18181935        {
    1819             // release socket lock
     1936                   
     1937#if DEBUG_SOCKET_ERROR
     1938printk("\n[ERROR] in %s : previous TX command / socket[%x,%d] / thread[%x,%x] / cycle %d\n",
     1939__FUNCTION__, process->pid, fdid, process->pid, this->trdid, cycle );
     1940#endif
    18201941            remote_queuelock_release( socket_lock_xp );
    1821                    
    1822             printk("\n[ERROR] in %s : previous TX command / socket[%x,%d] / thread[%x,%x]\n",
    1823             __FUNCTION__, process->pid, fdid, process->pid, this->trdid );
    18241942            return -1;
    18251943        }
    18261944
    1827         // allocate a temporary kernel buffer
    1828         req.type  = KMEM_KCM;
    1829         req.order = bits_log2( length );
    1830         req.flags = AF_NONE;
    1831         tx_buf    = kmem_alloc( &req ); 
    1832 
    1833         if( tx_buf == NULL )
    1834         {
    1835             // release socket lock
    1836             remote_queuelock_release( socket_lock_xp );
    1837                    
    1838             printk("\n[ERROR] in %s : no memory for tx_buf / socket[%x,%d] / thread[%x,%x]\n",
    1839             __FUNCTION__, process->pid, fdid, process->pid, this->trdid );
    1840             return -1;
    1841         }
    1842 
    1843         // copy data from user u_buf to kernel tx_buf   
    1844         hal_copy_from_uspace( XPTR( local_cxy , tx_buf ),
     1945        // get tx_buf pointer from socket pointer
     1946        tx_buf = (uint8_t*)hal_remote_lpt( XPTR( file_cxy , &socket_ptr->tx_buf ));
     1947
     1948        // copy data from user u_buf to kernel socket tx_buf   
     1949        hal_copy_from_uspace( XPTR( file_cxy , tx_buf ),
    18451950                              u_buf,
    18461951                              length );
     1952#if DEBUG_SOCKET_SEND
     1953if (DEBUG_SOCKET_SEND < cycle )
     1954printk("\n[%s] thread[%x,%x] / socket[%x,%d] copied %d bytes to tx_buf (%x,%x)\n",
     1955__FUNCTION__, process->pid, this->trdid, process->pid, fdid, length, file_cxy, tx_buf );
     1956putb("tx_buf : 16 first data bytes" , tx_buf , 16 );
     1957#endif
    18471958
    18481959        // register command in socket descriptor
     
    18521963        hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_len    ) , length );
    18531964        hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_todo   ) , length );
     1965        hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_ack    ) , 0 );
    18541966        hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_valid  ) , true );
    18551967
     
    18691981        thread_unblock( server_xp , THREAD_BLOCKED_CLIENT );
    18701982
    1871         // start retransmission timer
    1872         socket_alarm_start( socket_xp , TCP_RETRANSMISSION_TIMEOUT );
     1983        // start retransmission timer for TCP socket
     1984        if( socket_type == SOCK_STREAM ) 
     1985        {
     1986            alarm_start( client_xp,
     1987                         hal_get_cycles() + CONFIG_SOCK_RETRY_TIMEOUT,
     1988                         &socket_alarm_handler,
     1989                         socket_xp );
     1990        }
    18731991
    18741992#if DEBUG_SOCKET_SEND   
    1875 cycle = (uint32_t)hal_get_cycles();
    18761993if( DEBUG_SOCKET_SEND < cycle )
    1877 printk("\n[%s] thread[%x,%x] socket[%x,%d] register SEND => blocks on <IO> / cycle %d\n",
    1878 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle );
     1994printk("\n[%s] thread[%x,%x] / socket[%x,%d] registers SEND => blocks on <IO>\n",
     1995__FUNCTION__, process->pid, this->trdid, process->pid, fdid );
    18791996#endif
    18801997        // client thread blocks itself and deschedules
     
    18852002cycle = (uint32_t)hal_get_cycles();
    18862003if( DEBUG_SOCKET_SEND < cycle )
    1887 printk("\n[%s] thread[%x,%x] socket[%x,%d] for SEND resumes / cycle %d\n",
     2004printk("\n[%s] thread[%x,%x] / socket[%x,%d] resumes for SEND / cycle %d\n",
    18882005__FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle );
    18892006#endif
    1890         // stop retransmission timer
    1891         socket_alarm_stop();
    1892 
    1893         // take socket lock
     2007        // stop retransmission timer for TCP socket
     2008        if( socket_type == SOCK_STREAM )
     2009        {
     2010            alarm_stop( client_xp );
     2011        }
     2012
     2013        // take socket lock
    18942014        remote_queuelock_acquire( socket_lock_xp );
    18952015     
     
    18972017        tx_todo    = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_todo ));
    18982018        cmd_valid  = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_valid ));
    1899         cmd_status = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_sts ));
     2019        cmd_sts    = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_sts ));
    19002020
    19012021        // reset tx_client in socket descriptor
     
    19062026     
    19072027// check SEND command completed when TX client thread resumes
    1908 assert( __FUNCTION__, (((tx_todo == 0) || (cmd_status != CMD_STS_SUCCESS)) && (cmd_valid == false)),
    1909 "illegal socket state when client thread resumes after TX_SEND\n"
    1910 " tx_todo = %d / tx_status = %d / tx_valid = %d\n",
    1911 tx_todo, cmd_status, cmd_valid );
    1912 
    1913         // release the tx_buf
    1914         req.ptr = tx_buf;
    1915         kmem_free( &req );
    1916 
    1917         if( cmd_status != CMD_STS_SUCCESS )
     2028assert( __FUNCTION__,
     2029(((tx_todo == 0) || (cmd_sts != CMD_STS_SUCCESS)) && (cmd_valid == false)),
     2030"client thread resumes from SEND / bad state : tx_todo %d / tx_sts %d / tx_valid %d",
     2031tx_todo, cmd_sts, cmd_valid );
     2032
     2033        if( cmd_sts != CMD_STS_SUCCESS )
    19182034        {
    19192035
    1920 #if DEBUG_SOCKET_SEND
    1921 cycle = (uint32_t)hal_get_cycles();
    1922 if( DEBUG_SOCKET_RECV < cycle )
    1923 printk("\n[%s] error %s for TX_SEND / socket[%x,%d] / thread[%x,%x]\n",
    1924 __FUNCTION__, socket_cmd_sts_str(cmd_status), process->pid, fdid, process->pid, this->trdid );
     2036#if DEBUG_SOCKET_ERROR   
     2037printk("\n[ERROR] in %s : reported for SEND / socket[%x,%d] / thread[%x,%x] / cycle %d\n",
     2038__FUNCTION__, process->pid, fdid, process->pid, this->trdid, cycle );
    19252039#endif
    19262040            return -1;
     
    19322046cycle = (uint32_t)hal_get_cycles();
    19332047if (DEBUG_SOCKET_SEND < cycle )
    1934 printk("\n[%s] thread[%x,%x] success for SEND / socket[%x,%d] / length %d / cycle %d\n",
     2048printk("\n[%s] thread[%x,%x] SEND success / socket[%x,%d] / bytes %d / cycle %d\n",
    19352049__FUNCTION__, process->pid, this->trdid, process->pid, fdid, length, cycle );
    19362050#endif
     
    19402054    }  // end SEND command
    19412055
    1942     ////
    1943     else                                 // RECV command
     2056    /////////////////////////////////////////////////////////////
     2057    else                                       // RECV command
    19442058    {
    19452059
    19462060#if DEBUG_SOCKET_RECV
    1947 uint32_t    cycle = (uint32_t)hal_get_cycles();
    1948 if (DEBUG_SOCKET_SEND < cycle )
    1949 printk("\n[%s] thread[%x,%x] received RECV command for socket[%x,%d] / length %d / cycle %d\n",
     2061if (DEBUG_SOCKET_RECV < cycle )
     2062printk("\n[%s] thread[%x,%x] / socket[%x,%d] get RECV / length %d / cycle %d\n",
    19502063__FUNCTION__, process->pid, this->trdid, process->pid, fdid, length, cycle );
    19512064#endif
    19522065        // check no previous RX command
    1953         if( (hal_remote_l32( XPTR( file_cxy , &socket_ptr->rx_valid )) == true) ||
    1954             (hal_remote_l64( XPTR( file_cxy , &socket_ptr->rx_client)) != XPTR_NULL) )
     2066        if( hal_remote_l32( XPTR( file_cxy , &socket_ptr->rx_valid )) == true )
    19552067        {
    1956             // release socket lock
     2068                   
     2069#if DEBUG_SOCKET_ERROR   
     2070printk("\n[ERROR] in %s : previous RX command on socket[%x,%d] / thread[%x,%x] / cycle %d\n",
     2071__FUNCTION__, process->pid, fdid, process->pid, this->trdid, cycle );
     2072#endif
    19572073            remote_queuelock_release( socket_lock_xp );
    1958                    
    1959             printk("\n[ERROR] in %s : previous RX command on socket[%x,%d] / thread[%x,%x]\n",
    1960             __FUNCTION__, process->pid, fdid, process->pid, this->trdid );
    19612074            return -1;
    19622075        }
     
    19692082                   
    19702083#if DEBUG_SOCKET_RECV 
    1971 uint32_t cycle = (uint32_t)hal_get_cycles();
     2084cycle = (uint32_t)hal_get_cycles();
    19722085if( DEBUG_SOCKET_RECV < cycle )
    1973 printk("\n[%s] thread[%x,%x] socket[%x,%d] TCP connection closed / cycle %d\n",
     2086printk("\n[%s] thread[%x,%x] / socket[%x,%d] TCP connection closed / cycle %d\n",
    19742087__FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle );
    19752088#endif
    19762089            return 0;
    19772090        }
    1978         // build extended pointer on socket.rx_buf
    1979         xptr_t rx_buf_xp   = XPTR( file_cxy , &socket_ptr->rx_buf );
    1980 
    1981         // get rx_buf status
    1982         buf_status = remote_buf_status( rx_buf_xp );
    1983 
    1984         if( buf_status == 0 )
     2091
     2092        // build extended pointer on socket rx_buf
     2093        rx_buf_xp = XPTR( file_cxy , &socket_ptr->rx_buf );
     2094
     2095        // get socket rx_buf status
     2096        rx_buf_sts = remote_buf_status( rx_buf_xp );
     2097
     2098        // register RECV command and deschedule when rx_buf empty
     2099        if( rx_buf_sts == 0 )
    19852100        {
    19862101            // registers RX_RECV command in socket descriptor
     
    19932108
    19942109#if DEBUG_SOCKET_RECV 
    1995 uint32_t cycle = (uint32_t)hal_get_cycles();
    19962110if( DEBUG_SOCKET_RECV < cycle )
    1997 printk("\n[%s] thread[%x,%x] socket[%x,%d] rx_buf empty => blocks on <IO> / cycle %d\n",
    1998 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle );
     2111printk("\n[%s] thread[%x,%x] socket[%x,%d] for RECV : rx_buf empty => blocks on <IO>\n",
     2112__FUNCTION__, process->pid, this->trdid, process->pid, fdid );
    19992113#endif
    20002114            // client thread blocks itself and deschedules
     
    20052119cycle = (uint32_t)hal_get_cycles();
    20062120if( DEBUG_SOCKET_RECV < cycle )
    2007 printk("\n[%s] thread[%x,%x] socket[%x,%d] for RECV resumes / cycle %d\n",
     2121printk("\n[%s] thread[%x,%x] socket[%x,%d] for RECV : resumes / cycle %d\n",
    20082122__FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle );
    20092123#endif
     
    20112125            remote_queuelock_acquire( socket_lock_xp );
    20122126
    2013             // get rx_sts and rx_buf status
     2127            // get command status, command valid, and rx_buf status
    20142128            cmd_valid  = hal_remote_l32( XPTR( file_cxy , &socket_ptr->rx_valid ));
    2015             cmd_status = hal_remote_l32( XPTR( file_cxy , &socket_ptr->rx_sts ));
    2016             buf_status = remote_buf_status( rx_buf_xp );
     2129            cmd_sts    = hal_remote_l32( XPTR( file_cxy , &socket_ptr->rx_sts ));
     2130            rx_buf_sts = remote_buf_status( rx_buf_xp );
    20172131       
    2018 assert( __FUNCTION__, (((buf_status != 0) || (cmd_status != CMD_STS_SUCCESS)) && (cmd_valid == false)),
    2019 "illegal socket state when client thread resumes after RX_RECV\n"
    2020 " buf_status = %d / rx_sts = %d / rx_valid = %d\n",
    2021 buf_status , cmd_status , cmd_valid );
    2022 
    2023             // reset rx_client in socket descriptor
    2024             hal_remote_s64( XPTR( file_cxy , &socket_ptr->rx_client  ) , XPTR_NULL );
    2025 
    2026             // reset rx_buf for an UDP socket
    2027             if( socket_type == SOCK_DGRAM ) remote_buf_reset( rx_buf_xp );
    2028 
    2029             // release socket lock
    2030             remote_queuelock_release( socket_lock_xp );
    2031 
    2032             if( cmd_status == CMD_STS_EOF )           // EOF (remote close) reported
     2132assert( __FUNCTION__, (cmd_valid == false),
     2133"client thread resumes from RECV but rx_valid is true" );
     2134
     2135            if( cmd_sts == CMD_STS_EOF )           // EOF reported by RX server
    20332136            {
    20342137
    20352138#if DEBUG_SOCKET_RECV
    2036 cycle = (uint32_t)hal_get_cycles();
    20372139if( DEBUG_SOCKET_RECV < cycle )
    2038 printk("\n[%s] EOF for RX_RECV / socket[%x,%d] / thread[%x,%x]\n",
     2140printk("\n[%s] EOF received for socket[%x,%d] / thread[%x,%x]\n",
    20392141__FUNCTION__, process->pid, fdid, process->pid, this->trdid );
    20402142#endif
     2143                // release socket lock
     2144                remote_queuelock_release( socket_lock_xp );
     2145
    20412146                return 0;
    20422147            }
    2043             else if( cmd_status != CMD_STS_SUCCESS )   // other error reported
     2148            else if( cmd_sts != CMD_STS_SUCCESS )   // error reported by RX server
    20442149            {
    20452150
    2046 #if DEBUG_SOCKET_RECV
    2047 cycle = (uint32_t)hal_get_cycles();
    2048 if( DEBUG_SOCKET_RECV < cycle )
    2049 printk("\n[%s] error %s for RX_RECV / socket[%x,%d] / thread[%x,%x]\n",
    2050 __FUNCTION__, socket_cmd_sts_str(cmd_status), process->pid, fdid, process->pid, this->trdid );
    2051 #endif
     2151#if DEBUG_SOCKET_ERROR
     2152printk("\n[ERROR] in %s : rx_server for socket[%x,%d] / thread[%x,%x] / cycle %d\n",
     2153__FUNCTION__, process->pid, fdid, process->pid, this->trdid, cycle );
     2154#endif
     2155                // release socket lock
     2156                remote_queuelock_release( socket_lock_xp );
     2157
    20522158                return -1;
    20532159            }
    2054 
     2160            else if( rx_buf_sts == 0 )              // annormally empty rx_buf
     2161            {
     2162
     2163#if DEBUG_SOCKET_ERROR
     2164printk("\n[ERROR] in %s : rx_buf empty for socket[%x,%d] / thread[%x,%x] / cycle %d\n",
     2165__FUNCTION__, process->pid, fdid, process->pid, this->trdid, cycle );
     2166#endif
     2167                // release socket lock
     2168                remote_queuelock_release( socket_lock_xp );
     2169
     2170                return -1;
     2171            }
    20552172        }
    20562173
    20572174        // number of bytes extracted from rx_buf cannot be larger than u_buf size
    2058         moved_bytes = ( length < buf_status ) ? length : buf_status;
     2175        moved_bytes = ( length < rx_buf_sts ) ? length : rx_buf_sts;
    20592176
    20602177        // move data from kernel rx_buf to user u_buf
     
    20622179                                u_buf,
    20632180                                moved_bytes );
    2064 #if DEBUG_SOCKET_SEND
    2065 cycle = (uint32_t)hal_get_cycles();
    2066 if (DEBUG_SOCKET_SEND < cycle )
    2067 printk("\n[%s] thread[%x,%x] success for RECV / socket[%x,%d] / length %d / cycle %d\n",
     2181#if DEBUG_SOCKET_RECV
     2182cycle = (uint32_t)hal_get_cycles();
     2183if (DEBUG_SOCKET_RECV < cycle )
     2184printk("\n[%s] thread[%x,%x] : RECV success / socket[%x,%d] / bytes %d / cycle %d\n",
    20682185__FUNCTION__, process->pid, this->trdid, process->pid, fdid, moved_bytes, cycle );
    20692186#endif
     2187        // release socket lock
     2188        remote_queuelock_release( socket_lock_xp );
     2189
    20702190        return moved_bytes;
    20712191
     
    20952215} // end socket_recv()
    20962216
     2217////////////////////////////////////
     2218int socket_sendto( uint32_t    fdid,
     2219                   uint8_t   * u_buf,
     2220                   uint32_t    length,
     2221                   uint32_t    remote_ip,
     2222                   uint16_t    remote_port )
     2223{
     2224    printk("\n[ERROR] in %s : this function is not implemented yet\n",
     2225    __FUNCTION__, fdid, u_buf, length, remote_ip, remote_port );
     2226    return -1;
     2227
     2228}  // end socket_sendto()
     2229
     2230//////////////////////////////////////
     2231int socket_recvfrom( uint32_t    fdid,
     2232                     uint8_t   * u_buf,
     2233                     uint32_t    length,
     2234                     uint32_t    remote_ip,
     2235                     uint16_t    remote_port )
     2236{
     2237    printk("\n[ERROR] in %s : this function is not implemented yet\n",
     2238    __FUNCTION__, fdid, u_buf, length, remote_ip, remote_port );
     2239    return -1;
     2240
     2241} // end socket_recvfrom()
     2242
    20972243////////////////////////////////////////////
    20982244void socket_display( xptr_t       socket_xp,
    2099                      const char * func_str )
    2100 {
     2245                     const char * func_str,
     2246                     const char * string )
     2247{
     2248    uint32_t   cycle = (uint32_t)hal_get_cycles();
     2249
    21012250    socket_t * socket = GET_PTR( socket_xp );
    21022251    cxy_t      cxy    = GET_CXY( socket_xp );
     
    21112260    uint32_t   remote_port = hal_remote_l32( XPTR( cxy , &socket->remote_port ));
    21122261    uint32_t   tx_valid    = hal_remote_l32( XPTR( cxy , &socket->tx_valid ));
     2262    xptr_t     tx_client   = hal_remote_l64( XPTR( cxy , &socket->tx_client ));
    21132263    uint32_t   tx_cmd      = hal_remote_l32( XPTR( cxy , &socket->tx_cmd ));
    21142264    uint32_t   tx_sts      = hal_remote_l32( XPTR( cxy , &socket->tx_sts ));
     
    21182268    uint32_t   tx_nxt      = hal_remote_l32( XPTR( cxy , &socket->tx_nxt ));         
    21192269    uint32_t   tx_wnd      = hal_remote_l32( XPTR( cxy , &socket->tx_wnd ));         
     2270    uint32_t   tx_ack      = hal_remote_l32( XPTR( cxy , &socket->tx_ack ));         
    21202271    uint32_t   rx_valid    = hal_remote_l32( XPTR( cxy , &socket->rx_valid ));
     2272    xptr_t     rx_client   = hal_remote_l64( XPTR( cxy , &socket->rx_client ));
    21212273    uint32_t   rx_cmd      = hal_remote_l32( XPTR( cxy , &socket->rx_cmd ));
    21222274    uint32_t   rx_sts      = hal_remote_l32( XPTR( cxy , &socket->rx_sts ));
    21232275    uint32_t   rx_nxt      = hal_remote_l32( XPTR( cxy , &socket->rx_nxt ));         
    21242276    uint32_t   rx_wnd      = hal_remote_l32( XPTR( cxy , &socket->rx_wnd ));         
    2125     uint32_t   rx_irs      = hal_remote_l32( XPTR( cxy , &socket->rx_irs ));         
    2126 
    2127     if( func_str == NULL )
    2128     {
    2129         printk("\n****** socket[%x,%d] / xptr[%x,%x]*****\n",
    2130         pid, fdid, cxy, socket );
     2277    uint32_t   rx_irs      = hal_remote_l32( XPTR( cxy , &socket->rx_irs )); 
     2278
     2279    remote_queuelock_t * lock_ptr = &socket->lock; 
     2280    uint32_t   taken       = hal_remote_l32( XPTR( cxy , &lock_ptr->taken ));
     2281
     2282    thread_t * tx_ptr = GET_PTR( tx_client );
     2283    cxy_t      tx_cxy = GET_CXY( tx_client );
     2284    trdid_t    tx_tid = hal_remote_l32( XPTR( tx_cxy , &tx_ptr->trdid ));
     2285
     2286    thread_t * rx_ptr = GET_PTR( rx_client );
     2287    cxy_t      rx_cxy = GET_CXY( rx_client );
     2288    trdid_t    rx_tid = hal_remote_l32( XPTR( rx_cxy , &rx_ptr->trdid ));
     2289
     2290    if( string == NULL )
     2291    {
     2292        printk("\n****** socket[%x,%d] / lock %d / in %s / cycle %d *****\n",
     2293        pid, fdid, taken, func_str, cycle );
    21312294    }
    21322295    else
    21332296    {
    2134         printk("\n***** socket[%x,%d] / xptr[%x,%x] / from %s *****\n",
    2135         pid, fdid, cxy, socket, func_str );
    2136     }
    2137     printk(" - state %s / channel %d\n"
    2138            " - local_addr %x / local_port %x\n"
    2139            " - remote_addr %x / remote_port %x\n"
    2140            " - tx_valid %d (%s) / tx_sts %d / tx_len %x / tx_todo %x\n"
    2141            " - tx_una %x / tx_nxt %x / tx_wnd %x\n"
    2142            " - rx_valid %d (%s) / rx_sts %d\n"
    2143            " - rx_nxt %x / rx_wnd %x / rx_irs %x\n",
    2144            socket_state_str(state), channel ,
    2145            local_addr, local_port,
    2146            remote_addr, remote_port,
    2147            tx_valid, socket_cmd_type_str(tx_cmd), tx_sts, tx_len, tx_todo,
    2148            tx_una, tx_nxt, tx_wnd,
    2149            rx_valid, socket_cmd_type_str(rx_cmd), rx_sts,
    2150            rx_nxt, rx_wnd, rx_irs );
     2297        printk("\n***** socket[%x,%d] / lock %d / in %s %s / cycle %d *****\n",
     2298        pid, fdid, taken, func_str, string, cycle );
     2299    }
     2300    printk(" - state %s / channel %d / local [%x,%x] / remote[%x,%x]\n"
     2301           " - tx : valid %d / client [%x,%x] / cmd %s \n"
     2302           "        sts %d / len %x / todo %x / ack %x / una %x / nxt %x / wnd %x\n"
     2303           " - rx : valid %d / client [%x,%x] / cmd %s\n"
     2304           "        sts %d / nxt %x / wnd %x / irs %x\n",
     2305           socket_state_str(state), channel,
     2306           local_addr, local_port, remote_addr, remote_port,
     2307           tx_valid, pid, tx_tid, socket_cmd_type_str(tx_cmd),
     2308           tx_sts, tx_len, tx_todo, tx_ack, tx_una, tx_nxt, tx_wnd,
     2309           rx_valid, pid, rx_tid, socket_cmd_type_str(rx_cmd),
     2310           rx_sts, rx_nxt, rx_wnd, rx_irs );
    21512311
    21522312}  // end socket_display()
  • trunk/kernel/kern/ksocket.h

    r669 r683  
    11/*
    2  * ksocket.h - kernel socket descriptor and API definition.
     2 * ksocket.h - kernel socket definition.
    33 *
    44 * Authors  Alain Greiner    (2016,2017,2018,2019,2020)
     
    4040 * existing sockets is split in as many subsets as the number of NIC channels, in order
    4141 * to parallelize the transfers. The distribution key defining the channel index
    42  * is computed from the (remote_addr/remote_port) couple: by the NIC hardware for the
    43  * RX packets; by the software for the TX packets, using a dedicated NIC driver function.
     42 * is computed from the (remote_addr/remote_port) couple (by the NIC hardware for the
     43 * RX packets; by the software for the TX packets) using a dedicated NIC driver function.
    4444 * All sockets that have the same key share the same channel, and each socket is
    4545 * therefore linked to two chdevs : NIC_TX[key] & NIC_RX[key].
     
    5252 *   to the associated TX server (mainly used to handle the TCP ACKs).
    5353 * - the kernel "crq" buffer allows to store concurrent remote client connect requests
    54  *   to a local server socket. It is allocated in socket.
     54 *   to a local server socket.
    5555 *
    5656 * The synchronisation mechanism between the client threads and the server threads
    5757 * is different for the TX and RX directions:
    5858 *
    59  * 1) TX stream
     59 * 1) TX direction (sent packets)
    6060 *
    6161 * - The internal API between the TX client thread and the NIC_TX server thread defines
    6262 *   four command types, stored in the "tx_cmd" variable of the socket descriptor:
    63  *   . SOCKET_TX_CONNECT : TCP client request to start the 3 steps connection handshake.
    64  *   . SOCKET_TX_ACCEPT  : TCP server request to accept one pending connection request.
     63 *   . SOCKET_TX_CONNECT : request to start the connection handshake (TCP client only).
     64 *   . SOCKET_TX_ACCEPT  : request to accept one connection request (TCP server only).
    6565 *   . SOCKET_TX_SEND    : local (UDP/TCP) request to send data to a remote (UDP/TCP).
    6666 *   . SOCKET_TX_CLOSE   : local TCP socket request remote TCP socket to close connection.
     
    6969 *   reset the "tx_error" field, and registers itself in the "tx_client" field.
    7070 *   Then, it unblocks the TX server thread from the BLOCKED_CLIENT condition, blocks itself
    71  *   on the BLOCKED_IO condition, and deschedules. For a SEND, the "tx_buf" kernel buffer
    72  *   is dynamicaly allocated by the client thread, that copies the payload from the user
    73  *   buffer to this kernel buffer, that is used as retransmission buffer, when required.
     71 *   on the BLOCKED_IO condition, and deschedules. For a SEND, the client thread copies
     72 *   the payload contained in the "u_buf" user buffer to the socket "tx_buf" kernel buffer
     73 *   that is used as retransmission buffer, when required.
    7474 * - A command is valid for the TX server when the socket descriptor "tx_valid" is true.
    75  *   For a SEND command, the "tx_valid" is reset by the NIC_TX server when the last byte has
    76  *   been sent, but the TX client thread is unblocked by the NIC_RX server thread only when
    77  *   the last byte has been acknowledged, or to report an error.
     75 *   For a SEND command, the "tx_valid" is reset by the NIC_TX server thread when the last
     76 *   byte has been sent, but the TX client thread is unblocked by the NIC_RX server thread
     77 *   only when the last byte has been acknowledged, or to report an error.
    7878 *   For the CONNECT, ACCEPT and CLOSE commands, the "tx_valid" is reset by the NIC_TX server
    7979 *   when the first segment of the handshake has been sent, but the TX client thread is
     
    8888 *   When "tx_valid" or "r2t_valid" are true, the TX server thread build and send an UDP
    8989 *   packet or TCP segment. A single SEND command can require a large number of TCP
    90  *   segments to move a big data buffer.
     90 *   segments to move a big data buffer, before unblocking the client thread.
    9191 *   This TX server thread blocks and deschedules on the BLOCKED_ISR condition when there
    9292 *   the NIC_RX queue is full . It is unblocked by the hardware NIC_TX_ISR.
    93  * - In order to detect and report error for multiple simultaneous TX accesses to the same
    94  *   socket, the client thread makes a double check before posting a new TX command :
     93 * - As multiple simultaneous TX accesses to the same socket are forbiden, the client
     94 *   thread makes a double check before posting a new TX command :
    9595 *   the "tx_valid" field must be false, and the "tx_client" field must be XPTR_NULL.
    9696 *   The "tx_valid" field is reset by the TX server thread, and the "tx_client"
     
    136136 * 3) R2T queue
    137137 *
    138  * To implement the TCP "3 steps handshake" protocol for connection or to send RST,
    139  * the RX server thread can directly request the associated TX server thread to send
    140  * control packets in  the TX stream, using a dedicate R2T (RX to TX) FIFO stored in
    141  * the socket descriptor. Each R2T request occupy one byte in this R2T queue.
     138 * The RX server thread can directly request the associated TX server thread to send
     139 * control packets in  the TX stream, using a dedicate R2T (RX to TX) queue embedded in
     140 * the socket descriptor, and implemented as a remote_buf_t FIFO.
     141 * It is used for TCP acknowledge and for the TCP three-steps handshake.
     142 * Each R2T request occupy exactly one single byte defining the TCP flags to be set.
    142143 *
    143144 * 4) CRQ queue
    144145 *
    145146 * The remote CONNECT requests received by a TCP socket (SYN segments) are stored in a
    146  * dedicated CRQ FIFO stored in the local socket descriptor. These requests are consumed
    147  * by the local client thread executing an ACCEPT.
    148  * Each CRQ request occupy sizeof(connect_request_t) bytes in this CRQ queue.
     147 * dedicated CRQ queue, and consumed  by the local client thread executing an ACCEPT.
     148 * This CRQ queue is embedded in the local socket descriptor,  and implemented as a
     149 * remote_buf_t FIFO. Each request occupy sizeof(connect_request_t) bytes in the queue.
    149150 * The connect_request_t structure containing the request arguments is defined below.
    150151 *
     
    171172 * This enum defines the set of command status that can be returned by the NIC_RX and
    172173 * NIC_TX server threads to the TX & RX client threads.
    173  * The success must be signaled by the null value / the various failure cases are
    174  * signaled by a non-null value.
    175174 ****************************************************************************************/
    176175typedef enum socket_cmd_sts_e
     
    217216tcp_socket_state_t;
    218217
    219 /*****************************************************************************************
     218/****************************************************************************************
    220219 * This structure defines one connection request, registered in the CRQ queue.
    221  ****************************************************************************************/
     220 ***************************************************************************************/
    222221typedef struct connect_request_s
    223222{
     
    229228connect_request_t;
    230229
    231 /*****************************************************************************************
     230/****************************************************************************************
    232231 * This structure defines the socket descriptor.
    233  ****************************************************************************************/
     232 ***************************************************************************************/
    234233typedef struct socket_s
    235234{
     
    253252    uint8_t         *  tx_buf;       /*! pointer on TX data buffer in kernel space     */
    254253    uint32_t           tx_len;       /*! number of data bytes for a SEND command       */
    255     uint32_t           tx_todo;      /*! number of bytes not yet sent                  */
    256     xlist_entry_t      tx_temp;      /*! temporary list of sockets (root in TX chdev)  */
     254    uint32_t           tx_todo;      /*! number of bytes not yet sent in tx_buf        */
     255    uint32_t           tx_ack;       /*! number of bytes acknowledged in tx_buf        */
    257256
    258257    xlist_entry_t      rx_list;      /*! all sockets attached to same NIC_RX channel   */
     
    271270    uint32_t           tx_wnd;       /*! number of acceptable bytes in TX_data stream  */
    272271    uint32_t           tx_una;       /*! first unack byte in TX_data stream            */
     272
    273273    uint32_t           rx_nxt;       /*! next expected byte in RX_data stream          */
    274274    uint32_t           rx_wnd;       /*! number of acceptable bytes in RX_data stream  */
     
    319319
    320320/****************************************************************************************
    321  * This function is called by the dev_nic_rx_handle_tcp() function, executed by the
    322  * NIC_RX[channel] server thread, to register a R2T request defined by the <flags>
     321 * This blocking function is called by the dev_nic_rx_handle_tcp() function, executed by
     322 * the NIC_RX[channel] server thread, to register a R2T request defined by the <flags>
    323323 * argument in the socket R2T queue, specified by the <queue_xp> argument.
    324324 * This function unblocks the NIC_TX[channel] server thread, identified by the <channel>
    325325 * argumentfrom the THREAD_BLOCKED_CLIENT condition.
     326 *
     327 * WARNING : It contains a waiting loop and return only when an empty slot has been
     328 * found in the R2T queue.
    326329 ****************************************************************************************
    327330 * @ queue_xp   : [in] extended pointer on the R2T qeue descriptor.
     
    330333 ***************************************************************************************/
    331334void socket_put_r2t_request( xptr_t    queue_xp,
    332                              uint32_t  flags,
     335                             uint8_t   flags,
    333336                             uint32_t  channel );
     337
     338/****************************************************************************************
     339 * This function is called by the nic_tx_server thread to extract an R2T request
     340 * (one byte) from a R2T queue, specified by the <queue_xp> argument, to the buffer
     341 * defined by the <flags> argument.
     342 *****************************************************************************************
     343 * @ queue_xp      : [in]  extended pointer on the CRQ queue descriptor.
     344 * @ flags         : [out] buffer for TCP flags to be set.
     345 * @ return 0 if success / return -1 if queue empty.
     346 ***************************************************************************************/
     347error_t socket_get_r2t_request (xptr_t    queue_xp,
     348                                uint8_t * flags );
    334349 
    335350/****************************************************************************************
     
    339354 * by the <queue_xp> argument.
    340355 ****************************************************************************************
    341  * @ queue_xp      : [in] extended pointer on the CRQ qeue descriptor.
     356 * @ queue_xp      : [in] extended pointer on the CRQ queue descriptor.
    342357 * @ remote_addr   : [in] remote socket IP address.
    343358 * @ remote_port   : [in] remote socket port.
     
    374389 ****************************************************************************************
    375390 * @ socket_xp     : [in] extended pointer on socket descriptor.
    376  $ @ string        : [in] name of calling function.
     391 * @ func_str      : [in] name of calling function.
     392 * @ string        : [in] string defining the calling context (can be NULL)
    377393 ***************************************************************************************/
    378394void socket_display( xptr_t         socket_xp,
    379                      const char   * func_str );
     395                     const char   * func_str,
     396                     const char   * string );
    380397
    381398
     
    464481 * This blocking function contains two blocking conditions because it requests services
    465482 * to both the NIC_RX server thread, and he NIC_TX server thread.
    466  * It can be split in five steps:
     483 * It is structured in five steps:
    467484 * 1) It makes several checkings on the listening socket domain, type, and state.
    468485 * 2) If the socket CRQ queue is empty, the function makes an SOCKET_RX_ACCEPT command
     
    529546 * arguments, to a connected (TCP or UDP) socket, identified by the <fdid> argument.
    530547 * The work is actually done by the NIC_TX server thread, and the synchronisation
     548 * between the client and the server threads uses the "tx_valid" set/reset flip-flop:
     549 * The client thread registers itself in the socket descriptor, registers in the queue
     550 * rooted in the NIC_TX[index] chdev, set "tx_valid", unblocks the server thread, and
     551 * finally blocks on THREAD_BLOCKED_IO, and deschedules.
     552 * When the TX server thread completes the command (all data has been sent for an UDP
     553 * socket, or acknowledged for a TCP socket), the server thread reset "rx_valid" and
     554 * unblocks the client thread.
     555 * This function can be called by a thread running in any cluster.
     556 * WARNING : This implementation does not support several concurent SEND commands
     557 * on the same socket, as only one TX thread can register in a given socket.
     558 ****************************************************************************************
     559 * @ fdid      : [in] file descriptor index identifying the socket.
     560 * @ u_buf     : [in] pointer on buffer containing packet in user space.
     561 * @ length    : [in] packet size in bytes.
     562 * @ return number of sent bytes if success / return -1 if failure.
     563 ***************************************************************************************/
     564int socket_send( uint32_t    fdid,
     565                 uint8_t   * u_buf,
     566                 uint32_t    length );
     567
     568/****************************************************************************************
     569 * This blocking function implements the recv() syscall.
     570 * It is used to receive data that has been stored by the NIC_RX server thread in the
     571 * rx_buf of a connected socket, identified by the <fdid> argument. 
     572 * The synchronisation between the client and the server threads uses the "rx_valid"
     573 * set/reset flip-flop: If "rx_valid" is set, the client simply moves the available
     574 * data from the "rx_buf" to the user buffer identified by the <u_buf> and <length>
     575 * arguments, and reset the "rx_valid" flip_flop. If "rx_valid" is not set, the client
     576 * thread register itself in the socket descriptor, registers in the clients queue rooted
     577 * in the NIC_RX[index] chdev, and finally blocks on THREAD_BLOCKED_IO, and deschedules.
     578 * The client thread is re-activated by the RX server, that set the "rx_valid" flip-flop
     579 * as soon as data is available in the "rx_buf". The number of bytes actually transfered
     580 * can be less than the user buffer size.
     581 * This  function can be called by a thread running in any cluster.
     582 * WARNING : This implementation does not support several concurent RECV
     583 * commands on the same socket, as only one RX thread can register in a given socket.
     584 ****************************************************************************************
     585 * @ fdid        : [in] file descriptor index identifying the local socket.
     586 * @ u_buf       : [in] pointer on buffer in user space.
     587 * @ length      : [in] buffer size in bytes.
     588 * @ return number of received bytes if success / return -1 if failure.
     589 ***************************************************************************************/
     590int socket_recv( uint32_t    fdid,
     591                 uint8_t   * u_buf,
     592                 uint32_t    length );
     593
     594/****************************************************************************************
     595 * This blocking function implements the sendto() syscall.
     596 * It is used to send data stored in the user buffer, identified the <u_buf> and <length>
     597 * to a remote process identified by the <remote_ip> and <remote_port> arguments,
     598 * through a local, unconnected (UDP) socket, identified by the <fdid> argument.
     599 * The work is actually done by the NIC_TX server thread, and the synchronisation
    531600 * between the client and the server threads uses the "rx_valid" set/reset flip-flop:
    532601 * The client thread registers itself in the socket descriptor, registers in the queue
     
    539608 * WARNING : This implementation does not support several concurent SEND/SENDTO commands
    540609 * on the same socket, as only one TX thread can register in a given socket.
    541  ****************************************************************************************
    542  * @ fdid      : [in] file descriptor index identifying the socket.
    543  * @ u_buf     : [in] pointer on buffer containing packet in user space.
    544  * @ length    : [in] packet size in bytes.
     610 * TODO : this function is not implemented yet.
     611 ****************************************************************************************
     612 * @ fdid        : [in] file descriptor index identifying the local socket.
     613 * @ u_buf       : [in] pointer on buffer containing packet in user space.
     614 * @ length      : [in] packet size in bytes.
     615 * @ remote_ip   : [in] remote socket IP address.
     616 * @ remote_port : [in] remote socket port address.
    545617 * @ return number of sent bytes if success / return -1 if failure.
    546618 ***************************************************************************************/
    547 int socket_send( uint32_t    fdid,
    548                  uint8_t   * u_buf,
    549                  uint32_t    length );
    550 
    551 /****************************************************************************************
    552  * This blocking function implements the recv() syscall.
     619int socket_sendto( uint32_t   fdid,
     620                   uint8_t  * u_buf,
     621                   uint32_t   length,
     622                   uint32_t   remote_ip,
     623                   uint16_t   remote_port );
     624
     625/****************************************************************************************
     626 * This blocking function implements the recvfrom() syscall.
    553627 * It is used to receive data that has been stored by the NIC_RX server thread in the
    554  * rx_buf of a connected (TCP or UDP) socket, identified by the <fdid> argument.
     628 * rx_buf of a non connected socket, identified by the <fdid> argument, from a
     629 * remote process identified by the <remote_ip> and <remote_port> arguments.
    555630 * The synchronisation between the client and the server threads uses the "rx_valid"
    556631 * set/reset flip-flop: If "rx_valid" is set, the client simply moves the available
     
    565640 * WARNING : This implementation does not support several concurent RECV/RECVFROM
    566641 * commands on the same socket, as only one RX thread can register in a given socket.
    567  ****************************************************************************************
    568  * @ fdid      : [in] file descriptor index identifying the socket.
    569  * @ u_buf     : [in] pointer on buffer in user space.
    570  * @ length    : [in] buffer size in bytes.
     642 * TODO : this function is not implemented yet.
     643 ****************************************************************************************
     644 * @ fdid        : [in] file descriptor index identifying the local socket.
     645 * @ u_buf       : [in] pointer on buffer in user space.
     646 * @ length      : [in] buffer size in bytes.
     647 * @ remote_ip   : [in] remote socket IP address.
     648 * @ remote_port : [in] remote socket port address.
    571649 * @ return number of received bytes if success / return -1 if failure.
    572650 ***************************************************************************************/
    573 int socket_recv( uint32_t    fdid,
    574                  uint8_t   * u_buf,
    575                  uint32_t    length );
     651int socket_recvfrom( uint32_t    fdid,
     652                     uint8_t   * u_buf,
     653                     uint32_t    length,
     654                     uint32_t    remote_ip,
     655                     uint16_t    remote_port );
    576656
    577657/****************************************************************************************
  • trunk/kernel/kern/pipe.c

    r669 r683  
    22 * pipe.c - single writer, single reader pipe implementation           
    33 *
    4  * Author     Alain Greiner (2016,2017,2018,2019,2020)
     4 * Author     Alain Greiner     (2016,2017,2018,2019,2020)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    3232                      uint32_t size )
    3333{
    34     kmem_req_t     req;
    3534    remote_buf_t * buf;
    3635    pipe_t       * pipe;
     
    5554
    5655    // 3. allocate memory for pipe descriptor
    57     req.type  = KMEM_KCM;
    58     req.order = bits_log2( sizeof(pipe_t) );
    59     req.flags = AF_ZERO;
    60     pipe = kmem_remote_alloc( cxy , &req );
     56    pipe = kmem_remote_alloc( cxy , bits_log2(sizeof(pipe_t)) , AF_ZERO );
    6157
    6258    if( pipe == NULL )
     
    7672void pipe_destroy( xptr_t pipe_xp )
    7773{
    78     kmem_req_t req;
    79 
    8074    pipe_t * pipe_ptr = GET_PTR( pipe_xp );
    8175    cxy_t    pipe_cxy = GET_CXY( pipe_xp );
     
    8882
    8983    // release pipe descriptor
    90     req.type = KMEM_KCM;
    91     req.ptr  = pipe_ptr;
    92     kmem_remote_free( pipe_cxy , &req );
     84    kmem_remote_free( pipe_cxy , pipe_ptr , bits_log2(sizeof(pipe_t)) );
    9385
    9486}  // end pipe_destroy()
    95 
    9687
    9788//////////////////////////////////////////
  • trunk/kernel/kern/printk.c

    r669 r683  
    4141//////////////////////////////////////////////////////////////////////////////////////
    4242// This static function is called by printk(), nolock_printk(), and snprintk(),
    43 // functions to build a string from a printf-like format, and stores it
    44 // in the buffer defined by the <string> and <length> arguments.
    45 // It does NOT add a terminating NUL character in the <string> buffer.
    46 // If success, it returns the number of bytes actually copied in the string buffer.
     43// functions to build a string from a printf-like <format>, and stores it
     44// in the buffer defined by the <string> and <size> arguments.
     45// The <format> itself is supposed to be a NUL terminated string. The <string>
     46// buffer <size> must be large enough to contains also the NUL terminating character.
     47// If success, it returns the number of bytes actually copied in the <string> buffer,
     48// but this length does NOT include the terminating NUL character.
    4749// It returns -2 in case of illegal format, it returns -1 if the formated string
    48 // exceeds the length argument.
     50// exceeds the <size> argument.
    4951//////////////////////////////////////////////////////////////////////////////////////
    5052// @ string    : buffer allocated by caller.
    51 // @ length    : buffer size in bytes
     53// @ size      : buffer size in bytes
    5254// @ format    : printf like format.
    5355// @ args      : va_list of arguments.
     
    5557//////////////////////////////////////////////////////////////////////////////////////
    5658static int32_t format_to_string( char       * string,
    57                                  uint32_t     length,
     59                                 uint32_t     size,
    5860                                 const char * format,
    5961                                 va_list    * args )
    6062{
    6163
    62 #define TO_STRING(x) do { string[ps] = (x); ps++; if(ps==length) return -1; } while(0);
     64#define TO_STRING(x) do { string[ps] = (x); ps++; if(ps==size) return -1; } while(0);
    6365
    6466    uint32_t   ps = 0;        // index in string buffer
     
    7476            goto format_to_string_arguments;
    7577        }
    76         else                  // copy one char to string
     78        else                  // copy one char of format to string
    7779        {
    7880            TO_STRING( *format );
     
    8183    }
    8284
    83     TO_STRING( 0 );
    84     return ps;
     85    TO_STRING( 0 );      // NUL character written in buffer
     86    return (ps - 1);     // but not counted in length
    8587
    8688format_to_string_arguments:
     
    9597        switch (*format)
    9698        {
    97             case ('c'):             // char conversion
    98             {
    99                 int val = va_arg( *args , int );
    100                 buf[0] = (char)val;
     99            case ('c'):             // one printable character
     100            {
     101                buf[0] = (char)va_arg( *args , uint32_t );
    101102                pbuf   = buf;
    102103                len    = 1;
    103104                break;
    104105            }
    105             case ('d'):             // up to 10 digits decimal signed integer
     106            case ('b'):             // one ASCII code value (2 hexadecimal digits)
     107            {
     108                uint8_t val = (uint8_t)va_arg( *args , uint32_t );
     109                buf[1] = HexaTab[val & 0xF];
     110                buf[0] = HexaTab[(val >> 4) & 0xF];
     111                pbuf   = buf;
     112                len    = 2;
     113                break;
     114            }           
     115            case ('d'):            // one int32_t (up to 10 decimal digits after sign)
    106116            {
    107117                int32_t val = va_arg( *args , int32_t );
     
    120130                break;
    121131            }
    122             case ('u'):             // up to 10 digits decimal unsigned integer
     132            case ('u'):           // one uint32_t (up to 10 decimal digits)
    123133            {
    124134                uint32_t val = va_arg( *args , uint32_t );
     
    132142                break;
    133143            }
    134             case ('x'):             // up to 8 digits hexad after "0x"
    135             case ('X'):             // exactly 8 digits hexa after "0x"
     144            case ('x'):           // one uint32_t (up to 8 hexa digits after "0x")
     145
    136146            {
    137147                uint32_t val = va_arg( *args , uint32_t );
     
    141151                {
    142152                    buf[7 - i] = HexaTab[val & 0xF];
    143                     if( (*format == 'x') && ((val >> 4) == 0) )  break;
    144153                    val = val >> 4;
     154                    if(val == 0)  break;
    145155                }
    146156                len =  i + 1;
     
    148158                break;
    149159            }
    150             case ('l'):             // up to 16 digits hexa after "0x"
    151             case ('L'):             // exactly 16 digits hexa after "0x"
     160            case ('X'):         // one uint32_t (exactly 8 hexa digits after "0x")
     161            {
     162                uint32_t val = va_arg( *args , uint32_t );
     163                TO_STRING( '0' );
     164                TO_STRING( 'x' );
     165                for(i = 0 ; i < 8 ; i++)
     166                {
     167                    buf[7 - i] = (val != 0) ? HexaTab[val & 0xF] : '0';
     168                    val = val >> 4;
     169                }
     170                len = 8;
     171                pbuf = &buf[0];
     172                break;
     173            }
     174            case ('l'):          // one uint64_t (up to 16 digits hexa after "0x")
    152175            {
    153176                uint64_t val = (((uint64_t)va_arg( *args, uint32_t)) << 32) |
     
    158181                {
    159182                    buf[15 - i] = HexaTab[val & 0xF];
    160                     if( (*format == 'l') && ((val >> 4) == 0) )  break;
    161183                    val = val >> 4;
     184                    if( val == 0)  break;
    162185                }
    163186                len =  i + 1;
     
    165188                break;
    166189            }
    167             case ('s'):             /* string */
     190            case ('L'):          // one uint64_t (exactly 16 digits hexa after "0x")
     191            {
     192                uint64_t val = (((uint64_t)va_arg( *args, uint32_t)) << 32) |
     193                               ((uint64_t)va_arg( *args, uint32_t));
     194                TO_STRING( '0' );
     195                TO_STRING( 'x' );
     196                for(i = 0 ; i < 16 ; i++)
     197                {
     198                    buf[15 - i] = (val != 0) ? HexaTab[val & 0xF] : '0';
     199                    val = val >> 4;
     200                }
     201                len =  16;
     202                pbuf = &buf[0];
     203                break;
     204            }
     205            case ('s'):             /* one characters string */
    168206            {
    169207                char* str = va_arg( *args , char* );
     
    213251    // build a string from format
    214252    length = format_to_string( buffer,
    215                       CONFIG_PRINTK_BUF_SIZE,
    216                       format,
    217                       &args );
     253                               CONFIG_PRINTK_BUF_SIZE,
     254                               format,
     255                               &args );
    218256    va_end( args );
    219257
     
    258296    // build a string from format
    259297    length = format_to_string( buffer,
    260                       CONFIG_PRINTK_BUF_SIZE,
    261                       format,
    262                       &args );
     298                               CONFIG_PRINTK_BUF_SIZE,
     299                               format,
     300                               &args );
    263301    va_end( args );
    264302
     
    315353        if( length > 0  )  // display panic message on TXT0, including formated string
    316354        {
    317             printk("\n[ASSERT] in %s / core[%x,%d] / thread[%x,%x] / cycle %d\n       %s\n",
     355            printk("\n[ASSERT] in %s / core[%x,%d] / thread[%x,%x] / cycle %d\n   <%s>\n",
    318356            func_name, local_cxy, lid, pid, trdid, cycle, buffer );
    319357        }
     
    332370{
    333371    va_list       args;
    334     int32_t       string_length;
     372    int32_t       length;
    335373
    336374    // build args va_list
     
    338376
    339377    // build a string from format
    340     string_length = format_to_string( buffer , size , format , &args );
     378    length = format_to_string( buffer , size , format , &args );
     379
     380    // release args list
    341381    va_end( args );
    342382
    343     if( (string_length < 0) || (string_length == (int32_t)size) )  // failure
    344     {
    345         return -1;
    346     }
    347     else                                                           // success
    348     {
    349         // add NUL character
    350         buffer[string_length] = 0;
    351 
    352         return string_length;
    353     }
     383    if( length < 0 )   return -1;
     384    else               return length;
     385
    354386}   // end snprintk()
    355387
  • trunk/kernel/kern/printk.h

    r669 r683  
    2424///////////////////////////////////////////////////////////////////////////////////
    2525// The printk.c and printk.h files define the functions used by the kernel
    26 // to display messages on the kernel terminal TXT0, using a busy waiting policy.
    27 // It calls synchronously the TXT0 driver, without descheduling.
     26// to build, or display on terminal TXT0, formated strings.
     27// In case ofdisplay, it calls synchronously the TXT0 driver, without descheduling.
    2828//
    29 // For the formated string, the supported formats are defined below :
     29// The supported formats are defined below :
    3030//   %c : single ascii character (8 bits)
     31//   %b : exactly 2 hexadecimal digits (8 bits)
    3132//   %d : up to 10 digits decimal integer (32 bits)
    3233//   %u : up to 10 digits unsigned decimal (32 bits)
     
    4748
    4849/**********************************************************************************
    49  * These debug functions display a formated string defined by the <format,...>
     50 * These functions display a formated string defined by the <format,...>
    5051 * argument on the kernel terminal TXT0, with or without taking the TXT0 lock.
    5152 **********************************************************************************
     
    6465
    6566/**********************************************************************************
    66  * This debug function displays a [ASSERT] message on kernel TXT0 terminal
     67 * This function displays an [ASSERT] message on kernel TXT0 terminal
    6768 * if Boolean expression <expr> is false. It prints a detailed message including:
    6869 * - the calling core [cxy,lpid]
     
    8384 * This function build a formated string in a buffer defined by the <buffer>
    8485 * and <buf_size> arguments, from the format defined by the <format,...> argument.
    85  * This function set the NUL terminating character in target <buffer>.
     86 * This function set the NUL terminating character in target <buffer>,
     87 * but the returned length does not include this NUL character.
    8688 **********************************************************************************
    8789 * @ buffer     : pointer on target buffer (allocated by caller).
     
    142144 * @ string   : buffer name or identifier.
    143145 * @ buffer   : local pointer on bytes array.
    144  * @ size     : number of bytes bytes to display.
     146 * @ size     : number of bytes to display.
    145147 *********************************************************************************/
    146148void putb( char     * string,
  • trunk/kernel/kern/process.c

    r669 r683  
    22 * process.c - process related functions definition.
    33 *
    4  * Authors  Ghassan Almaless (2008,2009,2010,2011,2012)
     4 * Authors  Ghassan Almaless       (2008,2009,2010,2011,2012)
    55 *          Mohamed Lamine Karaoui (2015)
    6  *          Alain Greiner (2016,2017,2018,2019,2020)
     6 *          Alain Greiner          (2016,2017,2018,2019,2020)
    77 *
    88 * Copyright (c) UPMC Sorbonne Universites
     
    7070//////////////////////////////////////////////////////////////////////////////////////////
    7171
    72 /////////////////////////////////
    73 process_t * process_alloc( void )
    74 {
    75 
    76 assert( __FUNCTION__, (sizeof(process_t) < CONFIG_PPM_PAGE_SIZE),
    77 "process descriptor exceeds 1 page" );
    78 
    79         kmem_req_t req;
    80 
    81     req.type  = KMEM_PPM;
    82         req.order = 0;
    83         req.flags = AF_KERNEL | AF_ZERO;
    84     return kmem_alloc( &req );
    85 }
    86 
    87 ////////////////////////////////////////
    88 void process_free( process_t * process )
    89 {
    90     kmem_req_t  req;
    91 
    92         req.type = KMEM_PPM;
    93         req.ptr  = process;
    94         kmem_free( &req );
    95 }
    96 
    9772////////////////////////////////////////////////////
    9873error_t process_reference_init( process_t * process,
     
    11691    vmm_t     * vmm;
    11792
    118     // build extended pointer on this reference process
     93#if DEBUG_PROCESS_REFERENCE_INIT || DEBUG_PROCESS_ERROR
     94thread_t * this  = CURRENT_THREAD;
     95uint32_t   cycle = (uint32_t)hal_get_cycles();
     96#endif
     97
     98    // build extended pointer on reference process
    11999    process_xp = XPTR( local_cxy , process );
    120100
     
    130110
    131111#if DEBUG_PROCESS_REFERENCE_INIT
    132 thread_t * this = CURRENT_THREAD;
    133 uint32_t cycle = (uint32_t)hal_get_cycles();
    134112if( DEBUG_PROCESS_REFERENCE_INIT < cycle )
    135113printk("\n[%s] thread[%x,%x] enter to initialize process %x / cycle %d\n",
     
    156134    if( error )
    157135    {
    158         printk("\n[ERROR] in %s : cannot create empty GPT\n", __FUNCTION__ );
     136
     137#if DEBUG_PROCESS_ERROR
     138printk("\n[ERROR] in %s : thread[%x,%x] cannot create empty GPT / cycle %d\n",
     139__FUNCTION__, this->process->pid, this->trdid, cycle );
     140#endif
    159141        return -1;
    160142    }
     
    173155    if( error )
    174156    {
     157
     158#if DEBUG_PROCESS_ERROR
     159printk("\n[ERROR] in %s : thread[%x,%x] cannot register kernel vsegs in VMM / cycle %d\n",
     160__FUNCTION__, this->process->pid, this->trdid, cycle );
     161#endif
    175162        printk("\n[ERROR] in %s : cannot register kernel vsegs in VMM\n", __FUNCTION__ );
    176163        return -1;
     
    233220        if( error )
    234221        {
    235             printk("\n[ERROR] in %s : cannot open stdout pseudo-file\n", __FUNCTION__ );
     222
     223#if DEBUG_PROCESS_ERROR
     224printk("\n[ERROR] in %s : thread[%x,%x] cannot open stdin pseudo file / cycle %d\n",
     225__FUNCTION__, this->process->pid, this->trdid, cycle );
     226#endif
    236227            return -1;
    237228        }
     
    256247        if( error )
    257248        {
    258             printk("\n[ERROR] in %s : cannot open stdout pseudo-file\n", __FUNCTION__ );
     249
     250#if DEBUG_PROCESS_ERROR
     251printk("\n[ERROR] in %s : thread[%x,%x] cannot open stdout pseudo file / cycle %d\n",
     252__FUNCTION__, this->process->pid, this->trdid, cycle );
     253#endif
    259254            return -1;
    260255        }
     
    279274        if( error )
    280275        {
    281             printk("\n[ERROR] in %s : cannot open stderr pseudo-file\n", __FUNCTION__ );
     276
     277#if DEBUG_PROCESS_ERROR
     278printk("\n[ERROR] in %s : thread[%x,%x] cannot open stderr pseudo file / cycle %d\n",
     279__FUNCTION__, this->process->pid, this->trdid, cycle );
     280#endif
    282281            return -1;
    283282        }
     
    302301
    303302        // recreate all open files from parent process fd_array to child process fd_array
    304         process_fd_replicate( process_xp , parent_xp );
     303        error = process_fd_replicate( process_xp , parent_xp );
     304
     305        if( error )
     306        {
     307
     308#if DEBUG_PROCESS_ERROR
     309printk("\n[ERROR] in %s : thread[%x,%x] cannot replicate fd_array / cycle %d\n",
     310__FUNCTION__, this->process->pid, this->trdid, cycle );
     311#endif
     312            return -1;
     313        }
     314
    305315    }
    306316
     
    379389    vmm_t   * vmm;
    380390
     391#if DEBUG_PROCESS_COPY_INIT || DEBUG_PROCESS_ERROR
     392thread_t * this = CURRENT_THREAD; 
     393uint32_t cycle = (uint32_t)hal_get_cycles();
     394#endif
     395
    381396    // get reference process cluster and local pointer
    382397    cxy_t       ref_cxy = GET_CXY( reference_process_xp );
     
    394409
    395410#if DEBUG_PROCESS_COPY_INIT
    396 thread_t * this = CURRENT_THREAD; 
    397 uint32_t cycle = (uint32_t)hal_get_cycles();
    398411if( DEBUG_PROCESS_COPY_INIT < cycle )
    399412printk("\n[%s] thread[%x,%x] enter for process %x / cycle %d\n",
     
    410423    // create an empty GPT as required by the architecture
    411424    error = hal_gpt_create( &vmm->gpt );
     425
    412426    if( error )
    413427    {
    414         printk("\n[ERROR] in %s : cannot create empty GPT\n", __FUNCTION__ );
     428
     429#if DEBUG_PROCESS_ERROR
     430printk("\n[ERROR] in %s : thread[%x,%x] cannot create empty GPT / cycle %d\n",
     431__FUNCTION__, this->process->pid, this->trdid, cycle );
     432#endif
    415433        return -1;
    416434    }
     
    421439    // register kernel vsegs in VMM as required by the architecture
    422440    error = hal_vmm_kernel_update( local_process );
     441
    423442    if( error )
    424443    {
    425         printk("\n[ERROR] in %s : cannot register kernel vsegs in VMM\n", __FUNCTION__ );
     444
     445#if DEBUG_PROCESS_ERROR
     446printk("\n[ERROR] in %s : thread[%x,%x] cannot register kernel vsegs in VMM / cycle %d\n",
     447__FUNCTION__, this->process->pid, this->trdid, cycle );
     448#endif
    426449        return -1;
    427450    }
     
    431454    // initialize locks protecting GPT and VSL
    432455    error = vmm_user_init( local_process );
     456
    433457    if( error )
    434458    {
    435         printk("\n[ERROR] in %s : cannot register user vsegs in VMM\n", __FUNCTION__ );
     459
     460#if DEBUG_PROCESS_ERROR
     461printk("\n[ERROR] in %s : thread[%x,%x] cannot register user vsegs in VMM / cycle %d\n",
     462__FUNCTION__, this->process->pid, this->trdid, cycle );
     463#endif
    436464        return -1;
    437465    }
     
    598626
    599627    // release memory allocated to process descriptor
    600     process_free( process );
     628        kmem_free( process , bits_log2(sizeof(process_t)) );
    601629
    602630#if DEBUG_PROCESS_DESTROY
     
    9741002{
    9751003    error_t        error;
    976     process_t    * process_ptr;   // local pointer on process
     1004    process_t    * process;       // local pointer on process
    9771005    xptr_t         process_xp;    // extended pointer on process
    9781006
     1007#if DEBUG_PROCESS_GET_LOCAL_COPY || DEBUG_PROCESS_ERROR
     1008thread_t * this  = CURRENT_THREAD;
     1009uint32_t   cycle = (uint32_t)hal_get_cycles();
     1010#endif
     1011
    9791012    cluster_t * cluster = LOCAL_CLUSTER;
    9801013
    9811014#if DEBUG_PROCESS_GET_LOCAL_COPY
    982 thread_t * this = CURRENT_THREAD;
    983 uint32_t cycle = (uint32_t)hal_get_cycles();
    9841015if( DEBUG_PROCESS_GET_LOCAL_COPY < cycle )
    9851016printk("\n[%s] thread[%x,%x] enter for process %x in cluster %x / cycle %d\n",
     
    9961027    {
    9971028        process_xp  = XLIST_ELEMENT( iter , process_t , local_list );
    998         process_ptr = GET_PTR( process_xp );
    999         if( process_ptr->pid == pid )
     1029        process    = GET_PTR( process_xp );
     1030        if( process->pid == pid )
    10001031        {
    10011032            found = true;
     
    10171048
    10181049        // allocate memory for local process descriptor
    1019         process_ptr = process_alloc();
    1020 
    1021         if( process_ptr == NULL )  return NULL;
     1050        process = kmem_alloc( bits_log2(sizeof(process_t)) , AF_ZERO );
     1051
     1052        if( process == NULL )  return NULL;
    10221053
    10231054        // initialize local process descriptor copy
    1024         error = process_copy_init( process_ptr , ref_xp );
    1025 
    1026         if( error ) return NULL;
     1055        error = process_copy_init( process , ref_xp );
     1056
     1057        if( error )
     1058        {
     1059
     1060#if DEBUG_PROCESS_ERROR
     1061printk("\n[ERROR] in %s : thread[%x,%x] cannot initialize local process copy / cycle %d\n",
     1062__FUNCTION__, this->process->pid, this->trdid, cycle );
     1063#endif
     1064            return NULL;
     1065        }
    10271066    }
    10281067
     
    10311070if( DEBUG_PROCESS_GET_LOCAL_COPY < cycle )
    10321071printk("\n[%s] thread[%x,%x] exit in cluster %x / process %x / cycle %d\n",
    1033 __FUNCTION__, this->process->pid, this->trdid, local_cxy, process_ptr, cycle );
    1034 #endif
    1035 
    1036     return process_ptr;
     1072__FUNCTION__, this->process->pid, this->trdid, local_cxy, process, cycle );
     1073#endif
     1074
     1075    return process;
    10371076
    10381077}  // end process_get_local_copy()
     
    11111150    xptr_t    max_xp;          // extended pointer on max field in fd_array
    11121151
     1152#if DEBUG_PROCESS_FD_REGISTER
     1153thread_t * this  = CURRENT_THREAD;
     1154uint32_t   cycle = (uint32_t)hal_get_cycles();
     1155#endif
     1156
    11131157    // get target process cluster and local pointer
    11141158    process_t * process_ptr = GET_PTR( process_xp );
     
    11201164
    11211165#if DEBUG_PROCESS_FD_REGISTER
    1122 thread_t * this  = CURRENT_THREAD;
    1123 uint32_t   cycle = (uint32_t)hal_get_cycles();
    1124 pid_t      pid   = hal_remote_l32( XPTR( process_cxy , &process_ptr->pid) );
     1166pid_t  tgt_pid   = hal_remote_l32( XPTR( process_cxy , &process_ptr->pid) );
    11251167if( DEBUG_PROCESS_FD_REGISTER < cycle )
    11261168printk("\n[%s] thread[%x,%x] enter for process %x / cycle %d\n",
    1127 __FUNCTION__, this->process->pid, this->trdid, pid, cycle );
     1169__FUNCTION__, this->process->pid, this->trdid, tgt_pid, cycle );
    11281170#endif
    11291171
     
    11681210if( DEBUG_PROCESS_FD_REGISTER < cycle )
    11691211printk("\n[%s] thread[%x,%x] exit for process %x / fdid %d / cycle %d\n",
    1170 __FUNCTION__, this->process->pid, this->trdid, pid, id, cycle );
     1212__FUNCTION__, this->process->pid, this->trdid, tgt_pid, id, cycle );
    11711213#endif
    11721214
     
    13841426}  // end process_fd_get_xptr_from_local()
    13851427
    1386 /////////////////////////////////////////
    1387 void process_fd_replicate( xptr_t dst_xp,
    1388                            xptr_t src_xp )
     1428////////////////////////////////////////////
     1429error_t process_fd_replicate( xptr_t dst_xp,
     1430                              xptr_t src_xp )
    13891431{
    13901432    uint32_t fdid;      // current file descriptor index
     
    14351477            if( error )
    14361478            {
    1437                 printk("\n[ERROR] in %s : cannot create new file\n", __FUNCTION__ );
    1438                 return;
     1479
     1480#if DEBUG_PROCESS_ERROR
     1481thread_t * this  = CURRENT_THREAD;
     1482uint32_t   cycle = (uint32_t)hal_get_cycles();
     1483printk("\n[ERROR] in %s : thread[%x,%x] cannot create file descriptor / cycle %d\n",
     1484__FUNCTION__, this->process->pid, this->trdid, cycle );
     1485#endif
     1486                return -1;
    14391487            }
    14401488
     
    14461494    // release lock on source process fd_array
    14471495        remote_queuelock_release( src_lock_xp );
     1496
     1497    return 0;
    14481498
    14491499}  // end process_fd_replicate()
     
    14941544    uint32_t max = hal_remote_l32( XPTR( owner_cxy , &owner_ptr->fd_array.max ));
    14951545
    1496     printk("\n***** fd_array for pid %x in cluster %x / max %d *****\n",
     1546    // get pointers on TXT0 chdev
     1547    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
     1548    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
     1549    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
     1550
     1551    // get extended pointer on remote TXT0 lock
     1552    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
     1553
     1554    // get TXT0 lock
     1555    remote_busylock_acquire( lock_xp );
     1556
     1557    nolock_printk("\n***** fd_array for pid %x in cluster %x / max %d *****\n",
    14971558    pid, process_cxy, max );
    14981559
     
    15201581
    15211582                // display relevant file descriptor info
    1522                 printk(" - %d : type %s / ptr %x (%s)\n",
     1583                nolock_printk(" - %d : type %s / ptr %x (%s)\n",
    15231584                fdid, process_fd_type_str(file_type), file_ptr, name );
    15241585            }
     
    15261587            {
    15271588                // display relevant file decriptor info
    1528                 printk(" - %d : type %s / ptr %x\n",
     1589                nolock_printk(" - %d : type %s / ptr %x\n",
    15291590                fdid , process_fd_type_str(file_type), file_ptr );
    15301591            }
     
    15321593        else
    15331594        {
    1534             printk(" - %d : empty slot\n",
    1535             fdid );
     1595            nolock_printk(" - %d : empty slot\n", fdid );
    15361596        }
    15371597    }
     1598
     1599    // get TXT0 lock
     1600    remote_busylock_acquire( lock_xp );
     1601
    15381602}   // end process_fd_display()
    15391603
     
    15481612{
    15491613    ltid_t         ltid;
     1614    ltid_t         ltid_min;
     1615
    15501616    bool_t         found = false;
     1617    lpid_t         lpid  = LPID_FROM_PID( process->pid );
    15511618 
    15521619// check arguments
     
    15541621assert( __FUNCTION__, (thread != NULL) , "thread argument is NULL" );
    15551622
    1556     // get the lock protecting th_tbl for all threads
    1557     // but the idle thread executing kernel_init (cannot yield)
     1623    // get the lock protecting th_tbl for all threads but the idle thread
    15581624    if( thread->type != THREAD_IDLE ) rwlock_wr_acquire( &process->th_lock );
    15591625
     1626    // compute ltid_min : 0 for an user thread / 1 for a kernel thread
     1627    ltid_min = (lpid == 0) ? 1 : 0;
     1628 
    15601629    // scan th_tbl
    1561     for( ltid = 0 ; ltid < CONFIG_THREADS_MAX_PER_CLUSTER ; ltid++ )
     1630    for( ltid = ltid_min ; ltid < CONFIG_THREADS_MAX_PER_CLUSTER ; ltid++ )
    15621631    {
    15631632        if( process->th_tbl[ltid] == NULL )
     
    15811650    if( thread->type != THREAD_IDLE ) rwlock_wr_release( &process->th_lock );
    15821651
    1583     return (found) ? 0 : 0xFFFFFFFF;
     1652    return (found) ? 0 : -1;
    15841653
    15851654}  // end process_register_thread()
     
    16471716"parent process must be the reference process" );
    16481717
    1649 #if DEBUG_PROCESS_MAKE_FORK
    1650 uint32_t   cycle;
     1718#if DEBUG_PROCESS_MAKE_FORK || DEBUG_PROCESS_ERROR
     1719uint32_t   cycle  = (uint32_t)hal_get_cycles();
    16511720thread_t * this  = CURRENT_THREAD;
    16521721trdid_t    trdid = this->trdid;
     
    16551724
    16561725#if( DEBUG_PROCESS_MAKE_FORK & 1 )
    1657 cycle   = (uint32_t)hal_get_cycles();
    16581726if( DEBUG_PROCESS_MAKE_FORK < cycle )
    16591727printk("\n[%s] thread[%x,%x] enter / cluster %x / cycle %d\n",
     
    16621730
    16631731    // allocate a process descriptor
    1664     process = process_alloc();
     1732    process = kmem_alloc( bits_log2(sizeof(process_t)) , AF_ZERO );
    16651733
    16661734    if( process == NULL )
    16671735    {
    1668         printk("\n[ERROR] in %s : cannot get process in cluster %x\n",
    1669         __FUNCTION__, local_cxy );
     1736
     1737#if DEBUG_PROCESS_ERROR
     1738printk("\n[ERROR] in %s : thread[%x,%x] cannot allocate process descriptor / cxy %x / cycle %d\n",
     1739__FUNCTION__, pid, trdid, local_cxy, cycle );
     1740#endif
    16701741        return -1;
    16711742    }
     
    16751746    if( error )
    16761747    {
    1677         printk("\n[ERROR] in %s : cannot get PID in cluster %x\n",
    1678         __FUNCTION__, local_cxy );
    1679         process_free( process );
     1748
     1749#if DEBUG_PROCESS_ERROR
     1750printk("\n[ERROR] in %s : thread[%x,%x] cannot get PID / cxy %x / cycle %d\n",
     1751__FUNCTION__, pid, trdid, local_cxy, cycle );
     1752#endif
     1753            kmem_free( process , bits_log2(sizeof(process_t)) );
    16801754        return -1;
    16811755    }
    16821756
    16831757#if( DEBUG_PROCESS_MAKE_FORK & 1 )
    1684 cycle = (uint32_t)hal_get_cycles();
    16851758if( DEBUG_PROCESS_MAKE_FORK < cycle )
    1686 printk("\n[%s] thread[%x,%x] allocated child_process %x / cycle %d\n",
    1687 __FUNCTION__, pid, trdid, new_pid, cycle );
     1759printk("\n[%s] thread[%x,%x] allocated child_process %x\n",
     1760__FUNCTION__, pid, trdid, new_pid );
    16881761#endif
    16891762
     
    16941767    if( error )
    16951768    {
    1696         printk("\n[ERROR] in %s : cannot initialize child process in cluster %x\n",
    1697         __FUNCTION__, local_cxy );
    1698         process_free( process );
     1769
     1770#if DEBUG_PROCESS_ERROR
     1771printk("\n[ERROR] in %s : thread[%x,%x] cannot initialize child process / cxy %x / cycle %d\n",
     1772__FUNCTION__, pid, trdid, local_cxy, cycle );
     1773#endif
     1774        cluster_pid_release( new_pid );
     1775            kmem_free( process , bits_log2(sizeof(process_t)) );
    16991776        return -1;
    17001777    }
    17011778
    17021779#if( DEBUG_PROCESS_MAKE_FORK & 1 )
    1703 cycle = (uint32_t)hal_get_cycles();
    17041780if( DEBUG_PROCESS_MAKE_FORK < cycle )
    1705 printk("\n[%s] thread[%x,%x] initialized child_process %x / cycle %d\n",
    1706 __FUNCTION__, pid, trdid, new_pid, cycle );
     1781printk("\n[%s] thread[%x,%x] initialized child_process %x\n",
     1782__FUNCTION__, pid, trdid, new_pid );
    17071783#endif
    17081784
     
    17121788    if( error )
    17131789    {
    1714         printk("\n[ERROR] in %s : cannot copy VMM in cluster %x\n",
    1715         __FUNCTION__, local_cxy );
    1716         process_free( process );
     1790
     1791#if DEBUG_PROCESS_ERROR
     1792printk("\n[ERROR] in %s : thread[%x,%x] cannot copy VMM to child process / cxy %x / cycle %d\n",
     1793__FUNCTION__, pid, trdid, local_cxy, cycle );
     1794#endif
    17171795        cluster_pid_release( new_pid );
     1796            kmem_free( process , bits_log2(sizeof(process_t)) );
    17181797        return -1;
    17191798    }
    17201799
    17211800#if( DEBUG_PROCESS_MAKE_FORK & 1 )
    1722 cycle = (uint32_t)hal_get_cycles();
    17231801if( DEBUG_PROCESS_MAKE_FORK < cycle )
    17241802{
    1725     printk("\n[%s] thread[%x,%x] copied VMM from parent to child / cycle %d\n",
    1726     __FUNCTION__, pid, trdid, cycle );
     1803    printk("\n[%s] thread[%x,%x] copied VMM from parent to child\n",
     1804    __FUNCTION__, pid, trdid );
    17271805    hal_vmm_display( XPTR( local_cxy , process ) , true );
    17281806}
     
    17361814
    17371815#if( DEBUG_PROCESS_MAKE_FORK & 1 )
    1738 cycle = (uint32_t)hal_get_cycles();
    17391816if( DEBUG_PROCESS_MAKE_FORK < cycle )
    1740 printk("\n[%s] thread[%x,%x] / child_process %x takes TXT ownership / cycle %d\n",
    1741 __FUNCTION__ , pid, trdid, new_pid, cycle );
     1817printk("\n[%s] thread[%x,%x] / child_process %x takes TXT ownership\n",
     1818__FUNCTION__ , pid, trdid, new_pid );
    17421819#endif
    17431820
     
    17531830    if( error )
    17541831    {
    1755         printk("\n[ERROR] in %s : cannot create thread in cluster %x\n",
    1756         __FUNCTION__, local_cxy );
    1757         process_free( process );
     1832
     1833#if DEBUG_PROCESS_ERROR
     1834printk("\n[ERROR] in %s : thread[%x,%x] cannot create main thread / cxy %x / cycle %d\n",
     1835__FUNCTION__, pid, trdid, local_cxy, cycle );
     1836#endif
    17581837        cluster_pid_release( new_pid );
     1838            kmem_free( process , bits_log2(sizeof(process_t)) );
    17591839        return -1;
    17601840    }
     
    17651845
    17661846#if( DEBUG_PROCESS_MAKE_FORK & 1 )
    1767 cycle = (uint32_t)hal_get_cycles();
    17681847if( DEBUG_PROCESS_MAKE_FORK < cycle )
    1769 printk("\n[%s] thread[%x,%x] created main thread %x / cycle %d\n",
    1770 __FUNCTION__, pid, trdid, thread, cycle );
     1848printk("\n[%s] thread[%x,%x] created main thread %x\n",
     1849__FUNCTION__, pid, trdid, thread );
    17711850#endif
    17721851
     
    17871866 
    17881867#if( DEBUG_PROCESS_MAKE_FORK & 1 )
    1789 cycle = (uint32_t)hal_get_cycles();
    17901868if( DEBUG_PROCESS_MAKE_FORK < cycle )
    1791 printk("\n[%s] thread[%x,%x] set COW in DATA / ANON / REMOTE for parent and child / cycle %d\n",
    1792 __FUNCTION__, pid, trdid, cycle );
     1869printk("\n[%s] thread[%x,%x] set COW in DATA / ANON / REMOTE for parent and child\n",
     1870__FUNCTION__, pid, trdid );
    17931871#endif
    17941872
     
    18191897}   // end process_make_fork()
    18201898
    1821 ////////////////////////////////////////////////i//////////////////////////////////////
    1822 // This static function is called by the thread_user_exec() function :
    1823 // - to register the main() arguments (args) in the <exec_info> structure.
    1824 // - to register the environment variables (envs) in the <exec_info> structure.
    1825 // In both cases the input is an array of NULL terminated string pointers in user
    1826 // space, and the strings can be dispatched anywhere in the user process space.
    1827 // This array of pointers is defined by the <u_pointers> argument. The empty slots
    1828 // contain the NULL value, and the N non-empty slots are indexed from 0 to (N-1).
    1829 // - The max number of envs, and the max number of args are defined by the
    1830 //   CONFIG_PROCESS_ARGS_NR and CONFIG_PROCESS_ENVS_MAX_NR parameters.
    1831 // - The numbers of pages to store the (args) and (envs) strings are defined by the
    1832 //   CONFIG_VMM_ENVS_SIZE and CONFIG_VMM_STACK_SIZE parameters.
    1833 ///////////////////////////////////////////////////////////////////////////////////////
    1834 // Implementation note:
    1835 // It allocates a kernel buffer to store a kernel copy of both the array of pointers,
    1836 // and the strings. It set the pointers and copies the strings in this kernel buffer.
    1837 // Finally, it registers the buffer & the actual number of strings in the process
    1838 // exec_info structure  (defined in the <process.h> file).
    1839 ///////////////////////////////////////////////////////////////////////////////////////
    1840 // @ is_args     : [in]    true if called for (args) / false if called for (envs).
    1841 // @ u_pointers  : [in]    array of pointers on the strings (in user space).
    1842 // @ exec_info   : [out]   pointer on the exec_info structure.
    1843 // @ return 0 if success / non-zero if too many strings or no memory.
    1844 ///////////////////////////////////////////////////////////////////////////////////////
    1845 error_t process_exec_get_strings( bool_t         is_args,
    1846                                   char        ** u_pointers,
    1847                                   exec_info_t  * exec_info )
    1848 {
    1849     uint32_t     index;           // slot index in pointers array
    1850     uint32_t     length;          // string length (in bytes)
    1851     uint32_t     pointers_bytes;  // number of bytes to store pointers
    1852     uint32_t     max_index;       // max size of pointers array
    1853     char      ** k_pointers;      // base of kernel array of pointers
    1854     char       * k_buf_ptr;       // pointer on first empty slot in strings buffer
    1855     uint32_t     k_buf_space;     // number of bytes available in string buffer
    1856     kmem_req_t   req;             // kernel memory allocator request
    1857     char       * k_buf;           // kernel buffer for both pointers & strings
    1858 
    1859 #if DEBUG_PROCESS_EXEC_GET_STRINGS
    1860 thread_t * this  = CURRENT_THREAD;
    1861 uint32_t   cycle = (uint32_t)hal_get_cycles();
    1862 #endif
    1863 
    1864     // Allocate one block of physical memory for both the pointers and the strings
    1865     // as defined by the CONFIG_VMM_ARGS_SIZE and CONFIG_VMM_ENVS_SIZE parameters
    1866     // - the array of pointers is stored in the first bytes of the kernel buffer
    1867     // - the strings themselve are stored in the next bytes of this buffer
    1868     // Set the k_pointers, k_buf_ptr, k_buf_space, and max_index
    1869 
    1870     if( is_args )
    1871     {
    1872         req.type   = KMEM_PPM;
    1873         req.order  = bits_log2( CONFIG_VMM_ARGS_SIZE );
    1874         req.flags  = AF_KERNEL | AF_ZERO;
    1875         k_buf      = kmem_alloc( &req );
    1876 
    1877         pointers_bytes = CONFIG_PROCESS_ARGS_MAX_NR * sizeof(char *);
    1878         k_pointers     = (char **)k_buf;
    1879         k_buf_ptr      = k_buf + pointers_bytes;
    1880         k_buf_space    = (CONFIG_VMM_ARGS_SIZE * CONFIG_PPM_PAGE_SIZE) - pointers_bytes;
    1881         max_index      = CONFIG_PROCESS_ARGS_MAX_NR;
    1882 
    1883 #if DEBUG_PROCESS_EXEC_GET_STRINGS
    1884 if( DEBUG_PROCESS_EXEC_GET_STRINGS < cycle )
    1885 printk("\n[%s] thread[%x,%x] for args / u_buf %x / k_buf %x\n",
    1886 __FUNCTION__, this->process->pid, this->trdid, u_pointers, k_buf );
    1887 #endif
    1888 
    1889     }
    1890     else
    1891     {
    1892         req.type   = KMEM_PPM;
    1893         req.order  = bits_log2( CONFIG_VMM_ENVS_SIZE );
    1894         req.flags  = AF_KERNEL | AF_ZERO;
    1895         k_buf      = kmem_alloc( &req );
    1896 
    1897         pointers_bytes = CONFIG_PROCESS_ENVS_MAX_NR * sizeof(char *);
    1898         k_pointers     = (char **)k_buf;
    1899         k_buf_ptr      = k_buf + pointers_bytes;
    1900         k_buf_space    = (CONFIG_VMM_ENVS_SIZE * CONFIG_PPM_PAGE_SIZE) - pointers_bytes;
    1901         max_index      = CONFIG_PROCESS_ENVS_MAX_NR;
    1902 
    1903 #if DEBUG_PROCESS_EXEC_GET_STRINGS
    1904 if( DEBUG_PROCESS_EXEC_GET_STRINGS < cycle )
    1905 printk("\n[%s] thread[%x,%x] for envs / u_buf %x / k_buf %x\n",
    1906 __FUNCTION__, this->process->pid, this->trdid, u_pointers, k_buf );
    1907 #endif
    1908 
    1909     }
    1910 
    1911     // copy the user array of pointers to kernel buffer
    1912     hal_copy_from_uspace( XPTR( local_cxy , k_pointers ),
    1913                           u_pointers,
    1914                           pointers_bytes );
    1915 
    1916     // WARNING : the pointers copied in the k_pointers[] array are user pointers,
    1917     // after the loop below, the k_pointers[] array contains kernel pointers.
    1918 
    1919 #if DEBUG_PROCESS_EXEC_GET_STRINGS
    1920 if( DEBUG_PROCESS_EXEC_GET_STRINGS < cycle )
    1921 printk("\n[%s] thread[%x,%x] copied u_ptr array to k_ptr array\n"
    1922 "    p0 = %x / p1 = %x / p2 = %x / p3 = %x\n",
    1923 __FUNCTION__, this->process->pid, this->trdid,
    1924 k_pointers[0], k_pointers[1], k_pointers[2], k_pointers[3] );
    1925 #endif
    1926 
    1927     // scan kernel array of pointers to copy strings to kernel buffer
    1928     for( index = 0 ; index < max_index ; index++ )
    1929     {
    1930         // exit loop if (k_pointers[] == NUll)
    1931         if( k_pointers[index] == NULL ) break;
    1932 
    1933         // compute string length
    1934         length = hal_strlen_from_uspace( k_pointers[index] ) + 1;
    1935 
    1936         // return error if overflow in kernel buffer
    1937         if( length > k_buf_space ) return -1;
    1938 
    1939         // copy the string to kernel buffer
    1940         hal_copy_from_uspace( XPTR( local_cxy , k_buf_ptr ),
    1941                               k_pointers[index],
    1942                               length );
    1943 
    1944 #if DEBUG_PROCESS_EXEC_GET_STRINGS
    1945 if( DEBUG_PROCESS_EXEC_GET_STRINGS < cycle )
    1946 printk("\n[%s] thread[%x,%x] copied string[%d] <%s> to kernel buffer / length %d\n",
    1947 __FUNCTION__, this->process->pid, this->trdid, index, k_buf_ptr, length );
    1948 #endif
    1949 
    1950         // replace the user pointer by a kernel pointer in the k_pointer[] array
    1951         k_pointers[index] = k_buf_ptr;
    1952 
    1953         // increment loop variables
    1954         k_buf_ptr   += length;
    1955         k_buf_space -= length;
    1956 
    1957     }  // end loop on index
    1958 
    1959     // update into exec_info structure
    1960     if( is_args )
    1961     {
    1962         exec_info->args_pointers  =  k_pointers;
    1963         exec_info->args_nr        =  index;
    1964     }
    1965     else
    1966     {
    1967         exec_info->envs_pointers  =  k_pointers;
    1968         exec_info->envs_buf_free  =  k_buf_ptr;
    1969         exec_info->envs_nr        =  index;
    1970     }
    1971 
    1972 #if DEBUG_PROCESS_EXEC_GET_STRINGS
    1973 if( DEBUG_PROCESS_EXEC_GET_STRINGS < cycle )
    1974 printk("\n[%s] thread[%x,%x] copied %d strings to kernel buffer\n",
    1975 __FUNCTION__, this->process->pid, this->trdid, index );
    1976 #endif
    1977 
    1978     return 0;
    1979 
    1980 } // end process_exec_get_strings()
     1899#if DEBUG_PROCESS_MAKE_EXEC
     1900
     1901/////////////////////////////////////////////////////////////////////////////////////////
     1902// This static debug function displays the current state of the exec_info structure
     1903// embedded in the calling process descriptor.
     1904//
     1905// WARNING : It can be used after execution of the sys_exec function, but it cannot
     1906//           be used after execution of the process_make_exec() function, because the
     1907//           kernel pointers have been replaced by user pointers.
     1908/////////////////////////////////////////////////////////////////////////////////////////
     1909static void process_exec_info_display( bool_t args_ok,
     1910                                       bool_t envs_ok )
     1911{
     1912    uint32_t   i;
     1913    char     * str;    // local pointer on a string
     1914
     1915    process_t * process = CURRENT_THREAD->process;
     1916
     1917    // get relevant info from calling process descriptor
     1918    pid_t       pid      = process->pid;
     1919
     1920    uint32_t    args_nr  = process->exec_info.args_nr;
     1921    char     ** args     = process->exec_info.args_pointers;
     1922
     1923    uint32_t    envs_nr  = process->exec_info.envs_nr;
     1924    char     ** envs     = process->exec_info.envs_pointers;
     1925
     1926    char      * path     = process->exec_info.path;
     1927
     1928    // get pointers on TXT0 chdev
     1929    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
     1930    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
     1931    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
     1932
     1933    // get extended pointer on remote TXT0 lock
     1934    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
     1935
     1936    // get TXT0 lock
     1937    remote_busylock_acquire( lock_xp );
     1938
     1939    nolock_printk("\n***** exec_info for process %x in cluster %x / %s\n",
     1940    pid , local_cxy , path );
     1941
     1942    // display arguments if required
     1943    if( args_ok )
     1944    {
     1945        for( i = 0 ; i < args_nr ; i++ )
     1946        {
     1947            str = args[i];
     1948            if( str != NULL)         // display pointer and string
     1949            nolock_printk(" - &arg[%d] = %x / arg[%d] = <%s>\n", i, str, i, str );
     1950            else                     // display WARNING
     1951            nolock_printk(" - unexpected NULL pointer for &arg[%d]\n", i );
     1952        }
     1953    }
     1954
     1955    // display env variables if required
     1956    if( envs_ok )
     1957    {
     1958        for( i = 0 ; i < envs_nr ; i++ )
     1959        {
     1960            str = envs[i];
     1961            if( str != NULL)     // display pointer and string
     1962            nolock_printk(" - &env[%d] = %x / env[%d] = <%s>\n", i, str, i, str );
     1963            else                     // display WARNING
     1964            nolock_printk(" - unexpected NULL pointer for &env[%d]\n", i );
     1965        }
     1966    }
     1967
     1968    // release TXT0 lock
     1969    remote_busylock_release( lock_xp );
     1970
     1971}  // end process_exec_info_display()
     1972
     1973#endif // DEBUG_PROCESS_MAKE_EXEC
    19811974
    19821975/////////////////////////////////
     
    20031996    uint32_t         envs_size;               // envs vseg size (bytes)
    20041997
     1998#if DEBUG_PROCESS_MAKE_EXEC || DEBUG_PROCESS_ERROR
     1999uint32_t cycle = (uint32_t)hal_get_cycles();
     2000#endif
     2001
    20052002    // get calling thread, process, pid, trdid, and ref_xp
    20062003    this    = CURRENT_THREAD;
     
    20142011
    20152012#if DEBUG_PROCESS_MAKE_EXEC
    2016 uint32_t cycle = (uint32_t)hal_get_cycles();
    20172013if( DEBUG_PROCESS_MAKE_EXEC < cycle )
    20182014printk("\n[%s] thread[%x,%x] enters for <%s> / cycle %d\n",
     
    20322028        if( error )
    20332029        {
    2034                 printk("\n[ERROR] in %s : thread[%x,%x] failed to open file <%s>\n",
    2035         __FUNCTION__, pid, trdid, elf_path );
     2030
     2031#if DEBUG_PROCESS_ERROR
     2032printk("\n[ERROR] in %s : thread[%x,%x] failed to open file <%s> / cycle %d\n",
     2033__FUNCTION__, pid, trdid, elf_path, cycle );
     2034#endif
    20362035                return -1;
    20372036        }
     
    20642063#endif
    20652064
    2066     // 4. register the "args" vseg in VSL and map it in GPT, if required
    2067     // this vseg contains both the array of pointers and the strings
     2065    // 4. register the "args" vseg in VSL and map it in GPT, if args_nr != 0.
     2066    //    As this vseg contains an array of pointers, the kernel pointers
     2067    //    are replaced by user pointers in new process space.
    20682068    args_nr = process->exec_info.args_nr;
    20692069
     
    20712071    {
    20722072        // get args vseg base and size in user space
    2073         args_base = CONFIG_VMM_UTILS_BASE << CONFIG_PPM_PAGE_SHIFT;
    2074         args_size = CONFIG_VMM_ARGS_SIZE << CONFIG_PPM_PAGE_SHIFT;
     2073        args_base = CONFIG_VMM_UTILS_BASE << CONFIG_PPM_PAGE_ORDER;
     2074        args_size = CONFIG_VMM_ARGS_SIZE << CONFIG_PPM_PAGE_ORDER;
    20752075
    20762076        // create and register args vseg in VMM
     
    20852085        if( vseg == NULL )
    20862086        {
    2087                  printk("\n[ERROR] in %s : thread[%x,%x] cannot get args vseg for <%s>\n",
    2088              __FUNCTION__, pid, trdid, elf_path );
     2087
     2088#if DEBUG_PROCESS_ERROR
     2089printk("\n[ERROR] in %s : thread[%x,%x] cannot create args vseg for <%s> / cycle %d\n",
     2090__FUNCTION__, pid, trdid, elf_path, cycle );
     2091#endif
    20892092                     return -1;
    20902093        }
     
    20982101}
    20992102#endif
    2100         // map all pages for this "args" vseg
     2103        // map all pages for the "args" vseg
    21012104        uint32_t fake_attr;   // required for hal_gpt_lock_pte()
    21022105        ppn_t    fake_ppn;    // required for hal_gpt_lock_pte()
    21032106
    2104         xptr_t   gpt  = XPTR( local_cxy , &process->vmm.gpt );
    2105         uint32_t attr = GPT_MAPPED | GPT_SMALL | GPT_READABLE | GPT_USER | GPT_CACHABLE;
    2106         vpn_t    vpn  = CONFIG_VMM_UTILS_BASE;
    2107         ppn_t    ppn  = ((ppn_t)process->exec_info.args_pointers >> CONFIG_PPM_PAGE_SHIFT);
     2107        xptr_t   base_xp = XPTR( local_cxy , process->exec_info.args_pointers );
     2108        xptr_t   gpt_xp  = XPTR( local_cxy , &process->vmm.gpt );
     2109        uint32_t attr    = GPT_MAPPED | GPT_SMALL | GPT_READABLE | GPT_USER | GPT_CACHABLE;
     2110        vpn_t    vpn     = CONFIG_VMM_UTILS_BASE;
     2111        ppn_t    ppn     = ppm_base2ppn( base_xp );
    21082112
    21092113        for( n = 0 ; n < CONFIG_VMM_ARGS_SIZE ; n++ ) 
    21102114        {
    21112115            // lock the PTE
    2112             if (hal_gpt_lock_pte( gpt , vpn , &fake_attr , &fake_ppn ) )
     2116            if (hal_gpt_lock_pte( gpt_xp , vpn + n , &fake_attr , &fake_ppn ) )
    21132117            {
    2114                 printk("\n[ERROR] in %s : thread[%x,%x] cannot map args vpn %x for <%s>\n",
    2115                 __FUNCTION__, pid, trdid, vpn, elf_path );
     2118
     2119#if DEBUG_PROCESS_ERROR
     2120printk("\n[ERROR] in %s : thread[%x,%x] cannot map vpn[%x] of args vseg for <%s> / cycle %d\n",
     2121__FUNCTION__, pid, trdid,  vpn + n , elf_path , cycle );
     2122#endif
    21162123                        return -1;
    21172124            }
    21182125
    21192126            // map and unlock the PTE
    2120             hal_gpt_set_pte( gpt , vpn + n , attr , ppn + n );
    2121         }
     2127            hal_gpt_set_pte( gpt_xp , vpn + n , attr , ppn + n );
     2128       }
    21222129
    21232130#if( DEBUG_PROCESS_MAKE_EXEC & 1 )
     
    21272134    __FUNCTION__, pid, trdid );
    21282135    hal_vmm_display( ref_xp , true );
     2136    process_exec_info_display( true , false );   // args & not envs
    21292137}
    21302138#endif
    21312139
    2132         // set user space pointers in array of pointers
    2133         char  ** ptr    = process->exec_info.args_pointers;
    2134 
     2140        // build pointer on args buffer in kernel space
     2141        char  ** k_args = process->exec_info.args_pointers;
     2142
     2143        // build pointer on args buffer in user space
     2144        char  ** u_args = (char **)args_base;
     2145
     2146        // set user space pointers in kernel args buffer
    21352147        for( n = 0 ; n < args_nr ; n++ )
    21362148        {
    2137             ptr[n] = ptr[n] + args_base - (intptr_t)ptr;
     2149            k_args[n] = (char *)((intptr_t)k_args[n] + (intptr_t)u_args - (intptr_t)k_args);
    21382150        }
    2139     }
    2140 
    2141     // 5. register the "envs" vseg in VSL and map it in GPT, if required
    2142     // this vseg contains both the array of pointers and the strings
     2151
     2152#if( DEBUG_PROCESS_MAKE_EXEC & 1 )
     2153if( DEBUG_PROCESS_MAKE_EXEC < cycle )
     2154printk("\n[%s] thread[%x,%x] args user pointers set in exec_info\n",
     2155__FUNCTION__, pid, trdid );
     2156#endif
     2157
     2158    }
     2159
     2160    // 5. register the "envs" vseg in VSL and map it in GPT, if envs_nr != 0.
     2161    //    As this vseg contains an array of pointers, the kernel pointers
     2162    //    are replaced by user pointers in new process space.
     2163
    21432164    envs_nr = process->exec_info.envs_nr;
    21442165
     
    21462167    {
    21472168        // get envs vseg base and size in user space from config
    2148         envs_base = (CONFIG_VMM_UTILS_BASE + CONFIG_VMM_ARGS_SIZE) << CONFIG_PPM_PAGE_SHIFT;
    2149         envs_size = CONFIG_VMM_ENVS_SIZE << CONFIG_PPM_PAGE_SHIFT;
    2150 
    2151         // TODO (inspired from args)
     2169        envs_base = (CONFIG_VMM_UTILS_BASE + CONFIG_VMM_ARGS_SIZE) << CONFIG_PPM_PAGE_ORDER;
     2170        envs_size = CONFIG_VMM_ENVS_SIZE << CONFIG_PPM_PAGE_ORDER;
     2171
     2172        // TODO (should be similar to the code for args above)
     2173
     2174#if( DEBUG_PROCESS_MAKE_EXEC & 1 )
     2175if( DEBUG_PROCESS_MAKE_EXEC < cycle )
     2176printk("\n[%s] thread[%x,%x] envs user pointers set in exec_info\n",
     2177__FUNCTION__, pid, trdid );
     2178#endif
     2179
    21522180    }
    21532181
     
    21562184    // register extended pointer on .elf file in process descriptor
    21572185        error = elf_load_process( file_xp , process );
     2186
    21582187    if( error )
    21592188        {
    2160                 printk("\n[ERROR] in %s : thread[%x,%x] failed to access <%s>\n",
    2161         __FUNCTION__, pid, trdid, elf_path );
     2189
     2190#if DEBUG_PROCESS_ERROR
     2191printk("\n[ERROR] in %s : thread[%x,%x] failed to access file <%s> / cycle %d\n",
     2192__FUNCTION__, pid, trdid , elf_path , cycle );
     2193#endif
    21622194        return -1;
    21632195        }
     
    21832215    if( vseg == NULL )
    21842216    {
    2185             printk("\n[ERROR] in %s : thread[%x,%x] cannot set u_stack vseg for <%s>\n",
    2186         __FUNCTION__, pid, trdid, elf_path );
     2217
     2218#if DEBUG_PROCESS_ERROR
     2219printk("\n[ERROR] in %s : thread[%x,%x] failed to set u_stack vseg for <%s> / cycle %d\n",
     2220__FUNCTION__, pid, trdid , elf_path , cycle );
     2221#endif
    21872222                return -1;
    21882223    }
     
    22052240    if( error )
    22062241    {
    2207         printk("\n[ERROR] in %s : thread[%x,%x] cannot update thread for <%s>\n",
    2208         __FUNCTION__ , pid, trdid, elf_path );
     2242
     2243#if DEBUG_PROCESS_ERROR
     2244printk("\n[ERROR] in %s : thread[%x,%x] failed to set main thread for <%s> / cycle %d\n",
     2245__FUNCTION__, pid, trdid , elf_path , cycle );
     2246#endif
    22092247        return -1;
    22102248    }
    22112249
     2250    // should not be reached, avoid a warning
    22122251        return 0;
    22132252
     
    22942333if( DEBUG_PROCESS_ZERO_CREATE < cycle )
    22952334printk("\n[%s] initialized hal specific VMM in cluster%x\n", __FUNCTION__, local_cxy );
     2335hal_vmm_display( XPTR( local_cxy , process ) , true );
    22962336#endif
    22972337
     
    23562396
    23572397    // allocates memory for process descriptor from local cluster
    2358         process = process_alloc();
     2398    process = kmem_alloc( bits_log2(sizeof(process_t)) , AF_ZERO );
    23592399    if( process == NULL )
    23602400    {
     
    25062546}  // end process_init_create()
    25072547
    2508 /////////////////////////////////////////
    2509 void process_display( xptr_t process_xp )
    2510 {
    2511     process_t   * process_ptr;
    2512     cxy_t         process_cxy;
     2548///////////////////////////////////////////////////
     2549uint32_t process_build_string( xptr_t   process_xp,
     2550                               char   * buffer,
     2551                               uint32_t size )
     2552{
     2553    int32_t       length;          // actual length of the string
     2554
     2555    process_t   * process_ptr;     // process descriptor local pointer
     2556    cxy_t         process_cxy;     // process descriptor cluster identifier
    25132557
    25142558    xptr_t        parent_xp;       // extended pointer on parent process
    2515     process_t   * parent_ptr;
    2516     cxy_t         parent_cxy;
     2559    process_t   * parent_ptr;      // parent process local pointer
     2560    cxy_t         parent_cxy;      // parent process cluster identifier
    25172561
    25182562    xptr_t        owner_xp;        // extended pointer on owner process
    2519     process_t   * owner_ptr;
    2520     cxy_t         owner_cxy;
    2521 
    2522     pid_t         pid;
    2523     pid_t         ppid;
    2524     lpid_t        lpid;
    2525     uint32_t      state;
    2526     uint32_t      th_nr;
     2563    process_t   * owner_ptr;       // owner process local pointer
     2564    cxy_t         owner_cxy;       // owner process cluster identifier
     2565
     2566    pid_t         pid;             // process identifier
     2567    pid_t         ppid;            // parent process identifier
     2568    lpid_t        lpid;            // local process identifier
     2569    uint32_t      state;           // terminaison state
     2570    uint32_t      th_nr;           // number of threads
    25272571
    25282572    xptr_t        txt_file_xp;     // extended pointer on TXT_RX file descriptor
     
    25402584    char          elf_name[CONFIG_VFS_MAX_NAME_LENGTH];
    25412585
     2586assert( __FUNCTION__ , (size >= 80 ) , "buffer size too small" );
     2587
    25422588    // get cluster and local pointer on process
    25432589    process_ptr = GET_PTR( process_xp );
     
    25662612    if( lpid )                                   // user process
    25672613    {
    2568 
    25692614        // get extended pointer on file descriptor associated to TXT_RX
    25702615        txt_file_xp = hal_remote_l64( XPTR( owner_cxy , &owner_ptr->fd_array.array[0] ) );
    25712616
    2572         assert( __FUNCTION__, (txt_file_xp != XPTR_NULL) ,
    2573         "process must be attached to one TXT terminal" );
     2617assert( __FUNCTION__, (txt_file_xp != XPTR_NULL) ,
     2618"process must be attached to one TXT terminal" );
    25742619
    25752620        // get TXT_RX chdev pointers
     
    25822627                           XPTR( txt_chdev_cxy , txt_chdev_ptr->name ) );
    25832628   
     2629        // get TXT_owner process
    25842630        txt_owner_xp = (xptr_t)hal_remote_l64( XPTR( txt_chdev_cxy,
    25852631                                                     &txt_chdev_ptr->ext.txt.owner_xp ) );
    2586 
    25872632        // get process .elf name
    25882633        elf_file_xp   = hal_remote_l64( XPTR( process_cxy , &process_ptr->vfs_bin_xp ) );
     
    25942639    else                                         // kernel process_zero
    25952640    {
    2596         // TXT name and .elf name are not registered in kernel process_zero
     2641        // TXT name and .elf name are not registered in kernel process
    25972642        strcpy( txt_name , "txt0_rx" );
    25982643        txt_owner_xp = process_xp;
     
    26032648    if( txt_owner_xp == process_xp )
    26042649    {
    2605         nolock_printk("PID %X | %s (FG) | %X | PPID %X | TS %X | %d | %s\n",
     2650        length = snprintk( buffer, size,
     2651        "PID %X | %s (FG) | %X | PPID %X | TS %X | %d | %s\n",
    26062652        pid, txt_name, process_ptr, ppid, state, th_nr, elf_name );
    26072653    }
    26082654    else
    26092655    {
    2610         nolock_printk("PID %X | %s (BG) | %X | PPID %X | TS %X | %d | %s\n",
     2656        length = snprintk( buffer, size,
     2657        "PID %X | %s (BG) | %X | PPID %X | TS %X | %d | %s\n",
    26112658        pid, txt_name, process_ptr, ppid, state, th_nr, elf_name );
    26122659    }
     2660
     2661    // check length
     2662    if( (length < 0) )
     2663    {
     2664        length = snprintk( buffer , size ,
     2665        "buffer too small for process %x in cluster %x", pid , process_cxy );
     2666    }
     2667
     2668    return length; 
     2669
     2670}  // end process_build_string()
     2671
     2672/////////////////////////////////////////
     2673void process_display( xptr_t process_xp )
     2674{
     2675    char  buffer[CONFIG_PROCESS_DISPLAY_BUF_SIZE];
     2676
     2677    // build the string to be displayed
     2678    process_build_string( process_xp,
     2679                          buffer,
     2680                          CONFIG_PROCESS_DISPLAY_BUF_SIZE );
     2681    // display the string
     2682    nolock_puts( buffer );
     2683
    26132684}  // end process_display()
    26142685
  • trunk/kernel/kern/process.h

    r669 r683  
    9898 * This structure defines the information required by the process_make_exec() function
    9999 * to create a new reference process descriptor, and the associated main thread.
    100  * All fields in this structure are filled by the sys_exec() function, using the
    101  * process_exec_get_strings() function.
     100 * All fields in this structure are filled by the sys_exec() function.
    102101 *
    103102 * It contains three parts:
     
    106105 * - the "envs_pointers" & "envs_nr" fields define the env variables (one env == one string).
    107106 *
    108  * For both the arguments, and the environment variables, the array of pointers and the
    109  * strings themselve are stored in kernel space in the same kernel buffer containing
    110  * an integer number of pages, defined by CONFIG_VMM_ARGS_SIZE and CONFIG_VMM_ENVS_SIZE.
    111  * This aligned kernel buffer (one or several contiguous physical pages) contains :
     107 * For both the arguments and the environment variables, the array of pointers and the
     108 * strings themselve are stored in the same kernel buffer. These kernel buffers contain
     109 * an integer number of contiguous pages, defined by the CONFIG_VMM_ARGS_SIZE and
     110 * CONFIG_VMM_ENVS_SIZE parameters respectively.
     111 * Each kernel (args / envs) buffer contains :
    112112 * - in the first bytes, a fixed size kernel array of pointers on the strings.
    113113 * - in the following bytes, the strings themselves.
    114  * The size of these arrays of pointers is defined by CONFIG_PROCESS_ARGS_MAX_NR
    115  * and CONFIG¨PROCESS_ENVS_MAX_NR.
    116  *
    117  * WARNING: The "args_pointers" & "envs_pointers" kernel buffer are directly mapped to
    118  *          the "args" and "envs" user vsegs to be accessed by the user process.
    119  *          Therefore, the arrays of pointers build by the sys_exec() function contain
    120  *          kernel pointers, but the process_make_exec() function replace these pointers
    121  *          by user pointers in the new process user space.
     114 * The size of these arrays of pointers is defined by the CONFIG_PROCESS_ARGS_MAX_NR and
     115 * CONFIG_PROCESS_ENVS_MAX_NR parameters respectively.
     116 *
     117 * WARNING (1) The "args_pointers[i]" & "envs_pointers[i] stored in the dynamically
     118 *             allocated kernel buffers are local pointers. They must be extended by the
     119 *             local cluster identifier to compute a valid PPN.
     120 * WARNING (2) The "args" & "envs" kernel buffers will be mapped to the "args" and "envs"
     121 *             user vsegs, to be accessed by the new user process.
     122 *             The process_make_exec() function must therefore replace the kernel pointers
     123 *             set by sys_exec(), by user pointers in the new process user space.
    122124 ********************************************************************************************/
    123125
     
    232234 * The process GPT is initialised as required by the target architecture.
    233235 * The "kcode" and "kdata" segments are registered in the process VSL.
     236 * This function does not return an error code: in case of failure, it print a PANIC message
     237 * on kernel terminal TXT0, and the core goes to sleep mode.
    234238 *********************************************************************************************
    235239 * @ process  : [in] pointer on process descriptor to initialize.
     
    241245/*********************************************************************************************
    242246 * This function allocates memory and initializes the "process_init" descriptor and the
    243  * associated "thread_init" descriptor. It is called once at the end of the kernel
    244  * initialisation procedure. Its local process identifier is 1, and parent process
    245  * is the kernel process in cluster 0.
     247 * associated "thread_init" descriptor. It is called once at the end of the kernel_init()
     248 * procedure. Its local process identifier is 1, and parent process is the kernel process.
    246249 * The "process_init" is the first user process, and all other user processes will be forked
    247250 * from this process. The code executed by "process_init" is stored in a .elf file, whose
    248251 * pathname is defined by the CONFIG_PROCESS_INIT_PATH configuration variable.
    249  * The process_init does not use the [STDIN/STDOUT/STDERR] streams, but it is linked
    250  * to kernel TXT0, because these streams must be defined for all user processes.
     252 * This function does not return an error code: in case of failure, it print a PANIC message
     253 * on kernel terminal TXT0, and the core goes to sleep mode.
    251254 ********************************************************************************************/
    252255void process_init_create( void );
     
    415418
    416419/*********************************************************************************************
    417  * This function is called twice by the sys_exec() function :
    418  * - to register the main() arguments (args) in the process <exec_info> structure.
    419  * - to register the environment variables (envs) in the <exec_info> structure.
    420  * In both cases the input is an array of NULL terminated string pointers in user space,
    421  * identified by the <u_pointers> argument. The strings can be dispatched anywhere in
    422  * the calling user process space. The max number of envs, and the max number of args are
    423  * defined by the CONFIG_PROCESS_ARGS_NR and CONFIG_PROCESS_ENVS_MAX_NR parameters.
    424  *********************************************************************************************
    425  * Implementation Note:
    426  * Both the array of pointers and the strings themselve are stored in kernel space in one
    427  * single, dynamically allocated, kernel buffer containing an integer number of pages,
    428  * defined by the CONFIG_VMM_ENVS_SIZE and CONFIG_VMM_STACK_SIZE parameters.
    429  * This aligned kernel buffer (one or several contiguous physical pages) contains :
    430  * - in the first bytes a fixed size kernel array of kernel pointers on the strings.
    431  * - in the following bytes the strings themselves.
    432  * All the pointers, and the actual number of strings are stored in the process exec_info
    433  * structure defined in the <process.h> file.
    434  *********************************************************************************************
    435  * @ is_args     : [in]    true if called for (args) / false if called for (envs).
    436  * @ u_pointers  : [in]    array of pointers on the strings (in user space).
    437  * @ exec_info   : [inout] pointer on the exec_info structure.
    438  * @ return 0 if success / non-zero if too many strings or no memory.
    439  ********************************************************************************************/
    440 error_t process_exec_get_strings( bool_t         is_args,
    441                                   char        ** u_pointers,
    442                                   exec_info_t  * exec_info );
    443 
    444 /*********************************************************************************************
    445420 * This function implements the "execve" system call, and is called by sys_exec() function.
    446421 * It must be called by the main thread of the calling "old" process.
     
    595570 * @ dst_xp   : extended pointer on the source process descriptor (in owner cluster).
    596571 * @ src_xp   : extended pointer on the destination process descriptor (in owner cluster).
    597  ********************************************************************************************/
    598 void process_fd_replicate( xptr_t dst_xp,
    599                            xptr_t src_xp );
     572 * @ return 0 if success / return -1 if failure
     573 ********************************************************************************************/
     574error_t process_fd_replicate( xptr_t dst_xp,
     575                              xptr_t src_xp );
    600576
    601577/*********************************************************************************************
     
    617593 ********************************************************************************************/
    618594void process_fd_display( xptr_t process_xp );
     595
     596/*********************************************************************************************
     597 * This utility function builds in the buffer defined by the <buffer> and <size> arguments
     598 * a printable string describing the current state of a process descriptor identified
     599 * by the <process_xp> argument, or a WARNING message if the buffer size is too small.
     600 *********************************************************************************************
     601 * @ process_xp  : extended pointer on target process descriptor.
     602 * @ buffer      : kernel buffer for string.
     603 * @ size        : buffer size in bytes.
     604 * @ return always the string length (not including NUL), that can be a warning message.
     605 ********************************************************************************************/
     606uint32_t process_build_string( xptr_t   process_xp,
     607                               char   * buffer,
     608                               uint32_t size );
    619609
    620610/********************   Thread Related Operations   *****************************************/
  • trunk/kernel/kern/scheduler.c

    r669 r683  
    22 * scheduler.c - Core scheduler implementation.
    33 *
    4  * Author    Alain Greiner (2016,2017,2018)
     4 * Author    Alain Greiner       (2016,2017,2018,2019,2020)
    55 *
    66 * Copyright (c)  UPMC Sorbonne Universites
     
    6363// @ returns pointer on selected thread descriptor
    6464////////////////////////////////////////////////////////////////////////////////////////////
    65 static thread_t * sched_select( scheduler_t * sched )
     65static thread_t * __attribute__((__noinline__))sched_select( scheduler_t * sched )
    6666{
    6767    thread_t     * thread;
     
    8383        while( done == false )
    8484        {
    85 
    86 // check kernel threads list
    87 assert( __FUNCTION__, (count < sched->k_threads_nr), "bad kernel threads list" );
    88 
    8985            // get next entry in kernel list
    9086            current = current->next;
     
    117113        while( done == false )
    118114        {
    119 
    120 // check user threads list
    121 assert( __FUNCTION__, (count < sched->u_threads_nr), "bad user threads list" );
    122 
    123115            // get next entry in user list
    124116            current = current->next;
  • trunk/kernel/kern/scheduler.h

    r662 r683  
    22 * scheduler.h - Core scheduler definition.
    33 *
    4  * Author    Alain Greiner (2016,2017,2018,2019,2020)
     4 * Author    Alain Greiner       (2016,2017,2018,2019,2020)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
  • trunk/kernel/kern/thread.c

    r669 r683  
    33 *
    44 * Author  Ghassan Almaless (2008,2009,2010,2011,2012)
    5  *         Alain Greiner (2016,2017,2018,2019,2020)
     5 *         Alain Greiner    (2016,2017,2018,2019,2020)
    66 *
    77 * Copyright (c) UPMC Sorbonne Universites
     
    6767  }
    6868}
    69 
    70 /////////////////////////////////////////////////////////////////////////////////////
    71 // This static function allocates physical memory for a thread descriptor.
    72 // It can be called by the three functions:
    73 // - thread_user_create()
    74 // - thread_user_fork()
    75 // - thread_kernel_create()
    76 /////////////////////////////////////////////////////////////////////////////////////
    77 // @ return pointer on thread descriptor if success / return NULL if failure.
    78 /////////////////////////////////////////////////////////////////////////////////////
    79 static thread_t * thread_alloc( void )
    80 {
    81         kmem_req_t     req;    // kmem request
    82 
    83         // allocates memory for thread descriptor + kernel stack
    84         req.type  = KMEM_PPM;
    85         req.order = CONFIG_THREAD_DESC_ORDER;
    86         req.flags = AF_KERNEL | AF_ZERO;
    87 
    88     return kmem_alloc( &req );
    89 
    90 }  // end thread_alloc()
    91  
    9269
    9370/////////////////////////////////////////////////////////////////////////////////////
     
    144121
    145122#if DEBUG_BUSYLOCK
    146     xlist_root_init( XPTR( local_cxy , &thread->busylocks_root ) );
     123xlist_root_init( XPTR( local_cxy , &thread->busylocks_root ) );
    147124#endif
    148125
     
    161138    list_entry_init( &thread->sched_list );
    162139
    163     // initialize the embedded alarm to unlink
     140    // initialize the embedded alarm
    164141    list_entry_init( &thread->alarm.list );
    165142
     
    187164    dqdt_increment_threads();
    188165
     166    // nitialize timer alarm
     167    alarm_init( &thread->alarm );
     168
    189169#if CONFIG_INSTRUMENTATION_PGFAULTS
    190     thread->info.false_pgfault_nr    = 0;
    191     thread->info.false_pgfault_cost  = 0;
    192     thread->info.false_pgfault_max   = 0;
    193     thread->info.local_pgfault_nr    = 0;
    194     thread->info.local_pgfault_cost  = 0;
    195     thread->info.local_pgfault_max   = 0;
    196     thread->info.global_pgfault_nr   = 0;
    197     thread->info.global_pgfault_cost = 0;
    198     thread->info.global_pgfault_max  = 0;
     170thread->info.false_pgfault_nr    = 0;
     171thread->info.false_pgfault_cost  = 0;
     172thread->info.false_pgfault_max   = 0;
     173thread->info.local_pgfault_nr    = 0;
     174thread->info.local_pgfault_cost  = 0;
     175thread->info.local_pgfault_max   = 0;
     176thread->info.global_pgfault_nr   = 0;
     177thread->info.global_pgfault_cost = 0;
     178thread->info.global_pgfault_max  = 0;
    199179#endif
    200180
     
    273253
    274254    // allocate memory for thread descriptor
    275     thread = thread_alloc();
     255    thread = kmem_alloc( CONFIG_THREAD_DESC_ORDER , AF_ZERO );
    276256
    277257    if( thread == NULL )
     
    467447
    468448    // allocate memory for child thread descriptor
    469     child_ptr = thread_alloc();
     449    child_ptr = kmem_alloc( CONFIG_THREAD_DESC_ORDER , AF_ZERO );
    470450
    471451    if( child_ptr == NULL )
     
    677657uint32_t cycle = (uint32_t)hal_get_cycles();
    678658if( DEBUG_THREAD_USER_EXEC < cycle )
    679 printk("\n[%s] thread[%x,%x] enter / cycle %d\n",
    680 __FUNCTION__, process->pid, thread->trdid, cycle );
     659printk("\n[%s] thread[%x,%x] enter / argc %d / argv %x / cycle %d\n",
     660__FUNCTION__, process->pid, thread->trdid, argc, argv, cycle );
    681661#endif
    682662
     
    727707#endif
    728708
    729     // restore CPU registers ... and jump to user code
     709    // restore CPU registers => jump to user code
    730710    hal_do_cpu_restore( thread->cpu_context );
    731711
     
    759739
    760740    // allocate memory for new thread descriptor
    761     thread = thread_alloc();
     741    thread = kmem_alloc( CONFIG_THREAD_DESC_ORDER , AF_ZERO );
    762742
    763743    if( thread == NULL )
     
    839819
    840820// check arguments
    841 assert( __FUNCTION__, (type == THREAD_IDLE) , "illegal thread type" );
    842 assert( __FUNCTION__, (core_lid < LOCAL_CLUSTER->cores_nr) , "illegal core index" );
     821assert( __FUNCTION__, (type == THREAD_IDLE),
     822"illegal thread type" );
     823
     824assert( __FUNCTION__, (core_lid < LOCAL_CLUSTER->cores_nr),
     825"illegal core index" );
    843826
    844827    // set type in thread descriptor
     
    848831    error = process_register_thread( &process_zero , thread , &trdid );
    849832
    850 assert( __FUNCTION__, (error == 0), "cannot register idle_thread in kernel process" );
     833assert( __FUNCTION__, (error == 0),
     834"cannot register idle_thread in kernel process" );
    851835
    852836    // set trdid in thread descriptor
     
    863847                         NULL );   // no user stack for a kernel thread
    864848
    865 assert( __FUNCTION__, (error == 0), "cannot initialize idle_thread" );
     849assert( __FUNCTION__, (error == 0),
     850"cannot initialize idle_thread" );
    866851
    867852    // allocate CPU context
    868853    error = hal_cpu_context_alloc( thread );
    869854
    870 assert( __FUNCTION__, (error == 0), "cannot allocate CPU context" );
     855assert( __FUNCTION__,(error == 0),
     856"cannot allocate CPU context" );
    871857
    872858    // initialize CPU context
     
    963949
    964950    // release memory for thread descriptor (including kernel stack)
    965     kmem_req_t   req;
    966     req.type  = KMEM_PPM;
    967     req.ptr   = thread;
    968     kmem_free( &req );
     951    kmem_free( thread , CONFIG_THREAD_DESC_ORDER );
    969952
    970953#if DEBUG_THREAD_DESTROY
     
    10911074}  // end thread_unblock()
    10921075
    1093 //////////////////////////////////////
     1076//////////////////////////////////////////////
    10941077void thread_delete_request( xptr_t  target_xp,
    1095                     bool_t  is_forced )
     1078                            bool_t  is_forced )
    10961079{
    10971080    reg_t       save_sr;                // for critical section
     
    14751458        thread->busylocks - 1, (uint32_t)hal_get_cycles() );
    14761459
    1477 #if DEBUG_BUSYLOCK
     1460#if DEBUG_BUSYLOCK_TYPE
    14781461
    14791462// scan list of busylocks
  • trunk/kernel/kern/thread.h

    r669 r683  
    33 *
    44 * Author  Ghassan Almaless (2008,2009,2010,2011,2012)
    5  *         Alain Greiner (2016,2017,2018,2019,2020)
     5 *         Alain Greiner    (2016,2017,2018,2019,2020)
    66 *
    77 * Copyright (c) UPMC Sorbonne Universites
     
    9696#define THREAD_BLOCKED_LOCK      0x1000  /*! ANY : wait queuelock or rwlock           */
    9797#define THREAD_BLOCKED_CLIENT    0x2000  /*! DEV : wait clients queue non empty       */
    98 #define THREAD_BLOCKED_ALARM     0x4000  /*! ANY : wait a timer based alarm           */
     98#define THREAD_BLOCKED_SLEEP     0x4000  /*! ANY : wait a timer based alarm           */
    9999
    100100/***************************************************************************************
Note: See TracChangeset for help on using the changeset viewer.