/*
 * signal.c - signal-management related operations implementation
 * 
 * Author  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 <hal_types.h>
#include <hal_atomic.h>
#include <printk.h>
#include <thread.h>
#include <spinlock.h>
#include <signal.h>

//////////////////////////////////////
void signal_rise( process_t * process, 
                  uint32_t    sig_id )
{
    // get the lock protecting the set of local threads
	spinlock_lock( &process->th_lock );

    // loop on local threads
	thread_t * thread;
	uint32_t   i;
	for( i = 0 ; i < process->th_nr ; i++ )
	{
		thread = process->th_tbl[i];
		hal_atomic_or( &thread->signals , (1 << sig_id) );

        signal_dmsg("\n[INFO] %s : thread %x in process %x received signal %d\n",
                    __FUNCTION__, thread->trdid , process->pid , sig_id );
	}

    // release the lock
	spinlock_unlock( &process->th_lock );

}  // end signal_rise()

/*

SIGNAL_HANDLER(kill_sigaction)
{
	thread_s * this = CURRENT_THREAD;

	printk("\n[INFO] %s : threadReceived signal %d, pid %d, tid %x, core %d  [ KILLED ]\n",
	       sig,
	       this->process->pid,
	       this,
	       cpu_get_id());

	sys_thread_exit((void*)EINTR);
}

///////////////////////////////////////////////
void signal_manager_init( process_t * process )
{
	memset(&process->sig_mgr, 0, sizeof(process->sig_mgr));
	process->sig_mgr.sigactions[SIGCHLD] = SIG_IGNORE;
	process->sig_mgr.sigactions[SIGURG]  = SIG_IGNORE;
}


/////////////////////////////////////
void signal_notify( thread_t * this )
{
	uint32_t     sig_state;
	uint32_t     sig;
	sig_mgr_t  * sig_mgr;
	uint32_t     irq_state;

	sig_state = this->signals;
	sig       = 0;
 
	while((sig_state != 0) && ((sig_state & 0x1) == 0) && (sig < SIG_NR))
	{
		sig ++; 
		sig_state >>= 1;
	}
  
	if(sig)
	{
		cpu_disable_all_irq(&irq_state);

		if(thread_isSignaled(this))
		{
			cpu_restore_irq(irq_state);
			return;
		}

		thread_set_signaled(this);
		cpu_restore_irq(irq_state);

		spinlock_lock(&this->lock);
		this->info.sig_state &= ~(1 << sig);
		spinlock_unlock(&this->lock);

		sig_mgr = &this->process->sig_mgr;

		if(sig_mgr->sigactions[sig] == SIG_IGNORE)
			return;

		if(sig_mgr->sigactions[sig] == SIG_DEFAULT)
			kill_sigaction(sig);

		cpu_signal_notify(this, sig_mgr->sigactions[sig], sig);
	}
}
*/
