Changeset 669 for trunk/kernel/kern


Ignore:
Timestamp:
Nov 19, 2020, 11:44:34 PM (4 years ago)
Author:
alain
Message:

1) Introduce up to 4 command lines arguments in the KSH "load" command.
These arguments are transfered to the user process through the
argc/argv mechanism, using the user space "args" vseg.

2) Introduce the named and anonymous "pipes", for inter-process communication
through the pipe() and mkfifo() syscalls.

3) Introduce the "chat" application to validate the two above mechanisms.

4) Improve printk() and assert() fonctions in printk.c.

Location:
trunk/kernel/kern
Files:
2 added
20 edited

Legend:

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

    r494 r669  
    11/*
    2  * kern/time.c - thread time related management
    3  *
    4  * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless
    5  * Copyright (c) 2011,2012 UPMC Sorbonne Universites
     2 * alarm.c - timer based kernel alarm implementation           
    63 *
    7  * This file is part of ALMOS-kernel.
     4 * Author     Alain Greiner (2016,2017,2018,2019,2020)
    85 *
    9  * ALMOS-kernel is free software; you can redistribute it and/or modify it
     6 * Copyright (c) UPMC Sorbonne Universites
     7 *
     8 * This file is part of ALMOS-MKH.
     9 *
     10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
    1011 * under the terms of the GNU General Public License as published by
    1112 * the Free Software Foundation; version 2.0 of the License.
    1213 *
    13  * ALMOS-kernel is distributed in the hope that it will be useful, but
     14 * ALMOS-MKH is distributed in the hope that it will be useful, but
    1415 * WITHOUT ANY WARRANTY; without even the implied warranty of
    1516 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     
    1718 *
    1819 * You should have received a copy of the GNU General Public License
    19  * along with ALMOS-kernel; if not, write to the Free Software Foundation,
     20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
    2021 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
    2122 */
    2223
    23 #include <types.h>
     24#include <kernel_config.h>
     25#include <hal_kernel_types.h>
     26#include <printk.h>
     27#include <list.h>
    2428#include <thread.h>
    25 #include <task.h>
    26 #include <scheduler.h>
    27 #include <time.h>
    28 #include <list.h>
    29 #include <rt_timer.h>
    30 #include <kmagics.h>
     29#include <core.h>
     30#include <alarm.h>
    3131
    32 error_t alarm_wait(struct alarm_info_s *info, uint_t msec)
     32////////////////////////////////////////////////////////////////////////////////////////////
     33// This static function registers the alarm identified ny the <new_alarm> argument
     34// in the list of alarms rooted in the core identified by the <core> argument.
     35// When the existing list of alarms is not empty, it scan the list to insert the new
     36// alarm in the right place to respect the absolute dates ordering.
     37////////////////////////////////////////////////////////////////////////////////////////////
     38// @ new_alarm  : local pointer on the new alarm.
     39// @ core       : local pointer on the target core.
     40////////////////////////////////////////////////////////////////////////////////////////////
     41static void alarm_register( alarm_t * new_alarm,
     42                            core_t  * core )
    3343{
    34         register uint_t tm_now;
    35         struct cpu_s *cpu;
    36         struct alarm_s *alarm_mgr;
    37         struct list_entry *iter;
    38         struct alarm_info_s *current;
    39         uint_t irq_state;
     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
    4048
    41         cpu       = current_cpu;
    42         alarm_mgr = &cpu->alarm_mgr;
     49    bool_t         done = false;
    4350
    44         cpu_disable_all_irq(&irq_state);
     51    // get pointers on root of alarms and lock
     52    list_entry_t * root = &core->alarms_root;
     53    busylock_t   * lock = &core->alarms_lock;
    4554
    46         tm_now          = cpu_get_ticks(cpu) * MSEC_PER_TICK;
    47         info->signature = ALRM_INFO_ID;
    48         info->tm_wakeup = tm_now + msec;
     55    // get pointer on new_alarm list_entry
     56    list_entry_t * new_entry = &new_alarm->list;
    4957
    50         if(list_empty(&alarm_mgr->wait_queue))
    51                 list_add_first(&alarm_mgr->wait_queue, &info->list);
    52         else
    53         {
    54                 list_foreach_forward(&alarm_mgr->wait_queue, iter)
    55                 {
    56                         current = list_element(iter, struct alarm_info_s, list);
    57      
    58                         if(info->tm_wakeup <= current->tm_wakeup)
    59                         {
    60                                 list_add_pred(iter, &info->list);
    61                                 goto NEXT_TRAITMENT;
    62                         }
    63                 }
    64                 list_add_last(&alarm_mgr->wait_queue, &info->list);
    65         }
     58    // get new_alarm date
     59    cycle_t        new_date = new_alarm->date;
    6660
    67 NEXT_TRAITMENT:
    68         cpu_restore_irq(irq_state);
    69         return 0;
    70 }
     61    // take the lock
     62    busylock_acquire( lock );
    7163
    72 void alarm_clock(struct alarm_s *alarm, uint_t ticks_nr)
     64    // insert new alarm to respect dates order
     65    if( list_is_empty( root ) )                     // list empty
     66    {
     67        list_add_first( root , new_entry );
     68    }
     69    else                                            // list non empty
     70    {
     71        for( current = root->next ;
     72             (current != root) && (done == false) ;
     73             current = current->next )
     74        {
     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 );
     80
     81            // get date for current alarm
     82            current_date  = current_alarm->date;
     83
     84            if( current_date > new_date )  // insert new alarm just before current
     85            {
     86                new_entry->next = current;
     87                new_entry->pred = previous;
     88
     89                current->pred  = new_entry;
     90                previous->next = new_entry;
     91               
     92                done = true;
     93            }
     94        }  // end for
     95       
     96        if( done == false ) // new_date is larger than all registered dates
     97        {
     98            list_add_last( root , new_entry );
     99        }
     100    }
     101
     102    // release the lock
     103    busylock_release( lock );
     104
     105}  // end alarm_register()
     106
     107//////////////////////////////////////
     108void alarm_start( cycle_t    date,
     109                  void     * func_ptr,
     110                  xptr_t     args_xp,
     111                  thread_t * thread )
    73112{
    74         register uint_t tm_msec;
    75         register struct list_entry *iter;
    76         register struct alarm_info_s *info;
    77  
    78         tm_msec = ticks_nr * MSEC_PER_TICK;
     113    // get pointer on alarm
     114    alarm_t * alarm = &thread->alarm;
    79115
    80         list_foreach_forward(&alarm->wait_queue, iter)
    81         {
    82                 info = list_element(iter, struct alarm_info_s, list);
     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 );
    83123
    84                 assert((info->signature == ALRM_INFO_ID), "Not an ALRM info object");
     124}  // end alarm_start()
    85125
    86                 if(tm_msec < info->tm_wakeup)
    87                         break;
     126/////////////////////////////////////
     127void 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 );
    88149   
    89                 list_unlink(iter);
    90                 event_send(info->event, current_cpu->gid);
    91         }
    92 }
     150}  // end alarm_update()
    93151
    94 error_t alarm_manager_init(struct alarm_s *alarm)
     152////////////////////////////////////
     153void alarm_stop( thread_t * thread )
    95154{
    96         list_root_init(&alarm->wait_queue);
    97         return 0;
    98 }
     155    // get pointer on alarm
     156    alarm_t * alarm = &thread->alarm;
    99157
     158    // get pointer on core
     159    core_t * core = thread->core;
    100160
    101 #if CONFIG_THREAD_TIME_STAT
     161    // get pointer on lock protecting the alarms list
     162    busylock_t * lock = &core->alarms_lock;
    102163
    103 inline void tm_sleep_compute(struct thread_s *thread)
    104 {
    105         uint_t tm_now;
     164    // unlink the alarm from the list rooted in core
     165    busylock_acquire( lock );
     166    list_unlink( &alarm->list );
     167    busylock_release( lock );
    106168
    107         if(thread->type == TH_IDLE)
    108                 return;
     169}  // end alarm_stop()
    109170
    110         rt_timer_read(&tm_now);
    111         thread->info.tm_sleep += (tm_now - thread->info.tm_tmp);
    112         thread->info.tm_tmp    = tm_now;
    113 }
    114 
    115 inline void tm_usr_compute(struct thread_s *thread)
    116 {
    117         uint_t tm_now;
    118 
    119         rt_timer_read(&tm_now);
    120         thread->info.tm_usr += (tm_now - thread->info.tm_tmp);
    121         thread->info.tm_tmp  = tm_now;
    122 }
    123 
    124 inline void tm_sys_compute(struct thread_s *thread)
    125 {
    126         uint_t tm_now;
    127 
    128         rt_timer_read(&tm_now);
    129         thread->info.tm_sys += (tm_now - thread->info.tm_tmp);
    130         thread->info.tm_tmp  = tm_now;
    131 }
    132 
    133 inline void tm_wait_compute(struct thread_s *thread)
    134 {
    135         uint_t tm_now;
    136 
    137         if(thread->type == TH_IDLE)
    138                 return;
    139 
    140         rt_timer_read(&tm_now);
    141         thread->info.tm_wait += (tm_now - thread->info.tm_tmp);
    142         thread->info.tm_tmp   = tm_now;
    143         thread->info.tm_exec  = tm_now;
    144 }
    145 
    146 inline void tm_exit_compute(struct thread_s *thread)
    147 {
    148         uint_t tm_now;
    149  
    150         rt_timer_read(&tm_now);
    151         thread->info.tm_sys += tm_now - thread->info.tm_tmp;
    152         thread->info.tm_dead = tm_now;
    153 }
    154 
    155 inline void tm_born_compute(struct thread_s *thread)
    156 {
    157         uint_t tm_now;
    158  
    159         rt_timer_read(&tm_now);
    160         thread->info.tm_born = tm_now;
    161         thread->info.tm_tmp  = tm_now;
    162         thread->info.tm_exec = tm_now;
    163 }
    164 
    165 inline void tm_create_compute(struct thread_s *thread)
    166 {
    167         rt_timer_read(&thread->info.tm_create);
    168 }
    169 
    170 
    171 #endif  /* CONFIG_THREAD_TIME_STAT */
  • trunk/kernel/kern/alarm.h

    r23 r669  
    11/*
    2  * time.h: thread time related management
    3  *
    4  * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless
    5  * Copyright (c) 2011,2012 UPMC Sorbonne Universites
     2 * alarm.h - timer based kernel alarm specification           
    63 *
    7  * This file is part of ALMOS-kernel.
     4 * Author     Alain Greiner (2016,2017,2018,2019,2020)
    85 *
    9  * ALMOS-kernel is free software; you can redistribute it and/or modify it
     6 * Copyright (c) UPMC Sorbonne Universites
     7 *
     8 * This file is part of ALMOS-MKH.
     9 *
     10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
    1011 * under the terms of the GNU General Public License as published by
    1112 * the Free Software Foundation; version 2.0 of the License.
    1213 *
    13  * ALMOS-kernel is distributed in the hope that it will be useful, but
     14 * ALMOS-MKH is distributed in the hope that it will be useful, but
    1415 * WITHOUT ANY WARRANTY; without even the implied warranty of
    1516 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     
    1718 *
    1819 * You should have received a copy of the GNU General Public License
    19  * along with ALMOS-kernel; if not, write to the Free Software Foundation,
     20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
    2021 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
    2122 */
    2223
    23 #ifndef _TIME_H_
    24 #define _TIME_H_
    2524
    26 #include <types.h>
     25#ifndef _ALARM_H_
     26#define _ALARM_H_
     27
     28#include <hal_kernel_types.h>
    2729#include <list.h>
    28 #include <device.h>
    2930
    30 struct event_s;
     31/****  Forward declarations  ****/
    3132
    32 struct alarm_info_s
     33struct  thread_s;
     34
     35/******************************************************************************************
     36 *   This structure defines a generic, timer based, kernel alarm.
     37 *
     38 * - An alarm being attached to a given thread, the alarm descriptor is embedded in the
     39 *   thread descriptor. A client thread can use the alarm_start() function to dynamically
     40 *   activate the alarm. It can use the alarm_stop() function to desactivate this alarm.
     41 * - 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>.
     43 * - When an alarm is created by a client thread, it is registered in the list of alarms
     44 *   rooted in the core running the client thread. When it is stopped, the alarm is simply
     45 *   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.
     48 * - The list of alarms is ordered by increasing dates. At each TICK received by a core,
     49 *   the date of the first registered alarm is compared to the current date (in the
     50 *   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. 
     52 *
     53 * This mechanism is used bi the almos_mkh implementation of the TCP protocoL.
     54 ******************************************************************************************/
     55
     56typedef struct alarm_s
    3357{
    34         uint_t signature;
     58    cycle_t        date;           /*! absolute date for handler execution                */
     59    void         * func_ptr;       /*! local pointer on alarm handler function            */
     60    xptr_t         args_xp;        /*! local pointer on handler arguments                 */
     61    list_entry_t   list;           /*! all alarms attached to the same core               */
     62}
     63alarm_t;
    3564
    36         /* Public members */
    37         struct event_s *event;
     65/*******************************************************************************************
     66 * This defines the generic prototype for an alarm handler.
     67 ******************************************************************************************/
    3868
    39         /* Private members */
    40         uint_t tm_wakeup;
    41         struct list_entry list;
    42 };
     69typedef void (alarm_handler_t) ( xptr_t args_xp );
    4370
    44 struct alarm_s
    45 {
    46         struct list_entry wait_queue;
    47 };
     71/*******************************************************************************************
     72 * 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>.
     75 *******************************************************************************************
     76 * @ date       : absolute date (in cycles).
     77 * @ func_ptr   : local pointer on the handler to execute when the alarm rings.
     78 * @ args_xp    : extended pointer on the handler arguments.
     79 * @ thread     : local pointer on the client thread.
     80 ******************************************************************************************/
     81void alarm_start( cycle_t           date,
     82                  void            * func_ptr,
     83                  xptr_t            args_xp,
     84                  struct thread_s * thread );
     85
     86/*******************************************************************************************
     87 * This function updates the date of the alarm attached to the thread identified by the
     88 * <thread> argument. The list of alarms rooted in the core running the client thread
     89 * is modified to respect the absolute dates ordering.
     90 *******************************************************************************************
     91 * @ thread     : local pointer on the client thread.
     92 * @ new_date   : absolute new date (in cycles).
     93 ******************************************************************************************/
     94void alarm_update( struct thread_s * thread,
     95                   cycle_t           new_date );
     96
     97/*******************************************************************************************
     98 * This function unlink an alarm identified by the <thread> argument from the list of
     99 * alarms rooted in the core descriptor.
     100 *******************************************************************************************
     101 * @ thread     : local pointer on the client thread.
     102 ******************************************************************************************/
     103void alarm_stop( struct thread_s * thread );
    48104
    49105
    50 struct timeb {
    51         time_t         time;
    52         unsigned short millitm;
    53         short          timezone;
    54         short          dstflag;
    55 };
    56 
    57 struct timeval {
    58         clock_t tv_sec;    /* secondes */
    59         clock_t tv_usec;   /* microsecondes */
    60 };
    61 
    62 struct timezone {
    63         int tz_minuteswest;     /* minutes west of Greenwich */
    64         int tz_dsttime;         /* type of DST correction */
    65 };
    66 
    67 
    68 struct tms
    69 {
    70        clock_t tms_utime;  /* user time */
    71        clock_t tms_stime;  /* system time */
    72        clock_t tms_cutime; /* user time of children */
    73        clock_t tms_cstime; /* system time of children */
    74 };
    75 
    76 
    77 error_t alarm_manager_init(struct alarm_s *alarm);
    78 error_t alarm_wait(struct alarm_info_s *info, uint_t msec);
    79 
    80 void alarm_clock(struct alarm_s *alarm, uint_t ticks_nr);
    81 
    82 int sys_clock (uint64_t *val);
    83 int sys_alarm (unsigned nb_sec);
    84 int sys_ftime (struct timeb *utime);
    85 int sys_times(struct tms *utms);
    86 int sys_gettimeofday(struct timeval *tv, struct timezone *tz);
    87 
    88 #if CONFIG_THREAD_TIME_STAT
    89 struct thread_s;
    90 inline void tm_sleep_compute(struct thread_s *thread);
    91 inline void tm_usr_compute(struct thread_s *thread);
    92 inline void tm_sys_compute(struct thread_s *thread);
    93 inline void tm_wait_compute(struct thread_s *thread);
    94 inline void tm_exit_compute(struct thread_s *thread);
    95 inline void tm_born_compute(struct thread_s *thread);
    96 inline void tm_create_compute(struct thread_s *thread);
    97 
    98 #else
    99 
    100 #define tm_sleep_compute(thread)
    101 #define tm_usr_compute(thread)
    102 #define tm_sys_compute(thread)
    103 #define tm_wait_compute(thread)
    104 #define tm_exit_compute(thread)
    105 #define tm_born_compute(thread)
    106 #define tm_create_compute(thread)
    107 
    108 #endif  /* CONFIG_SCHED_STAT */
    109 
    110 #endif  /* _TIME_H_ */
     106#endif  /* _ALARM_H_ */
  • trunk/kernel/kern/chdev.c

    r662 r669  
    450450    chdev_t     * chdev_ptr;
    451451
    452     assert( (file_xp != XPTR_NULL) ,
     452    assert( __FUNCTION__, (file_xp != XPTR_NULL) ,
    453453    "file_xp == XPTR_NULL\n" );
    454454
     
    462462    inode_ptr  = (vfs_inode_t *)hal_remote_lpt( XPTR( file_cxy , &file_ptr->inode ) );
    463463
    464     assert( (inode_type == INODE_TYPE_DEV) ,
    465     "inode type %d is not INODE_TYPE_DEV\n", inode_type );
     464    assert( __FUNCTION__, (inode_type == FILE_TYPE_DEV) ,
     465    "inode type %d is not FILE_TYPE_DEV\n", inode_type );
    466466
    467467    // get chdev local pointer from inode extension
  • trunk/kernel/kern/chdev.h

    r662 r669  
    6666
    6767/****************************************************************************************
    68  * This define the generic prototypes for the three functions that must be defined
    69  * by the drivers implementing a generic device:
     68 * This defines the generic prototypes for the functions that must be defined
     69 * by all drivers implementing a generic device:
    7070 * - "cmd"     : start a blocking I/O operation.
    7171 * - "isr"     : complete an I/O operation.
     
    272272/****************************************************************************************
    273273 * This function returns an extended pointer on the chdev associated to a pseudo file
    274  * descriptor (type INODE_TYPE_DEV) identified by the <file_xp> argument.
     274 * descriptor (type FILE_TYPE_DEV) identified by the <file_xp> argument.
    275275 * It can be called by a thread running in any cluster.
    276276 * It enters kernel panic if the inode has not the expected type.
  • trunk/kernel/kern/cluster.c

    r657 r669  
    533533
    534534    // check lpid
    535     assert( (lpid < CONFIG_MAX_PROCESS_PER_CLUSTER),
     535    assert( __FUNCTION__, (lpid < CONFIG_MAX_PROCESS_PER_CLUSTER),
    536536    "illegal LPID = %d" , lpid );
    537537
    538538    // check owner cluster
    539     assert( (owner_cxy == local_cxy) ,
     539    assert( __FUNCTION__, (owner_cxy == local_cxy) ,
    540540    "local_cluster %x !=  owner_cluster %x" , local_cxy , owner_cxy );
    541541
     
    732732    uint32_t      pref_nr;       // number of owned processes in cluster cxy
    733733
    734 assert( (cluster_is_active( cxy ) ), "illegal cluster index" );
     734assert( __FUNCTION__, (cluster_is_active( cxy ) ), "illegal cluster index" );
    735735
    736736    // get extended pointer on root and lock for local process list in cluster
  • trunk/kernel/kern/core.c

    r657 r669  
    2626#include <hal_kernel_types.h>
    2727#include <hal_special.h>
    28 #include <errno.h>
    2928#include <printk.h>
    3029#include <thread.h>
    3130#include <chdev.h>
     31#include <alarm.h>
    3232#include <dev_pic.h>
    3333#include <rpc.h>
    3434#include <cluster.h>
    3535#include <kmem.h>
    36 #include <dqdt.h>
    3736#include <core.h>
    3837
     
    5251        core->rand_last         = hal_time_stamp() & 0xFFF;
    5352
    54     // initialize scheduler
     53    // initialize the scheduler
    5554        sched_init( core );
     55
     56    // initialise the alarms lock
     57    busylock_init( &core->alarms_lock , LOCK_CORE_ALARMS );
     58
     59    // initialise the alarms list
     60    list_root_init( &core->alarms_root );
    5661}
     62
     63///////////////////////////////////////
     64void core_check_alarms( core_t * core )
     65{
     66    alarm_handler_t * handler;
     67
     68    // get pointer on root of alarms list
     69    list_entry_t * root = &core->alarms_root;
     70
     71    // does nothing if list is empty
     72    if( list_is_empty( root ) ) return;
     73
     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 )
     84    {
     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 );
     90    }
     91}   // end core_check_alarms()
    5792
    5893//////////////////////
     
    73108    }
    74109
    75     assert( false , "core not found" );
     110    assert( __FUNCTION__, false , "core not found" );
     111
     112    return 0;
    76113}
    77114
     
    104141        // handle scheduler
    105142        if( (ticks % CONFIG_SCHED_TICKS_PER_QUANTUM) == 0 ) sched_yield( "TICK");
     143
     144    // handle alarms
     145    core_check_alarms( core );
    106146}
    107147
  • trunk/kernel/kern/core.h

    r657 r669  
    2828#include <kernel_config.h>
    2929#include <hal_kernel_types.h>
     30#include <busylock.h>
    3031#include <list.h>
    3132#include <rpc.h>
     
    3637struct thread_s;
    3738struct chdev_s;
    38 enum   pic_impl_e;
    3939
    4040/****************************************************************************************
     
    5454        uint32_t            time_stamp;     /*! previous time stamp (read from register)   */
    5555
     56    list_entry_t        alarms_root;    /*! root of list of attached alarms            */
     57    busylock_t          alarms_lock;    /*! lock protecting the list of alarms         */
     58
    5659        uint32_t            ticks_nr;       /*! number of elapsed ticks                    */
    5760        uint32_t            usage;          /*! cumulated busy_percent (idle / total)      */
     
    7073 * It makes the association [gid] <=> [lid], as defined in arch_info, via the
    7174 * boot_info_t structure build by the bootloader in each cluster.
    72  * It allocates memory for the PIC infrastructure specific core extension.
    73  * It does NOT initialize the <thread_idle> and the <pic_extend> fields,
    74  * that must be completed later.
     75 * It initializes the core scheduler structures, and the alarms list and lock.
     76 * It allocates memory for the PIC infrastructure specific core extension,
     77 * but it does NOT initialize the <pic_extend> fields, that must be completed later.
    7578 ***************************************************************************************
    7679 * @ core      : pointer on core descriptor to initialise.
     
    8487/***************************************************************************************
    8588 * This function returns the calling core local index (lid), making an associative
    86  * in the local core_tbl[] array based on the hardwired (gid).
     89 * search in the local core_tbl[] array, based on the hardwired (gid).
    8790 ***************************************************************************************
    8891 * @ returns always the lid value.
     
    113116/***************************************************************************************
    114117 * This function must be called at each TICK.
    115  * It updates the  cycles and ticks counter in the calling core descriptor.
    116  * It handles all pending alarms depending on the ticks counter value.
    117  * It handles the scheduling, depending on the ticks counter value.
    118  * It handles the global DQDT update, depending on the ticks counter vakue.
     118 * - it updates the ticks counter in the calling core descriptor.
     119 * - it checks the registered alarms depending on the ticks counter value.
     120 * - it calls the scheduler, depending on the ticks counter value.
    119121 ***************************************************************************************
    120122 * @ core       : pointer on core descriptor.
  • trunk/kernel/kern/do_syscall.c

    r657 r669  
    3737int sys_undefined( void )
    3838{
    39     assert( false , "undefined system call" );
     39    assert( __FUNCTION__, false , "undefined system call" );
    4040    return 0;
    4141}
     
    199199        int  error = 0;
    200200       
    201     assert( (this == CURRENT_THREAD),
     201    assert( __FUNCTION__, (this == CURRENT_THREAD),
    202202    "wrong <this> argument\n" );
    203203
     
    223223
    224224    // check kernel stack overflow
    225     assert( (CURRENT_THREAD->signature == THREAD_SIGNATURE),
     225    assert( __FUNCTION__, (CURRENT_THREAD->signature == THREAD_SIGNATURE),
    226226    "kernel stack overflow after for thread %x in cluster %x\n", CURRENT_THREAD, local_cxy );
    227227
  • trunk/kernel/kern/dqdt.c

    r637 r669  
    119119                                  xptr_t   parent_xp )
    120120{
    121     assert( (level <= 5) , __FUNCTION__, "illegal DQDT level %d\n", level );
     121    assert( __FUNCTION__, (level <= 5) , "illegal DQDT level\n" );
    122122 
    123123    uint32_t node_x;         // node X coordinate
     
    344344    uint32_t    y_size  = cluster->y_size;
    345345
    346     assert( ((x_size <= 16) && (y_size <= 16)) , "illegal mesh size\n");
     346    assert( __FUNCTION__, ((x_size <= 16) && (y_size <= 16)) , "illegal mesh size\n");
    347347 
    348348    // compute level_max
     
    533533    uint32_t      current_level;
    534534
    535 assert( (level <= 5) , __FUNCTION__, "illegal DQDT level %d\n", level );
     535assert( __FUNCTION__, (level <= 5) , "illegal DQDT level\n" );
    536536
    537537#if DEBUG_DQDT_GET_ROOT
  • trunk/kernel/kern/kernel_init.c

    r662 r669  
    140140    "KHM_STATE",             //  6
    141141    "HTAB_STATE",            //  7
    142 
    143     "VFS_CTX",               //  8
    144     "PPM_FREE",              //  9
    145     "THREAD_JOIN",           // 10
    146     "XHTAB_STATE",           // 11
    147     "CHDEV_QUEUE",           // 12
    148     "CHDEV_TXT0",            // 13
    149     "CHDEV_TXTLIST",         // 14
    150     "PAGE_STATE",            // 15
    151     "MUTEX_STATE",           // 16
    152     "CONDVAR_STATE",         // 17
    153     "SEM_STATE",             // 18
    154     "PROCESS_CWD",           // 19
    155     "BARRIER_STATE",         // 20
    156     "LISTEN_SOCKET",         // 21
    157 
    158     "CLUSTER_PREFTBL",       // 22
    159 
    160     "SOCKET_STATE",          // 23
    161     "PPM_DIRTY",             // 24
    162     "CLUSTER_LOCALS",        // 25
    163     "CLUSTER_COPIES",        // 26
    164     "PROCESS_CHILDREN",      // 27
    165     "PROCESS_USERSYNC",      // 28
    166     "PROCESS_FDARRAY",       // 29
    167     "PROCESS_DIR",           // 30
    168     "VMM_VSL",               // 31
    169 
    170     "PROCESS_THTBL",         // 32
    171 
    172     "MAPPER_STATE",          // 33
    173     "VFS_SIZE",              // 34
    174     "VFS_FILE",              // 35
    175     "VFS_MAIN",              // 36
    176     "FATFS_FAT",             // 37
    177     "FBF_WINDOWS",           // 38
     142    "CORE_ALARMS",           //  8
     143
     144    "VFS_CTX",               //  9
     145    "PPM_FREE",              // 10
     146    "THREAD_JOIN",           // 11
     147    "XHTAB_STATE",           // 12
     148    "CHDEV_QUEUE",           // 13
     149    "CHDEV_TXT0",            // 14
     150    "CHDEV_TXTLIST",         // 15
     151    "PAGE_STATE",            // 16
     152    "MUTEX_STATE",           // 17
     153    "CONDVAR_STATE",         // 18
     154    "SEM_STATE",             // 19
     155    "PROCESS_CWD",           // 20
     156    "BARRIER_STATE",         // 21
     157    "LISTEN_SOCKET",         // 22
     158
     159    "CLUSTER_PREFTBL",       // 23
     160
     161    "SOCKET_STATE",          // 24
     162    "PPM_DIRTY",             // 25
     163    "CLUSTER_LOCALS",        // 26
     164    "CLUSTER_COPIES",        // 27
     165    "PROCESS_CHILDREN",      // 28
     166    "PROCESS_USERSYNC",      // 29
     167    "PROCESS_FDARRAY",       // 30
     168    "PROCESS_DIR",           // 31
     169    "VMM_VSL",               // 32
     170
     171    "PROCESS_THTBL",         // 33
     172
     173    "MAPPER_STATE",          // 34
     174    "VFS_SIZE",              // 35
     175    "VFS_FILE",              // 36
     176    "VFS_MAIN",              // 37
     177    "FATFS_FAT",             // 38
     178    "FBF_WINDOWS",           // 39
    178179};       
    179180
     
    303304                                  LOCK_CHDEV_TXT0 );
    304305           
     306            // make TXT specific initialisations
     307            dev_txt_init( &txt0_tx_chdev );                 
     308
    305309            // initialize TXT_RX[0] chdev
    306310            txt0_rx_chdev.func    = func;
     
    313317           
    314318            // make TXT specific initialisations
    315             dev_txt_init( &txt0_tx_chdev );                 
    316319            dev_txt_init( &txt0_rx_chdev );
    317320
     
    12281231
    12291232            hal_remote_s32( XPTR( CONFIG_VFS_ROOT_CXY , &vfs_root_inode_ptr->type ),
    1230                             INODE_TYPE_DIR );
     1233                            FILE_TYPE_DIR );
    12311234
    12321235            hal_remote_spt( XPTR( CONFIG_VFS_ROOT_CXY , &vfs_root_inode_ptr->extend ),
     
    13721375
    13731376// check local FATFS and VFS context copies
    1374 assert( (((fatfs_ctx_t *)vfs_fat_ctx_ptr->extend)->sectors_per_cluster == 8),
    1375 "illegal FATFS context in cluster %x\n", local_cxy );
     1377assert( __FUNCTION__, (((fatfs_ctx_t *)vfs_fat_ctx_ptr->extend)->sectors_per_cluster == 8),
     1378"illegal FATFS context" );
    13761379
    13771380        }
     
    14681471    if( (core_lid == 0) && (local_cxy == 0) )
    14691472    {
    1470        process_init_create();
     1473        process_init_create();
    14711474    }
    14721475
  • trunk/kernel/kern/ksocket.c

    r668 r669  
    3434#include <thread.h>
    3535#include <vfs.h>
     36#include <alarm.h>
     37#include <dev_nic.h>
    3638#include <ksocket.h>
    37 #include <dev_nic.h>
    3839
    3940//////////////////////////////////////////////////////////////////////////////////////
     
    127128}
    128129
     130///////////////////////////////////////////////////////////////////////////////////////////
     131// This static function implements the alarm handler used by a TX client thread to
     132// handle a retransmission timeout for a TX command (ACCEPT / CONNECT / CLOSE / SEND).
     133// The <args_xp> argument is actually an extended pointer on the involved socket.
     134// First, it updates the retransmission timeout. Then, it get the type of TX command,
     135// and request the NIC_TX server thread to re-send the unacknowledged segment.
     136///////////////////////////////////////////////////////////////////////////////////////////
     137// @ args_xp    : extended pointer on the involved socket.
     138///////////////////////////////////////////////////////////////////////////////////////////
     139static void __attribute__((noinline)) socket_alarm_handler( xptr_t args_xp )
     140{
     141    // 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 );
     144
     145    // get relevant infos from socket descriptor
     146    uint32_t   tx_cmd    = hal_remote_l32( XPTR( sock_cxy , &sock_ptr->tx_cmd ));
     147    uint32_t   channel   = hal_remote_l32( XPTR( sock_cxy , &sock_ptr->nic_channel ));
     148    xptr_t     thread_xp = hal_remote_l64( XPTR( sock_cxy , &sock_ptr->tx_client ));
     149
     150assert( __FUNCTION__, (thread_xp != XPTR_NULL),
     151"illegal tx_client field for a retransmission timeout" );
     152
     153    // get TX client thread cluster and local pointer
     154    thread_t * thread_ptr = GET_PTR( thread_xp );
     155    cxy_t      thread_cxy = GET_CXY( thread_xp );
     156
     157assert( __FUNCTION__, (thread_cxy == local_cxy),
     158"the client thread must be running in the same cluster as the alarm handler" );
     159
     160    // get pointers on NIC_TX[index] chdev
     161    xptr_t    tx_chdev_xp  = chdev_dir.nic_tx[channel];
     162    chdev_t * tx_chdev_ptr = GET_PTR( tx_chdev_xp );
     163    cxy_t     tx_chdev_cxy = GET_CXY( tx_chdev_xp );
     164
     165    // get pointers on NIC_TX[channel] server thread
     166    thread_t * tx_server_ptr = hal_remote_lpt( XPTR( tx_chdev_cxy , &tx_chdev_ptr->server ));
     167    xptr_t     tx_server_xp  = XPTR( tx_chdev_cxy , tx_server_ptr );
     168
     169    // update the date in alarm
     170    alarm_update( thread_ptr , hal_get_cycles() + TCP_RETRANSMISSION_TIMEOUT );
     171   
     172    //////////////////////////////
     173    if( tx_cmd == CMD_TX_CONNECT ) 
     174    {
     175
     176#if DEBUG_SOCKET_ALARM
     177uint32_t cycle = (uint32_t)hal_get_cycles();
     178printk("\n[%s] rings for TX_CONNECT : request a new SYN segment / cycle %d\n",
     179__FUNCTION__ , cycle );
     180#endif
     181        // set tx_valid to request the NIC_TX server to send a new SYN segment
     182        hal_remote_s32( XPTR( sock_cxy , &sock_ptr->tx_valid ) , true );
     183
     184        // update socket state
     185        hal_remote_s32( XPTR( sock_cxy , &sock_ptr->state ) , TCP_STATE_BOUND );
     186
     187        // unblock the NIC_TX server thread
     188        thread_unblock( tx_server_xp , THREAD_BLOCKED_CLIENT );
     189    }
     190    /////////////////////////////
     191    if( tx_cmd == CMD_TX_ACCEPT ) 
     192    {
     193
     194#if DEBUG_SOCKET_ALARM
     195uint32_t cycle = (uint32_t)hal_get_cycles();
     196printk("\n[%s] rings for TX_ACCEPT : request a new SYN-ACK segment / cycle %d\n",
     197__FUNCTION__ , cycle );
     198#endif
     199        // set tx_valid to request the NIC_TX server to send a new SYN-ACK segment
     200        hal_remote_s32( XPTR( sock_cxy , &sock_ptr->tx_valid ) , true );
     201
     202        // update socket state
     203        hal_remote_s32( XPTR( sock_cxy , &sock_ptr->state ) , TCP_STATE_SYN_RCVD );
     204
     205        // unblock the NIC_TX server thread
     206        thread_unblock( tx_server_xp , THREAD_BLOCKED_CLIENT );
     207    }
     208    ////////////////////////////
     209    if( tx_cmd == CMD_TX_CLOSE )
     210    {
     211
     212#if DEBUG_SOCKET_ALARM
     213uint32_t cycle = (uint32_t)hal_get_cycles();
     214printk("\n[%s] rings for TX_CLOSE : request a new FIN-ACK segment / cycle %d\n",
     215__FUNCTION__ , cycle );
     216#endif
     217        // set tx_valid to request the NIC_TX server to send a new FIN-ACK segment
     218        hal_remote_s32( XPTR( sock_cxy , &sock_ptr->tx_valid ) , true );
     219
     220        // update socket state
     221        hal_remote_s32( XPTR( sock_cxy , &sock_ptr->state ) , TCP_STATE_ESTAB );
     222
     223        // unblock the NIC_TX server thread
     224        thread_unblock( tx_server_xp , THREAD_BLOCKED_CLIENT );
     225    }
     226    ///////////////////////////
     227    if( tx_cmd == CMD_TX_SEND )
     228    {
     229        // TODO build a new TX_SEND command
     230    }
     231}   // 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///////////////////////////////////////////////////////////////////////////////////////////
     239static 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///////////////////////////////////////////////////////////////////////////////////////////
     261static 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}
     269
    129270/////////////////////////////////////////////////////////////////////////////////////////
    130271// This static function registers the socket defined by the <socket_xp> argument into
     
    222363
    223364    // build various TX extended pointers
    224     xptr_t    tx_lock_xp = XPTR( tx_chdev_cxy , &tx_chdev_ptr->wait_lock );
    225     xptr_t    tx_list_xp = XPTR( socket_cxy   , &socket_ptr->tx_list );
     365    xptr_t    tx_lock_xp   = XPTR( tx_chdev_cxy , &tx_chdev_ptr->wait_lock );
     366    xptr_t    tx_list_xp   = XPTR( socket_cxy   , &socket_ptr->tx_list );
     367    xptr_t    tx_list_next = hal_remote_l64( tx_list_xp );
     368    xptr_t    tx_list_pred = hal_remote_l64( tx_list_xp + sizeof(xptr_t) );
    226369
    227370    // get pointers on NIC_RX[channel] chdev
     
    231374
    232375    // build various RX extended pointers
    233     xptr_t    rx_lock_xp = XPTR( rx_chdev_cxy , &rx_chdev_ptr->wait_lock );
    234     xptr_t    rx_list_xp = XPTR( socket_cxy   , &socket_ptr->rx_list );
    235 
    236     // remove socket from the NIC_TX[channel] chdev clients queue
    237     remote_busylock_acquire( tx_lock_xp );
    238     xlist_unlink( tx_list_xp );
    239     remote_busylock_release( tx_lock_xp );
    240 
    241     // remove socket from the NIC_RX[channel] chdev clients queue
    242     remote_busylock_acquire( rx_lock_xp );
    243     xlist_unlink( rx_list_xp );
    244     remote_busylock_release( rx_lock_xp );
     376    xptr_t    rx_lock_xp   = XPTR( rx_chdev_cxy , &rx_chdev_ptr->wait_lock );
     377    xptr_t    rx_list_xp   = XPTR( socket_cxy   , &socket_ptr->rx_list );
     378    xptr_t    rx_list_next = hal_remote_l64( rx_list_xp );
     379    xptr_t    rx_list_pred = hal_remote_l64( rx_list_xp + sizeof(xptr_t) );
     380
     381    // remove socket from the NIC_TX[channel] chdev clients queue if registered
     382    if( (tx_list_next != XPTR_NULL) || (tx_list_pred != XPTR_NULL) )
     383    {
     384        remote_busylock_acquire( tx_lock_xp );
     385        xlist_unlink( tx_list_xp );
     386        remote_busylock_release( tx_lock_xp );
     387    }
     388
     389    // remove socket from the NIC_RX[channel] chdev clients queue if registered
     390    if( (rx_list_next != XPTR_NULL) || (rx_list_pred != XPTR_NULL) )
     391    {
     392        remote_busylock_acquire( rx_lock_xp );
     393        xlist_unlink( rx_list_xp );
     394        remote_busylock_release( rx_lock_xp );
     395    }
    245396
    246397#if DEBUG_SOCKET_LINK
     
    253404}  // end socket_unlink_from_servers()
    254405       
     406/////////////////////////////////////////////////////////////////////////////////////////
     407// This function registers the socket defined by the <socket_xp> argument into the
     408// list of listening sockets rooted in the nic_rx[0] chdev.
     409/////////////////////////////////////////////////////////////////////////////////////////
     410// @ socket_xp   : [in]  extended pointer on socket descriptor
     411/////////////////////////////////////////////////////////////////////////////////////////
     412static void socket_link_to_listen( xptr_t socket_xp )
     413{
     414    // get socket cluster and local pointer
     415    socket_t * socket_ptr = GET_PTR( socket_xp );
     416    cxy_t      socket_cxy = GET_CXY( socket_xp );
     417
     418    // get pointers on NIC_RX[0] chdev
     419    xptr_t    rx0_chdev_xp  = chdev_dir.nic_rx[0];
     420    chdev_t * rx0_chdev_ptr = GET_PTR( rx0_chdev_xp );
     421    cxy_t     rx0_chdev_cxy = GET_CXY( rx0_chdev_xp );
     422   
     423    // build extended pointers on list of listening sockets
     424    xptr_t    rx0_root_xp = XPTR( rx0_chdev_cxy , &rx0_chdev_ptr->ext.nic.root );
     425    xptr_t    rx0_lock_xp = XPTR( rx0_chdev_cxy , &rx0_chdev_ptr->ext.nic.lock );
     426
     427    // build extended pointer on socket rx_list field
     428    xptr_t    list_entry_xp = XPTR( socket_cxy , &socket_ptr->rx_list );
     429
     430    // register socket in listening sockets list
     431    remote_busylock_acquire( rx0_lock_xp );
     432    xlist_add_last( rx0_root_xp , list_entry_xp );
     433    remote_busylock_release( rx0_lock_xp );
     434
     435}  // end socket_link_to_listen()
     436
     437/////////////////////////////////////////////////////////////////////////////////////////
     438// This function removes the socket defined by the <socket_xp> argument from the
     439// list of listening sockets rooted in the nic_rx[0] chdev.
     440/////////////////////////////////////////////////////////////////////////////////////////
     441// @ socket_xp   : [in]  extended pointer on socket descriptor
     442/////////////////////////////////////////////////////////////////////////////////////////
     443static void socket_unlink_from_listen( xptr_t socket_xp )
     444{
     445    // get socket cluster and local pointer
     446    socket_t * socket_ptr = GET_PTR( socket_xp );
     447    cxy_t      socket_cxy = GET_CXY( socket_xp );
     448
     449    // get pointers on NIC_RX[0] chdev
     450    xptr_t    rx0_chdev_xp  = chdev_dir.nic_rx[0];
     451    chdev_t * rx0_chdev_ptr = GET_PTR( rx0_chdev_xp );
     452    cxy_t     rx0_chdev_cxy = GET_CXY( rx0_chdev_xp );
     453   
     454    // build extended pointers on lock protecting list of listening sockets
     455    xptr_t    rx0_lock_xp = XPTR( rx0_chdev_cxy , &rx0_chdev_ptr->ext.nic.lock );
     456
     457    // build extended pointer on socket rx_list field
     458    xptr_t    list_entry_xp = XPTR( socket_cxy , &socket_ptr->rx_list );
     459
     460    // register socket in listening sockets list
     461    remote_busylock_acquire( rx0_lock_xp );
     462    xlist_unlink( list_entry_xp );
     463    remote_busylock_release( rx0_lock_xp );
     464
     465}  // end socket_unlink_from_listen()
     466
    255467/////////////////////////////////////////////////////////////////////////////////////////
    256468// This static function is called by the socket_build() and socket_accept() functions.
     
    276488                              uint32_t  * fdid_ptr )
    277489{
    278     uint32_t    fdid;
    279 
    280     thread_t  * this    = CURRENT_THREAD;
    281     process_t * process = this->process;
    282 
     490    uint32_t       fdid;
    283491    kmem_req_t     req;
    284492    socket_t     * socket;
     
    287495    error_t        error;
    288496
     497    thread_t  * this    = CURRENT_THREAD;
     498    process_t * process = this->process;
     499
    289500#if DEBUG_SOCKET_CREATE
    290501uint32_t cycle = (uint32_t)hal_get_cycles();
     
    294505#endif
    295506   
    296     // allocate memory for socket descriptor
     507    // 1. allocate memory for socket descriptor
    297508    req.type   = KMEM_KCM;
    298509    req.order  = bits_log2( sizeof(socket_t) );
     
    307518    }
    308519
    309     // allocate memory for rx_buf buffer
     520    // 2. allocate memory for rx_buf buffer
    310521    error = remote_buf_init( XPTR( cxy , &socket->rx_buf ),
    311                              NIC_RX_BUF_SIZE );
     522                             bits_log2( CONFIG_SOCK_RX_BUF_SIZE ) );
    312523
    313524    if( error )
     
    321532    }
    322533
    323     // allocate memory for r2tq queue
     534    // 3. allocate memory for r2tq queue
    324535    error = remote_buf_init( XPTR( cxy , &socket->r2tq ),
    325                              NIC_R2T_QUEUE_SIZE );
     536                             bits_log2( CONFIG_SOCK_R2T_BUF_SIZE ) );
    326537    if( error )
    327538    {
    328539        printk("\n[ERROR] in %s : cannot allocate R2T queue / thread[%x,%x]\n",
    329540        __FUNCTION__, process->pid, this->trdid );
    330         remote_buf_destroy( XPTR( cxy , &socket->rx_buf ) );
     541        remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) );
    331542        req.type = KMEM_KCM;
    332543        req.ptr  = socket;
     
    337548    // don't allocate memory for crqq queue, as it is done by the socket_listen function
    338549
    339     //  allocate memory for file descriptor
     550    //  4. allocate memory for file descriptor
    340551        req.type  = KMEM_KCM;
    341552        req.order = bits_log2( sizeof(vfs_file_t) );
     
    347558        printk("\n[ERROR] in %s : cannot allocate file descriptor / thread[%x,%x]\n",
    348559        __FUNCTION__, process->pid, this->trdid );
    349         remote_buf_destroy( XPTR( cxy , &socket->r2tq ) );
    350         remote_buf_destroy( XPTR( cxy , &socket->rx_buf ) );
     560        remote_buf_release_data( XPTR( cxy , &socket->r2tq ) );
     561        remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) );
    351562        req.type = KMEM_KCM;
    352563        req.ptr  = socket;
     
    355566    }
    356567   
    357     // get an fdid value, and register file descriptor in fd_array[]
     568    // 5. get an fdid value, and register file descriptor in fd_array[]
    358569    error = process_fd_register( process->ref_xp,
    359570                                 XPTR( cxy , file ),
     
    366577        req.ptr  = file;
    367578        kmem_free( &req );
    368         remote_buf_destroy( XPTR( cxy , &socket->r2tq ) );
    369         remote_buf_destroy( XPTR( cxy , &socket->rx_buf ) );
     579        remote_buf_release_data( XPTR( cxy , &socket->r2tq ) );
     580        remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) );
    370581        req.ptr  = socket;
    371582        kmem_free( &req );
     
    388599
    389600    // initialize file descriptor
    390     hal_remote_s32( XPTR( cxy , &file->type        ) , INODE_TYPE_SOCK );
     601    hal_remote_s32( XPTR( cxy , &file->type        ) , FILE_TYPE_SOCK );
    391602    hal_remote_spt( XPTR( cxy , &file->socket      ) , socket );
    392     hal_remote_s32( XPTR( cxy , &file->refcount    ) , 1 );
    393603
    394604    // initialize socket lock
     
    414624// It remove the associated file from the reference process fd_array. It unlink the
    415625// socket from the NIC_TX [k] and NIC_RX[k] chdevs. It release all memory allocated
    416 // for the structures associated to the target socket socket : file descriptor,
    417 // socket descriptor, RX buffer, R2T queue, CRQ queue.
     626// for the structures associated to the target socket : file descriptor, socket
     627// descriptor, RX buffer, R2T queue, CRQ queue.
    418628/////////////////////////////////////////////////////////////////////////////////////////
    419629// @ file_xp  : extended pointer on the file descriptor.
     
    427637
    428638// check file_xp argument
    429 assert( (file_xp != XPTR_NULL), "illegal argument\n" );
     639assert( __FUNCTION__, (file_xp != XPTR_NULL), "illegal argument\n" );
    430640
    431641    // get cluster & local pointer for file descriptor
    432642    vfs_file_t * file_ptr = GET_PTR( file_xp );
    433643    cxy_t        file_cxy = GET_CXY( file_xp );
    434 
    435 #if DEBUG_SOCKET_DESTROY
    436 uint32_t cycle = (uint32_t)hal_get_cycles();
    437 if( DEBUG_SOCKET_DESTROY < cycle )
    438 printk("\n[%s] thread[%x,%x] enter / file[%x,%x] / cycle %d\n",
    439 __FUNCTION__, process->pid, this->trdid, file_cxy, file_ptr, cycle );
    440 #endif
    441644
    442645    // get local pointer for socket and file type
     
    445648   
    446649// check file descriptor type
    447 assert( (file_type == INODE_TYPE_SOCK), "illegal file type\n" );
    448 
    449     // get socket nic_channel and fdid
    450     uint32_t channel = hal_remote_l32( XPTR( file_cxy , &socket_ptr->nic_channel ));
     650assert( __FUNCTION__, (file_type == FILE_TYPE_SOCK), "illegal file type\n" );
     651
     652    // get socket nic_channel, state, pid and fdid
     653    uint32_t state   = hal_remote_l32( XPTR( file_cxy , &socket_ptr->state ));
    451654    uint32_t fdid    = hal_remote_l32( XPTR( file_cxy , &socket_ptr->fdid ));
    452 
    453     // remove socket from NIC_TX & NIC_RX chdev queues when socket is connected
    454     if( channel < LOCAL_CLUSTER->nb_nic_channels )
     655   
     656#if DEBUG_SOCKET_DESTROY
     657uint32_t cycle = (uint32_t)hal_get_cycles();
     658pid_t    pid   = hal_remote_l32( XPTR( file_cxy , &socket_ptr->pid ));
     659if( DEBUG_SOCKET_DESTROY < cycle )
     660printk("\n[%s] thread[%x,%x] enter / file[%x,%x] / cycle %d\n",
     661__FUNCTION__, process->pid, this->trdid, pid, fdid, cycle );
     662#endif
     663
     664    // remove socket from NIC_TX & NIC_RX chdev queues
     665    //  or from the listening sockets list
     666    if( state == TCP_STATE_LISTEN )
     667    {
     668        socket_unlink_from_listen( XPTR( file_cxy , socket_ptr ) );
     669    }
     670    else
    455671    {
    456672        socket_unlink_from_servers( XPTR( file_cxy , socket_ptr ) );
     
    466682
    467683    // release memory allocated for buffers attached to socket descriptor
    468     remote_buf_destroy( XPTR( file_cxy , &socket_ptr->crqq ) );
    469     remote_buf_destroy( XPTR( file_cxy , &socket_ptr->r2tq ) );
    470     remote_buf_destroy( XPTR( file_cxy , &socket_ptr->rx_buf ) );
     684    remote_buf_release_data( XPTR( file_cxy , &socket_ptr->crqq ) );
     685    remote_buf_release_data( XPTR( file_cxy , &socket_ptr->r2tq ) );
     686    remote_buf_release_data( XPTR( file_cxy , &socket_ptr->rx_buf ) );
    471687
    472688    // release memory allocated for socket descriptor
     
    619835                 uint16_t  port )
    620836{
    621     vfs_inode_type_t    file_type;
     837    vfs_file_type_t    file_type;
    622838    socket_t          * socket;
    623839    uint32_t            socket_type;
     
    651867
    652868    // check file descriptor type
    653     if( file_type != INODE_TYPE_SOCK )
     869    if( file_type != FILE_TYPE_SOCK )
    654870    {
    655871        printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x]",
     
    691907    vfs_file_t        * file_ptr;
    692908    cxy_t               file_cxy;
    693     vfs_inode_type_t    file_type;
     909    vfs_file_type_t    file_type;
    694910    socket_t          * socket_ptr;
    695911    uint32_t            socket_type;
     
    726942
    727943    // check file descriptor type
    728     if( file_type != INODE_TYPE_SOCK )
     944    if( file_type != FILE_TYPE_SOCK )
    729945    {
    730946        printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x]\n",
     
    733949    }
    734950
    735     // get relevant infos from <fdid> socket descriptor
     951    // get relevant infos from socket descriptor
    736952    socket_type       = hal_remote_l32( XPTR( file_cxy , &socket_ptr->type ));
    737953    socket_state      = hal_remote_l32( XPTR( file_cxy , &socket_ptr->state ));
     
    755971    }
    756972   
    757     // compute CRQ queue depth : max( crq_depth , NIC_CRQ_QUEUE_SIZE )
    758     uint32_t depth = ( crq_depth > NIC_CRQ_QUEUE_SIZE ) ? crq_depth : NIC_CRQ_QUEUE_SIZE;
     973    // compute CRQ queue depth : max( crq_depth , CONFIG_SOCK_CRQ_BUF_SIZE )
     974    uint32_t depth = ( crq_depth > CONFIG_SOCK_CRQ_BUF_SIZE ) ?
     975                     crq_depth : CONFIG_SOCK_CRQ_BUF_SIZE;
    759976
    760977    // allocate memory for the CRQ queue
    761978    error = remote_buf_init( XPTR( file_cxy , &socket_ptr->crqq ),
    762                                    depth * sizeof(connect_request_t) );
     979                                   bits_log2( depth * sizeof(connect_request_t)) );
    763980    if( error )
    764981    {
     
    771988    hal_remote_s32( XPTR( file_cxy , &socket_ptr->state ) , TCP_STATE_LISTEN );
    772989
    773     // get pointers on NIC_RX[0] chdev
    774     xptr_t    rx0_chdev_xp  = chdev_dir.nic_rx[0];
    775     chdev_t * rx0_chdev_ptr = GET_PTR( rx0_chdev_xp );
    776     cxy_t     rx0_chdev_cxy = GET_CXY( rx0_chdev_xp );
    777    
    778     // build extended pointers on list of listening sockets
    779     xptr_t    rx0_root_xp = XPTR( rx0_chdev_cxy , &rx0_chdev_ptr->ext.nic.root );
    780     xptr_t    rx0_lock_xp = XPTR( rx0_chdev_cxy , &rx0_chdev_ptr->ext.nic.lock );
    781 
    782     // build extended pointer on socket rx_list field
    783     xptr_t    list_entry_xp = XPTR( file_cxy , &socket_ptr->rx_list );
    784 
    785     // register  <fdid> socket in listening sockets list
    786     remote_busylock_acquire( rx0_lock_xp );
    787     xlist_add_last( rx0_root_xp , list_entry_xp );
    788     remote_busylock_release( rx0_lock_xp );
     990    // register socket in the list of listening socket
     991    socket_link_to_listen( XPTR( file_cxy , socket_ptr ) );
    789992
    790993#if DEBUG_SOCKET_LISTEN
     
    8081011    vfs_file_t        * file_ptr;
    8091012    cxy_t               file_cxy;
    810     vfs_inode_type_t    file_type;           // file descriptor type
     1013    vfs_file_type_t    file_type;           // file descriptor type
    8111014    socket_t          * socket_ptr;          // local pointer on remote waiting socket
    8121015    uint32_t            socket_type;         // listening socket type   
     
    8661069
    8671070    // check file descriptor type
    868     if( file_type != INODE_TYPE_SOCK )
     1071    if( file_type != FILE_TYPE_SOCK )
    8691072    {
    8701073        printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x]\n",
     
    9761179        crq_status   = remote_buf_status( crq_xp );
    9771180
    978 assert( (((crq_status > 0) || (cmd_status!= CMD_STS_SUCCESS)) && (cmd_valid == false)),
     1181assert( __FUNCTION__, (((crq_status > 0) || (cmd_status!= CMD_STS_SUCCESS)) && (cmd_valid == false)),
    9791182"illegal socket state when client thread resumes after RX_ACCEPT" );
    9801183
     
    9991202                                    &new_remote_window );
    10001203
    1001 assert( (error == 0),
     1204assert( __FUNCTION__, (error == 0),
    10021205"cannot get a connection request from a non-empty CRQ" );
    10031206
     
    10821285    // unblock NIC_TX server thread
    10831286    thread_unblock( tx_server_xp , THREAD_BLOCKED_CLIENT );
    1084  
     1287 
     1288    // start retransmission timer
     1289    socket_alarm_start( new_socket_xp , TCP_RETRANSMISSION_TIMEOUT );
     1290
    10851291#if DEBUG_SOCKET_ACCEPT
    10861292cycle = (uint32_t)hal_get_cycles();
     
    11001306__FUNCTION__, process->pid, this->trdid, process->pid, new_fdid, cycle );
    11011307#endif
     1308
     1309    // stop retransmission timer
     1310    socket_alarm_stop();
    11021311
    11031312    // get new socket state, tx_valid and tx_sts
     
    11061315    cmd_status = hal_remote_l32( XPTR( new_socket_cxy , &new_socket_ptr->tx_sts ));
    11071316
    1108 assert( (((new_state == TCP_STATE_ESTAB) || (cmd_status != CMD_STS_SUCCESS))
     1317assert( __FUNCTION__, (((new_state == TCP_STATE_ESTAB) || (cmd_status != CMD_STS_SUCCESS))
    11091318        && (cmd_valid == false)),
    11101319"illegal socket state when client thread resumes after TX_ACCEPT" );
     
    11431352                    uint16_t remote_port )
    11441353{
    1145     vfs_inode_type_t    file_type;
    1146     socket_t          * socket_ptr;       // local pointer on thread descriptor
     1354    vfs_file_type_t    file_type;
     1355    xptr_t              socket_xp;        // extended pointer on socket descriptor
     1356    socket_t          * socket_ptr;       // local pointer on socket descriptor
    11471357    volatile uint32_t   socket_state;     // socket state (modified by the NIC_TX thread)
    11481358    uint32_t            socket_type;      // socket type 
     
    11751385    file_type  = hal_remote_l32( XPTR( file_cxy , &file_ptr->type ) );
    11761386    socket_ptr = hal_remote_lpt( XPTR( file_cxy , &file_ptr->socket ) );
     1387    socket_xp  = XPTR( file_cxy , socket_ptr );
    11771388
    11781389#if DEBUG_SOCKET_CONNECT
     
    11841395
    11851396    // check file descriptor type
    1186     if( file_type != INODE_TYPE_SOCK )
     1397    if( file_type != FILE_TYPE_SOCK )
    11871398    {
    11881399        printk("\n[ERROR] in %s : illegal file type %s",
     
    12631474        thread_unblock( tx_server_xp , THREAD_BLOCKED_CLIENT );
    12641475 
     1476        // start retransmission timer
     1477        socket_alarm_start( socket_xp , TCP_RETRANSMISSION_TIMEOUT );
     1478
    12651479#if DEBUG_SOCKET_CONNECT
    12661480cycle = (uint32_t)hal_get_cycles();
     
    12791493__FUNCTION__, pid, trdid, pid, fdid, cycle );
    12801494#endif
     1495
     1496        // stop retransmission timer
     1497        socket_alarm_stop();
    12811498
    12821499        // get socket state, tx_valid and tx_sts
     
    12851502        socket_state = hal_remote_l32( XPTR( file_cxy , &socket_ptr->state ));
    12861503
    1287 assert( (((socket_state == TCP_STATE_ESTAB) || (cmd_status != CMD_STS_SUCCESS))
     1504assert( __FUNCTION__, (((socket_state == TCP_STATE_ESTAB) || (cmd_status != CMD_STS_SUCCESS))
    12881505        && (cmd_valid == false)),
    12891506"illegal socket state when client thread resumes after TX_CONNECT" );
     
    13311548    trdid_t      trdid     = this->trdid;
    13321549
    1333     // get pointer on socket descriptor
    1334     cxy_t        file_cxy    = GET_CXY( file_xp );
    1335     vfs_file_t * file_ptr    = GET_PTR( file_xp );
     1550    // get pointers on socket descriptor
     1551    cxy_t        file_cxy   = GET_CXY( file_xp );
     1552    vfs_file_t * file_ptr   = GET_PTR( file_xp );
    13361553    socket_t   * socket_ptr = hal_remote_lpt( XPTR( file_cxy , &file_ptr->socket ) );
    1337 
    1338 assert( (hal_remote_l32( XPTR( file_cxy , &socket_ptr->fdid )) == fdid),
     1554    xptr_t       socket_xp  = XPTR( file_cxy , socket_ptr );
     1555
     1556assert( __FUNCTION__, (hal_remote_l32( XPTR( file_cxy , &socket_ptr->fdid )) == fdid),
    13391557"unconsistent file_xp & fdid arguments");
    13401558
     
    13801598cycle = (uint32_t)hal_get_cycles();
    13811599if( cycle > DEBUG_DEV_NIC_TX )
    1382 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s / destroy socket / cycle %d\n",
     1600printk("\n[%s] thread[%x,%x] socket[%x,%d] %s => directly destroy socket / cycle %d\n",
    13831601__FUNCTION__, pid, trdid, pid, fdid, socket_state_str( socket_state ), cycle );
    13841602#endif
     
    13961614cycle = (uint32_t)hal_get_cycles();
    13971615if( cycle > DEBUG_DEV_NIC_TX )
    1398 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s / destroy socket / cycle %d\n",
     1616printk("\n[%s] thread[%x,%x] socket[%x,%d] %s => directly destroy socket / cycle %d\n",
    13991617__FUNCTION__, pid, trdid, pid, fdid, socket_state_str( socket_state ), cycle );
    14001618#endif
     
    14201638        hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_valid  ), true );
    14211639       
     1640        // release socket lock
     1641        remote_queuelock_release( socket_lock_xp );
     1642
    14221643        // unblock NIC_TX server thread
    14231644        thread_unblock( tx_server_xp , THREAD_BLOCKED_CLIENT );
    1424  
    1425         // release socket lock
    1426         remote_queuelock_release( socket_lock_xp );
     1645
     1646        // start retransmission timer
     1647        socket_alarm_start( socket_xp , TCP_RETRANSMISSION_TIMEOUT );
    14271648
    14281649#if DEBUG_SOCKET_CLOSE
    14291650cycle = (uint32_t)hal_get_cycles();
    14301651if( DEBUG_SOCKET_CLOSE < cycle )
    1431 printk("\n[%s] thread[%x,%x] socket[%x,%d] blocks on <IO> waiting close / cycle %d \n",
    1432 __FUNCTION__, pid, trdid, pid, fdid, cycle );
    1433 #endif
    1434         // block itself and deschedule
     1652printk("\n[%s] thread[%x,%x] socket[%x,%d] %s => blocks on <IO> waiting close / cycle %d \n",
     1653__FUNCTION__, pid, trdid, pid, fdid, socket_state_str( socket_state ), cycle );
     1654#endif
     1655        // client thread block itself and deschedule
    14351656        thread_block( client_xp , THREAD_BLOCKED_IO );
    14361657        sched_yield( "blocked in close" );
     
    14421663__FUNCTION__, pid, trdid, pid, fdid, cycle );
    14431664#endif
     1665        // stop retransmission timer
     1666        socket_alarm_stop();
     1667
    14441668        // take socket lock
    14451669        remote_queuelock_acquire( socket_lock_xp );
     
    14501674        cmd_valid    = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_valid ) );
    14511675
    1452 assert( (((socket_state == TCP_STATE_CLOSED) || (cmd_status != CMD_STS_SUCCESS))
     1676assert( __FUNCTION__, (((socket_state == TCP_STATE_CLOSED) || (cmd_status != CMD_STS_SUCCESS))
    14531677         && (cmd_valid == false)),
    14541678"illegal socket state when client thread resumes after TX_CLOSE\n"
     
    14831707
    14841708////////////////////////////////////////////////////////////////////////////////////////
    1485 // This static and blocking function is executed by an user thread calling one of the
    1486 // four functions: socket_send() / socket_recv() / socket_sendto() / socket_recvfrom()
     1709// This static function is called by the two functions socket_send() & socket_recv().
    14871710// It can be used for both UDP and TCP sockets.
    14881711////////////////////////////////////////////////////////////////////////////////////////
     
    14911714// @ u_buf     : pointer on user buffer in user space.
    14921715// @ length    : number of bytes.
    1493 // @ explicit  : explicit remote IP address and port when true.
    14941716////////////////////////////////////////////////////////////////////////////////////////
    14951717// Implementation note : The behavior is different for SEND & RECV
     
    15121734                      uint32_t   fdid,
    15131735                      uint8_t  * u_buf,
    1514                       uint32_t   length,
    1515                       bool_t     explicit,
    1516                       uint32_t   explicit_addr,
    1517                       uint32_t   explicit_port )
    1518 {
    1519     vfs_inode_type_t    file_type;       // file descriptor type
     1736                      uint32_t   length )
     1737{
     1738    vfs_file_type_t    file_type;       // file descriptor type
     1739    xptr_t              socket_xp;       // extended pointer on socket descriptor
    15201740    socket_t          * socket_ptr;      // local pointer on socket descriptor
    15211741    uint32_t            socket_state;    // current socket state
     
    15291749    chdev_t           * chdev_ptr;
    15301750    cxy_t               chdev_cxy;
    1531     uint32_t            remote_addr;
    1532     uint32_t            remote_port;
    15331751    uint32_t            buf_status;      // number of bytes in rx_buf
    15341752    int32_t             moved_bytes;     // total number of moved bytes (fot return)
     
    15621780    file_type  = hal_remote_l32( XPTR( file_cxy , &file_ptr->type ) );
    15631781
    1564     // get local pointer on socket
     1782    // get pointers on socket
    15651783    socket_ptr = hal_remote_lpt( XPTR( file_cxy , &file_ptr->socket ) );
     1784    socket_xp  = XPTR( file_cxy , socket_ptr );
    15661785
    15671786    // check file descriptor type
    1568     if( file_type != INODE_TYPE_SOCK )
     1787    if( file_type != FILE_TYPE_SOCK )
    15691788    {
    15701789        printk("\n[ERROR] in %s : illegal file type %s / socket[%x,%d]\n",
     
    15841803    nic_channel  = hal_remote_l32( XPTR( file_cxy , &socket_ptr->nic_channel ));
    15851804
    1586     // handle the explicit remote address and port
    1587     if( socket_type == SOCK_DGRAM )                  // UDP socket
    1588     {
    1589         if( socket_state == UDP_STATE_UNBOUND )
    1590         {
    1591             // release socket lock
    1592             remote_queuelock_release( socket_lock_xp );
    1593                    
    1594             printk("\n[ERROR] in %s : SEND/RECV for socket[%x,%d] in state %s\n",
    1595             __FUNCTION__, process->pid, fdid, socket_state_str(socket_state) );
    1596             return -1;
    1597         }
    1598 
    1599         if( explicit )
    1600         {
    1601             // update remote IP address and port into socket descriptor
    1602             hal_remote_s32( XPTR( file_cxy , &socket_ptr->remote_addr ), explicit_addr );
    1603             hal_remote_s32( XPTR( file_cxy , &socket_ptr->remote_port ), explicit_port );
    1604 
    1605             // update socket state if required
    1606             if( socket_state == UDP_STATE_BOUND )
    1607             {
    1608                 hal_remote_s32( XPTR( file_cxy , &socket_ptr->state ), UDP_STATE_ESTAB );
    1609             }
    1610         }
    1611     }
    1612     else                                            // TCP socket
    1613     {
    1614         if( explicit )
    1615         {
    1616             // get remote IP address and port from socket descriptor
    1617             remote_addr = hal_remote_l32( XPTR( file_cxy , &socket_ptr->remote_addr ));
    1618             remote_port = hal_remote_l32( XPTR( file_cxy , &socket_ptr->remote_port ));
    1619 
    1620             if( (remote_addr != explicit_addr) || (remote_port != explicit_port) )
    1621             {
    1622                 // release socket lock
    1623                 remote_queuelock_release( socket_lock_xp );
    1624                    
    1625                 printk("\n[ERROR] in %s : wrong expliciy access for socket[%x,%d]\n",
    1626                 __FUNCTION__, process->pid, fdid );
    1627                 return -1;
    1628             }
    1629         }
    1630     }
    1631 
    1632     ///////////////////////////////////////////////////////
    1633     if( is_send )                       // TX_SEND command
     1805    /////////////
     1806    if( is_send )                       // SEND command
    16341807    {
    16351808
     
    16961869        thread_unblock( server_xp , THREAD_BLOCKED_CLIENT );
    16971870
     1871        // start retransmission timer
     1872        socket_alarm_start( socket_xp , TCP_RETRANSMISSION_TIMEOUT );
     1873
    16981874#if DEBUG_SOCKET_SEND   
    16991875cycle = (uint32_t)hal_get_cycles();
     
    17121888__FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle );
    17131889#endif
     1890        // stop retransmission timer
     1891        socket_alarm_stop();
     1892
    17141893        // take socket lock
    17151894        remote_queuelock_acquire( socket_lock_xp );
     
    17271906     
    17281907// check SEND command completed when TX client thread resumes
    1729 assert( (((tx_todo == 0) || (cmd_status != CMD_STS_SUCCESS)) && (cmd_valid == false)),
     1908assert( __FUNCTION__, (((tx_todo == 0) || (cmd_status != CMD_STS_SUCCESS)) && (cmd_valid == false)),
    17301909"illegal socket state when client thread resumes after TX_SEND\n"
    17311910" tx_todo = %d / tx_status = %d / tx_valid = %d\n",
     
    17591938        }
    17601939
    1761     }  // end TX_SEND command
    1762 
    1763     ////////////////////////////////////////////////////////
    1764     else                                 // RX_RECV command
     1940    }  // end SEND command
     1941
     1942    ////
     1943    else                                 // RECV command
    17651944    {
    17661945
     
    18372016            buf_status = remote_buf_status( rx_buf_xp );
    18382017       
    1839 assert( (((buf_status != 0) || (cmd_status != CMD_STS_SUCCESS)) && (cmd_valid == false)),
     2018assert( __FUNCTION__, (((buf_status != 0) || (cmd_status != CMD_STS_SUCCESS)) && (cmd_valid == false)),
    18402019"illegal socket state when client thread resumes after RX_RECV\n"
    18412020" buf_status = %d / rx_sts = %d / rx_valid = %d\n",
     
    18912070        return moved_bytes;
    18922071
    1893     }  // end RX_RECV command
     2072    }  // end RECV command
    18942073} // end socket_move_data()
    1895 
    18962074
    18972075///////////////////////////////////
     
    19002078                 uint32_t    length )
    19012079{
    1902     int nbytes = socket_move_data( true,           // SEND
    1903                                    fdid,
    1904                                    u_buf,
    1905                                    length,
    1906                                    false, 0, 0 );  // no explicit remote socket
    1907     return nbytes;
    1908 
     2080    return socket_move_data( true,           // SEND
     2081                             fdid,
     2082                             u_buf,
     2083                             length );
    19092084}  // end socket_send()
    1910 
    1911 /////////////////////////////////////
    1912 int socket_sendto( uint32_t    fdid,
    1913                    uint8_t   * u_buf,
    1914                    uint32_t    length,
    1915                    uint32_t    remote_addr,
    1916                    uint32_t    remote_port )
    1917 {
    1918     int nbytes = socket_move_data( true,          // SEND
    1919                                    fdid,
    1920                                    u_buf,
    1921                                    length,
    1922                                    true,          // explicit remote socket
    1923                                    remote_addr,
    1924                                    remote_port );
    1925     return nbytes;
    1926 
    1927 }  // end socket_sendto()
    19282085
    19292086///////////////////////////////////
     
    19322089                 uint32_t    length )
    19332090{
    1934     int nbytes = socket_move_data( false,          // RECV
    1935                                    fdid,
    1936                                    u_buf,
    1937                                    length,
    1938                                    false, 0, 0 );  // no explicit remote socket
    1939     return nbytes;
    1940 
     2091    return socket_move_data( false,          // RECV
     2092                             fdid,
     2093                             u_buf,
     2094                             length );
    19412095} // end socket_recv()
    1942 
    1943 
    1944 ///////////////////////////////////////
    1945 int socket_recvfrom( uint32_t    fdid,
    1946                      uint8_t   * u_buf,
    1947                      uint32_t    length,
    1948                      uint32_t    remote_addr,
    1949                      uint32_t    remote_port )
    1950 {
    1951     int nbytes = socket_move_data( false,         // RECV
    1952                                    fdid,
    1953                                    u_buf,
    1954                                    length,
    1955                                    true,          // explicit remote socket
    1956                                    remote_addr,
    1957                                    remote_port );
    1958     return nbytes;
    1959 
    1960 }  // end socket_recvfrom()
    19612096
    19622097////////////////////////////////////////////
  • trunk/kernel/kern/ksocket.h

    r668 r669  
    440440 * @ fdid      : [in] file descriptor index identifying the local server socket.
    441441 * @ crq_depth : [in] depth of CRQ queue of pending connection requests.
     442 * @ return 0 if success / return -1 if failure
    442443 ***************************************************************************************/
    443444int socket_listen( uint32_t fdid,
     
    549550
    550551/****************************************************************************************
    551  * This blocking function implements the sendto() syscall.
    552  * It registers the <remote_addr> and <remote_port> arguments in the local socket
    553  * descriptor, and does the same thing as the socket_send() function above,
    554  * but can be called  on an unconnected UDP socket.
    555  ****************************************************************************************
    556  * @ fdid        : [in] file descriptor index identifying the socket.
    557  * @ u_buf       : [in] pointer on buffer containing packet in user space.
    558  * @ length      : [in] packet size in bytes.
    559  * @ remote_addr : [in] destination IP address.
    560  * @ remote_port : [in] destination port.
    561  * @ return number of sent bytes if success / return -1 if failure.
    562  ***************************************************************************************/
    563 int socket_sendto( uint32_t    fdid,
    564                    uint8_t   * u_buf,
    565                    uint32_t    length,
    566                    uint32_t    remote_addr,
    567                    uint32_t    remote_port );
    568 
    569 /****************************************************************************************
    570552 * This blocking function implements the recv() syscall.
    571553 * It is used to receive data that has been stored by the NIC_RX server thread in the
     
    594576
    595577/****************************************************************************************
    596  * This blocking function implements the recvfrom() syscall.
    597  * It registers the <remote_addr> and <remote_port> arguments in the local socket
    598  * descriptor, and does the same thing as the socket_recv() function above,
    599  * but can be called on an unconnected UDP socket.
    600  ****************************************************************************************
    601  * @ fdid        : [in] file descriptor index identifying the socket.
    602  * @ u_buf       : [in] pointer on buffer containing packet in user space.
    603  * @ length      : [in] packet size in bytes.
    604  * @ remote_addr : [in] destination IP address.
    605  * @ remote_port : [in] destination port.
    606  * @ return number of received bytes if success / return -1 if failure.
    607  ***************************************************************************************/
    608 int socket_recvfrom( uint32_t    fdid,
    609                      uint8_t   * u_buf,
    610                      uint32_t    length,
    611                      uint32_t    remote_addr,
    612                      uint32_t    remote_port );
    613 
    614 /****************************************************************************************
    615578 * This blocking function implements the close() syscall for a socket.
    616579 * - For a UDP socket, it simply calls the static socket_destroy() function to release
  • trunk/kernel/kern/printk.c

    r662 r669  
    22 * printk.c - Kernel Log & debug messages API implementation.
    33 *
    4  * authors  Alain Greiner (2016,2017,2018)
     4 * authors  Alain Greiner (2016,2017,2018,2019,2020)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    3434
    3535///////////////////////////////////////////////////////////////////////////////////
    36 //      Extern variables
     36//      Extern
    3737///////////////////////////////////////////////////////////////////////////////////
    3838
    3939extern chdev_directory_t  chdev_dir;  // defined in chdev.h / allocated in kernel_init.c
    4040
    41 /////////////////////////////////////
    42 uint32_t snprintf( char     * string,
    43                    uint32_t   length,
    44                    char     * format, ... )
    45 {
    46 
    47 #define TO_STREAM(x) do { string[ps] = (x); ps++; if(ps==length) return -1; } while(0);
    48 
    49     va_list    args;      // printf arguments
    50     uint32_t   ps;        // pointer to the string buffer
    51 
    52     ps = 0;   
    53     va_start( args , format );
    54 
    55 xprintf_text:
    56 
     41//////////////////////////////////////////////////////////////////////////////////////
     42// 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.
     47// It returns -2 in case of illegal format, it returns -1 if the formated string
     48// exceeds the length argument.
     49//////////////////////////////////////////////////////////////////////////////////////
     50// @ string    : buffer allocated by caller.
     51// @ length    : buffer size in bytes
     52// @ format    : printf like format.
     53// @ args      : va_list of arguments.
     54// @ return string length if success / -1 if buffer too small / -2 if illegal format.
     55//////////////////////////////////////////////////////////////////////////////////////
     56static int32_t format_to_string( char       * string,
     57                                 uint32_t     length,
     58                                 const char * format,
     59                                 va_list    * args )
     60{
     61
     62#define TO_STRING(x) do { string[ps] = (x); ps++; if(ps==length) return -1; } while(0);
     63
     64    uint32_t   ps = 0;        // index in string buffer
     65
     66format_to_string_text:
     67
     68    // handle one character per iteration
    5769    while ( *format != 0 )
    5870    {
     
    6072        {
    6173            format++;
    62             goto xprintf_arguments;
     74            goto format_to_string_arguments;
    6375        }
    6476        else                  // copy one char to string
    6577        {
    66             TO_STREAM( *format );
     78            TO_STRING( *format );
    6779            format++;
    6880        }
    6981    }
    7082
    71     va_end( args );
    72    
    73     // add terminating NUL chracter
    74     TO_STREAM( 0 );
     83    TO_STRING( 0 );
    7584    return ps;
    7685
    77 xprintf_arguments:
     86format_to_string_arguments:
    7887
    7988    {
     
    8493        uint32_t          i;
    8594       
    86         // Ignore fields width and precision
    87         for ( ; (*format >= '0' && *format <= '9') || (*format == '.') ; format++ );
    88 
    8995        switch (*format)
    9096        {
    9197            case ('c'):             // char conversion
    9298            {
    93                 int val = va_arg( args, int );
    94                 buf[0] = val;
     99                int val = va_arg( *args , int );
     100                buf[0] = (char)val;
    95101                pbuf   = buf;
    96102                len    = 1;
    97103                break;
    98104            }
    99             case ('b'):             // excactly 2 digits hexadecimal integer
    100             {
    101                 int  val = va_arg( args, int );
    102                 int  val_lsb = val & 0xF;
    103                 int  val_msb = (val >> 4) & 0xF;
    104                 buf[0] = HexaTab[val_msb];
    105                 buf[1] = HexaTab[val_lsb];
    106                 len  = 2;
    107                 pbuf = buf;
    108                 break;
    109             }
    110105            case ('d'):             // up to 10 digits decimal signed integer
    111106            {
    112                 int val = va_arg( args, int );
     107                int32_t val = va_arg( *args , int32_t );
    113108                if (val < 0)
    114109                {
    115                     TO_STREAM( '-' );
     110                    TO_STRING( '-' );
    116111                    val = -val;
    117112                }
     
    127122            case ('u'):             // up to 10 digits decimal unsigned integer
    128123            {
    129                 uint32_t val = va_arg( args, uint32_t );
    130                 for(i = 0; i < 10; i++)
    131                 {
    132                     buf[9 - i] = HexaTab[val % 10];
    133                     if (!(val /= 10)) break;
    134                 }
    135                 len =  i + 1;
    136                 pbuf = &buf[9 - i];
    137                 break;
    138             }
    139             case ('x'):             // up to 8 digits hexadecimal
    140             case ('l'):             // up to 16 digits hexadecimal
    141             {
    142                 uint32_t imax;
    143                 uint64_t val;
    144                
    145                 if ( *format == 'l' )   // 64 bits
    146                 {
    147                     val = va_arg( args, uint64_t);
    148                     imax = 16;
    149                 }
    150                 else                    // 32 bits
    151                 {
    152                     val = va_arg( args, uint32_t);
    153                     imax = 8;
    154                 }
    155                
    156                 TO_STREAM( '0' );
    157                 TO_STREAM( 'x' );
    158                
    159                 for(i = 0; i < imax; i++)
    160                 {
    161                     buf[(imax-1) - i] = HexaTab[val % 16];
    162                     if (!(val /= 16))  break;
    163                 }
    164                 len =  i + 1;
    165                 pbuf = &buf[(imax-1) - i];
    166                 break;
    167             }
    168             case ('X'):             // exactly 8 digits hexadecimal
    169             {
    170                 uint32_t val = va_arg( args , uint32_t );
    171                 for(i = 0; i < 8; i++)
    172                 {
    173                     buf[7 - i] = HexaTab[val % 16];
    174                     val = (val>>4);
    175                 }
    176                 len =  8;
    177                 pbuf = buf;
    178                 break;
    179             }
    180             case ('s'):             /* string */
    181             {
    182                 char* str = va_arg( args, char* );
    183                 while (str[len]) { len++; }
    184                 pbuf = str;
    185                 break;
    186             }
    187             default:       // unsupported argument type
    188             {
    189                 return -1;
    190             }
    191         }  // end switch on  argument type
    192 
    193         format++;
    194 
    195         // copy argument to string
    196         for( i = 0 ; i < len ; i++ )
    197         {
    198             TO_STREAM( pbuf[i] );
    199         }
    200        
    201         goto xprintf_text;
    202     }
    203 } // end snprintf()
    204 
    205 //////////////////////////////////////////////////////////////////////////////////////
    206 // This static function is called by printk(), assert() and nolock_printk()
    207 // to display a formated string on TXT0, using a busy waiting policy.
    208 //////////////////////////////////////////////////////////////////////////////////////
    209 // @ format    : printf like format.
    210 // @ args      : va_list of arguments.
    211 //////////////////////////////////////////////////////////////////////////////////////
    212 static void kernel_printf( const char * format,
    213                            va_list    * args )
    214 {
    215 
    216 printf_text:
    217 
    218     while (*format)
    219     {
    220         uint32_t i;
    221         for (i = 0 ; format[i] && (format[i] != '%') ; i++);
    222         if (i)
    223         {
    224             dev_txt_sync_write( format, i );
    225             format += i;
    226         }
    227         if (*format == '%')
    228         {
    229             format++;
    230             goto printf_arguments;
    231         }
    232     }
    233 
    234     return;
    235 
    236 printf_arguments:
    237 
    238     {
    239         char      buf[20];
    240         char    * pbuf = NULL;
    241         uint32_t  len  = 0;
    242         static const char HexaTab[] = "0123456789ABCDEF";
    243         uint32_t i;
    244 
    245         switch (*format++)
    246         {
    247             case ('c'):             /* char conversion */
    248             {
    249                 int  val = va_arg( *args , int );
    250                 len = 1;
    251                 buf[0] = (char)val;
    252                 pbuf = &buf[0];
    253                 break;
    254             }
    255             case ('b'):             /* exactly 2 digits hexadecimal */
    256             {
    257                 int  val = va_arg( *args, int );
    258                 int  val_lsb = val & 0xF;
    259                 int  val_msb = (val >> 4) & 0xF;
    260                 buf[0] = HexaTab[val_msb];
    261                 buf[1] = HexaTab[val_lsb];
    262                 len  = 2;
    263                 pbuf = buf;
    264                 break;
    265             }
    266             case ('d'):             /* up to 10 digits signed decimal */
    267             {
    268                 int val = va_arg( *args , int );
    269                 if (val < 0)
    270                 {
    271                     val = -val;
    272                     dev_txt_sync_write( "-" , 1 );
    273                 }
    274                 for(i = 0; i < 10; i++)
    275                 {
    276                     buf[9 - i] = HexaTab[val % 10];
    277                     if (!(val /= 10)) break;
    278                 }
    279                 len =  i + 1;
    280                 pbuf = &buf[9 - i];
    281                 break;
    282             }
    283             case ('u'):             /* up to 10 digits unsigned decimal */
    284             {
    285124                uint32_t val = va_arg( *args , uint32_t );
    286125                for(i = 0; i < 10; i++)
     
    293132                break;
    294133            }
    295             case ('x'):             /* up to 8 digits hexadecimal */
     134            case ('x'):             // up to 8 digits hexad after "0x"
     135            case ('X'):             // exactly 8 digits hexa after "0x"
    296136            {
    297137                uint32_t val = va_arg( *args , uint32_t );
    298                 dev_txt_sync_write( "0x" , 2 );
    299                 for(i = 0; i < 8; i++)
     138                TO_STRING( '0' );
     139                TO_STRING( 'x' );
     140                for(i = 0 ; i < 8 ; i++)
    300141                {
    301142                    buf[7 - i] = HexaTab[val & 0xF];
    302                     if (!(val = (val>>4)))  break;
     143                    if( (*format == 'x') && ((val >> 4) == 0) )  break;
     144                    val = val >> 4;
    303145                }
    304146                len =  i + 1;
     
    306148                break;
    307149            }
    308             case ('X'):             /* exactly 8 digits hexadecimal */
     150            case ('l'):             // up to 16 digits hexa after "0x"
     151            case ('L'):             // exactly 16 digits hexa after "0x"
    309152            {
    310                 uint32_t val = va_arg( *args , uint32_t );
    311                 dev_txt_sync_write( "0x" , 2 );
    312                 for(i = 0; i < 8; i++)
    313                 {
    314                     buf[7 - i] = HexaTab[val & 0xF];
    315                     val = (val>>4);
    316                 }
    317                 len =  8;
    318                 pbuf = buf;
    319                 break;
    320             }
    321             case ('l'):            /* up to 16 digits hexadecimal */
    322             {
    323                 uint64_t val = va_arg( *args , uint64_t );
    324                 dev_txt_sync_write( "0x" , 2 );
    325                 for(i = 0; i < 16; i++)
     153                uint64_t val = (((uint64_t)va_arg( *args, uint32_t)) << 32) |
     154                               ((uint64_t)va_arg( *args, uint32_t));
     155                TO_STRING( '0' );
     156                TO_STRING( 'x' );
     157                for(i = 0 ; i < 16 ; i++)
    326158                {
    327159                    buf[15 - i] = HexaTab[val & 0xF];
    328                     if (!(val = (val>>4)))  break;
     160                    if( (*format == 'l') && ((val >> 4) == 0) )  break;
     161                    val = val >> 4;
    329162                }
    330163                len =  i + 1;
     
    332165                break;
    333166            }
    334             case ('L'):           /* exactly 16 digits hexadecimal */
    335             {
    336                 uint64_t val = va_arg( *args , uint64_t );
    337                 dev_txt_sync_write( "0x" , 2 );
    338                 for(i = 0; i < 16; i++)
    339                 {
    340                     buf[15 - i] = HexaTab[val & 0xF];
    341                     val = (val>>4);
    342                 }
    343                 len =  16;
    344                 pbuf = buf;
    345                 break;
    346             }
    347167            case ('s'):             /* string */
    348168            {
    349169                char* str = va_arg( *args , char* );
    350                 while (str[len])
    351                 {
    352                     len++;
    353                 }
     170                while (str[len]) { len++; }
    354171                pbuf = str;
    355172                break;
    356173            }
    357             default:
     174            default:       // unsupported argument type
    358175            {
    359                 dev_txt_sync_write( "\n[PANIC] in kernel_printf() : illegal format\n", 45 );
     176                return -2;
    360177            }
    361         }
    362 
    363         if( pbuf != NULL ) dev_txt_sync_write( pbuf, len );
     178        }  // end switch on  argument type
     179
     180        format++;
     181
     182        // copy argument sub-string to the string buffer
     183        for( i = 0 ; i < len ; i++ )
     184        {
     185            TO_STRING( pbuf[i] );
     186        }
    364187       
    365         goto printf_text;
    366     }
    367 
    368 }  // end kernel_printf()
     188        goto format_to_string_text;
     189    }
     190}   // end format_to_string()
    369191
    370192//////////////////////////////////
    371193void printk( char * format , ... )
    372194{
     195    char          buffer[CONFIG_PRINTK_BUF_SIZE];
    373196    va_list       args;
     197    int32_t       length;
     198
     199    // build args va_list
     200    va_start( args , format );
    374201
    375202    // get pointers on TXT0 chdev
     
    384211    remote_busylock_acquire( lock_xp );
    385212
    386     // display format on TXT0 in busy waiting mode
    387     va_start( args , format );
    388     kernel_printf( format , &args );
     213    // build a string from format
     214    length = format_to_string( buffer,
     215                      CONFIG_PRINTK_BUF_SIZE,
     216                      format,
     217                      &args );
    389218    va_end( args );
     219
     220    if( length > 0  )        // call TXT driver to display formated string on TXT0
     221    {
     222        dev_txt_sync_write( buffer , length );
     223    }
     224    else if( length == -2 )  // illegal format => display a warning on TXT0
     225    {
     226        thread_t * this = CURRENT_THREAD;
     227
     228        nolock_printk("\n[PANIC] from printk : illegal format\n"
     229                      "thread[%x,%x] on core[%x,%d] at cycle %l\n",
     230                      this->process->pid, this->trdid,
     231                      local_cxy, this->core->lid, hal_get_cycles() );
     232    }
     233    else                     // format too long => display a warning on TXT0
     234    {
     235        thread_t * this = CURRENT_THREAD;
     236
     237        nolock_printk("\n[PANIC] from printk : formated string too long\n"
     238                      "thread[%x,%x] on core[%x,%d] at cycle %l\n",
     239                      this->process->pid, this->trdid,
     240                      local_cxy, this->core->lid, hal_get_cycles() );
     241    }
    390242
    391243    // release TXT0 lock
    392244    remote_busylock_release( lock_xp );
    393 }
     245
     246}   // end printk()
    394247
    395248/////////////////////////////////////////
    396249void nolock_printk( char * format , ... )
    397250{
     251    char          buffer[CONFIG_PRINTK_BUF_SIZE];
    398252    va_list       args;
    399 
    400     // call kernel_printf on TXT0, in busy waiting mode
     253    int32_t       length;
     254
     255    // build args va_list
    401256    va_start( args , format );
    402     kernel_printf( format , &args );
     257
     258    // build a string from format
     259    length = format_to_string( buffer,
     260                      CONFIG_PRINTK_BUF_SIZE,
     261                      format,
     262                      &args );
    403263    va_end( args );
    404 }
    405 
    406 ////////////////////////////////////
    407 void panic( const char * function_name,
    408             uint32_t     line,
    409             cycle_t      cycle,
    410             const char * format,
    411             ... )
    412 {
    413     // get pointers on TXT0 chdev
    414     xptr_t    txt0_xp = chdev_dir.txt_tx[0];
    415     cxy_t     txt0_cxy = GET_CXY(txt0_xp);
    416     chdev_t * txt0_ptr = GET_PTR(txt0_xp);
    417 
    418     // get extended pointer on remote TXT0 lock
    419     xptr_t lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
    420 
    421     // get TXT0 lock
    422     remote_busylock_acquire( lock_xp );
    423 
    424     // get calling thread
    425     thread_t * current = CURRENT_THREAD;
    426 
    427     // print generic infos
    428     nolock_printk("\n\n[PANIC] in %s: line %d | cycle %d\n"
    429                   "core[%x,%d] | thread %x (%x) | process %x (%x)\n",
    430                   function_name, line, (uint32_t)cycle,
    431                   local_cxy, current->core->lid,
    432                   current->trdid, current,
    433                   current->process->pid, current->process );
    434 
    435     // call kernel_printf to print format
    436     va_list args;
    437     va_start(args, format);
    438     kernel_printf(format, &args);
    439     va_end(args);
    440 
    441     // release TXT0 lock
    442     remote_busylock_release( lock_xp );
    443 
    444     // suicide
    445     hal_core_sleep();
    446 }
    447 
    448 //////////////////////////
    449 void puts( char * string )
     264
     265    if( length > 0  )        // call TXT driver to display formated string on TXT0
     266    {
     267        dev_txt_sync_write( buffer , length );
     268    }
     269    else if( length == -2 )  // illegal format => display a warning on TXT0
     270    {
     271        thread_t * this = CURRENT_THREAD;
     272
     273        nolock_printk("\n[PANIC] from print : illegal format\n"
     274                      "thread[%x,%x] on core[%x,%d] at cycle %l\n",
     275                      this->process->pid, this->trdid,
     276                      local_cxy, this->core->lid, hal_get_cycles() );
     277    }
     278    else                  // buffer too small => display a warning on TXT0
     279    {
     280        thread_t * this = CURRENT_THREAD;
     281
     282        nolock_printk("\n[PANIC] from printk : formated string too long\n"
     283                      "thread[%x,%x] on core[%x,%d] at cycle %l\n",
     284                      this->process->pid, this->trdid,
     285                      local_cxy, this->core->lid, hal_get_cycles() );
     286    }
     287
     288}   // end nolock_printk()
     289
     290//////////////////////////////////////
     291void assert( const char   * func_name,
     292             bool_t         expr,
     293             char         * format , ... )
     294{
     295    if( expr == false )
     296    {
     297        thread_t * this  = CURRENT_THREAD;
     298        trdid_t    trdid = this->trdid;
     299        pid_t      pid   = this->process->pid;
     300        uint32_t   lid   = this->core->lid;
     301        uint32_t   cycle = (uint32_t)hal_get_cycles();
     302
     303        char       buffer[CONFIG_PRINTK_BUF_SIZE];
     304        va_list    args;
     305
     306        va_start( args , format );
     307
     308        // build a string from format
     309        int32_t   length = format_to_string( buffer,
     310                                             CONFIG_PRINTK_BUF_SIZE,
     311                                             format,
     312                                             &args );
     313        va_end( args );
     314
     315        if( length > 0  )  // display panic message on TXT0, including formated string
     316        {
     317            printk("\n[ASSERT] in %s / core[%x,%d] / thread[%x,%x] / cycle %d\n       %s\n",
     318            func_name, local_cxy, lid, pid, trdid, cycle, buffer );
     319        }
     320        else              // display minimal panic message on TXT0
     321        {
     322            printk("\n[ASSERT] in %s / core[%x,%d] / thread[%x,%x] / cycle %d\n",
     323            func_name, local_cxy, lid, pid, trdid, cycle );
     324        }
     325    }
     326}   // end assert( __FUNCTION__,)
     327   
     328//////////////////////////////////////
     329int32_t snprintk( char       * buffer,
     330                  uint32_t     size,
     331                  char       * format, ... )
     332{
     333    va_list       args;
     334    int32_t       string_length;
     335
     336    // build args va_list
     337    va_start( args , format );
     338
     339    // build a string from format
     340    string_length = format_to_string( buffer , size , format , &args );
     341    va_end( args );
     342
     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    }
     354}   // end snprintk()
     355
     356////////////////////////////////
     357void puts( const char * string )
    450358{
    451359    uint32_t   n = 0;
     
    459367    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
    460368
    461     // get extended pointer on remote TXT0 lock
    462     xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
    463 
    464     // get TXT0 lock
    465     remote_busylock_acquire( lock_xp );
     369    if( txt0_xp != XPTR_NULL )
     370    {
     371        // get extended pointer on remote TXT0 lock
     372        xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
     373
     374        // display string on TTY0
     375        remote_busylock_acquire( lock_xp );
     376        dev_txt_sync_write( string , n );
     377        remote_busylock_release( lock_xp );
     378    }
     379}   // end puts()
     380
     381///////////////////////////////////////
     382void nolock_puts( const char * string )
     383{
     384    uint32_t   n = 0;
     385
     386    // compute string length
     387    while ( string[n] > 0 ) n++;
    466388
    467389    // display string on TTY0
    468390    dev_txt_sync_write( string , n );
    469 
    470     // release TXT0 lock
    471     remote_busylock_release( lock_xp );
    472 }
     391 
     392}   // end nolock_puts()
     393
    473394
    474395
     
    496417    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
    497418
    498     // get extended pointer on remote TXT0 chdev lock
    499     xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
    500 
    501     // get TXT0 lock
    502     remote_busylock_acquire( lock_xp );
     419    if( txt0_xp != XPTR_NULL )
     420    {
     421        // get extended pointer on remote TXT0 chdev lock
     422        xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
     423
     424        // display buf on TTY0
     425        remote_busylock_acquire( lock_xp );
     426        dev_txt_sync_write( buf , 10 );
     427        remote_busylock_release( lock_xp );
     428    }
     429}   // end putx()
     430
     431////////////////////////////////
     432void nolock_putx( uint32_t val )
     433{
     434    static const char HexaTab[] = "0123456789ABCDEF";
     435
     436    char      buf[10];
     437    uint32_t  c;
     438
     439    buf[0] = '0';
     440    buf[1] = 'x';
     441
     442    // build buffer
     443    for (c = 0; c < 8; c++)
     444    {
     445        buf[9 - c] = HexaTab[val & 0xF];
     446        val = val >> 4;
     447    }
    503448
    504449    // display buf on TTY0
    505450    dev_txt_sync_write( buf , 10 );
    506451
    507     // release TXT0 lock
    508     remote_busylock_release( lock_xp );
    509 }
     452}   // end nilock_putx()
    510453
    511454////////////////////////
     
    525468    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
    526469
    527     // get TXT0 lock
    528     remote_busylock_acquire( lock_xp );
     470    if( txt0_xp != XPTR_NULL )
     471    {
     472        // get TXT0 lock
     473        remote_busylock_acquire( lock_xp );
     474
     475        if (val < 0)
     476        {
     477            val = -val;
     478            dev_txt_sync_write( "-" , 1 );
     479        }
     480
     481        for(i = 0; i < 10 ; i++)
     482        {
     483            buf[9 - i] = HexaTab[val % 10];
     484            if (!(val /= 10)) break;
     485        }
     486
     487        // display buf on TTY0
     488        dev_txt_sync_write( &buf[9-i] , i+1 );
     489
     490        // release TXT0 lock
     491        remote_busylock_release( lock_xp );
     492    }
     493}   // end putd()
     494
     495///////////////////////////////
     496void nolock_putd( int32_t val )
     497{
     498    static const char HexaTab[] = "0123456789ABCDEF";
     499
     500    char      buf[10];
     501    uint32_t  i;
    529502
    530503    if (val < 0)
     
    543516    dev_txt_sync_write( &buf[9-i] , i+1 );
    544517
    545     // release TXT0 lock
    546     remote_busylock_release( lock_xp );
    547 }
     518}   // end nolock_putd()
    548519
    549520/////////////////////////
     
    570541    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
    571542
    572     // get extended pointer on remote TXT0 chdev lock
    573     xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
    574 
    575     // get TXT0 lock
    576     remote_busylock_acquire( lock_xp );
     543    if( txt0_xp != XPTR_NULL )
     544    {
     545        // get extended pointer on remote TXT0 chdev lock
     546        xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
     547
     548        // display string on TTY0
     549        remote_busylock_acquire( lock_xp );
     550        dev_txt_sync_write( buf , 18 );
     551        remote_busylock_release( lock_xp );
     552    }
     553}   // end putl()
     554
     555////////////////////////////////
     556void nolock_putl( uint64_t val )
     557{
     558    static const char HexaTab[] = "0123456789ABCDEF";
     559
     560    char      buf[18];
     561    uint32_t  c;
     562
     563    buf[0] = '0';
     564    buf[1] = 'x';
     565
     566    // build buffer
     567    for (c = 0; c < 16; c++)
     568    {
     569        buf[17 - c] = HexaTab[(unsigned int)val & 0xF];
     570        val = val >> 4;
     571    }
    577572
    578573    // display string on TTY0
    579574    dev_txt_sync_write( buf , 18 );
    580575
    581     // release TXT0 lock
    582     remote_busylock_release( lock_xp );
    583 }
     576}   // end nolock_putl()
    584577
    585578/////////////////////////////
     
    603596    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
    604597
    605     // get TXT0 lock
    606     remote_busylock_acquire( lock_xp );
    607 
    608     // display string on TTY0
    609     nolock_printk("\n***** %s *****\n", string );
    610 
    611     for ( line = 0 , byte = 0 ; line < nlines ; line++ )
    612     {
    613          nolock_printk(" %X | %b %b %b %b | %b %b %b %b | %b %b %b %b | %b %b %b %b |\n",
    614          buffer + byte,
    615          buffer[byte+ 0],buffer[byte+ 1],buffer[byte+ 2],buffer[byte+ 3],
    616          buffer[byte+ 4],buffer[byte+ 5],buffer[byte+ 6],buffer[byte+ 7],
    617          buffer[byte+ 8],buffer[byte+ 9],buffer[byte+10],buffer[byte+11],
    618          buffer[byte+12],buffer[byte+13],buffer[byte+14],buffer[byte+15] );
    619 
    620          byte += 16;
    621     }
    622 
    623     // release TXT0 lock
    624     remote_busylock_release( lock_xp );
    625 }
     598    if( txt0_xp != XPTR_NULL )
     599    {
     600        // get TXT0 lock
     601        remote_busylock_acquire( lock_xp );
     602
     603        // display string on TTY0
     604        nolock_printk("\n***** %s *****\n", string );
     605
     606        for ( line = 0 , byte = 0 ; line < nlines ; line++ )
     607        {
     608            nolock_printk(" %X | %b %b %b %b | %b %b %b %b | %b %b %b %b | %b %b %b %b |\n",
     609            buffer + byte,
     610            buffer[byte+ 0],buffer[byte+ 1],buffer[byte+ 2],buffer[byte+ 3],
     611            buffer[byte+ 4],buffer[byte+ 5],buffer[byte+ 6],buffer[byte+ 7],
     612            buffer[byte+ 8],buffer[byte+ 9],buffer[byte+10],buffer[byte+11],
     613            buffer[byte+12],buffer[byte+13],buffer[byte+14],buffer[byte+15] );
     614
     615            byte += 16;
     616        }
     617
     618        // release TXT0 lock
     619        remote_busylock_release( lock_xp );
     620    }
     621}   // end putb()
    626622
    627623
  • trunk/kernel/kern/printk.h

    r657 r669  
    2626// to display messages on the kernel terminal TXT0, using a busy waiting policy.
    2727// It calls synchronously the TXT0 driver, without descheduling.
     28//
     29// For the formated string, the supported formats are defined below :
     30//   %c : single ascii character (8 bits)
     31//   %d : up to 10 digits decimal integer (32 bits)
     32//   %u : up to 10 digits unsigned decimal (32 bits)
     33//   %x : up to 8 digits hexadecimal integer (32 bits)
     34//   %X : exactly 8 digits hexadecimal integer (32 bits)
     35//   %l : up to 16 digits hexadecimal integer (64 bits)
     36//   %L : exactly 16 digits hexadecimal integer (64 bits)
     37//   %s : NUL terminated character string
    2838///////////////////////////////////////////////////////////////////////////////////
    2939
     
    3747
    3848/**********************************************************************************
    39  * This function build a formatted string.
    40  * The supported formats are defined below :
    41  *   %b : exactly 2 digits hexadecimal integer (8 bits)
    42  *   %c : single ascii character (8 bits)
    43  *   %d : up to 10 digits decimal integer (32 bits)
    44  *   %u : up to 10 digits unsigned decimal (32 bits)
    45  *   %x : up to 8 digits hexadecimal integer (32 bits)
    46  *   %X : exactly 8 digits hexadecimal integer (32 bits)
    47  *   %l : up to 16 digits hexadecimal integer (64 bits)
    48  *   %L : exactly 16 digits hexadecimal integer (64 bits)
    49  *   %s : NUL terminated character string
     49 * These debug functions display a formated string defined by the <format,...>
     50 * argument on the kernel terminal TXT0, with or without taking the TXT0 lock.
    5051 **********************************************************************************
    51  * @ string     : pointer on target buffer (allocated by caller).
    52  * @ length     : target buffer length (number of bytes).
    53  * @ format     : format respecting the printf syntax.
    54  * @ returns the string length (including NUL) if success / return -1 if error.
    55  *********************************************************************************/
    56 uint32_t snprintf( char     * string,
    57                    uint32_t   length,
    58                    char     * format, ... );
    59 
    60 /**********************************************************************************
    61  * This function displays a formatted string on the kernel terminal TXT0,
    62  * after taking the TXT0 lock.
    63  * It uses a busy waiting policy, calling directly the relevant TXT driver,
     52 * Implementation note:
     53 * It uses a buffer allocated in the stack, defined by CONFIG_PRINTK_BUFFER_SIZE.
     54 * It calls the snprintk() function to build a printable string in this buffer,
     55 * and calls directly the dev_txt_sync_write() driver function without using the
     56 * TXT server thread.
     57 * It displays a [PANIC] message on kernel TXT0 terminal if the formated string
     58 * exceeds the buffer size, or if the format is undefined.
    6459 **********************************************************************************
    6560 * @ format     : formatted string.
    6661 *********************************************************************************/
    67 void printk( char* format, ... );
     62void printk       ( char * format, ... );
     63void nolock_printk( char * format, ... );
    6864
    6965/**********************************************************************************
    70  * This function displays a formatted string on the kernel terminal TXT0,
    71  * without taking the TXT0 lock.
    72  * It uses a busy waiting policy, calling directly the relevant TXT driver,
     66 * This debug function displays a [ASSERT] message on kernel TXT0 terminal
     67 * if Boolean expression <expr> is false. It prints a detailed message including:
     68 * - the calling core [cxy,lpid]
     69 * - the calling thread[pid,trdid]
     70 * - the current cycle
     71 * - the <func_name> argument
     72 * - the <string> argument
    7373 **********************************************************************************
    74  * @ format     : formatted string.
     74 * @ func_name  : calling function name.
     75 * @ expr       : Boolean expression to be checked.
     76 * @ format     : formated message argument.
    7577 *********************************************************************************/
    76 void nolock_printk( char* format, ... );
    77 
     78void assert( const char   * func_name,
     79             bool_t         expr,
     80             char         * format , ... );
    7881
    7982/**********************************************************************************
    80  * This function is called in case of kernel panic. It printt a detailed message
    81  * on the TXT0 terminal after taking the TXT0 lock, and call the hal_core_sleep()
    82  * function to block the calling core.  It is used by the assert macro (below).
     83 * This function build a formated string in a buffer defined by the <buffer>
     84 * and <buf_size> arguments, from the format defined by the <format,...> argument.
     85 * This function set the NUL terminating character in target <buffer>.
    8386 **********************************************************************************
    84  * @ file_name     : File where the assert macro was invoked
    85  * @ function_name : Name of the calling function.
    86  * @ line          : Line number where the assert macro was invoked
    87  * @ cycle         : Cycle where the macro was invoked
    88  * @ format        : Formatted string
    89  * ...             : arguments of the format string
    90  *
    91  * See assert macro documentation for information about printed information.
     87 * @ buffer     : pointer on target buffer (allocated by caller).
     88 * @ buf_size   : target buffer length (number of bytes).
     89 * @ format     : format respecting the printf syntax.
     90 * @ returns  string length (not including NUL) if success / -1 if error.
    9291 *********************************************************************************/
    93 void panic( const char * function_name,
    94             uint32_t     line,
    95             cycle_t      cycle,
    96             const char * format,
    97             ... ) __attribute__((__noreturn__));
     92int32_t snprintk( char       * buffer,
     93                  uint32_t     buf_size,
     94                  char       * format, ... );
    9895
    9996/**********************************************************************************
    100  * This macro displays a formated message on kernel TXT0 terminal,
    101  * and forces the calling core in sleeping mode if a Boolean condition is false.
    102  * Actually used to debug the kernel.
    103  *
    104  * Extra information printed by assert:
    105  * - Current thread, process, and core
    106  * - Function name / line number in file / cycle
     97 * These functions displays a non-formated string on TXT0 terminal.
     98 * They are actually used for low level debug, and call directly the TXT driver,
     99 * without using the TXT server thread.
    107100 **********************************************************************************
    108  * @ condition     : condition that must be true.
    109  * @ format        : formatted string
     101 * @ string   : non-formatted, NUL terminated string.
    110102 *********************************************************************************/
    111 #define assert( expr, format, ... )                                               \
    112 {                                                                                 \
    113     uint32_t __line_at_expansion = __LINE__;                                      \
    114     const volatile cycle_t __assert_cycle = hal_get_cycles();                     \
    115     if ( ( expr ) == false )                                                      \
    116     {                                                                             \
    117         panic( __FUNCTION__,                                                      \
    118                __line_at_expansion,                                               \
    119                __assert_cycle,                                                    \
    120                ( format ), ##__VA_ARGS__ );                                       \
    121     }                                                                             \
    122 }
     103void puts( const char * string );
     104void nolock_puts( const char * string );
    123105
    124106/**********************************************************************************
    125  * This debug function displays a non-formated message on TXT0 terminal.
    126  * This function is actually used to debug the assembly level kernel functions.
    127  **********************************************************************************
    128  * @ string   : non-formatted string.
    129  *********************************************************************************/
    130 void puts( char * string );
    131 
    132 /**********************************************************************************
    133  * This debug function displays a 32 bits value in hexadecimal on TXT0 terminal.
    134  * This function is actually used to debug the assembly level kernel functions.
     107 * These functions display a 32 bits value in hexadecimal on TXT0 terminal.
     108 * They are actually used for low level debug, and call directly the TXT driver,
     109 * without using the TXT server thread.
    135110 **********************************************************************************
    136111 * @ val   : 32 bits unsigned value.
    137112 *********************************************************************************/
    138113void putx( uint32_t val );
     114void nolock_putx( uint32_t val );
    139115
    140116/**********************************************************************************
    141  * This debug function displays a 32 bits signed value in decimal on TXT0 terminal.
    142  * This function is actually used to debug the assembly level kernel functions.
     117 * These functions display a 32 bits signed value in decimal on TXT0 terminal.
     118 * They are actually used for low level debug, and call directly the TXT driver,
     119 * without using the TXT server thread.
    143120 **********************************************************************************
    144121 * @ val   : 32 bits signed value.
    145122 *********************************************************************************/
    146123void putd( int32_t val );
     124void nolock_putd( int32_t val );
    147125
    148126/**********************************************************************************
    149  * This debug function displays a 64 bits value in hexadecimal on TXT0 terminal.
    150  * This function is actually used to debug the assembly level kernel functions.
     127 * These functions display a 64 bits value in hexadecimal on TXT0 terminal.
     128 * They are actually used low level debug, and call directly the TXT driver,
     129 * without using the TXT server thread.
    151130 **********************************************************************************
    152131 * @ val   : 64 bits unsigned value.
    153132 *********************************************************************************/
    154133void putl( uint64_t val );
     134void nolock_putl( uint64_t val );
    155135
    156136/**********************************************************************************
  • trunk/kernel/kern/process.c

    r662 r669  
    4141#include <thread.h>
    4242#include <chdev.h>
     43#include <ksocket.h>
    4344#include <list.h>
    4445#include <string.h>
     
    7273process_t * process_alloc( void )
    7374{
     75
     76assert( __FUNCTION__, (sizeof(process_t) < CONFIG_PPM_PAGE_SIZE),
     77"process descriptor exceeds 1 page" );
     78
    7479        kmem_req_t req;
    7580
    76     req.type  = KMEM_KCM;
    77         req.order = bits_log2( sizeof(process_t) );
    78         req.flags = AF_KERNEL;
    79 
     81    req.type  = KMEM_PPM;
     82        req.order = 0;
     83        req.flags = AF_KERNEL | AF_ZERO;
    8084    return kmem_alloc( &req );
    8185}
     
    8690    kmem_req_t  req;
    8791
    88         req.type = KMEM_KCM;
     92        req.type = KMEM_PPM;
    8993        req.ptr  = process;
    9094        kmem_free( &req );
     
    109113    char        rx_path[40];
    110114    char        tx_path[40];
    111     xptr_t      file_xp;
    112     xptr_t      chdev_xp;
    113     chdev_t   * chdev_ptr;
    114     cxy_t       chdev_cxy;
    115115    pid_t       parent_pid;
    116116    vmm_t     * vmm;
     
    211211
    212212        // attach process to TXT
    213         process_txt_attach( process , txt_id );
     213        process_txt_attach( process_xp , txt_id );
    214214
    215215#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
     
    220220#endif
    221221        // build path to TXT_RX[i] and TXT_TX[i] chdevs
    222         snprintf( rx_path , 40 , "/dev/external/txt%d_rx", txt_id );
    223         snprintf( tx_path , 40 , "/dev/external/txt%d_tx", txt_id );
     222        snprintk( rx_path , 40 , "/dev/external/txt%d_rx", txt_id );
     223        snprintk( tx_path , 40 , "/dev/external/txt%d_tx", txt_id );
    224224
    225225        // create stdin pseudo file         
     
    237237        }
    238238
    239 assert( (stdin_id == 0) , "stdin index must be 0" );
     239assert( __FUNCTION__, (stdin_id == 0) , "stdin index must be 0" );
    240240
    241241#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
     
    260260        }
    261261
    262 assert( (stdout_id == 1) , "stdout index must be 1" );
     262assert( __FUNCTION__, (stdout_id == 1) , "stdout index must be 1" );
    263263
    264264#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
     
    283283        }
    284284
    285 assert( (stderr_id == 2) , "stderr index must be 2" );
     285assert( __FUNCTION__, (stderr_id == 2) , "stderr index must be 2" );
    286286
    287287#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
     
    295295    else                                            // normal user process
    296296    {
    297         // get extended pointer on stdin pseudo file in parent process
    298         file_xp = (xptr_t)hal_remote_l64( XPTR( parent_cxy,
    299                                                 &parent_ptr->fd_array.array[0] ) );
    300 
    301         // get extended pointer on parent process TXT chdev
    302         chdev_xp = chdev_from_file( file_xp );
    303  
    304         // get cluster and local pointer on chdev
    305         chdev_cxy = GET_CXY( chdev_xp );
    306         chdev_ptr = GET_PTR( chdev_xp );
    307  
    308         // get parent process TXT terminal index
    309         txt_id = hal_remote_l32( XPTR( chdev_cxy , &chdev_ptr->channel ) );
    310 
    311         // attach child process to parent process TXT terminal
    312         process_txt_attach( process , txt_id );
    313 
    314         // copy all open files from parent process fd_array to this process
    315         process_fd_remote_copy( XPTR( local_cxy , &process->fd_array ),
    316                                 XPTR( parent_cxy , &parent_ptr->fd_array ) );
     297        // get parent process TXT index
     298        txt_id = process_txt_get_index( parent_xp );
     299
     300        // attach child process to same TXT terminal as parent
     301        process_txt_attach( process_xp , txt_id );
     302
     303        // recreate all open files from parent process fd_array to child process fd_array
     304        process_fd_replicate( process_xp , parent_xp );
    317305    }
    318306
    319307    // initialize lock protecting CWD changes
    320     remote_busylock_init( XPTR( local_cxy ,
    321                                 &process->cwd_lock ), LOCK_PROCESS_CWD );
     308    remote_busylock_init( XPTR( local_cxy , &process->cwd_lock ), LOCK_PROCESS_CWD );
    322309
    323310#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
     
    415402
    416403// check user process
    417 assert( (local_process->pid != 0), "LPID cannot be 0" );
     404assert( __FUNCTION__, (local_process->pid != 0), "LPID cannot be 0" );
    418405
    419406    // initialize VSL as empty
     
    520507
    521508// check no more threads
    522 assert( (process->th_nr == 0),
     509assert( __FUNCTION__, (process->th_nr == 0),
    523510"process %x in cluster %x contains threads", pid , local_cxy );
    524511
     
    616603cycle = (uint32_t)hal_get_cycles();
    617604if( DEBUG_PROCESS_DESTROY < cycle )
    618 printk("\n[%s] thread[%x,%x] exit / process %x in cluster %x / cycle %d\n",
     605printk("\n[%s] thread[%x,%x] exit for process %x in cluster %x / cycle %d\n",
    619606__FUNCTION__, this->process->pid, this->trdid, pid, local_cxy, cycle );
    620607#endif
     
    683670
    684671// check action type
    685 assert( ((type == DELETE_ALL_THREADS ) ||
     672assert( __FUNCTION__, ((type == DELETE_ALL_THREADS ) ||
    686673         (type == BLOCK_ALL_THREADS )  ||
    687674         (type == UNBLOCK_ALL_THREADS )), "illegal action type" );
     
    809796
    810797// check target process is an user process
    811 assert( (LPID_FROM_PID( process->pid ) != 0 ),
     798assert( __FUNCTION__, (LPID_FROM_PID( process->pid ) != 0 ),
    812799"process %x is not an user process\n", process->pid );
    813800
     
    894881
    895882// check target process is an user process
    896 assert( (LPID_FROM_PID( process->pid ) != 0),
     883assert( __FUNCTION__, (LPID_FROM_PID( process->pid ) != 0),
    897884"process %x is not an user process\n", process->pid );
    898885
     
    916903            {
    917904                // mark target thread for delete and block it
    918                 thread_delete( target_xp , true );                   // forced
     905                thread_delete_request( target_xp , true );                   // forced
    919906            }
    920907        }
     
    950937
    951938// check target process is an user process
    952 assert( ( LPID_FROM_PID( process->pid ) != 0 ),
     939assert( __FUNCTION__, ( LPID_FROM_PID( process->pid ) != 0 ),
    953940"process %x is not an user process\n", process->pid );
    954941
     
    10271014        xptr_t ref_xp = cluster_get_reference_process_from_pid( pid );
    10281015
    1029         assert( (ref_xp != XPTR_NULL) , "illegal pid\n" );
     1016        assert( __FUNCTION__, (ref_xp != XPTR_NULL) , "illegal pid\n" );
    10301017
    10311018        // allocate memory for local process descriptor
     
    10811068    switch( type )
    10821069    {
    1083         case INODE_TYPE_FILE : return "FILE";
    1084         case INODE_TYPE_DIR  : return "DIR";
    1085         case INODE_TYPE_FIFO : return "FIFO";
    1086         case INODE_TYPE_PIPE : return "PIPE";
    1087         case INODE_TYPE_SOCK : return "SOCK";
    1088         case INODE_TYPE_DEV  : return "DEV";
    1089         case INODE_TYPE_BLK  : return "BLK";
    1090         case INODE_TYPE_SYML : return "SYML";
     1070        case FILE_TYPE_REG : return "FILE";
     1071        case FILE_TYPE_DIR  : return "DIR";
     1072        case FILE_TYPE_FIFO : return "FIFO";
     1073        case FILE_TYPE_PIPE : return "PIPE";
     1074        case FILE_TYPE_SOCK : return "SOCK";
     1075        case FILE_TYPE_DEV  : return "DEV";
     1076        case FILE_TYPE_BLK  : return "BLK";
     1077        case FILE_TYPE_SYML : return "SYML";
    10911078       
    10921079        default              : return "undefined";
     
    11291116
    11301117// check target process is owner process
    1131 assert( (process_xp == hal_remote_l64( XPTR( process_cxy , &process_ptr->owner_xp ) ) ),
     1118assert( __FUNCTION__, (process_xp == hal_remote_l64( XPTR( process_cxy , &process_ptr->owner_xp ) ) ),
    11321119"process must be owner process\n" );
    11331120
     
    11451132    max_xp  = XPTR( process_cxy , &process_ptr->fd_array.max );
    11461133
    1147     // take lock protecting reference fd_array
     1134    // take lock protecting fd_array
    11481135        remote_queuelock_acquire( lock_xp );
    11491136
     
    11581145        entry_xp = hal_remote_l64( XPTR( process_cxy , &process_ptr->fd_array.array[id] ) );
    11591146       
     1147        // take the first empty slot
    11601148        if ( entry_xp == XPTR_NULL )
    11611149        {
     
    11651153            // update max when required
    11661154            if( id > max ) hal_remote_s32( max_xp , id );
    1167 
    1168             // increase file refcount
    1169             vfs_file_count_up( file_xp );
    11701155
    11711156            // exit loop
     
    12081193
    12091194// check target process is owner process
    1210 assert( (process_xp == hal_remote_l64( XPTR( process_cxy , &process_ptr->owner_xp ) ) ),
     1195assert( __FUNCTION__, (process_xp == hal_remote_l64( XPTR( process_cxy , &process_ptr->owner_xp ) ) ),
    12111196"process must be owner process\n" );
    12121197
     
    12531238        // release the fd_array entry in process copy
    12541239        hal_remote_s64( XPTR( copy_cxy , &copy_ptr->fd_array.array[fdid] ), XPTR_NULL );
    1255 
    1256         // decrease file refcount
    1257         vfs_file_count_down( file_xp );
    12581240    }
    12591241
     
    12611243    if( fdid == max ) hal_remote_s32( fd_max_xp , max-1 );
    12621244
    1263     // release the lock protecting reference fd_array
     1245    // release the lock protecting fd_array
    12641246        remote_queuelock_release( fd_lock_xp );
    12651247
     
    12791261void process_fd_clean_all( xptr_t process_xp )
    12801262{
    1281     uint32_t  id;
     1263    uint32_t  fdid;
    12821264    xptr_t    file_xp;         // one fd_array entry
    12831265    xptr_t    lock_xp;         // extendad pointer on lock protecting fd_array
    12841266    uint32_t  max;             // number of registered files
    1285     error_t   error;
    12861267
    12871268    // get process cluster, local pointer and PID
    12881269    process_t * process_ptr = GET_PTR( process_xp );
    12891270    cxy_t       process_cxy = GET_CXY( process_xp );
    1290     pid_t       pid         = hal_remote_l32( XPTR( process_cxy , &process_ptr->pid) );
    12911271
    12921272// check target process is owner process
    1293 assert( (process_xp == hal_remote_l64( XPTR( process_cxy , &process_ptr->owner_xp )) ),
     1273assert( __FUNCTION__, (process_xp == hal_remote_l64( XPTR( process_cxy , &process_ptr->owner_xp )) ),
    12941274"process must be owner process\n" );
    12951275
     
    12981278uint32_t   cycle = (uint32_t)hal_get_cycles();
    12991279if( DEBUG_PROCESS_FD_CLEAN_ALL < cycle )
    1300 printk("\n[%s] thread[%x,%x] enter for process %x / cycle %d\n",
    1301 __FUNCTION__, this->process->pid, this->trdid, pid, cycle );
     1280printk("\n[%s] thread[%x,%x] enter / cycle %d\n",
     1281__FUNCTION__, this->process->pid, this->trdid, cycle );
    13021282
    13031283process_fd_display( process_xp );
     
    13131293        remote_queuelock_acquire( lock_xp );
    13141294
    1315     for ( id = 0; id <= max ; id++ )
     1295    for( fdid = 0 ; fdid <= max ; fdid++ )
    13161296    {
    13171297        // get fd_array entry
    1318         file_xp = hal_remote_l64( XPTR( process_cxy , &process_ptr->fd_array.array[id] ) );
     1298        file_xp = hal_remote_l64( XPTR( process_cxy , &process_ptr->fd_array.array[fdid] ) );
    13191299       
    13201300        if ( file_xp != XPTR_NULL )
    13211301        {
    1322             // close the file or socket
    1323             error = sys_close( id );
    1324 
    1325             if( error )
    1326             printk("/n[ERROR] in %s : cannot close the file %d for process %x\n",
    1327             __FUNCTION__, id, pid );
     1302            vfs_file_t * file_ptr = GET_PTR( file_xp );
     1303            cxy_t        file_cxy = GET_CXY( file_xp );
     1304
     1305            // get file type
     1306            uint32_t file_type = hal_remote_l32( XPTR( file_cxy , &file_ptr->type ));
     1307 
     1308            if( file_type == FILE_TYPE_REG )
     1309            {
     1310                vfs_close( file_xp , fdid );
     1311            }
     1312            if( file_type == FILE_TYPE_SOCK )
     1313            {
     1314                socket_close( file_xp , fdid );
     1315            }
    13281316        }
    13291317    }
     
    13481336    process_t * process_ptr = GET_PTR( process_xp );
    13491337
    1350 assert( (hal_remote_l64( XPTR( process_cxy , &process_ptr->owner_xp )) == process_xp),
     1338assert( __FUNCTION__, (hal_remote_l64( XPTR( process_cxy , &process_ptr->owner_xp )) == process_xp),
    13511339"process_xp argument must be the owner process" );
    13521340
     
    13791367            remote_queuelock_acquire( lock_xp );
    13801368
    1381         // access reference process descriptor
     1369        // access owner process descriptor
    13821370        file_xp = hal_remote_l64( XPTR( owner_cxy , &owner_ptr->fd_array.array[fdid] ) );
    13831371
     
    13861374           // update local fd_array
    13871375            process->fd_array.array[fdid] = file_xp;
    1388        
    1389             // increase file refcount
    1390             vfs_file_count_up( file_xp );
    13911376        }
    13921377
     
    13991384}  // end process_fd_get_xptr_from_local()
    14001385
    1401 ///////////////////////////////////////////
    1402 void process_fd_remote_copy( xptr_t dst_xp,
    1403                              xptr_t src_xp )
    1404 {
    1405     uint32_t fd;
    1406     xptr_t   entry;
    1407 
    1408     // get cluster and local pointer for src fd_array
    1409     cxy_t        src_cxy = GET_CXY( src_xp );
    1410     fd_array_t * src_ptr = GET_PTR( src_xp );
    1411 
    1412     // get cluster and local pointer for dst fd_array
    1413     cxy_t        dst_cxy = GET_CXY( dst_xp );
    1414     fd_array_t * dst_ptr = GET_PTR( dst_xp );
     1386/////////////////////////////////////////
     1387void process_fd_replicate( xptr_t dst_xp,
     1388                           xptr_t src_xp )
     1389{
     1390    uint32_t fdid;      // current file descriptor index
     1391    xptr_t   old_xp;    // extended pointer on a file descriptor (stored in SRC fd_array)
     1392    xptr_t   new_xp;    // extended pointer on a file descriptor (stored in DST fd_array)
     1393    error_t  error;
     1394
     1395    // get cluster and local pointer for SRC process
     1396    cxy_t       src_cxy = GET_CXY( src_xp );
     1397    process_t * src_ptr = GET_PTR( src_xp );
     1398
     1399assert( __FUNCTION__, (src_xp == hal_remote_l64( XPTR( src_cxy , &src_ptr->owner_xp ))),
     1400"src_xp process not in owner cluster" );
     1401
     1402    // get cluster and local pointer for DST fd_array
     1403    cxy_t       dst_cxy = GET_CXY( dst_xp );
     1404    process_t * dst_ptr = GET_PTR( dst_xp );
     1405
     1406assert( __FUNCTION__, (dst_xp == hal_remote_l64( XPTR( dst_cxy , &dst_ptr->owner_xp ))),
     1407"dst_xp process not in owner cluster" );
     1408
     1409    // build extende pointers on SRC fd_array lock and max fields
     1410    xptr_t  src_lock_xp = XPTR( src_cxy , &src_ptr->fd_array.lock );
     1411    xptr_t  src_max_xp  = XPTR( src_cxy , &src_ptr->fd_array.max );
    14151412
    14161413    // get the remote lock protecting the src fd_array
    1417         remote_queuelock_acquire( XPTR( src_cxy , &src_ptr->lock ) );
    1418 
    1419     // loop on all fd_array entries
    1420     for( fd = 0 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ )
     1414        remote_queuelock_acquire( src_lock_xp );
     1415 
     1416    // loop on fd_array entries
     1417    for( fdid = 0 ; fdid <= hal_remote_l32( src_max_xp ) ; fdid++ )
    14211418        {
    1422                 entry = (xptr_t)hal_remote_l64( XPTR( src_cxy , &src_ptr->array[fd] ) );
    1423 
    1424                 if( entry != XPTR_NULL )
     1419                old_xp = (xptr_t)hal_remote_l64( XPTR( src_cxy , &src_ptr->fd_array.array[fdid] ) );
     1420
     1421                if( old_xp != XPTR_NULL )
    14251422                {
    1426             // increment file descriptor refcount
    1427             vfs_file_count_up( entry );
    1428 
    1429                         // copy entry in destination process fd_array
    1430                         hal_remote_s64( XPTR( dst_cxy , &dst_ptr->array[fd] ) , entry );
     1423            // get the existing file descriptor cluster and local pointer
     1424            vfs_file_t * old_ptr = GET_PTR( old_xp );
     1425            cxy_t        old_cxy = GET_CXY( old_xp );
     1426
     1427            // get existing file attributes and local pointer on inode
     1428            uint32_t      attr      = hal_remote_l32( XPTR( old_cxy , &old_ptr->attr ) );
     1429            vfs_inode_t * inode_ptr = hal_remote_lpt( XPTR( old_cxy , &old_ptr->inode ) );
     1430
     1431            // create a new file descriptor in same cluster as the existing one
     1432            error = vfs_file_create( XPTR( old_cxy , inode_ptr ),
     1433                                     attr,
     1434                                     &new_xp );
     1435            if( error )
     1436            {
     1437                printk("\n[ERROR] in %s : cannot create new file\n", __FUNCTION__ );
     1438                return;
     1439            }
     1440
     1441                        // register new_xp in DST fd_array
     1442                        hal_remote_s64( XPTR( dst_cxy , &dst_ptr->fd_array.array[fdid] ) , new_xp );
    14311443                }
    14321444        }
    14331445
    14341446    // release lock on source process fd_array
    1435         remote_queuelock_release( XPTR( src_cxy , &src_ptr->lock ) );
    1436 
    1437 }  // end process_fd_remote_copy()
     1447        remote_queuelock_release( src_lock_xp );
     1448
     1449}  // end process_fd_replicate()
    14381450
    14391451
     
    14971509            file_type = hal_remote_l32( XPTR( file_cxy , &file_ptr->type ));
    14981510
    1499             // get file name for a true file
    1500             if( file_type == INODE_TYPE_FILE )
     1511            // get file name if inode exist
     1512            if( (file_type != FILE_TYPE_PIPE) && (file_type != FILE_TYPE_SOCK) )
    15011513            {
    15021514                // get inode pointers
     
    15071519                vfs_inode_get_name( inode_xp , name );
    15081520
    1509                 // display relevant file decriptor info
    1510                 printk(" - %d : type %s (%s)\n",
    1511                 fdid , process_fd_type_str(file_type), name );
     1521                // display relevant file descriptor info
     1522                printk(" - %d : type %s / ptr %x (%s)\n",
     1523                fdid, process_fd_type_str(file_type), file_ptr, name );
    15121524            }
    1513             else
     1525            else    // PIPE or SOCK types
    15141526            {
    15151527                // display relevant file decriptor info
    1516                 printk(" - %d : type %s\n",
    1517                 fdid , process_fd_type_str(file_type) );
     1528                printk(" - %d : type %s / ptr %x\n",
     1529                fdid , process_fd_type_str(file_type), file_ptr );
    15181530            }
    15191531        }
    15201532        else
    15211533        {
    1522             // display relevant file decriptor info
    15231534            printk(" - %d : empty slot\n",
    15241535            fdid );
     
    15401551 
    15411552// check arguments
    1542 assert( (process != NULL) , "process argument is NULL" );
    1543 assert( (thread != NULL) , "thread argument is NULL" );
     1553assert( __FUNCTION__, (process != NULL) , "process argument is NULL" );
     1554assert( __FUNCTION__, (thread != NULL) , "thread argument is NULL" );
    15441555
    15451556    // get the lock protecting th_tbl for all threads
     
    15801591
    15811592// check thread
    1582 assert( (thread != NULL) , "thread argument is NULL" );
     1593assert( __FUNCTION__, (thread != NULL) , "thread argument is NULL" );
    15831594
    15841595    process_t * process = thread->process;
     
    15941605
    15951606// check th_nr value
    1596 assert( (count > 0) , "process th_nr cannot be 0" );
     1607assert( __FUNCTION__, (count > 0) , "process th_nr cannot be 0" );
    15971608
    15981609    // remove thread from th_tbl[]
     
    16331644
    16341645// check parent process is the reference process
    1635 assert( (parent_process_xp == ref_xp ) ,
     1646assert( __FUNCTION__, (parent_process_xp == ref_xp ) ,
    16361647"parent process must be the reference process" );
    16371648
     
    17111722cycle = (uint32_t)hal_get_cycles();
    17121723if( DEBUG_PROCESS_MAKE_FORK < cycle )
    1713 printk("\n[%s] thread[%x,%x] copied VMM from parent to child / cycle %d\n",
    1714 __FUNCTION__, pid, trdid, cycle );
    1715 hal_vmm_display( XPTR( local_cxy , process ) , true );
     1724{
     1725    printk("\n[%s] thread[%x,%x] copied VMM from parent to child / cycle %d\n",
     1726    __FUNCTION__, pid, trdid, cycle );
     1727    hal_vmm_display( XPTR( local_cxy , process ) , true );
     1728}
    17161729#endif
    17171730
     
    17481761
    17491762// check main thread LTID
    1750 assert( (LTID_FROM_TRDID(thread->trdid) == 0) ,
     1763assert( __FUNCTION__, (LTID_FROM_TRDID(thread->trdid) == 0) ,
    17511764"main thread must have LTID == 0" );
    17521765
     
    18061819}   // end process_make_fork()
    18071820
    1808 /////////////////////////////////////////////////////
    1809 error_t process_make_exec( exec_info_t  * exec_info )
    1810 {
    1811     thread_t       * thread;                  // local pointer on this thread
     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///////////////////////////////////////////////////////////////////////////////////////
     1845error_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
     1860thread_t * this  = CURRENT_THREAD;
     1861uint32_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
     1884if( DEBUG_PROCESS_EXEC_GET_STRINGS < cycle )
     1885printk("\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
     1904if( DEBUG_PROCESS_EXEC_GET_STRINGS < cycle )
     1905printk("\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
     1920if( DEBUG_PROCESS_EXEC_GET_STRINGS < cycle )
     1921printk("\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,
     1924k_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
     1945if( DEBUG_PROCESS_EXEC_GET_STRINGS < cycle )
     1946printk("\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
     1973if( DEBUG_PROCESS_EXEC_GET_STRINGS < cycle )
     1974printk("\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()
     1981
     1982/////////////////////////////////
     1983error_t process_make_exec( void )
     1984{
     1985    thread_t       * this;                    // local pointer on this thread
    18121986    process_t      * process;                 // local pointer on this process
    18131987    pid_t            pid;                     // this process identifier
     1988    trdid_t          trdid;                   // this thread identifier
    18141989    xptr_t           ref_xp;                  // reference process for this process
    18151990        error_t          error;                   // value returned by called functions
    1816     char           * path;                    // path to .elf file
     1991    char           * elf_path;                // path to .elf file
    18171992    xptr_t           file_xp;                 // extended pointer on .elf file descriptor
    18181993    uint32_t         file_id;                 // file index in fd_array
    1819     uint32_t         args_nr;                 // number of main thread arguments
    1820     char          ** args_pointers;           // array of pointers on main thread arguments
    1821 
    1822     // get calling thread, process, pid and ref_xp
    1823     thread  = CURRENT_THREAD;
    1824     process = thread->process;
     1994    vseg_t         * vseg;                    // local pointer on created vseg(s)
     1995    uint32_t         n;                       // index for loops
     1996
     1997    uint32_t         args_nr;                 // actual number of args (from exec_info)
     1998    intptr_t         args_base;               // args vseg base address in user space
     1999    uint32_t         args_size;               // args vseg size (bytes)
     2000
     2001    uint32_t         envs_nr;                 // actual number of envs (from exec_info)
     2002    intptr_t         envs_base;               // envs vseg base address in user space
     2003    uint32_t         envs_size;               // envs vseg size (bytes)
     2004
     2005    // get calling thread, process, pid, trdid, and ref_xp
     2006    this    = CURRENT_THREAD;
     2007    process = this->process;
    18252008    pid     = process->pid;
     2009    trdid   = this->trdid;
    18262010    ref_xp  = process->ref_xp;
    18272011
    1828         // get relevant infos from exec_info
    1829         path          = exec_info->path;
    1830     args_nr       = exec_info->args_nr;
    1831     args_pointers = exec_info->args_pointers;
     2012        // get .elf pathname from exec_info structure
     2013        elf_path      = process->exec_info.path;
    18322014
    18332015#if DEBUG_PROCESS_MAKE_EXEC
    18342016uint32_t cycle = (uint32_t)hal_get_cycles();
    18352017if( DEBUG_PROCESS_MAKE_EXEC < cycle )
    1836 printk("\n[%s] thread[%x,%x] enters for %s / cycle %d\n",
    1837 __FUNCTION__, pid, thread->trdid, path, cycle );
    1838 #endif
    1839 
    1840     // open the file identified by <path>
     2018printk("\n[%s] thread[%x,%x] enters for <%s> / cycle %d\n",
     2019__FUNCTION__, pid, trdid, elf_path, cycle );
     2020#endif
     2021
     2022    // 1. open the file identified by <path>
    18412023    file_xp = XPTR_NULL;
    18422024    file_id = 0xFFFFFFFF;
    18432025        error   = vfs_open( process->vfs_root_xp,
    1844                             path,
     2026                            elf_path,
    18452027                        ref_xp,
    18462028                            O_RDONLY,
     
    18502032        if( error )
    18512033        {
    1852                 printk("\n[ERROR] in %s : failed to open file <%s>\n", __FUNCTION__ , path );
     2034                printk("\n[ERROR] in %s : thread[%x,%x] failed to open file <%s>\n",
     2035        __FUNCTION__, pid, trdid, elf_path );
    18532036                return -1;
    18542037        }
    18552038
    18562039#if (DEBUG_PROCESS_MAKE_EXEC & 1)
    1857 cycle = (uint32_t)hal_get_cycles();
    18582040if( DEBUG_PROCESS_MAKE_EXEC < cycle )
    1859 printk("\n[%s] thread[%x,%x] opened file <%s> / cycle %d\n",
    1860 __FUNCTION__, pid, thread->trdid, path, cycle );
    1861 #endif
    1862 
    1863     // delete all threads other than this main thread in all clusters
     2041printk("\n[%s] thread[%x,%x] opened file <%s>\n",
     2042__FUNCTION__, pid, trdid, elf_path );
     2043#endif
     2044
     2045    // 2. delete all threads other than this main thread in all clusters
    18642046    process_sigaction( pid , DELETE_ALL_THREADS );
    18652047
    18662048#if (DEBUG_PROCESS_MAKE_EXEC & 1)
    1867 cycle = (uint32_t)hal_get_cycles();
    18682049if( DEBUG_PROCESS_MAKE_EXEC < cycle )
    1869 printk("\n[%s] thread[%x,%x] deleted existing threads / cycle %d\n",
    1870 __FUNCTION__, pid, thread->trdid, cycle );
    1871 #endif
    1872 
    1873     // reset calling process VMM
     2050printk("\n[%s] thread[%x,%x] deleted existing threads\n",
     2051__FUNCTION__, pid, trdid );
     2052#endif
     2053
     2054    // 3. reset calling process VMM
    18742055    vmm_user_reset( process );
    18752056
    18762057#if( DEBUG_PROCESS_MAKE_EXEC & 1 )
    1877 cycle = (uint32_t)hal_get_cycles();
    18782058if( DEBUG_PROCESS_MAKE_EXEC < cycle )
    1879 printk("\n[%s] thread[%x,%x] completed VMM reset / cycle %d\n",
    1880 __FUNCTION__, pid, thread->trdid, cycle );
    1881 #endif
    1882 
    1883     // re-initialize the VMM (args/envs vsegs registration)
    1884     error = vmm_user_init( process );
    1885     if( error )
    1886     {
    1887         printk("\n[ERROR] in %s : cannot initialise VMM for %s\n", __FUNCTION__ , path );
    1888         vfs_close( file_xp , file_id );
    1889         // FIXME restore old process VMM [AG]
    1890         return -1;
    1891     }
    1892    
     2059{
     2060    printk("\n[%s] thread[%x,%x] completed VMM reset\n",
     2061    __FUNCTION__, pid, trdid );
     2062    hal_vmm_display( ref_xp , true );
     2063}
     2064#endif
     2065
     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
     2068    args_nr = process->exec_info.args_nr;
     2069
     2070    if( args_nr > 0 )
     2071    {
     2072        // 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;
     2075
     2076        // create and register args vseg in VMM
     2077        vseg = vmm_create_vseg( process,
     2078                                VSEG_TYPE_DATA,
     2079                                args_base,
     2080                                args_size,
     2081                                0,                 // file_offset unused for DATA type
     2082                                0,                 // file_size unused for DATA type
     2083                                XPTR_NULL,         // mapper_xp unused for DATA type
     2084                                0 );               // cxy unused for DATA type
     2085        if( vseg == NULL )
     2086        {
     2087                 printk("\n[ERROR] in %s : thread[%x,%x] cannot get args vseg for <%s>\n",
     2088             __FUNCTION__, pid, trdid, elf_path );
     2089                     return -1;
     2090        }
     2091
    18932092#if( DEBUG_PROCESS_MAKE_EXEC & 1 )
    1894 cycle = (uint32_t)hal_get_cycles();
    18952093if( DEBUG_PROCESS_MAKE_EXEC < cycle )
    1896 printk("\n[%s] thread[%x,%x] registered args/envs vsegs / cycle %d\n",
    1897 __FUNCTION__, pid, thread->trdid, cycle );
    1898 #endif
    1899 
    1900     // register code & data vsegs as well as entry-point in process VMM,
    1901     // and register extended pointer on .elf file in process descriptor
     2094{
     2095    printk("\n[%s] thread[%x,%x] args vseg registered in new process VSL\n",
     2096    __FUNCTION__, pid, trdid );
     2097    hal_vmm_display( ref_xp , true );
     2098}
     2099#endif
     2100        // map all pages for this "args" vseg
     2101        uint32_t fake_attr;   // required for hal_gpt_lock_pte()
     2102        ppn_t    fake_ppn;    // required for hal_gpt_lock_pte()
     2103
     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);
     2108
     2109        for( n = 0 ; n < CONFIG_VMM_ARGS_SIZE ; n++ ) 
     2110        {
     2111            // lock the PTE
     2112            if (hal_gpt_lock_pte( gpt , vpn , &fake_attr , &fake_ppn ) )
     2113            {
     2114                printk("\n[ERROR] in %s : thread[%x,%x] cannot map args vpn %x for <%s>\n",
     2115                __FUNCTION__, pid, trdid, vpn, elf_path );
     2116                        return -1;
     2117            }
     2118
     2119            // map and unlock the PTE
     2120            hal_gpt_set_pte( gpt , vpn + n , attr , ppn + n );
     2121        }
     2122
     2123#if( DEBUG_PROCESS_MAKE_EXEC & 1 )
     2124if( DEBUG_PROCESS_MAKE_EXEC < cycle )
     2125{
     2126    printk("\n[%s] thread[%x,%x] args vseg mapped in new process GPT\n",
     2127    __FUNCTION__, pid, trdid );
     2128    hal_vmm_display( ref_xp , true );
     2129}
     2130#endif
     2131
     2132        // set user space pointers in array of pointers
     2133        char  ** ptr    = process->exec_info.args_pointers;
     2134
     2135        for( n = 0 ; n < args_nr ; n++ )
     2136        {
     2137            ptr[n] = ptr[n] + args_base - (intptr_t)ptr;
     2138        }
     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
     2143    envs_nr = process->exec_info.envs_nr;
     2144
     2145    if( envs_nr > 0 )
     2146    {
     2147        // 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)
     2152    }
     2153
     2154
     2155    // 6. register code & data vsegs, and entry-point in process VMM,
     2156    // register extended pointer on .elf file in process descriptor
    19022157        error = elf_load_process( file_xp , process );
    19032158    if( error )
    19042159        {
    1905                 printk("\n[ERROR] in %s : failed to access <%s>\n", __FUNCTION__ , path );
    1906         vfs_close( file_xp , file_id );
    1907         // FIXME restore old process VMM [AG]
     2160                printk("\n[ERROR] in %s : thread[%x,%x] failed to access <%s>\n",
     2161        __FUNCTION__, pid, trdid, elf_path );
    19082162        return -1;
    19092163        }
    19102164
    19112165#if( DEBUG_PROCESS_MAKE_EXEC & 1 )
    1912 cycle = (uint32_t)hal_get_cycles();
    19132166if( DEBUG_PROCESS_MAKE_EXEC < cycle )
    1914 printk("\n[%s] thread[%x,%x] registered code/data vsegs / cycle %d\n",
    1915 __FUNCTION__, pid, thread->trdid, cycle );
    1916 #endif
    1917 
    1918     // update the existing main thread descriptor... and jump to user code
    1919     error = thread_user_exec( (void *)process->vmm.entry_point,
    1920                               args_nr,
    1921                               args_pointers );
     2167{
     2168    printk("\n[%s] thread[%x,%x] registered code/data vsegs / entry %x\n",
     2169    __FUNCTION__, pid, trdid, process->vmm.entry_point );
     2170    hal_vmm_display( ref_xp , true );
     2171}
     2172#endif
     2173
     2174    // 7. allocate an user stack vseg for main thread
     2175    vseg = vmm_create_vseg( process,
     2176                            VSEG_TYPE_STACK,
     2177                            LTID_FROM_TRDID( trdid ),
     2178                            0,                 // length unused
     2179                            0,                 // file_offset unused
     2180                            0,                 // file_size unused
     2181                            XPTR_NULL,         // mapper_xp unused
     2182                            local_cxy );
     2183    if( vseg == NULL )
     2184    {
     2185            printk("\n[ERROR] in %s : thread[%x,%x] cannot set u_stack vseg for <%s>\n",
     2186        __FUNCTION__, pid, trdid, elf_path );
     2187                return -1;
     2188    }
     2189
     2190#if( DEBUG_PROCESS_MAKE_EXEC & 1 )
     2191if( DEBUG_PROCESS_MAKE_EXEC < cycle )
     2192{
     2193    printk("\n[%s] thread[%x,%x] registered stack vseg\n",
     2194    __FUNCTION__, pid, trdid );
     2195    hal_vmm_display( ref_xp , true );
     2196}
     2197#endif
     2198
     2199    // update user stack in thread descriptor
     2200    this->user_stack_vseg = vseg;
     2201
     2202    // 8. update the main thread descriptor ... and jumps (one way) to user code
     2203    thread_user_exec( args_nr , args_base );
     2204
    19222205    if( error )
    19232206    {
    1924         printk("\n[ERROR] in %s : cannot update main thread for %s\n", __FUNCTION__ , path );
    1925         vfs_close( file_xp , file_id );
    1926         // FIXME restore old process VMM
     2207        printk("\n[ERROR] in %s : thread[%x,%x] cannot update thread for <%s>\n",
     2208        __FUNCTION__ , pid, trdid, elf_path );
    19272209        return -1;
    19282210    }
    19292211
    1930     assert( false, "we should not execute this code");
    1931  
    19322212        return 0;
    19332213
     
    21532433#if(DEBUG_PROCESS_INIT_CREATE & 1)
    21542434if( DEBUG_PROCESS_INIT_CREATE < cycle )
    2155 printk("\n[%s] thread[%x,%x] registered code/data vsegs in VMM\n",
    2156 __FUNCTION__, this->process->pid, this->trdid );
    2157 #endif
    2158 
    2159 #if (DEBUG_PROCESS_INIT_CREATE & 1)
    2160 hal_vmm_display( XPTR( local_cxy , process ) , true );
     2435{
     2436    printk("\n[%s] thread[%x,%x] registered code/data vsegs in VMM\n",
     2437    __FUNCTION__, this->process->pid, this->trdid );
     2438    hal_vmm_display( XPTR( local_cxy , process ) , true );
     2439}
    21612440#endif
    21622441
     
    22912570        txt_file_xp = hal_remote_l64( XPTR( owner_cxy , &owner_ptr->fd_array.array[0] ) );
    22922571
    2293         assert( (txt_file_xp != XPTR_NULL) ,
     2572        assert( __FUNCTION__, (txt_file_xp != XPTR_NULL) ,
    22942573        "process must be attached to one TXT terminal" );
    22952574
     
    23632642    }
    23642643
    2365     assert( false , "no free TXT terminal found" );
     2644    assert( __FUNCTION__, false , "no free TXT terminal found" );
    23662645
    23672646    return -1;
     
    23702649
    23712650/////////////////////////////////////////////
    2372 void process_txt_attach( process_t * process,
    2373                          uint32_t    txt_id )
     2651void process_txt_attach( xptr_t   process_xp,
     2652                         uint32_t txt_id )
    23742653{
    23752654    xptr_t      chdev_xp;     // extended pointer on TXT_RX chdev
     
    23792658    xptr_t      lock_xp;      // extended pointer on list lock in chdev
    23802659
     2660    process_t * process_ptr = GET_PTR(process_xp );
     2661    cxy_t       process_cxy = GET_CXY(process_xp );
     2662
    23812663// check process is in owner cluster
    2382 assert( (CXY_FROM_PID( process->pid ) == local_cxy) ,
     2664assert( __FUNCTION__, (process_xp == hal_remote_l64( XPTR( process_cxy , &process_ptr->owner_xp ))),
    23832665"process descriptor not in owner cluster" );
    23842666
    23852667// check terminal index
    2386 assert( (txt_id < LOCAL_CLUSTER->nb_txt_channels) ,
     2668assert( __FUNCTION__, (txt_id < LOCAL_CLUSTER->nb_txt_channels) ,
    23872669"illegal TXT terminal index" );
    23882670
     
    23992681    remote_busylock_acquire( lock_xp );
    24002682
    2401     // insert process in attached process list
    2402     xlist_add_last( root_xp , XPTR( local_cxy , &process->txt_list ) );
     2683    // insert owner process in list of attached processes to same TXT
     2684    xlist_add_last( root_xp , XPTR( process_cxy , &process_ptr->txt_list ) );
    24032685
    24042686    // release lock protecting list of processes attached to TXT
     
    24102692if( DEBUG_PROCESS_TXT < cycle )
    24112693printk("\n[%s] thread[%x,%x] attached process %x to TXT %d / cycle %d\n",
    2412 __FUNCTION__, this->process->pid, this->trdid, process->pid, txt_id , cycle );
     2694__FUNCTION__, this->process->pid, this->trdid,
     2695hal_remote_l32( XPTR( process_cxy , &process_ptr->pid, txt_id , cycle );
    24132696#endif
    24142697
     
    24332716
    24342717// check process descriptor in owner cluster
    2435 assert( (CXY_FROM_PID( process_pid ) == process_cxy ) ,
     2718assert( __FUNCTION__, (CXY_FROM_PID( process_pid ) == process_cxy ) ,
    24362719"process descriptor not in owner cluster" );
    24372720
     
    24712754
    24722755///////////////////////////////////////////////////
     2756uint32_t process_txt_get_index( xptr_t process_xp )
     2757{
     2758
     2759    // get target process cluster and local pointer
     2760    process_t * process_ptr = GET_PTR( process_xp );
     2761    cxy_t       process_cxy = GET_CXY( process_xp );
     2762
     2763assert( __FUNCTION__, (process_xp == hal_remote_l64( XPTR( process_cxy , &process_ptr->owner_xp))),
     2764"process descriptor not in owner cluster" );
     2765
     2766    // get extended pointer on STDIN pseudo file in owner process descriptor
     2767    xptr_t file_xp = hal_remote_l64( XPTR( process_cxy , &process_ptr->fd_array.array[0]));
     2768
     2769assert( __FUNCTION__, (file_xp != XPTR_NULL),
     2770"STDIN pseudo-file undefined in fd_array for process %x\n",
     2771hal_remote_l32( XPTR( process_cxy , &process_ptr->pid ) ) );
     2772
     2773    // get extended pointer on TXT chdev
     2774    xptr_t chdev_xp = chdev_from_file( file_xp );
     2775 
     2776assert( __FUNCTION__, (chdev_xp != XPTR_NULL),
     2777"chdev undefined for STDIN pseudo-file of process %x\n",
     2778hal_remote_l32( XPTR( process_cxy , &process_ptr->pid ) ) );
     2779
     2780    // get cluster and local pointer on chdev
     2781   cxy_t     chdev_cxy = GET_CXY( chdev_xp );
     2782   chdev_t * chdev_ptr = GET_PTR( chdev_xp );
     2783 
     2784   // get parent TXT terminal index
     2785   return hal_remote_l32( XPTR( chdev_cxy , &chdev_ptr->channel ) );
     2786
     2787}  // end process_txt_get_index()
     2788
     2789///////////////////////////////////////////////////
    24732790void process_txt_set_ownership( xptr_t process_xp )
    24742791{
    24752792    process_t * process_ptr;
    24762793    cxy_t       process_cxy;
    2477     pid_t       process_pid;
    24782794    xptr_t      file_xp;
    24792795    xptr_t      txt_xp;     
     
    24842800    process_cxy = GET_CXY( process_xp );
    24852801    process_ptr = GET_PTR( process_xp );
    2486     process_pid = hal_remote_l32( XPTR( process_cxy , &process_ptr->pid ) );
    24872802
    24882803    // check owner cluster
    2489     assert( (process_cxy == CXY_FROM_PID( process_pid )) ,
     2804    assert( __FUNCTION__, (process_xp == hal_remote_l64( XPTR( process_cxy , &process_ptr->owner_xp ))),
    24902805    "process descriptor not in owner cluster" );
    24912806
     
    25062821uint32_t txt_id = hal_remote_l32( XPTR( txt_cxy , &txt_ptr->channel ) );
    25072822if( DEBUG_PROCESS_TXT < cycle )
    2508 printk("\n[%s] thread[%x,%x] give TXT%d ownership to process %x / cycle %d\n",
    2509 __FUNCTION__, this->process->pid, this->trdid, txt_id, process_pid, cycle );
     2823printk("\n[%s] thread[%x,%x] give TXT%d ownership to process / cycle %d\n",
     2824__FUNCTION__, this->process->pid, this->trdid, txt_id, cycle );
    25102825#endif
    25112826
     
    25412856
    25422857// check owner cluster
    2543 assert( (process_cxy == CXY_FROM_PID( process_pid )) ,
     2858assert( __FUNCTION__, (process_cxy == CXY_FROM_PID( process_pid )) ,
    25442859"process descriptor not in owner cluster" );
    25452860
     
    25952910
    25962911// It must exist a KSH process for each user TXT channel
    2597 assert( (found == true), "KSH process not found for TXT%d", txt_id );
     2912assert( __FUNCTION__, (found == true), "KSH process not found for TXT%d", txt_id );
    25982913
    25992914        }
     
    26712986// check calling thread execute in target process owner cluster
    26722987pid_t process_pid = hal_remote_l32( XPTR( process_cxy , &process_ptr->pid ) );
    2673 assert( (process_cxy == CXY_FROM_PID( process_pid )) ,
     2988assert( __FUNCTION__, (process_cxy == CXY_FROM_PID( process_pid )) ,
    26742989"process descriptor not in owner cluster" );
    26752990
     
    27153030    xptr_t      txt0_lock_xp;
    27163031   
    2717     assert( (txt_id < LOCAL_CLUSTER->nb_txt_channels) ,
     3032    assert( __FUNCTION__, (txt_id < LOCAL_CLUSTER->nb_txt_channels) ,
    27183033    "illegal TXT terminal index" );
    27193034
  • trunk/kernel/kern/process.h

    r662 r669  
    7171 * This structure defines an array of extended pointers on the open file descriptors
    7272 * for a given process. The file descriptors are always stored in the same cluster
    73  * as the inode associated to the file. A free entry in this array contains XPTR_NULL.
     73 * as the object associated to the file descriptor (inode, socket, pipe, etc).
     74 * A free entry in this array contains XPTR_NULL.
    7475 * The array size is defined by the CONFIG_PROCESS_FILE_MAX_NR parameter.
    7576 *
    76  * NOTE: - Only the fd_array[] in the reference process contains the complete list of open
    77  *         files, and is protected by the lock against concurrent access.
    78  *       - the fd_array[] in a process copy is not used.
    79  *         open files to speed the fdid to xptr translation, but the "lock" and "max"
    80  *         fields are not significant for these copies.
     77 * NOTE: - Only the fd_array[] in the owner cluster process contains the complete list
     78 *         of open files, and is protected by the lock against concurrent access.
     79 *       - the fd_array[] in a process copy is only used to speed the fdid -> xptr
     80 *         translation, but the "lock" and "max" fields are not significant in these copies.
    8181 *       - The modifications made by the process_fd_register() function are only done
    8282 *         in the owner cluster.
    8383 *       - The modifications made by the process_fd_remove() function are done in the
    8484 *         owner cluster, and in all process_copies.
    85  *       - In case of miss on the local fd_array, the process_fd_get_xptr() access the
     85 *       - In case of miss on a local fd_array, the process_fd_get_xptr() access the
    8686 *         owner cluster fd_array, and update the fd_array local copy.
    8787 ********************************************************************************************/
     
    9494}
    9595fd_array_t;
     96
     97/*********************************************************************************************
     98 * This structure defines the information required by the process_make_exec() function
     99 * 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.
     102 *
     103 * It contains three parts:
     104 * - the "path" field is a string defining the pathname of the .elf file.
     105 * - the "args_pointers" & "args_nr" fields define the arguments (one arg == one string).
     106 * - the "envs_pointers" & "envs_nr" fields define the env variables (one env == one string).
     107 *
     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 :
     112 * - in the first bytes, a fixed size kernel array of pointers on the strings.
     113 * - 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.
     122 ********************************************************************************************/
     123
     124typedef struct exec_info_s
     125{
     126    char           path[CONFIG_VFS_MAX_PATH_LENGTH];  /*! .elf file path in kernel space    */
     127
     128    char        ** args_pointers;  /*! pointer on array of pointers on strings              */
     129    uint32_t       args_nr;        /*! actual number of arguments                           */
     130
     131    char        ** envs_pointers;  /*! pointer on array of pointers on strings              */
     132    uint32_t       envs_nr;        /*! actual number of environment variables               */
     133    char         * envs_buf_free;  /*! local pointer on first free slot in strings buffer   */
     134}
     135exec_info_t;
    96136
    97137/*********************************************************************************************
     
    112152 *    are actually use as read-only caches.
    113153 * 3) the <fd_array>, containing extended pointers on the open file descriptors, is only
    114  *    complete in the reference process cluster, other copies are read-only caches.
     154 *    complete in the owner process cluster, other copies are read-only caches.
    115155 * 4) The <sem_root>, <mutex_root>, <barrier_root>, <condvar_root>, and the associated
    116156 *    <sync_lock>, dynamically allocated, are only defined in the reference cluster.
     
    129169    fd_array_t         fd_array;         /*! embedded open file descriptors array            */
    130170
     171    exec_info_t        exec_info;        /*! embedded structure for args & envs              */
     172
    131173    xptr_t             vfs_root_xp;      /*! extended pointer on VFS root inode              */
    132174    xptr_t             vfs_bin_xp;       /*! extended pointer on .elf file descriptor        */
     
    165207}
    166208process_t;
    167 
    168 /*********************************************************************************************
    169  * This structure defines the information required by the process_make_exec() function
    170  * to create a new reference process descriptor, and the associated main thread.
    171  ********************************************************************************************/
    172 
    173 typedef struct exec_info_s
    174 {
    175     char               path[CONFIG_VFS_MAX_PATH_LENGTH];   /*!  .elf file path              */
    176 
    177     char            ** args_pointers;  /*! physical base address of array of pointers       */
    178     char             * args_buf_base;  /*! physical base address of kernel args buffer      */
    179     uint32_t           args_nr;        /*! actual number of arguments                       */
    180 
    181     char            ** envs_pointers;  /*! physical base address of array of pointers       */
    182     char             * envs_buf_base;  /*! physical base address of kernel args buffer      */
    183     char             * envs_buf_free;  /*! physical address of first free slot in envs_buf  */
    184     uint32_t           envs_nr;        /*! actual number of environment variables           */
    185 }
    186 exec_info_t;
    187209
    188210/***************   Process Descriptor Operations    *****************************************/
     
    393415
    394416/*********************************************************************************************
    395  * This function implements the "exec" system call, and is called by the sys_exec() function.
     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 ********************************************************************************************/
     440error_t process_exec_get_strings( bool_t         is_args,
     441                                  char        ** u_pointers,
     442                                  exec_info_t  * exec_info );
     443
     444/*********************************************************************************************
     445 * This function implements the "execve" system call, and is called by sys_exec() function.
     446 * It must be called by the main thread of the calling "old" process.
     447 * The <exec_info> structure in process descriptor contains all informations required
     448 * to update both the calling process descriptor and the calling thread descriptor.
    396449 * The "new" process keep the "old" process PID and PPID, all open files, and env variables,
    397  * the vfs_root and vfs_cwd, but build a brand new memory image (new VMM from the new .elf).
     450 * the vfs_root and vfs_cwd, but build a brand new memory image (new VMM from the .elf file).
    398451 * It is executed in the local cluster, that becomes both the "owner" and the "reference"
    399452 * cluster for the "new" process.
    400453 *********************************************************************************************
    401  * @ exec_info   : [in]  pointer on the exec_info structure.
     454 * Implementation note:
     455 * It executes the following sequence:
     456 * 1) it creates a file descriptor for the .elf file (pathname in exec_info).
     457 * 2) it deletes all other threads than the main thread, in all clusters.
     458 * 3) it reset the existing VMM (remove all user vsegs).
     459 * 4) it build the "args" user vseg from process exec_info, and registers in the VMM.
     460 * 5) TODO it build the "envs" user vseg from process exec_info, and registers in the VMM.
     461 * 6) it get the "code" and "data" user vsegs from the .elf file, and registers in the VMM.
     462 * 7) it allocates an user "stack" vseg, and registers in the VMM
     463 * 8) it calls thread_user_exec() to complete thread initialisation and jumps to user code.
     464 *********************************************************************************************
    402465 * @ return 0 if success / return non-zero if error.
    403466 ********************************************************************************************/
    404 error_t process_make_exec( exec_info_t * exec_info );
     467error_t process_make_exec( void );
    405468
    406469/*********************************************************************************************
     
    452515 * and return the slot index in the <fdid> buffer.
    453516 * It can be called by any thread in any cluster.
    454  * It takes the lock protecting the fd_array against concurrent accesses.
    455  * Note: we must use the owner process descriptor, because this fd_array must
    456  * contain all files open by a given process.
    457  *********************************************************************************************
    458  * @ process_xp : [in]  extended pointer on client reference process.
     517 * It takes the lock protecting the fd_array against concurrent slot allocations.
     518 * Note: we must use the owner process descriptor, because only this fd_array contains
     519 * all files open by a given process.
     520 *********************************************************************************************
     521 * @ process_xp : [in]  extended pointer on owner process.
    459522 * @ file_xp    : [in]  extended pointer on the file descriptor to be registered.
    460523 * @ fdid       : [out] buffer for allocated fd_array slot index.
     
    470533 * process descriptor, identified by the <process_xp> argument.
    471534 * It can be called by any thread in any cluster.
    472  * It takes the lock protecting the fd_array against concurrent accesses.
     535 * It takes the lock protecting the list of copies.
    473536 * Note: we must use the owner process descriptor, because only this owner cluster contains
    474537 * the complete list of process copies.
     
    523586
    524587/*********************************************************************************************
    525  * This function copies all non-zero entries (other than the three first stdin/stdout/stderr)
    526  * from a remote <src_xp> fd_array, embedded in a process descriptor, to another remote
    527  * <dst_xp> fd_array, embedded in another process descriptor.
    528  * The calling thread can be running in any cluster.
    529  * It takes the lock protecting the reference fd_array against concurrent accesses.
    530  * For each involved file descriptor, the refcount is incremented.
    531  *********************************************************************************************
    532  * @ dst_xp   : extended pointer on the destination fd_array_t.
    533  * @ src_xp   : extended pointer on the source fd_array_t.
    534  ********************************************************************************************/
    535 void process_fd_remote_copy( xptr_t dst_xp,
    536                              xptr_t src_xp );
     588 * This function scans all entries in a fd_array, identified by the <src_xp> argument, that
     589 * must be the process descriptor in owner cluster. For each non-zero entry, it allocates a
     590 * new file descriptor in the cluster containing the involved inode, and registers it in the
     591 * fd_array identified by the <dst_xp> argument, that must also be the process descriptor in
     592 * owner cluster. The calling thread itself can be running in any cluster.
     593 * It takes the lock protecting the <src_xp> fd_array against concurrent accesses.
     594 *********************************************************************************************
     595 * @ dst_xp   : extended pointer on the source process descriptor (in owner cluster).
     596 * @ src_xp   : extended pointer on the destination process descriptor (in owner cluster).
     597 ********************************************************************************************/
     598void process_fd_replicate( xptr_t dst_xp,
     599                           xptr_t src_xp );
    537600
    538601/*********************************************************************************************
     
    598661
    599662/*********************************************************************************************
    600  * This function attach a process, identified by the <process> argument to a TXT terminal,
     663 * This function attach a process, identified by the <process_xp> argument to a TXT terminal,
    601664 * identified by the <txt_id> channel index argument.
    602  * The process descriptor identified by the <process> argument must be in the owner cluster. 
    603  * It insert the process descriptor in the xlist rooted in the TXT_RX device.
     665 * The process descriptor identified by the <process_xp> argument must be in the owner
     666 * cluster. It insert the process descriptor in the xlist rooted in the TXT_RX device.
    604667 * It is called by the process_reference_init() function.
    605668 *********************************************************************************************
    606  * @ process  : local pointer on process descriptor.
    607  * @ txt_id   : TXT channel index.
    608  ********************************************************************************************/
    609 void process_txt_attach( process_t * process,
    610                          uint32_t    txt_id );
     669 * @ process_xp : extended pointer on process descriptor in owner cluster.
     670 * @ txt_id     : TXT channel index.
     671 ********************************************************************************************/
     672void process_txt_attach( xptr_t    process_xp,
     673                         uint32_t  txt_id );
    611674
    612675/*********************************************************************************************
     
    617680 * cluster, but the calling thread can be running in any cluster.
    618681 *********************************************************************************************
    619  * @ process_xp  : extended pointer on process descriptor.
     682 * @ process_xp  : extended pointer on process descriptor in owner cluster.
    620683 ********************************************************************************************/
    621684void process_txt_detach( xptr_t  process_xp );                     
     685
     686/*********************************************************************************************
     687 * This function returns the TXT terminal index allocated to a process identified by the
     688 * <process_xp> argument. The process descriptor identified by the <process_xp> argument
     689 * must be in the owner cluster, but the calling thread can be running in any cluster.
     690 *********************************************************************************************
     691 * @ process_xp  : extended pointer on process descriptor in owner cluster.
     692 ********************************************************************************************/
     693uint32_t process_txt_get_index( xptr_t process_xp );
    622694
    623695/*********************************************************************************************
     
    625697 * ownership of its attached TXT_RX terminal (i.e. put the process in foreground).
    626698 * It can be called by a thread running in any cluster, but the target process descriptor
    627  * must be the process owner.
     699 * must be in the owner cluster.
    628700 *********************************************************************************************
    629701 * @ owner_xp  : extended pointer on process descriptor in owner cluster.
     
    654726
    655727/*********************************************************************************************
    656  * This function returns an extended ponter on the current TXT owner process,
     728 * This function returns an extended pointer on the current TXT owner process,
    657729 * for the TXT terminal identified by the <channel> index.
    658730 *********************************************************************************************
  • trunk/kernel/kern/rpc.c

    r657 r669  
    102102void __attribute__((noinline)) rpc_undefined( xptr_t xp __attribute__ ((unused)) )
    103103{
    104         assert( false , "called in cluster %x", local_cxy );
     104        assert( __FUNCTION__, false , "called in cluster %x", local_cxy );
    105105}
    106106
     
    231231
    232232// response must be available for a blocking RPC
    233 assert( (*rpc->rsp == 0) , "illegal response for RPC %s\n", rpc_str[rpc->index] );
     233assert( __FUNCTION__, (*rpc->rsp == 0) , "illegal response for RPC %s\n", rpc_str[rpc->index] );
    234234
    235235    }
  • trunk/kernel/kern/scheduler.c

    r651 r669  
    8585
    8686// check kernel threads list
    87 assert( (count < sched->k_threads_nr), "bad kernel threads list" );
     87assert( __FUNCTION__, (count < sched->k_threads_nr), "bad kernel threads list" );
    8888
    8989            // get next entry in kernel list
     
    119119
    120120// check user threads list
    121 assert( (count < sched->u_threads_nr), "bad user threads list" );
     121assert( __FUNCTION__, (count < sched->u_threads_nr), "bad user threads list" );
    122122
    123123            // get next entry in user list
     
    196196
    197197// check target thread blocked
    198 assert( (thread->blocked & THREAD_BLOCKED_GLOBAL) , "thread not blocked" );
     198assert( __FUNCTION__, (thread->blocked & THREAD_BLOCKED_GLOBAL) , "thread not blocked" );
    199199 
    200200            // decrement response counter
     
    210210
    211211// check calling thread != target thread
    212 assert( (thread != CURRENT_THREAD) , "calling thread cannot delete itself" );
     212assert( __FUNCTION__, (thread != CURRENT_THREAD) , "calling thread cannot delete itself" );
    213213 
    214214            // get thread process descriptor
     
    287287
    288288// check process descriptor is local kernel process
    289 assert( ( thread->process == &process_zero ) , "illegal process descriptor");
     289assert( __FUNCTION__, ( thread->process == &process_zero ) , "illegal process descriptor");
    290290
    291291            // get thread ltid
     
    322322
    323323// check th_nr value
    324 assert( (process_zero.th_nr > 0) , "kernel process th_nr cannot be 0" );
     324assert( __FUNCTION__, (process_zero.th_nr > 0) , "kernel process th_nr cannot be 0" );
    325325
    326326            // remove thread from process th_tbl[]
     
    495495// This assert should always be true, as this check has been
    496496// done before, by any function that can possibly deschedule...
    497 assert( (current->busylocks == 0),
     497assert( __FUNCTION__, (current->busylocks == 0),
    498498"current thread hold %d busylocks\n", current->busylocks );
    499499
     
    511511
    512512// check next thread kernel_stack overflow
    513 assert( (next->signature == THREAD_SIGNATURE),
     513assert( __FUNCTION__, (next->signature == THREAD_SIGNATURE),
    514514"kernel stack overflow for thread %x on core[%x,%d]", next, local_cxy, lid );
    515515
    516516// check next thread attached to same core as the current thread
    517 assert( (next->core == current->core),
     517assert( __FUNCTION__, (next->core == current->core),
    518518"next_core_lid %d / current_core_lid %d", current->core->lid, next->core->lid );
    519519   
    520520// check next thread not blocked when type != IDLE
    521 assert( ((next->blocked == 0) || (next->type == THREAD_IDLE)) ,
     521assert( __FUNCTION__, ((next->blocked == 0) || (next->type == THREAD_IDLE)) ,
    522522"next thread %x (%s) is blocked on core[%x,%d]",
    523523next->trdid , thread_type_str(next->type) , local_cxy , lid );
  • trunk/kernel/kern/thread.c

    r662 r669  
    3030#include <hal_remote.h>
    3131#include <hal_vmm.h>
     32#include <hal_switch.h>
    3233#include <memcpy.h>
    3334#include <printk.h>
     
    120121
    121122// check type and trdid fields are initialized
    122 assert( (thread->type == type)   , "bad type argument" );
    123 assert( (thread->trdid == trdid) , "bad trdid argument" );
     123assert( __FUNCTION__, (thread->type == type)   , "bad type argument" );
     124assert( __FUNCTION__, (thread->trdid == trdid) , "bad trdid argument" );
    124125
    125126#if DEBUG_THREAD_INIT
     
    160161    list_entry_init( &thread->sched_list );
    161162
     163    // initialize the embedded alarm to unlink
     164    list_entry_init( &thread->alarm.list );
     165
    162166    // initialize waiting queue entries
    163167    list_entry_init( &thread->wait_list );
     
    220224    vseg_t       * us_vseg;      // user stack vseg
    221225
    222 assert( (attr != NULL) , "pthread attributes must be defined" );
     226assert( __FUNCTION__, (attr != NULL) , "pthread attributes must be defined" );
    223227
    224228#if DEBUG_THREAD_USER_CREATE
     
    370374        return -1;
    371375    }
    372     hal_cpu_context_init( thread );
     376    hal_cpu_context_init( thread,
     377                          false , 0 , 0 );   // not a main thread
    373378
    374379    // allocate & initialize FPU context
     
    662667}  // end thread_user_fork()
    663668
    664 ////////////////////////////////////////////////
    665 error_t thread_user_exec( void     * entry_func,
    666                           uint32_t   argc,
    667                           char    ** argv )
     669/////////////////////////////////////
     670void thread_user_exec( uint32_t argc,
     671                       intptr_t argv )
    668672{
    669673    thread_t  * thread  = CURRENT_THREAD;
     
    673677uint32_t cycle = (uint32_t)hal_get_cycles();
    674678if( DEBUG_THREAD_USER_EXEC < cycle )
    675 printk("\n[%s] thread[%x,%x] enter / entry %x / cycle %d\n",
    676 __FUNCTION__, process->pid, thread->trdid, entry_func , cycle );
     679printk("\n[%s] thread[%x,%x] enter / cycle %d\n",
     680__FUNCTION__, process->pid, thread->trdid, cycle );
    677681#endif
    678682
    679683// check parent thread attributes
    680 assert( (thread->type == THREAD_USER )          , "bad type" );
    681 assert( (thread->signature == THREAD_SIGNATURE) , "bad signature" );
    682 assert( (thread->busylocks == 0)                , "bad busylocks" );
     684assert( __FUNCTION__, (thread->type      == THREAD_USER )     , "bad type" );
     685assert( __FUNCTION__, (thread->signature == THREAD_SIGNATURE) , "bad signature" );
     686assert( __FUNCTION__, (thread->busylocks == 0)                , "bad busylocks" );
    683687
    684688        // re-initialize various thread descriptor fields
    685     thread->quantum         = 0;            // TODO
    686     thread->ticks_nr        = 0;            // TODO
    687     thread->time_last_check = 0;            // TODO
    688 
    689     thread->entry_func      = entry_func;
    690     thread->main_argc       = argc;
    691     thread->main_argv       = argv;
    692 
    693     // the main thread is always detached
    694     thread->flags           = THREAD_FLAG_DETACHED;
     689    thread->quantum         = 0;                               // TODO
     690    thread->ticks_nr        = 0;                               // TODO
     691    thread->time_last_check = 0;                               // TODO
     692    thread->entry_func      = (void*)process->vmm.entry_point;
     693    thread->flags           = THREAD_FLAG_DETACHED;            // main always detached
    695694    thread->blocked         = 0;
    696695    thread->errno           = 0;
    697     thread->fork_user       = 0;    // not inherited
    698     thread->fork_cxy        = 0;    // not inherited
    699 
    700     // re-initialize busylocks counters
    701     thread->busylocks       = 0;
     696    thread->fork_user       = 0;
     697    thread->fork_cxy        = 0;
    702698
    703699    // reset thread info
     
    707703    remote_busylock_init( XPTR( local_cxy , &thread->join_lock ), LOCK_THREAD_JOIN );
    708704
    709     // allocate an user stack vseg for main thread
    710     vseg_t * us_vseg = vmm_create_vseg( process,
    711                                         VSEG_TYPE_STACK,
    712                                         LTID_FROM_TRDID( thread->trdid ),
    713                                         0,                 // length unused
    714                                         0,                 // file_offset unused
    715                                         0,                 // file_size unused
    716                                         XPTR_NULL,         // mapper_xp unused
    717                                         local_cxy );
    718     if( us_vseg == NULL )
    719     {
    720             printk("\n[ERROR] in %s : cannot create stack vseg for main thread\n", __FUNCTION__ );
    721                 return -1;
    722     }
    723 
    724     // update user stack in thread descriptor
    725     thread->user_stack_vseg = us_vseg;
    726    
    727705    // release FPU ownership if required
    728706    if( thread->core->fpu_owner == thread ) thread->core->fpu_owner = NULL;
    729707
    730     // re-initialize FPU context
     708    // initialize thread FPU context
    731709    hal_fpu_context_init( thread );
     710
     711    // initialize thread CPU context
     712    hal_cpu_context_init( thread,
     713                          true,          // main thread
     714                          argc,
     715                          argv ); 
    732716
    733717#if DEBUG_THREAD_USER_EXEC
    734718cycle = (uint32_t)hal_get_cycles();
    735719if( DEBUG_THREAD_USER_EXEC < cycle )
    736 printk("\n[%s] thread[%x,%x] set CPU context & jump to user code / cycle %d\n",
    737 __FUNCTION__, process->pid, thread->trdid, cycle );
    738 hal_vmm_display( XPTR( local_cxy , process ) , true );
    739 #endif
    740 
    741     // re-initialize CPU context... and jump to user code
    742         hal_cpu_context_exec( thread );
    743 
    744     assert( false, "we should not execute this code");
    745  
    746     return 0;
     720{
     721    printk("\n[%s] thread[%x,%x] set CPU context & jump to user code / cycle %d\n",
     722    __FUNCTION__, process->pid, thread->trdid, cycle );
     723
     724    hal_cpu_context_display( XPTR( local_cxy , thread ) );
     725    hal_vmm_display( XPTR( local_cxy , process ) , true );
     726}
     727#endif
     728
     729    // restore CPU registers ... and jump to user code
     730    hal_do_cpu_restore( thread->cpu_context );
    747731
    748732}  // end thread_user_exec()
     
    761745    thread_t * this = CURRENT_THREAD;
    762746
    763 assert( ( (type == THREAD_IDLE) || (type == THREAD_RPC) || (type == THREAD_DEV) ) ,
     747assert( __FUNCTION__, ( (type == THREAD_IDLE) || (type == THREAD_RPC) || (type == THREAD_DEV) ) ,
    764748"illegal thread type" );
    765749
    766 assert( (core_lid < LOCAL_CLUSTER->cores_nr) ,
     750assert( __FUNCTION__, (core_lid < LOCAL_CLUSTER->cores_nr) ,
    767751"illegal core_lid" );
    768752
     
    829813    }
    830814
    831     hal_cpu_context_init( thread );
     815    hal_cpu_context_init( thread,
     816                          false , 0 , 0 );  // not a main thread
    832817
    833818#if DEBUG_THREAD_KERNEL_CREATE
     
    854839
    855840// check arguments
    856 assert( (type == THREAD_IDLE) , "illegal thread type" );
    857 assert( (core_lid < LOCAL_CLUSTER->cores_nr) , "illegal core index" );
     841assert( __FUNCTION__, (type == THREAD_IDLE) , "illegal thread type" );
     842assert( __FUNCTION__, (core_lid < LOCAL_CLUSTER->cores_nr) , "illegal core index" );
    858843
    859844    // set type in thread descriptor
     
    863848    error = process_register_thread( &process_zero , thread , &trdid );
    864849
    865 assert( (error == 0), "cannot register idle_thread in kernel process" );
     850assert( __FUNCTION__, (error == 0), "cannot register idle_thread in kernel process" );
    866851
    867852    // set trdid in thread descriptor
     
    878863                         NULL );   // no user stack for a kernel thread
    879864
    880 assert( (error == 0), "cannot initialize idle_thread" );
    881 
    882     // allocate & initialize CPU context if success
     865assert( __FUNCTION__, (error == 0), "cannot initialize idle_thread" );
     866
     867    // allocate CPU context
    883868    error = hal_cpu_context_alloc( thread );
    884869
    885 assert( (error == 0), "cannot allocate CPU context" );
    886 
    887     hal_cpu_context_init( thread );
     870assert( __FUNCTION__, (error == 0), "cannot allocate CPU context" );
     871
     872    // initialize CPU context
     873    hal_cpu_context_init( thread,
     874                          false , 0 , 0 );   // not a main thread
    888875
    889876}  // end thread_idle_init()
     
    949936#endif
    950937
     938    // unlink embedded alarm from the list rooted in core when required
     939    list_entry_t * entry = &thread->alarm.list;
     940    if( (entry->next != NULL) || (entry->pred != NULL) )  list_unlink( entry );
     941
    951942    // remove thread from process th_tbl[]
    952943    count = process_remove_thread( thread );
     
    10281019
    10291020    // check signal pending in scheduler
    1030     assert( sched->req_ack_pending , "no pending signal" );
     1021    assert( __FUNCTION__, sched->req_ack_pending , "no pending signal" );
    10311022   
    10321023    // enter critical section
     
    11011092
    11021093//////////////////////////////////////
    1103 void thread_delete( xptr_t  target_xp,
     1094void thread_delete_request( xptr_t  target_xp,
    11041095                    bool_t  is_forced )
    11051096{
     
    11501141// check target thread is not the main thread, because the main thread
    11511142// must be deleted by the parent process sys_wait() function
    1152 assert( ((CXY_FROM_PID( target_pid ) != target_cxy) || (target_ltid != 0)),
     1143assert( __FUNCTION__, ((CXY_FROM_PID( target_pid ) != target_cxy) || (target_ltid != 0)),
    11531144"target thread cannot be the main thread" );
    11541145
     
    12751266
    12761267    }
    1277 }  // end thread_delete()
     1268}  // end thread_delete_request()
    12781269
    12791270
  • trunk/kernel/kern/thread.h

    r662 r669  
    3737#include <core.h>
    3838#include <chdev.h>
     39#include <alarm.h>
    3940#include <cluster.h>
    4041#include <process.h>
     
    9596#define THREAD_BLOCKED_LOCK      0x1000  /*! ANY : wait queuelock or rwlock           */
    9697#define THREAD_BLOCKED_CLIENT    0x2000  /*! DEV : wait clients queue non empty       */
     98#define THREAD_BLOCKED_ALARM     0x4000  /*! ANY : wait a timer based alarm           */
    9799
    98100/***************************************************************************************
     
    160162        vseg_t            * user_stack_vseg; /*! local pointer on user stack vseg         */
    161163
    162     void              * entry_func;      /*! pointer on entry function                */
    163     void              * entry_args;      /*! pointer on entry function arguments      */
    164     uint32_t            main_argc;       /*! main thread number of arguments          */
    165     char             ** main_argv;       /*! main thread array of strings arguments   */
     164    void              * entry_func;      /*! pointer on thread entry function         */
     165    void              * entry_args;      /*! pthread     : pointer on arguments       */
    166166
    167167    uint32_t            flags;           /*! bit vector of flags                      */
     
    177177
    178178    chdev_t           * chdev;           /*! chdev pointer (for a DEV thread only)    */
     179
     180    alarm_t             alarm;           /*! embedded timer based alarm               */
    179181
    180182    reg_t               save_sr;         /*! used by sched_yield() function           */
     
    269271/***************************************************************************************
    270272 * This function is called by the process_make_exec() function to re-initialise the
    271  * calling thread descriptor, that will become the new process main thread.
    272  * It must be called by the main thread of the calling process.
     273 * calling thread descriptor, that will become the new process main thread, from
     274 * the process descriptor, and from the <args_nr> & <args_base> arguments.
    273275 * - The calling thread TRDID is not modified.
    274276 * - The kernel stack (currently in use) is not modified. 
    275  * - A new user stack vseg is created and initialised.
    276  * - The function calls the hal_cpu_context_exec() to re-initialize the CPU context
    277  *   and the uzone registered in kernel stack, an jump to user code. 
    278  ***************************************************************************************
    279  * @ entry_func : main thread entry point.
    280  * @ argc       : number of main thread arguments.
    281  * @ argv       : array of pointers on stringarguments.
    282  * @ returns 0 if success / returns ENOMEM if error.
    283  **************************************************************************************/
    284 error_t thread_user_exec( void     * entry_func,
    285                           uint32_t   argc,
    286                           char    ** argv);
     277 * - It calls the hal_cpu_context_init() to re-initialize the thread CPU context.
     278 * - It calls the hal_do_cpu_restore() to force execution of the new user code.
     279 ***************************************************************************************
     280 * @ argc   : actual number of main thread arguments.
     281 * @ argv   : user space pointer on array of pointers on arguments.
     282 **************************************************************************************/
     283void thread_user_exec( uint32_t  argc,
     284                       intptr_t  argv );
    287285
    288286/***************************************************************************************
     
    397395 * @ is_forced   : the deletion does not depends on the attached mode.
    398396 **************************************************************************************/
    399 void thread_delete( xptr_t  thread_xp,
    400                     bool_t  is_forced );
     397void thread_delete_request( xptr_t  thread_xp,
     398                            bool_t  is_forced );
    401399
    402400/***************************************************************************************
Note: See TracChangeset for help on using the changeset viewer.