/* * sys_thread_exit.c - terminates the execution of current thread * * Authors Ghassan Almaless (2008,2009,2010,2011,2012) * Alain Greiner (2016,2017) * * Copyright (c) UPMC Sorbonne Universites * * This file is part of ALMOS-MKH. * * ALMOS-MKH is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2.0 of the License. * * ALMOS-MKH is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ALMOS-MKH; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include //////////////////////////////////////// int sys_thread_exit( void * exit_value ) { thread_t * this = CURRENT_THREAD; core_t * core = this->core; reg_t irq_state; // register the exit_value pointer in thread descriptor this->exit_value = exit_value; // enter the join loop to wait the join if thread is joinable if( (this->flags & THREAD_FLAG_DETACHED) == 0 ) { while( 1 ) { // take the lock protecting the flags remote_spinlock_lock( XPTR( local_cxy, &this->flags_lock ) ); // check the JOIN flag if( this->flags & THREAD_FLAG_JOIN ) // parent made a join { // unblock the parent thread thread_unblock( this->parent , THREAD_BLOCKED_JOIN ); // release the lock protecting the flags remote_spinlock_unlock( XPTR( local_cxy, &this->flags_lock ) ); // exit while break; } else // no join done by parent thread { // set the EXIT flag this->flags |= THREAD_FLAG_EXIT; // block this thread thread_block( this , THREAD_BLOCKED_EXIT ); // release the lock protecting the flags remote_spinlock_unlock( XPTR( local_cxy, &this->flags_lock ) ); // deschedule sched_yield("waiting parent join"); } } } // Release FPU if required hal_disable_irq( &irq_state ); if( core->fpu_owner == this ) core->fpu_owner = NULL; hal_restore_irq( irq_state ); // suicide thread_kill( this ); return 0; } // end sys_thread_exit()