/*
 * alarm.h - timer based kernel alarm specification            
 *
 * Author     Alain Greiner (2016,2017,2018,2019,2020)
 *
 * 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
 */


#ifndef _ALARM_H_
#define _ALARM_H_

#include <hal_kernel_types.h>
#include <list.h>

/****  Forward declarations  ****/

struct  thread_s;

/******************************************************************************************
 *   This structure defines a generic, timer based, kernel alarm.
 *
 * - An alarm being attached to a given thread, the alarm descriptor is embedded in the
 *   thread descriptor. A client thread can use the alarm_start() function to dynamically
 *   activate the alarm. It can use the alarm_stop() function to desactivate this alarm.
 * - This kernel alarm is generic, as the alarm handler (executed when the alarm rings),
 *   and the handler arguments are defined by two pointers <func_ptr> and <args_xp>.
 * - When an alarm is created by a client thread, it is registered in the list of alarms
 *   rooted in the core running the client thread. When it is stopped, the alarm is simply
 *   removed from this list.
 * - When creating an alarm, the client thread must define an absolute date (in cycles),
 *   the func_ptr local pointer, and the args_xp extended pointer.
 * - The list of alarms is ordered by increasing dates. At each TICK received by a core,
 *   the date of the first registered alarm is compared to the current date (in the 
 *   core_clock() function). The alarm handler is executed when current_date >= alarm_date.
 * - It is the handler responsability to stop a ringing alarm, or update the date.  
 * 
 * This mechanism is used bi the almos_mkh implementation of the TCP protocoL.
 ******************************************************************************************/

typedef struct alarm_s
{
    cycle_t        date;           /*! absolute date for handler execution                */
    void         * func_ptr;       /*! local pointer on alarm handler function            */
    xptr_t         args_xp;        /*! local pointer on handler arguments                 */
    list_entry_t   list;           /*! all alarms attached to the same core               */
}
alarm_t;

/*******************************************************************************************
 * This defines the generic prototype for an alarm handler.
 ******************************************************************************************/

typedef void (alarm_handler_t) ( xptr_t args_xp );

/*******************************************************************************************
 * This function initializes the alarm descriptor embedded in the thread identified by the
 * <thread> argument from the <date>, <func_ptr>, <args_ptr> arguments, and registers it
 * in the ordered list rooted in the core running this <thread>.
 *******************************************************************************************
 * @ date       : absolute date (in cycles).
 * @ func_ptr   : local pointer on the handler to execute when the alarm rings.
 * @ args_xp    : extended pointer on the handler arguments.
 * @ thread     : local pointer on the client thread.
 ******************************************************************************************/
void alarm_start( cycle_t           date,
                  void            * func_ptr,
                  xptr_t            args_xp,
                  struct thread_s * thread );

/*******************************************************************************************
 * This function updates the date of the alarm attached to the thread identified by the
 * <thread> argument. The list of alarms rooted in the core running the client thread 
 * is modified to respect the absolute dates ordering.
 *******************************************************************************************
 * @ thread     : local pointer on the client thread.
 * @ new_date   : absolute new date (in cycles).
 ******************************************************************************************/
void alarm_update( struct thread_s * thread,
                   cycle_t           new_date );

/*******************************************************************************************
 * This function unlink an alarm identified by the <thread> argument from the list of
 * alarms rooted in the core descriptor.
 *******************************************************************************************
 * @ thread     : local pointer on the client thread.
 ******************************************************************************************/
void alarm_stop( struct thread_s * thread );


#endif	/* _ALARM_H_ */
