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

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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;
Note: See TracChangeset for help on using the changeset viewer.