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

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

File:
1 edited

Legend:

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

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