Changeset 409 for trunk/kernel/syscalls


Ignore:
Timestamp:
Dec 20, 2017, 4:51:09 PM (6 years ago)
Author:
alain
Message:

Fix bugs in exec

Location:
trunk/kernel/syscalls
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/kernel/syscalls/sys_fork.c

    r408 r409  
    11/*
    2  * sys_fork.c - Fork the current process.
     2 * sys_fork.c - Kernel function implementing the "fork" system call.
    33 *
    44 * Authors  Alain Greiner  (2016,2017)
  • trunk/kernel/syscalls/sys_kill.c

    r124 r409  
    11/*
    2  * sys_kill.c: Send a signal to a given process.
     2 * sys_kill.c - Send a signal to a given process.
    33 *
    44 * Author    Alain Greiner (2016,2017)
     
    2424#include <kernel_config.h>
    2525#include <hal_types.h>
     26#include <hal_irqmask.h>
    2627#include <errno.h>
    2728#include <thread.h>
     
    3637              uint32_t sig_id )
    3738{
     39    uint32_t    save_sr;       // required to enable IRQs
     40
     41#if CONFIG_SYSCALL_DEBUG
     42uint64_t    tm_start;
     43uint64_t    tm_end;
     44tm_start = hal_get_cycles();
     45#endif
     46
    3847    thread_t  * this    = CURRENT_THREAD;
    3948    process_t * process = this->process;
    40 
    41     // check signal index
    42         if( (sig_id == 0) || (sig_id >= SIG_NR) )
    43         {
    44         printk("\n[ERROR] in %s : illegal signal = %d for thread %x in process %x\n",
    45                __FUNCTION__ , sig_id , this->trdid , process->pid );
    46                 this->errno = EINVAL;
    47         return -1;
    48         }
    49 
    50     // get local pointer on local cluster manager
    51     cluster_t * cluster = LOCAL_CLUSTER;
    5249
    5350    // get owner process cluster and lpid
     
    5552    lpid_t  lpid       = LPID_FROM_PID( pid );
    5653
    57     // check PID
     54    // check pid
    5855    if( (lpid >= CONFIG_MAX_PROCESS_PER_CLUSTER) || cluster_is_undefined( owner_cxy ) )
    5956    {
    6057        printk("\n[ERROR] in %s : illegal target PID = %d for thread %x in process %x\n",
    61                __FUNCTION__ , pid , this->trdid , process->pid );
     58        __FUNCTION__ , pid , this->trdid , pid );
    6259                this->errno = EINVAL;
    6360        return -1;
    6461    }
    6562
    66     // get extended pointers on copies root and lock
    67     xptr_t root_xp = XPTR( owner_cxy , &cluster->pmgr.copies_root[lpid] );
    68     xptr_t lock_xp = XPTR( owner_cxy , &cluster->pmgr.copies_lock[lpid] );
    69 
    70     // take the lock protecting the copies
    71     remote_spinlock_lock( lock_xp );
    72 
    73     // TODO the loop below sequencialize the RPCs
    74     // they could be pipelined using a non-blocking RPC ...
    75  
    76     // loop on the process decriptor copies
    77     xptr_t  iter_xp;
    78     XLIST_FOREACH( root_xp , iter_xp )
     63    // check sig_id
     64    if( (sig_id != SIGSTOP) && (sig_id != SIGCONT) && (sig_id != SIGKILL) )
    7965    {
    80         xptr_t      process_xp  = XLIST_ELEMENT( iter_xp , process_t , copies_list );
    81         cxy_t       process_cxy = GET_CXY( process_xp );
    82         process_t * process_ptr = (process_t *)GET_PTR( process_xp );
    83 
    84         if( process_cxy == local_cxy )   // process copy is local
    85         {
    86             signal_rise( process_ptr , sig_id );
    87         }
    88         else                           // process copy is remote
    89         {
    90             rpc_signal_rise_client( process_cxy , process_ptr , sig_id );
    91         }
     66        printk("\n[ERROR] in %s : illegal signal type for thread %x in process %x\n",
     67        __FUNCTION__ , sig_id , this->trdid , pid );
     68                this->errno = EINVAL;
     69        return -1;
    9270    }
    9371
    94     // release the lock
    95     remote_spinlock_unlock( lock_xp );
     72    // enable IRQs
     73    hal_enable_irq( &save_sr );
     74
     75    // execute process_make_kill() function in owner cluster
     76    if( local_cxy == owner_cxy )                                // owner is local
     77    {
     78        process_make_kill( process , sig_id );
     79    }
     80    else                                                        // owner is remote
     81    {
     82        rpc_process_make_kill_client( owner_cxy , process , sig_id );
     83    }
     84
     85    // restore IRQs
     86    hal_restore_irq( save_sr );
    9687
    9788    hal_fence();
    9889
     90#if CONFIG_SYSCALL_DEBUG
     91tm_end = hal_get_cycles();
     92syscall_dmsg("\n[DBG] %s exit : core[%x,%d] / thread %x in process %x / cycle %d\n"
     93"process %x killed / cost = %d\n",
     94__FUNCTION__ , local_cxy , this->core->lid , this->trdid , this->process->pid ,
     95tm_start , pid , (uint32_t)(tm_end - tm_start) );
     96#endif
     97 
    9998        return 0;
    10099
  • trunk/kernel/syscalls/sys_read.c

    r408 r409  
    2525#include <hal_types.h>
    2626#include <hal_uspace.h>
     27#include <hal_irqmask.h>
    2728#include <hal_special.h>
    2829#include <errno.h>
     
    3536// TODO: concurrent user page(s) munmap need to be handled [AG]
    3637
    37 // instrumentation
     38// TODO : remove these debug variables
    3839extern uint32_t enter_sys_read;
    3940extern uint32_t enter_devfs_move;
     
    6263    uint32_t     nbytes;      // number of bytes actually read
    6364    reg_t        save_sr;     // required to enable IRQs during syscall
    64         uint32_t     tm_start;
    65         uint32_t     tm_end;
    66 
    67         tm_start = hal_get_cycles();
    68 
    69 #if CONFIG_READ_START
     65
     66#if CONFIG_SYSCALL_DEBUG
     67uint32_t     tm_start;
     68uint32_t     tm_end;
     69tm_start = hal_get_cycles();
     70#endif
     71
     72#if CONFIG_READ_DEBUG
    7073enter_sys_read = tm_start;
    7174#endif
     
    159162    hal_fence();
    160163
    161     tm_end = hal_get_cycles();
     164#if CONFIG_SYSCALL_DEBUG
     165tm_end = hal_get_cycles();
     166syscall_dmsg("\n[DBG] %s exit : core[%x,%d] / thread %x in process %x / cycle %d\n"
     167"nbytes = %d / first byte = %c / file_id = %d / cost = %d\n",
     168__FUNCTION__ , local_cxy , this->core->lid , this->trdid , this->process->pid ,
     169tm_start , nbytes , *((char *)(intptr_t)paddr) , file_id , tm_end - tm_start );
     170#endif
    162171
    163172#if CONFIG_READ_DEBUG
    164173exit_sys_read = tm_end;
    165174
    166 printk("\n@@@@@@@@@@@@ timing ro read character %c\n"
     175printk("\n@@@@@@@@@@@@ timing to read character %c\n"
    167176" - enter_sys_read     = %d / delta %d\n"
    168177" - enter_devfs_move   = %d / delta %d\n"
     
    195204exit_sys_read      , exit_sys_read      - exit_devfs_move    );
    196205#endif
    197 
    198 syscall_dmsg("\n[DBG] %s : core[%x,%d] / thread %x in process %x / cycle %d\n"
    199 "nbytes = %d / first byte = %c / file_id = %d / cost = %d\n",
    200 __FUNCTION__ , local_cxy , this->core->lid , this->trdid , this->process->pid ,
    201 tm_start , nbytes , *((char *)(intptr_t)paddr) , file_id , tm_end - tm_start );
    202206 
    203207        return nbytes;
  • trunk/kernel/syscalls/sys_signal.c

    r408 r409  
    3838    this->errno = EINVAL;
    3939    return -1;
    40    
    41         if((sig_id == 0) || (sig_id >= SIG_NR) || (sig_id == SIGKILL) || (sig_id == SIGSTOP))
    42         {
    43         printk("\n[ERROR] in %s : illega signal index = %d\n", __FUNCTION__ , sig_id );
    44                 this->errno = EINVAL;
    45                 return -1;
    46         }
    47 
    48         // register handler in signal manager for the calling process
    49         this->process->sig_mgr.sigactions[sig_id] = handler;
    50 
    51         signal_dmsg("\n[DBG] %s : handler @%x has been registred for signal %d\n",
    52                     __FUNCTION__ , handler , sig_id );
    53 
    54         return 0;
    5540}
    5641
  • trunk/kernel/syscalls/sys_thread_exit.c

    r408 r409  
    11/*
    2  * sys_thread_exit.c - terminates the execution of current thread
     2 * sys_thread_exit.c - terminates the execution of calling thread
    33 *
    4  * Authors       Ghassan Almaless (2008,2009,2010,2011,2012)
    5  *               Alain Greiner (2016,2017)
     4 * Authors   Alain Greiner (2016,2017)
    65 *
    76 * Copyright (c) UPMC Sorbonne Universites
     
    2423
    2524#include <hal_types.h>
    26 #include <hal_irqmask.h>
    2725#include <thread.h>
    2826#include <core.h>
     27#include <vmm.h>
    2928#include <scheduler.h>
    3029#include <printk.h>
    31 
    3230
    3331////////////////////////////////////////
    3432int sys_thread_exit( void * exit_value )
    3533{
    36         thread_t  * this = CURRENT_THREAD;
    37     core_t    * core = this->core;
    38     reg_t       irq_state;
     34    paddr_t      paddr;
     35    error_t          error;
    3936
    40     // register the exit_value pointer in thread descriptor
    41     this->exit_value = exit_value;
     37#if CONFIG_SYSCALL_DEBUG
     38uint32_t     tm_start;
     39uint32_t     tm_end;
     40tm_start = hal_get_cycles();
     41#endif
    4242
    43     // enter the join loop to wait the join if thread is joinable
    44     if( (this->flags & THREAD_FLAG_DETACHED) == 0 )
     43        thread_t  * this    = CURRENT_THREAD;
     44    process_t * process = this->process;
     45
     46    // check all locks released
     47        if( !thread_can_yield() )
     48        {
     49        printk("\n[ERROR] in %s : locks not released / thread %x in process %x\n",
     50        __FUNCTION__, this->trdid, process->pid );
     51        this->errno = EINVAL;
     52        return -1;
     53    }
     54
     55    // register the exit_value pointer in this thread descriptor
     56    this->join_value = exit_value;
     57
     58    if( (this->flags & THREAD_FLAG_DETACHED) == 0 )    // this thread is joinable
    4559    {
    46             while( 1 )
    47             {
    48             // take the lock protecting the flags
    49                 remote_spinlock_lock( XPTR( local_cxy, &this->flags_lock ) );
     60        // check exit_value in user space
     61        error = vmm_v2p_translate( false , exit_value , &paddr );
     62            if( error )
     63        {
     64            printk("\n[ERROR] in %s : illegal pointer = %x / thread %x in process %x\n",
     65            __FUNCTION__ , (intptr_t)exit_value, this->trdid , process->pid );
     66            this->errno = EINVAL;
     67            return -1;
     68        }
    5069
    51             // check the JOIN flag
    52             if( this->flags & THREAD_FLAG_JOIN )       // parent made a join
    53             {
    54                 // unblock the parent thread
    55                 thread_unblock( this->parent , THREAD_BLOCKED_JOIN );
     70        // take the lock protecting the join
     71        remote_spinlock_lock( XPTR( local_cxy, &this->join_lock ) );
    5672
    57                 // release the lock protecting the flags
    58                     remote_spinlock_unlock( XPTR( local_cxy, &this->flags_lock ) );
     73        if( this->flags & THREAD_FLAG_JOIN_DONE )       // parent thread arrived first
     74        {
     75            // unblock the parent thread
     76            thread_unblock( this->join_xp , THREAD_BLOCKED_EXIT );
    5977
    60                 // exit while
    61                 break;
    62             }
    63             else                                       // no join done by parent thread
    64             {
    65                 // set the EXIT flag
    66                 this->flags |= THREAD_FLAG_EXIT;
     78            // reset the JOIN_DONE flag in this thread
     79            this->flags &= ~THREAD_FLAG_JOIN_DONE;
    6780
    68                 // block this thread
    69                 thread_block( this , THREAD_BLOCKED_EXIT );
     81            // release the lock protecting the flags
     82                remote_spinlock_unlock( XPTR( local_cxy, &this->join_lock ) );
     83        }
     84        else                                           // this thread arrived first
     85        {
     86            // block this thread
     87            thread_block( this , THREAD_BLOCKED_JOIN );
    7088
    71                 // release the lock protecting the flags
    72                     remote_spinlock_unlock( XPTR( local_cxy, &this->flags_lock ) );
     89            // release the lock protecting the flags
     90                remote_spinlock_unlock( XPTR( local_cxy, &this->join_lock ) );
    7391
    74                 // deschedule
    75                 sched_yield("waiting parent join");
    76             }     
    77         }
    78         }
     92            // deschedule
     93            sched_yield( "WAITING JOIN" );
     94        }     
     95    }
    7996
    80         // Release FPU if required
    81         hal_disable_irq( &irq_state );
    82         if( core->fpu_owner == this )  core->fpu_owner = NULL;
    83         hal_restore_irq( irq_state );
     97#if CONFIG_SYSCALL_DEBUG
     98tm_end = hal_get_cycles();
     99syscall_dmsg("\n[DBG] %s : core[%x,%d] / thread %x in process %x / cycle %d\n"
     100"thread %x killed / cost = %d\n",
     101__FUNCTION__ , local_cxy , this->core->lid , this->trdid , this->process->pid , tm_start ,
     102this->trdid , (uint32_t)(tm_end - tm_start) );
     103#endif
    84104
    85         // suicide
    86     thread_kill( this );
    87         return 0;       
     105    // suicide using a rpc because  a thread cannot kill itself
     106    rpc_thread_kill_client( local_cxy , this );
    88107
    89 }  // end sys_thread_exit()
     108    return 0;   // never executed but required by compiler
     109
     110}  // end sys_thread exit
  • trunk/kernel/syscalls/sys_thread_join.c

    r408 r409  
    4040    cxy_t         target_cxy;
    4141    ltid_t        target_ltid;
    42     uint32_t      flags;        // target thread flags
    43     intptr_t      value;        // value returned by target thread
    44     paddr_t       paddr;        // required for vmm_v2p_translate()
     42        uint32_t      target_blocked;   // target thread blocked bit-vector
     43    uint32_t      target_flags;     // target thread flags bit-bector
     44    paddr_t       paddr;            // required for vmm_v2p_translate()
    4545
    46         thread_t  * this    = CURRENT_THREAD;
    47     process_t * process = this->process;
     46        thread_t    * this    = CURRENT_THREAD;
     47    process_t   * process = this->process;
    4848
    4949    // get target thread ltid and cxy
     
    8989
    9090    // check target thread joinable
    91     flags = hal_remote_lw( XPTR( target_cxy , &target_ptr->flags ) );
    92     if( flags & THREAD_FLAG_DETACHED )
     91    target_flags = hal_remote_lw( XPTR( target_cxy , &target_ptr->flags ) );
     92    if( target_flags & THREAD_FLAG_DETACHED )
    9393    {
    9494        printk("\n[ERROR] in %s : target thread not joinable\n", __FUNCTION__ );
     
    100100    if( target_ptr->signature != THREAD_SIGNATURE )
    101101    {
    102         printk("\n[PANIC] in %s : kernel stack overflow\n", __FUNCTION__ );
    103         hal_core_sleep();
     102        panic("\n[PANIC] in %s : kernel stack overflow\n", __FUNCTION__ );
    104103    }
    105104
    106     // wait target thread exit
    107     while( 1 )
     105    // get the lock protecting the join in target thread
     106    remote_spinlock_lock( XPTR( target_cxy , &target_ptr->join_lock ) );
     107
     108    // get the blocked bit_vector from the target thread
     109    target_blocked = hal_remote_lw( XPTR( target_cxy , &target_ptr->blocked ) );
     110
     111    if( target_blocked & THREAD_BLOCKED_JOIN )    // target thread arrived first
    108112    {
    109         // take the target thread lock protecting flags     
    110         remote_spinlock_lock( XPTR( target_cxy , &target_ptr->flags_lock ) );
     113        // unblock the target thread
     114        thread_unblock( target_xp , THREAD_BLOCKED_JOIN );
    111115
    112         // get the remote thread flags
    113         flags = hal_remote_lw( XPTR( target_cxy , &target_ptr->flags ) );
     116        // release the lock protecting flags     
     117        remote_spinlock_unlock( XPTR( target_cxy , &target_ptr->join_lock ) );
    114118
    115         // check the EXIT flag
    116         if( flags & THREAD_FLAG_EXIT )   // target made an exit
    117         {
    118             // unblock the target thread
    119             thread_unblock( target_xp , THREAD_BLOCKED_EXIT );
     119        // get the exit value from target thread
     120        *exit_value = hal_remote_lpt( XPTR( target_cxy , &target_ptr->join_value ) );
     121    }
     122    else                                          // this thread arrived first
     123    {
     124        // register this thread extended pointer in target thread
     125        hal_remote_swd( XPTR( target_cxy , &target_ptr->join_xp ) ,
     126                              XPTR( local_cxy , this ) );
    120127
    121             // release the target thread lock protecting flags     
    122             remote_spinlock_unlock( XPTR( target_cxy , &target_ptr->flags_lock ) );
     128        // set the JOIN_DONE flag in target thread
     129        hal_remote_atomic_or( XPTR( target_cxy , &target_ptr->flags ) ,
     130                              THREAD_FLAG_JOIN_DONE );
    123131
    124             // exit while
    125             break;
    126         }
    127         else                             // no exit done by target thread
    128         {
    129             // set the JOIN flag in target thread
    130             hal_remote_atomic_or( XPTR( target_xp , &target_ptr->flags ) ,
    131                                   THREAD_BLOCKED_JOIN );
     132        // block this thread on BLOCKED_EXIT
     133        thread_block( this , THREAD_BLOCKED_EXIT );
    132134
    133             // block this thread
    134             thread_block( this , THREAD_BLOCKED_JOIN );
     135        // release the lock protecting flags     
     136        remote_spinlock_unlock( XPTR( target_cxy , &target_ptr->join_lock ) );
    135137
    136             // release the target thread lock protecting flags
    137                 remote_spinlock_unlock( XPTR( target_cxy , &target_ptr->flags_lock ) );
    138 
    139             // deschedule
    140             sched_yield("waiting child exit");
    141         }
     138        // deschedule
     139        sched_yield( "WAITING_EXIT" );
     140   
     141        // get the exit value from target thread when resume
     142        *exit_value = hal_remote_lpt( XPTR( target_cxy , &target_ptr->join_value ) );
    142143    }
    143144
    144     // return exit_value from target thread descriptor
    145     value = (intptr_t)hal_remote_lpt( XPTR( target_cxy , &target_ptr->exit_value ) );
    146     *exit_value = (void *)value;
    147145    return 0;
    148146
  • trunk/kernel/syscalls/sys_write.c

    r408 r409  
    2525#include <hal_types.h>
    2626#include <hal_uspace.h>
     27#include <hal_irqmask.h>
    2728#include <hal_special.h>
    2829#include <errno.h>
     
    4445    uint32_t     nbytes;          // number of bytes actually written
    4546    reg_t        save_sr;         // required to enable IRQs during syscall
    46         uint32_t     tm_start;
    47         uint32_t     tm_end;
    4847
    49         tm_start = hal_get_cycles();
     48#if CONFIG_SYSCALL_DEBUG
     49uint32_t     tm_start;
     50uint32_t     tm_end;
     51tm_start = hal_get_cycles();
     52#endif
    5053
    5154        thread_t   * this = CURRENT_THREAD;
     
    136139    hal_fence();
    137140
    138     tm_end = hal_get_cycles();
    139 
     141#if CONFIG_SYSCALL_DEBUG
     142tm_end = hal_get_cycles();
    140143syscall_dmsg("\n[DBG] %s : core[%x,%d] / thread %x in process %x / cycle %d\n"
    141144"nbytes = %d / first byte = %c / file_id = %d / cost = %d\n",
    142145__FUNCTION__ , local_cxy , this->core->lid , this->trdid , this->process->pid ,
    143146tm_start , nbytes , *((char *)(intptr_t)paddr) , file_id , tm_end - tm_start );
     147#endif
    144148 
    145149        return nbytes;
  • trunk/kernel/syscalls/syscalls.h

    r408 r409  
    4040 * and makes the exit_value pointer available to any successful pthread_join() with the
    4141 * terminating thread.
    42  ******************************************************************************************
    43  * @ exit_vallue  : pointer to be returned to parent thread if thread is attached.
    44  * @ return 0 if success / return -1 if failure.
     42 * It actually set the THREAD_SIG_EXIT signal, set the THREAD_BLOCKED_GLOBAL bit in the
     43 * thread descriptor and deschedule.
     44 * The thread will be detached from its process, and the memory allocated to the thread
     45 * descriptor will be released later by the scheduler.
     46 ******************************************************************************************
     47 * @ exit_vallue  : pointer to be returned to joining thread if thread is attached.
     48 * @ return 0 if success / return -1 if all locks not released or illegal argument.
    4549 *****************************************************************************************/
    4650int sys_thread_exit( void * exit_value );
     
    8791 * [4] This function detach a joinable thread.
    8892 ******************************************************************************************
    89  * @ trdid   : thread identifier.i
     93 * @ trdid   : thread identifier.
    9094 * @ return 0 if success / return -1 if failure.
    9195 *****************************************************************************************/
     
    9397
    9498/******************************************************************************************
    95  * [5] This slot is not used.
    96  *****************************************************************************************/
     99 * [5] This function requests a target thread identified by its <trdid> argument
     100 * to be cancelled. Depending on killer thread and target thread location, it calls
     101 * the thread_kil() function or the rpc_thread_kill_client() function to do the work.
     102 * It actually set the THREAD_SIG_KILL signal, set the THREAD_BLOCKED_GLOBAL bit in the
     103 * target thread descriptor and return.
     104 * The thread will be detached from its process, and the memory allocated to the thread
     105 * descriptor will be released later by the scheduler.
     106 ******************************************************************************************
     107 * @ trdid   : thread identifier.
     108 * @ return 0 if success / return -1 if illegal argument.
     109 *****************************************************************************************/
     110int sys_thread_cancel( trdid_t  trdid );
    97111
    98112/******************************************************************************************
     
    158172 * @ status   : terminaison status (not used in present implementation).
    159173 *****************************************************************************************/
    160 void sys_exit( uint32_t status );
     174int sys_exit( uint32_t status );
    161175
    162176/******************************************************************************************
Note: See TracChangeset for help on using the changeset viewer.