/*
 * 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 is attached to a given thread, and 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 with the alarm_start() function, the client thread must define
 *   an absolute date (in cycles), the func_ptr 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 and delete a ringing alarm using the
 *   alarm_stop() function, or update the alarm date using the alarm_update() function.  
 * - The three alarm_start(), alarm_stop(), and alarm_update() access functions use
 *   the lock protecting the alarms list to handle concurrent accesses. These functions
 *   use extended pointers to access the alarm list, and can be called by a thread
 *   running in any cluster.
 * 
 * This embedded alarm mechanism is used by:
 * 1. the socket_accept(), socket_connect(), socket_send(), socket_close() functions,
 *    to implement the TCP retransmission machanism.
 * 2. the sys_thread_sleep() function, to implement the "sleep" mechanism.
 ******************************************************************************************/

typedef struct alarm_s
{
    bool_t         linked;         /*! active when true (i.e linked to the core list)     */
    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;           /*! set of active 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 initialises the alarm state to "inactive".
 *******************************************************************************************
 * @ alarm     : local pointer on alarm.
 ******************************************************************************************/
void alarm_init( alarm_t *  alarm );

/*******************************************************************************************
 * This function initializes the alarm descriptor embedded in the thread identified by the
 * <thread_xp> argument from the <date>, <func_ptr>, <args_ptr> arguments, and registers
 * this alarm in the ordered list rooted in the core running this thread.
 * It takes the lock protecting the alarms list against concurrent accesses.
 *******************************************************************************************
 * @ thread_xp  : extended pointer on the target 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.
 ******************************************************************************************/
void alarm_start( xptr_t    thread_xp, 
                  cycle_t   date,
                  void    * func_ptr,
                  xptr_t    args_xp );

/*******************************************************************************************
 * 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.
 * It takes the lock protecting the alarms list against concurrent accesses.
 *******************************************************************************************
 * @ thread_xp  : extended pointer on the target thread.
 * @ new_date   : absolute new date (in cycles).
 ******************************************************************************************/
void alarm_update( xptr_t     thread_xp,
                   cycle_t    new_date );

/*******************************************************************************************
 * This function unlink an alarm identified by the <thread> argument from the list of
 * alarms rooted in the core descriptor.
 * It takes the lock protecting the alarms list against concurrent accesses.
 *******************************************************************************************
 * @ thread_xp  : extended pointer on the target thread.
 ******************************************************************************************/
void alarm_stop( xptr_t    thread_xp );


#endif	/* _ALARM_H_ */
