Changeset 436 for trunk/kernel/syscalls


Ignore:
Timestamp:
Mar 7, 2018, 9:02:03 AM (4 years ago)
Author:
alain
Message:

1) improve the threads and process destruction mechanism.
2) introduce FIFOs in the soclib_tty driver.

Location:
trunk/kernel/syscalls
Files:
13 edited

Legend:

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

    r435 r436  
    3737                 reg_t  arg1 )
    3838{
    39     // get thread, process and core
    40     thread_t  * this    = CURRENT_THREAD;
    41     process_t * process = this->process;
    42     core_t    * core    = this->core;
    4339
    4440#if CONFIG_DEBUG_SYS_DISPLAY
    4541uint64_t    tm_start;
    4642uint64_t    tm_end;
     43thread_t  * this;
     44this     = CURRENT_THREAD;
    4745tm_start = hal_get_cycles();
    4846if( CONFIG_DEBUG_SYS_DISPLAY < tm_start )
    49 printk("\n[DBG] %s : thread %d enter / process %x / cycle = %d\n",
    50 __FUNCTION__, this, process->pid, (uint32_t)tm_start );
     47printk("\n[DBG] %s : thread %d enter / process %x / type  %d / cycle = %d\n",
     48__FUNCTION__, this, this->process->pid, type, (uint32_t)tm_start );
    5149#endif
    5250
     
    8078
    8179        // print message on TXT0 kernel terminal
    82         printk("\n[USER] thread %x / process %x / core[%x,%d] / cycle %d\n       %s",
    83         this->trdid , process->pid , local_cxy, core->lid ,
    84         (uint32_t)hal_get_cycles() , kbuf );
     80        printk("\n[USER] %s / cycle %d\n", kbuf, (uint32_t)hal_get_cycles() );
    8581    }
    8682    else if( type == DISPLAY_VMM )
     
    191187if( CONFIG_DEBUG_SYS_DISPLAY < tm_end )
    192188printk("\n[DBG] %s : thread %x exit / process %x / cost = %d / cycle %d\n",
    193 __FUNCTION__, this, process->pid, (uint32_t)(tm_end - tm_start) , (uint32_t)tm_end );
     189__FUNCTION__, this, this->process->pid, (uint32_t)(tm_end - tm_start) , (uint32_t)tm_end );
    194190#endif
    195191
  • trunk/kernel/syscalls/sys_exit.c

    r435 r436  
    4141    process_t * process = this->process;
    4242    pid_t       pid     = process->pid;
     43    trdid_t     trdid   = this->trdid;
    4344
    4445#if CONFIG_DEBUG_SYS_EXIT
     
    5556
    5657    // exit must be called by the main thread
    57     if( (owner_cxy != local_cxy) || (LTID_FROM_TRDID( this->trdid ) != 0) )
     58    if( (owner_cxy != local_cxy) || (LTID_FROM_TRDID( trdid ) != 0) )
    5859    {
    5960
    6061#if CONFIG_DEBUG_SYSCALLS_ERROR
    61 printk("\n[ERROR] %s must be called by thread 0 in process owner cluster\n"
    62        "         trdid = %x / pid = %x / local_cxy = %x\n",
    63 __FUNCTION__, this->trdid, pid, local_cxy );
     62printk("\n[ERROR] in %s : calling thread %x is not thread 0 in owner cluster %x\n",
     63__FUNCTION__, trdid, owner_cxy );
    6464#endif
    6565         this->errno = EINVAL;
     
    7373    process->term_state = status;
    7474
    75     // remove TXT ownership from owner process descriptor
    76     process_txt_reset_ownership( XPTR( local_cxy , process ) );
     75#if( CONFIG_DEBUG_SYS_EXIT & 1)
     76printk("\n[DBG] %s : set exit status in process term_state\n", __FUNCTION__);
     77#endif
    7778
    78     // block all process threads in all clusters
    79     process_sigaction( pid , BLOCK_ALL_THREADS );
     79    // remove process from TXT list
     80    process_txt_detach( XPTR( local_cxy , process ) );
    8081
    81     // mark all process threads in all clusters for delete
     82#if( CONFIG_DEBUG_SYS_EXIT & 1)
     83printk("\n[DBG] %s : removed from TXT list\n", __FUNCTION__);
     84#endif
     85
     86    // mark for delete all process threads in all clusters (but the main)
    8287    process_sigaction( pid , DELETE_ALL_THREADS );
     88
     89#if( CONFIG_DEBUG_SYS_EXIT & 1)
     90printk("\n[DBG] %s : deleted all other threads than main\n", __FUNCTION__);
     91#endif
    8392
    8493    // restore IRQs
    8594    hal_restore_irq( save_sr );
    8695
    87     // atomically update owner process descriptor term_state
     96    // block the main thread itself
     97    thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_GLOBAL );
     98
     99#if( CONFIG_DEBUG_SYS_EXIT & 1)
     100printk("\n[DBG] %s : blocked the main thread\n", __FUNCTION__);
     101#endif
     102
     103    // atomically update owner process descriptor term_state to ask
     104    // the parent process sys_wait() function to delete this main thread
    88105    hal_remote_atomic_or( XPTR( local_cxy , &process->term_state ) ,
    89106                          PROCESS_TERM_EXIT );
     107
     108#if( CONFIG_DEBUG_SYS_EXIT & 1)
     109printk("\n[DBG] %s : set EXIT flag in process term_state\n", __FUNCTION__);
     110#endif
     111
    90112    hal_fence();
    91113
     
    97119#endif
    98120
     121    // main thread deschedule
     122    sched_yield( "process exit" );
     123
     124    // this code should never be executed
     125    assert( false , __FUNCTION__ , "this code should not be executed...\n" );
    99126        return 0;
    100127
  • trunk/kernel/syscalls/sys_fg.c

    r421 r436  
    4545    thread_t  * this    = CURRENT_THREAD;
    4646
    47 #if CONFIG_SYSCALL_DEBUG
     47#if CONFIG_DEBUG_SYS_FG
    4848uint64_t    tm_start;
    4949uint64_t    tm_end;
    5050tm_start = hal_get_cycles();
    51 printk("\n[DBG] %s : core[%x,%d] enter / process %x / cycle %d\n",
    52 __FUNCTION__ , local_cxy , this->core->lid , pid, (uint32_t)tm_start );
     51if( CONFIG_DEBUG_SYS_FG < tm_start )
     52printk("\n[DBG] %s : thread %x enter / process %x / cycle %d\n",
     53__FUNCTION__ , CURRENT_THREAD , pid, (uint32_t)tm_start );
    5354#endif
    5455
     
    5859    if( process_xp == XPTR_NULL )
    5960    {
    60         syscall_dmsg("\n[ERROR] in %s : process %x not found\n",
    61         __FUNCTION__ , pid );
     61
     62#if CONFIG_DEBUG_SYSCALLS_ERROR
     63printk("\n[ERROR] in %s : process %x not found\n", __FUNCTION__ , pid );
     64#endif
    6265        this->errno = EINVAL;
    6366        return -1;
     
    7275
    7376    // get chdev cluster and local pointer
    74     chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
     77    chdev_ptr = GET_PTR( chdev_xp );
    7578    chdev_cxy = GET_CXY( chdev_xp );
    7679
     
    8083    hal_fence();
    8184
    82 #if CONFIG_SYSCALL_DEBUG
     85#if CONFIG_DEBUG_SYS_FG
    8386tm_end = hal_get_cycles();
    84 printk("\n[DBG] %s : core[%x,%d] exit / process %x / cost = %d\n",
    85 __FUNCTION__ , local_cxy , this->core->lid , pid, (uint32_t)(tm_end - tm_start) );
     87if( CONFIG_DEBUG_SYS_FG < tm_end )
     88printk("\n[DBG] %s : thread %x exit / process %x get TXT_%d ownership / cycle %d\n",
     89__FUNCTION__ , CURRENT_THREAD , pid,
     90hal_remote_lw( XPTR( chdev_cxy , &chdev_ptr->channel ) ) , (uint32_t)tm_end );
    8691#endif
    87  
     92
    8893        return 0;
    8994
    90 }  // end sys_kill()
     95}  // end sys_fg()
    9196
  • trunk/kernel/syscalls/sys_get_config.c

    r435 r436  
    8787tm_end = hal_get_cycles();
    8888if( CONFIG_DEBUG_SYS_GET_CONFIG < tm_end )
    89 printk("\n[DBG] %s : thread %x exit / process %x / cost %d / tycle %d\n",
     89printk("\n[DBG] %s : thread %x exit / process %x / cost %d / cycle %d\n",
    9090__FUNCTION__, this, process->pid, (uint32_t)(tm_end-tm_start), (uint32_t)tm_end );
    9191#endif
  • trunk/kernel/syscalls/sys_kill.c

    r435 r436  
    3737              uint32_t sig_id )
    3838{
    39     uint32_t    save_sr;       // required to enable IRQs
    40     xptr_t      owner_xp;      // extended pointer on target reference process
    41     cxy_t       owner_cxy;     // target process cluster
    42     process_t * owner_ptr;     // local pointer on target process
     39    xptr_t      owner_xp;      // extended pointer on target process in owner cluster
     40    cxy_t       owner_cxy;     // target process owner cluster
     41    process_t * owner_ptr;     // local pointer on target process in owner cluster
    4342    xptr_t      parent_xp;     // extended pointer on parent process
    4443    cxy_t       parent_cxy;    // parent process cluster
     
    4948    thread_t  * this    = CURRENT_THREAD;
    5049    process_t * process = this->process;
     50    trdid_t     trdid   = this->trdid;
    5151
    5252#if CONFIG_DEBUG_SYS_KILL
     
    5959#endif
    6060
    61     // process cannot kill itself
    62     if( pid == process->pid )
     61    // get pointers on process descriptor in owner cluster
     62    owner_xp  = cluster_get_owner_process_from_pid( pid );
     63    owner_cxy = GET_CXY( owner_xp );
     64    owner_ptr = GET_PTR( owner_xp );
     65   
     66    // check process found
     67    if( owner_xp == XPTR_NULL)
    6368    {
    6469
    6570#if CONFIG_DEBUG_SYSCALLS_ERROR
    66 printk("\n[ERROR] in %s : process %d cannot kill itself\n", __FUNCTION__ , pid );
     71printk("\n[ERROR] in %s : process %x not found\n", __FUNCTION__, pid );
    6772#endif
    6873        this->errno = EINVAL;
     
    7075    }
    7176
    72     // get cluster and pointers on owner target process descriptor
    73     owner_xp  = cluster_get_owner_process_from_pid( pid );
    74     owner_cxy = GET_CXY( owner_xp );
    75     owner_ptr = GET_PTR( owner_xp );
    76 
    77     // check process existence
    78     if( owner_xp == XPTR_NULL )
     77    // process can kill itself only when calling thread is the main thread
     78    if( (pid == process->pid) && ((owner_cxy != local_cxy) || (LTID_FROM_TRDID( trdid ))) )
    7979    {
    8080
    8181#if CONFIG_DEBUG_SYSCALLS_ERROR
    82 printk("\n[ERROR] in %s : process %x not found\n", __FUNCTION__ , pid );
     82printk("\n[ERROR] in %s : only main thread can kill itself\n", __FUNCTION__ );
    8383#endif
    8484        this->errno = EINVAL;
    8585        return -1;
    8686    }
    87    
     87
    8888    // get parent process PID
    8989    parent_xp  = hal_remote_lwd( XPTR( owner_cxy , &owner_ptr->parent_xp ) );
     
    9292    ppid       = hal_remote_lw( XPTR( parent_cxy , &parent_ptr->pid ) );
    9393
    94     // processes INIT
     94    // check processe INIT
    9595    if( pid == 1 )
    9696    {
     
    103103    }
    104104
    105     // enable IRQs
    106     hal_enable_irq( &save_sr );
    107 
    108105    // analyse signal type / supported values are : 0, SIGSTOP, SIGCONT, SIGKILL
    109106    switch( sig_id )
    110107    {
    111         case 0 :
     108        case 0 :          // does nothing
    112109        {
    113             // does nothing
    114110            retval = 0;
    115111            break;
    116112        }
    117         case SIGSTOP:     
     113        case SIGSTOP:     // block all target process threads
    118114        {
    119             // remove TXT ownership from target process
    120             process_txt_reset_ownership( owner_xp );
     115            // transfer TXT ownership
     116            process_txt_transfer_ownership( owner_xp );
    121117
    122             // block all threads in all clusters
     118            // block all threads in all clusters, but the main thread
    123119            process_sigaction( pid , BLOCK_ALL_THREADS );
     120
     121            // get pointer on target process main thread
     122            xptr_t main_xp = XPTR( owner_cxy , &owner_ptr->th_tbl[0] );
     123
     124            // block main thread
     125            thread_block( main_xp , THREAD_BLOCKED_GLOBAL );
    124126
    125127            // atomically update owner process termination state
    126128            hal_remote_atomic_or( XPTR( owner_cxy , &owner_ptr->term_state ) ,
    127129                                  PROCESS_TERM_STOP );
    128  
    129130            retval = 0;
    130131            break;
    131132        }
    132         case SIGCONT:
     133        case SIGCONT:     // unblock all target process threads
    133134        {
    134135            // unblock all threads in all clusters
    135136            process_sigaction( pid , UNBLOCK_ALL_THREADS );
    136137
    137             // atomically update reference process termination state
     138            // atomically update owner process termination state
    138139            hal_remote_atomic_and( XPTR( owner_cxy , &owner_ptr->term_state ) ,
    139140                                   ~PROCESS_TERM_STOP );
     
    144145        case SIGKILL:
    145146        {
    146             // remove TXT ownership from owner process descriptor
    147             process_txt_reset_ownership( owner_xp );
     147            // remove process from TXT list
     148            process_txt_detach( owner_xp );
    148149
    149             // block all process threads in all clusters
    150             process_sigaction( pid , BLOCK_ALL_THREADS );
    151 
    152             // mark all process threads in all clusters for delete
     150            // mark for delete all process threads in all clusters, but the main
    153151            process_sigaction( pid , DELETE_ALL_THREADS );
    154152
    155             // atomically update owner process descriptor flags
     153            // get pointer on target process main thread
     154            xptr_t main_xp = XPTR( owner_cxy , &owner_ptr->th_tbl[0] );
     155
     156            // block main thread
     157            thread_block( main_xp , THREAD_BLOCKED_GLOBAL );
     158
     159            // atomically update owner process descriptor term_state to ask
     160            // the parent process sys_wait() function to delete this main thread
    156161            hal_remote_atomic_or( XPTR( owner_cxy , &owner_ptr->term_state ) ,
    157162                                  PROCESS_TERM_KILL );
    158 
    159163            retval = 0;
    160164            break;
     
    172176    }
    173177   
    174     // restore IRQs
    175     hal_restore_irq( save_sr );
    176 
    177178    hal_fence();
    178179
     
    180181tm_end = hal_get_cycles();
    181182if( CONFIG_DEBUG_SYS_KILL < tm_end )
    182 printk("\n[DBG] %s : thread %x enter / process %x / sig %d / cost = %d / cycle %d\n",
     183printk("\n[DBG] %s : thread %x exit / process %x / sig %d / cost = %d / cycle %d\n",
    183184__FUNCTION__ , this, pid, sig_id, (uint32_t)(tm_end - tm_start), (uint32_t)tm_end );
    184185#endif
  • trunk/kernel/syscalls/sys_read.c

    r435 r436  
    3737
    3838extern uint32_t enter_sys_read;
    39 extern uint32_t enter_devfs_move;
     39extern uint32_t enter_devfs_read;
    4040extern uint32_t enter_txt_read;
    41 extern uint32_t enter_chdev_cmd;
    42 extern uint32_t enter_chdev_server;
    43 extern uint32_t enter_tty_cmd;
    44 extern uint32_t enter_tty_isr;
    45 extern uint32_t exit_tty_isr;
    46 extern uint32_t exit_tty_cmd;
    47 extern uint32_t exit_chdev_server;
    48 extern uint32_t exit_chdev_cmd;
     41extern uint32_t enter_chdev_cmd_read;
     42extern uint32_t enter_chdev_server_read;
     43extern uint32_t enter_tty_cmd_read;
     44extern uint32_t enter_tty_isr_read;
     45extern uint32_t exit_tty_isr_read;
     46extern uint32_t exit_tty_cmd_read;
     47extern uint32_t exit_chdev_server_read;
     48extern uint32_t exit_chdev_cmd_read;
    4949extern uint32_t exit_txt_read;
    50 extern uint32_t exit_devfs_move;
     50extern uint32_t exit_devfs_read;
    5151extern uint32_t exit_sys_read;
    5252
     
    6363    reg_t        save_sr;     // required to enable IRQs during syscall
    6464
    65 #if (CONFIG_DEBUG_SYS_READ & 1)
    66 enter_sys_read = (uint32_t)tm_start;
    67 #endif
    68 
    6965        thread_t  *  this    = CURRENT_THREAD;
    7066        process_t *  process = this->process;
     
    7975#endif
    8076
     77#if (CONFIG_DEBUG_SYS_READ & 1)
     78enter_sys_read = (uint32_t)tm_start;
     79#endif
     80
    8181    // check file_id argument
    8282        if( file_id >= CONFIG_PROCESS_FILE_MAX_NR )
     
    122122
    123123    // get file descriptor cluster and local pointer
    124     vfs_file_t * file_ptr = (vfs_file_t *)GET_PTR( file_xp );
     124    vfs_file_t * file_ptr = GET_PTR( file_xp );
    125125    cxy_t        file_cxy = GET_CXY( file_xp );
    126126
     
    165165    else if( type == INODE_TYPE_DEV )  // check ownership & read from from device
    166166    {
     167        // get cluster and pointers on TXT_RX chdev
     168        xptr_t    chdev_xp  = chdev_from_file( file_xp );
     169        cxy_t     chdev_cxy = GET_CXY( chdev_xp );
     170        chdev_t * chdev_ptr = GET_PTR( chdev_xp );
     171
     172        volatile xptr_t    owner_xp;   
     173
     174        while( 1 )
     175        {
     176            // extended pointer on owner process
     177            owner_xp  = hal_remote_lwd( XPTR( chdev_cxy , &chdev_ptr->ext.txt.owner_xp ) );
     178
     179            // check TXT_RX ownership
     180            if ( XPTR( local_cxy , process ) != owner_xp )
     181            {
     182                // deschedule without blocking
     183                sched_yield( "wait TXT ownership" );
     184            }
     185            else
     186            {
     187                break;
     188            }
     189        }
     190
    167191        // move count bytes from device
    168192        nbytes = devfs_user_move( true,             // from device to buffer
     
    171195                                  count );
    172196
    173         // check ownership
    174         xptr_t    chdev_xp  = chdev_from_file( file_xp );
    175         cxy_t     chdev_cxy = GET_CXY( chdev_xp );
    176         chdev_t * chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
    177         xptr_t    owner_xp  = hal_remote_lwd( XPTR( chdev_cxy , &chdev_ptr->ext.txt.owner_xp ) );
    178 
    179         if( XPTR( local_cxy , process ) != owner_xp )
    180         {
    181 
    182 #if CONFIG_DEBUG_SYSCALLS_ERROR
    183 printk("\n[ERROR] in %s : process %x not in foreground for TXT%d\n",
    184 __FUNCTION__, process->pid, hal_remote_lw( XPTR(chdev_cxy,&chdev_ptr->channel) ) );
    185 #endif
    186                     this->errno = EBADFD;
    187                     return -1;
    188         }
    189197    }
    190198    else
     
    215223printk("\n[DBG] %s : thread %x exit / process %x / cycle %d\n"
    216224"nbytes = %d / first byte = %c / file_id = %d / cost = %d\n",
    217 __FUNCTION__ , local_cxy , this->core->lid , this->trdid , this->process->pid ,
     225__FUNCTION__ , this, process->pid,
    218226(uint32_t)tm_start , nbytes , *((char *)(intptr_t)paddr) , file_id ,
    219227(uint32_t)(tm_end - tm_start) );
  • trunk/kernel/syscalls/sys_thread_cancel.c

    r410 r436  
    11/*
    2  * sys_thread_cancel.c - terminate execution of a target thread.
     2 * sys_thread_cancel.c - terminate execution of an user thread.
    33 *
    4  * Authors   Alain Greiner (2016,2017)
     4 * Authors   Alain Greiner (2016,2017, 2018)
    55 *
    6  * Copyright (c) 2011,2012 UPMC Sorbonne Universites
     6 * Copyright (c) UPMC Sorbonne Universites
    77 *
    88 * This file is part of ALMOS-MKH.
     
    3333{
    3434    xptr_t       target_xp;     // target thread extended pointer
    35         thread_t   * target_ptr;    // target thread local pointer
    36     cxy_t        target_cxy;    // target thread cluster
    37     ltid_t       target_ltid;   // target thread local index
    3835
    39 #if CONFIG_SYSCALL_DEBUG
    40 uint32_t     tm_start;
    41 uint32_t     tm_end;
    42 tm_start  = hal_get_cycles();
    43 #endif
    44 
     36    // get killer thread pointers
    4537        thread_t   * this    = CURRENT_THREAD;
    4638    process_t  * process = this->process;
    47 
    48     // check kernel stack overflow
    49     assert( (this->signature == THREAD_SIGNATURE), __FUNCTION__, "kernel stack overflow\n" );
    50 
    51     // get target thread ltid and cxy
    52     target_ltid = LTID_FROM_TRDID( trdid );
    53     target_cxy  = CXY_FROM_TRDID( trdid );
    54 
    55     // check trdid argument
    56         if( (target_ltid >= CONFIG_THREAD_MAX_PER_CLUSTER) || cluster_is_undefined( target_cxy ) ) 
    57         {
    58         printk("\n[ERROR] in %s : illegal trdid argument\n", __FUNCTION__ );
    59                 this->errno = EINVAL;
    60                 return -1;
    61         }
    6239
    6340    // get extended pointer on target thread
    6441        target_xp  = thread_get_xptr( process->pid , trdid );
    6542
     43    // check target_xp
    6644    if( target_xp == XPTR_NULL )
    6745    {
    68         printk("\n[ERROR] in %s : target thread not found\n", __FUNCTION__ );
     46
     47#if CONFIG_DEBUG_SYSCALLS_ERROR
     48printk("\n[ERROR] in %s : target thread %x not found\n", __FUNCTION__, trdid );
     49#endif
    6950        this->errno = EINVAL;
    7051        return -1;
    7152    }
    7253
    73     // get target thread local pointer
    74     target_ptr = (thread_t *)GET_PTR( target_xp );
     54#if CONFIG_DEBUG_SYS_THREAD_CANCEL
     55uint64_t     tm_start;
     56uint64_t     tm_end;
     57tm_start = hal_get_cycles();
     58if( CONFIG_DEBUG_SYS_THREAD_CANCEL < tm_start )
     59printk("\n[DBG] %s : thread %x enter to kill thread %x / cycle %d\n",
     60__FUCTION__, this, GET_PTR( target_xp ), (uint32_t)tm_start );
     61#endif
    7562
    7663    // cal the relevant kernel function
    77     if( target_cxy == local_cxy )    // target thread is local
    78     {
    79         thread_kill( target_ptr );
    80     }
    81     else
    82     {
    83         rpc_thread_kill_client( target_cxy , target_ptr );
    84     }
     64    thread_kill( target_xp,
     65                 0,           // is_exit
     66                 0 );         // is forced
    8567
    86 #if CONFIG_SYSCALL_DEBUG
     68#if CONFIG_DEBUG_SYS_THREAD_CANCEL
    8769tm_end = hal_get_cycles();
    88 syscall_dmsg("\n[DBG] %s : core[%x,%d] / thread %x in process %x / cycle %d\n"
    89 "thread %x killed / cost = %d\n",
    90 __FUNCTION__ , local_cxy , this->core->lid , this->trdid , this->process->pid , tm_start ,
    91 trdid , (uint32_t)(tm_end - tm_start) );
     70if( CONFIG_DEBUG_SYS_THREAD_CANCEL < tm_end )
     71printk("\n[DBG] %s : thread %x exit after kill thread %x / cycle %d\n",
     72__FUCTION__, this, GET_PTR( target_xp ), (uint32_t)tm_end );
    9273#endif
    9374
  • trunk/kernel/syscalls/sys_thread_exit.c

    r433 r436  
    3232int sys_thread_exit( void * exit_value )
    3333{
    34     paddr_t      paddr;
    35     error_t          error;
    36 
    37 #if CONFIG_SYSCALL_DEBUG
    38 uint32_t     tm_start;
    39 uint32_t     tm_end;
    40 tm_start = hal_get_cycles();
    41 #endif
    42 
    4334        thread_t  * this    = CURRENT_THREAD;
    4435    process_t * process = this->process;
    4536
    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 );
     37    // check exit_value argument
     38    if( exit_value != NULL )
     39    {
     40
     41#if CONFIG_DEBUG_SYSCALLS_ERROR
     42printk("\n[ERROR] in %s : exit_value argument must be NULL for thread %x in process %x\n",
     43__FUNCTION__ , exit_value, this->trdid , process->pid );
     44#endif
    5145        this->errno = EINVAL;
    5246        return -1;
    5347    }
    5448
    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
    59     {
    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         }
    69 
    70         // take the lock protecting the join
    71         remote_spinlock_lock( XPTR( local_cxy, &this->join_lock ) );
    72 
    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 );
    77 
    78             // reset the JOIN_DONE flag in this thread
    79             this->flags &= ~THREAD_FLAG_JOIN_DONE;
    80 
    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 );
    88 
    89             // release the lock protecting the join
    90                 remote_spinlock_unlock( XPTR( local_cxy, &this->join_lock ) );
    91 
    92             // deschedule
    93             sched_yield( "WAITING JOIN" );
    94         }     
    95     }
    96 
    97 #if CONFIG_SYSCALL_DEBUG
    98 tm_end = hal_get_cycles();
    99 syscall_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 ,
    102 this->trdid , (uint32_t)(tm_end - tm_start) );
     49#if CONFIG_DEBUG_SYS_THREAD_EXIT
     50uint64_t     tm_start;
     51uint64_t     tm_end;
     52tm_start = hal_get_cycles();
     53if( CONFIG_DEBUG_SYS_THREAD_EXIT < tm_start )
     54printk("\n[DBG] %s : thread %x enter / process %x / cycle %d\n",
     55__FUNCTION__ , this, process->pid , (uint32_t)tm_start );
    10356#endif
    10457
    105     // suicide using a rpc because  a thread cannot kill itself
    106     rpc_thread_kill_client( local_cxy , this );
     58    // cal the relevant kernel function
     59    thread_kill( XPTR( local_cxy , this ),
     60                 1,           // is_exit
     61                 0 );         // is forced
    10762
     63#if CONFIG_DEBUG_SYS_THREAD_EXIT
     64tm_end = hal_get_cycles();
     65if( CONFIG_DEBUG_SYS_THREAD_EXIT < tm_end )
     66printk("\n[DBG] %s : thread %x exit / process %x / cost %d / cycle %d\n",
     67__FUNCTION__, this, this->process->pid, (uint32_t)(tm_end - tm_start), (uint32_t)tm_end );
     68#endif
     69
     70    // deschedule <=> suicide, because blocked by thread_kill()
     71    sched_yield( "suicide after thread_exit" );
     72   
    10873    return 0;   // never executed but required by compiler
    10974
  • trunk/kernel/syscalls/sys_thread_join.c

    r421 r436  
    2525#include <hal_remote.h>
    2626#include <hal_special.h>
     27#include <hal_irqmask.h>
    2728#include <thread.h>
    2829#include <vmm.h>
     
    3637                      void    ** exit_value )
    3738{
     39    reg_t         save_sr;
    3840    xptr_t        target_xp;
    3941    thread_t    * target_ptr;
    4042    cxy_t         target_cxy;
    4143    ltid_t        target_ltid;
    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()
     44    xptr_t        target_join_lock_xp;
     45    xptr_t        target_flags_xp;
     46    xptr_t        target_blocked_xp;
     47    xptr_t        target_join_xp_xp;
     48    xptr_t        killer_xp;
     49    xptr_t        joining_xp;
     50    thread_t    * joining_ptr;
     51    process_t   * process;
    4552
    46         thread_t    * this    = CURRENT_THREAD;
    47     process_t   * process = this->process;
     53    // get joining thread pointers
     54        joining_ptr = CURRENT_THREAD;
     55    joining_xp  = XPTR( local_cxy , joining_ptr );
     56    process     = joining_ptr->process;
    4857
    4958    // get target thread ltid and cxy
     
    5160    target_cxy  = CXY_FROM_TRDID( trdid );
    5261
     62#if CONFIG_DEBUG_SYS_THREAD_JOIN
     63uint64_t     tm_start;
     64uint64_t     tm_end;
     65tm_start = hal_get_cycles();
     66if( CONFIG_DEBUG_SYS_THREAD_JOIN < tm_start )
     67printk("\n[DBG] %s : parent thread %x enter / process %x / target trdid %x / cycle %d\n",
     68__FUNCTION__ , joining_ptr , process->pid , trdid , (uint32_t)tm_start );
     69#endif
     70
    5371    // check trdid argument
    5472        if( (target_ltid >= CONFIG_THREAD_MAX_PER_CLUSTER) || cluster_is_undefined( target_cxy ) ) 
    5573        {
    56         printk("\n[ERROR] in %s : illegal trdid argument\n", __FUNCTION__ );
    57                 this->errno = EINVAL;
     74
     75#if CONFIG_DEBUG_SYSCALLS_ERROR
     76printk("\n[ERROR] in %s : illegal trdid argument %x\n", __FUNCTION__, trdid );
     77#endif
     78                joining_ptr->errno = EINVAL;
    5879                return -1;
    5980        }
    6081
    6182    // check exit_value argument
    62         if( (exit_value != NULL) && (vmm_v2p_translate( false , exit_value , &paddr ) != 0 ) )
     83        if( exit_value != NULL )
    6384        {
    64         printk("\n[ERROR] in %s : illegal exit_value argument\n", __FUNCTION__ );
    65                 this->errno = EINVAL;
     85
     86#if CONFIG_DEBUG_SYSCALLS_ERROR
     87printk("\n[ERROR] in %s : exit_value argument must be NULL\n", __FUNCTION__ );
     88#endif
     89                joining_ptr->errno = EINVAL;
    6690                return -1;
    6791        }
    6892
    6993    // check target thread != this thread
    70     if( this->trdid == trdid )
     94    if( joining_ptr->trdid == trdid )
    7195    {
    72         printk("\n[ERROR] in %s : this thread == target thread\n", __FUNCTION__ );
    73         this->errno = EDEADLK;
     96
     97#if CONFIG_DEBUG_SYSCALLS_ERROR
     98printk("\n[ERROR] in %s : this thread == target thread\n", __FUNCTION__ );
     99#endif
     100        joining_ptr->errno = EDEADLK;
    74101        return -1;
    75102    }
    76103
    77     // get extended pointer on target thread
     104    // get pointers on target thread
    78105        target_xp  = thread_get_xptr( process->pid , trdid );
     106    target_ptr = GET_PTR( target_xp );
    79107
    80108    if( target_xp == XPTR_NULL )
    81109    {
    82         printk("\n[ERROR] in %s : target thread not found\n", __FUNCTION__ );
    83         this->errno = ESRCH;
     110
     111#if CONFIG_DEBUG_SYSCALLS_ERROR
     112printk("\n[ERROR] in %s : target thread %x not found\n", __FUNCTION__, trdid );
     113#endif
     114        joining_ptr->errno = ESRCH;
    84115        return -1;
    85116    }
    86117
    87     // get cluster and local pointer on target thread
    88     target_ptr = (thread_t *)GET_PTR( target_xp );
     118    // get extended pointers on various fields in target thread
     119    target_join_lock_xp = XPTR( target_cxy , &target_ptr->join_lock );
     120    target_flags_xp     = XPTR( target_cxy , &target_ptr->flags );
     121    target_blocked_xp   = XPTR( target_cxy , &target_ptr->blocked );
     122    target_join_xp_xp   = XPTR( target_cxy , &target_ptr->join_xp );
    89123
    90124    // check target thread joinable
    91     target_flags = hal_remote_lw( XPTR( target_cxy , &target_ptr->flags ) );
    92     if( target_flags & THREAD_FLAG_DETACHED )
     125    if( (hal_remote_lw( target_flags_xp ) & THREAD_FLAG_DETACHED) == 0 )
    93126    {
    94         printk("\n[ERROR] in %s : target thread not joinable\n", __FUNCTION__ );
    95         this->errno = EINVAL;
     127
     128#if CONFIG_DEBUG_SYSCALLS_ERROR
     129printk("\n[ERROR] in %s : target thread %x not joinable\n", __FUNCTION__, trdid );
     130#endif
     131        joining_ptr->errno = EINVAL;
    96132        return -1;
    97133    }
    98134
    99     // check kernel stack overflow
    100     if( target_ptr->signature != THREAD_SIGNATURE )
     135    // mask IRQs
     136    hal_disable_irq( &save_sr );
     137
     138    // get the lock protecting the join in target thread
     139    remote_spinlock_lock( target_join_lock_xp );
     140
     141    // test the kill_done flag from the target thread
     142    if( hal_remote_lw( target_flags_xp ) & THREAD_FLAG_KILL_DONE )  // killer thread is first
    101143    {
    102         assert( false , __FUNCTION__ , "kernel stack overflow\n" );
     144        // get pointers on killer thread
     145        killer_xp  = (xptr_t)hal_remote_lwd( target_join_xp_xp );
     146
     147        // reset the kill_done flag in target thread
     148        hal_remote_atomic_and( target_flags_xp , ~THREAD_FLAG_KILL_DONE );
     149
     150        // unblock the killer thread
     151        thread_unblock( killer_xp , THREAD_BLOCKED_JOIN );
     152
     153        // release the lock protecting join     
     154        remote_spinlock_unlock( target_join_lock_xp );
     155
     156        // restore IRQs
     157        hal_restore_irq( save_sr );
     158    }
     159    else                                                          // joining thread is first
     160    {
     161        // set the join_done flag in target thread
     162        hal_remote_atomic_or( target_flags_xp , THREAD_FLAG_JOIN_DONE );
     163
     164        // block joining thread on BLOCKED_JOIN
     165        thread_block( joining_xp , THREAD_BLOCKED_JOIN );
     166
     167        // register the joining thread extended pointer in target thread
     168        hal_remote_swd( target_join_xp_xp , joining_xp );
     169
     170        // release the lock protecting the join     
     171        remote_spinlock_unlock( target_join_lock_xp );
     172
     173        // deschedule
     174        sched_yield( "joining thread waiting killer thread" );
     175   
     176        // restore IRQs
     177        hal_restore_irq( save_sr );
    103178    }
    104179
    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
    112     {
    113         // unblock the target thread
    114         thread_unblock( target_xp , THREAD_BLOCKED_JOIN );
    115 
    116         // release the lock protecting flags     
    117         remote_spinlock_unlock( XPTR( target_cxy , &target_ptr->join_lock ) );
    118 
    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 ) );
    127 
    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 );
    131 
    132         // block this thread on BLOCKED_EXIT
    133         thread_block( this , THREAD_BLOCKED_EXIT );
    134 
    135         // release the lock protecting flags     
    136         remote_spinlock_unlock( XPTR( target_cxy , &target_ptr->join_lock ) );
    137 
    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 ) );
    143     }
     180#if CONFIG_DEBUG_SYS_THREAD_JOIN
     181tm_end = hal_get_cycles();
     182if( CONFIG_DEBUG_SYS_THREAD_JOIN < tm_end )
     183printk("\n[DBG] %s : parent thread %x exit / process %x / target trdid %x / cycle %d\n",
     184__FUNCTION__, joining_ptr, process->pid, trdid, (uint32_t)tm_end );
     185#endif
    144186
    145187    return 0;
  • trunk/kernel/syscalls/sys_thread_sleep.c

    r408 r436  
    3030int sys_thread_sleep()
    3131{
     32
    3233    thread_t * this = CURRENT_THREAD;
    3334
    34     thread_dmsg("\n[DBG] %s : thread %x in process %x goes to sleep at cycle %d\n",
    35                 __FUNCTION__, this->trdid, this->process->pid, hal_get_cycles() );
     35#if CONFIG_DEBUG_SYS_THREAD_SLEEP
     36uint64_t     tm_start;
     37uint64_t     tm_end;
     38tm_start = hal_get_cycles();
     39if( CONFIG_DEBUG_SYS_THREAD_SLEEP < tm_start )
     40printk("\n[DBG] %s : thread %x blocked / process %x / cycle %d\n",
     41__FUNCTION__ , this, this->process->pid , (uint32_t)tm_start );
     42#endif
    3643
    37     thread_block( this , THREAD_BLOCKED_GLOBAL );
     44    thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_GLOBAL );
    3845    sched_yield("blocked on sleep");
    3946
    40     thread_dmsg("\n[DBG] %s : thread %x in process %x resume at cycle\n",
    41                 __FUNCTION__, this->trdid, this->process->pid, hal_get_cycles() );
     47#if CONFIG_DEBUG_SYS_THREAD_SLEEP
     48tm_end = hal_get_cycles();
     49if( CONFIG_DEBUG_SYS_THREAD_SLEEP < tm_end )
     50printk("\n[DBG] %s : thread %x resume / process %x / cycle %d\n",
     51__FUNCTION__ , this, this->process->pid , (uint32_t)tm_end );
     52#endif
    4253
    4354        return 0;
     55
    4456}  // end sys_thread_sleep()
  • trunk/kernel/syscalls/sys_thread_wakeup.c

    r23 r436  
    3434    process_t * process = this->process;
    3535
     36#if CONFIG_DEBUG_SYS_THREAD_WAKEUP
     37uint64_t     tm_start;
     38uint64_t     tm_end;
     39tm_start = hal_get_cycles();
     40if( CONFIG_DEBUG_SYS_THREAD_WAKEUP < tm_start )
     41printk("\n[DBG] %s : thread %x enter / activate thread %x in process %x / cycle %d\n",
     42__FUNCTION__ , this, trdid, this->process->pid, (uint32_t)tm_start );
     43#endif
     44
    3645    // get target thread ltid and cxy
    3746    ltid_t   target_ltid = LTID_FROM_TRDID( trdid );
     
    4150        if( (target_ltid >= CONFIG_THREAD_MAX_PER_CLUSTER) || cluster_is_undefined( target_cxy ) ) 
    4251        {
    43         printk("\n[ERROR] in %s : illegal trdid argument\n", __FUNCTION__ );
     52
     53#if CONFIG_DEBUG_SISCALLS_ERROR
     54printk("\n[ERROR] in %s : illegal trdid argument %x\n", __FUNCTION__, trdid );
     55#endif
    4456                this->errno = EINVAL;
    4557                return -1;
     
    5163    if( thread_xp == XPTR_NULL )
    5264    {
    53         printk("\n[ERROR] in %s : cannot find thread %x in process %x/n",
    54                __FUNCTION__ , trdid , CURRENT_THREAD->process->pid );
     65
     66#if CONFIG_DEBUG_SISCALLS_ERROR
     67printk("\n[ERROR] in %s : cannot find thread %x in process %x/n",
     68__FUNCTION__ , trdid , this->process->pid );
     69#endif
    5570        CURRENT_THREAD->errno = EINVAL;
    5671        return -1;
     
    6075    thread_unblock( thread_xp , THREAD_BLOCKED_GLOBAL );
    6176
     77#if CONFIG_DEBUG_SYS_THREAD_WAKEUP
     78tm_end = hal_get_cycles();
     79if( CONFIG_DEBUG_SYS_THREAD_WAKEUP < tm_end )
     80printk("\n[DBG] %s : thread %x exit / thread %x in process %x activated / cycle %d\n",
     81__FUNCTION__ , this, trdid, this->process->pid, (uint32_t)tm_end );
     82#endif
     83
    6284    return 0;
     85
    6386}  // end sys_thread_wakeup()
  • trunk/kernel/syscalls/sys_wait.c

    r435 r436  
    6868__FUNCTION__ , this->trdid , process->pid );
    6969#endif
    70         this->errno = EFAULT;
     70        this->errno = EINVAL;
    7171                return -1;
    7272        }
    7373
    74     // get process owner cluster
    75     cxy_t owner_cxy = CXY_FROM_PID( pid );
     74    // get process owner cluster and calling thread trdid
     75    cxy_t   owner_cxy = CXY_FROM_PID( pid );
     76    trdid_t trdid     = this->trdid;
    7677
    77     // This function must be executed in owner cluster
    78     assert( (owner_cxy == local_cxy) , __FUNCTION__ ,
    79     "calling thread must execute in owner cluster" );
     78    // wait must be executed by the main thread
     79    if( (owner_cxy != local_cxy) || (LTID_FROM_TRDID(trdid) != 0) )
     80    {
    8081
    81     // This function must be executed by the main thread
    82     assert( (process->th_tbl[0] == this) , __FUNCTION__ ,
    83     "this function must be executed by the main thread" );
    84    
     82#if CONFIG_DEBUG_SYSCALL_ERROR
     83printk("\n[ERROR] in %s : calling thread %x is not thread 0 in owner cluster %x\n",
     84__FUNCTION__ , trdid , owner_cxy );
     85#endif
     86        this->errno = EINVAL;
     87                return -1;
     88        }
     89
    8590    // get extended pointer on children list root and lock
    8691    xptr_t children_root_xp = XPTR( owner_cxy , &process->children_root );
     
    96101        remote_spinlock_lock( children_lock_xp );
    97102
    98         // scan the list of owner child process
     103        // scan the list of child process
    99104        XLIST_FOREACH( children_root_xp , iter_xp )
    100105        {
     
    115120            {
    116121                // get pointer on main thread and PID from child owner process
    117                 child_pid    = (pid_t)     hal_remote_lw ( XPTR(child_cxy,&child_ptr->pid));
    118                 child_thread = (thread_t *)hal_remote_lpt( XPTR(child_cxy,&child_ptr->th_tbl[0]));
     122                child_pid    = (pid_t)     hal_remote_lw (XPTR( child_cxy , &child_ptr->pid ));
     123                child_thread = (thread_t *)hal_remote_lpt(XPTR( child_cxy ,
     124                                                                &child_ptr->th_tbl[0] ));
    119125
    120126                // set the PROCESS_FLAG_WAIT in owner child descriptor
     
    135141__FUNCTION__, this, process->pid, child_pid, (uint32_t)tm_end );
    136142#endif
    137                  // return relevant info to calling parent process
     143                 // return child termination state  to parent process
    138144                 hal_copy_to_uspace( status , &child_state , sizeof(int) );
    139145                 return child_pid;
    140146            }
    141         }
     147        }  // end loop on children
    142148       
    143149        // release lock protecting children list
  • trunk/kernel/syscalls/syscalls.h

    r435 r436  
    100100/******************************************************************************************
    101101 * [5] This function requests a target thread identified by its <trdid> argument
    102  * to be cancelled. Depending on killer thread and target thread location, it calls
    103  * the thread_kil() function or the rpc_thread_kill_client() function to do the work.
    104  * It actually set the THREAD_SIG_KILL signal, set the THREAD_BLOCKED_GLOBAL bit in the
    105  * target thread descriptor and return.
     102 * to be cancelled. It calls the thread_kill() function to block the target thread
     103 * on the THREAD_BLOCKED_GLOBAL condition, and to set the THREAD_FLAG_REQ_DELETE.
    106104 * The thread will be detached from its process, and the memory allocated to the thread
    107  * descriptor will be released later by the scheduler.
     105 * descriptor will be released by the scheduler at the next scheduling point.
    108106 ******************************************************************************************
    109107 * @ trdid   : thread identifier.
Note: See TracChangeset for help on using the changeset viewer.