/* Event loop machinery for the remote server for GDB.
   Copyright (C) 1999-2013 Free Software Foundation, Inc.

   This file is part of GDB.

   This program 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; either version 3 of the License, or
   (at your option) any later version.

   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>. */

/* Based on src/gdb/event-loop.c.  */

#include "server.h"
#include "queue.h"

#include <sys/types.h>
#include <string.h>
#include <sys/time.h>

#ifdef USE_WIN32API
#include <windows.h>
#include <io.h>
#endif

#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

typedef struct gdb_event gdb_event;
typedef int (event_handler_func) (gdb_fildes_t);

/* Tell create_file_handler what events we are interested in.  */

#define GDB_READABLE	(1<<1)
#define GDB_WRITABLE	(1<<2)
#define GDB_EXCEPTION	(1<<3)

/* Events are queued by calling 'QUEUE_enque (gdb_event_p, event_queue,
   file_event_ptr)' and serviced later
   on by do_one_event.  An event can be, for instance, a file
   descriptor becoming ready to be read.  Servicing an event simply
   means that the procedure PROC will be called.  We have 2 queues,
   one for file handlers that we listen to in the event loop, and one
   for the file handlers+events that are ready.  The procedure PROC
   associated with each event is always the same (handle_file_event).
   Its duty is to invoke the handler associated with the file
   descriptor whose state change generated the event, plus doing other
   cleanups and such.  */

typedef struct gdb_event
  {
    /* Procedure to call to service this event.  */
    event_handler_func *proc;

    /* File descriptor that is ready.  */
    gdb_fildes_t fd;
  } *gdb_event_p;

/* Information about each file descriptor we register with the event
   loop.  */

typedef struct file_handler
  {
    /* File descriptor.  */
    gdb_fildes_t fd;

    /* Events we want to monitor.  */
    int mask;

    /* Events that have been seen since the last time.  */
    int ready_mask;

    /* Procedure to call when fd is ready.  */
    handler_func *proc;

    /* Argument to pass to proc.  */
    gdb_client_data client_data;

    /* Was an error detected on this fd?  */
    int error;

    /* Next registered file descriptor.  */
    struct file_handler *next_file;
  }
file_handler;

DECLARE_QUEUE_P(gdb_event_p);
static QUEUE(gdb_event_p) *event_queue = NULL;
DEFINE_QUEUE_P(gdb_event_p);

/* Gdb_notifier is just a list of file descriptors gdb is interested
   in.  These are the input file descriptor, and the target file
   descriptor.  Each of the elements in the gdb_notifier list is
   basically a description of what kind of events gdb is interested
   in, for each fd.  */

static struct
  {
    /* Ptr to head of file handler list.  */
    file_handler *first_file_handler;

    /* Masks to be used in the next call to select.  Bits are set in
       response to calls to create_file_handler.  */
    fd_set check_masks[3];

    /* What file descriptors were found ready by select.  */
    fd_set ready_masks[3];

    /* Number of valid bits (highest fd value + 1). (for select) */
    int num_fds;
  }
gdb_notifier;

/* Callbacks are just routines that are executed before waiting for the
   next event.  In GDB this is struct gdb_timer.  We don't need timers
   so rather than copy all that complexity in gdbserver, we provide what
   we need, but we do so in a way that if/when the day comes that we need
   that complexity, it'll be easier to add - replace callbacks with timers
   and use a delta of zero (which is all gdb currently uses timers for anyway).

   PROC will be executed before gdbserver goes to sleep to wait for the
   next event.  */

struct callback_event
  {
    int id;
    callback_handler_func *proc;
    gdb_client_data *data;
    struct callback_event *next;
  };

/* Table of registered callbacks.  */

static struct
  {
    struct callback_event *first;
    struct callback_event *last;

    /* Id of the last callback created.  */
    int num_callbacks;
  }
callback_list;

/* Free EVENT.  */

static void
gdb_event_xfree (struct gdb_event *event)
{
  xfree (event);
}

void
initialize_event_loop (void)
{
  event_queue = QUEUE_alloc (gdb_event_p, gdb_event_xfree);
}

/* Process one event.  If an event was processed, 1 is returned
   otherwise 0 is returned.  Scan the queue from head to tail,
   processing therefore the high priority events first, by invoking
   the associated event handler procedure.  */

static int
process_event (void)
{
  /* Let's get rid of the event from the event queue.  We need to
     do this now because while processing the event, since the
     proc function could end up jumping out to the caller of this
     function.  In that case, we would have on the event queue an
     event which has been processed, but not deleted.  */
  if (!QUEUE_is_empty (gdb_event_p, event_queue))
    {
      gdb_event *event_ptr = QUEUE_deque (gdb_event_p, event_queue);
      event_handler_func *proc = event_ptr->proc;
      gdb_fildes_t fd = event_ptr->fd;

      gdb_event_xfree (event_ptr);
      /* Now call the procedure associated with the event.  */
      if ((*proc) (fd))
	return -1;
      return 1;
    }

  /* This is the case if there are no event on the event queue.  */
  return 0;
}

/* Append PROC to the callback list.
   The result is the "id" of the callback that can be passed back to
   delete_callback_event.  */

int
append_callback_event (callback_handler_func *proc, gdb_client_data data)
{
  struct callback_event *event_ptr;

  event_ptr = xmalloc (sizeof (*event_ptr));
  event_ptr->id = callback_list.num_callbacks++;
  event_ptr->proc = proc;
  event_ptr->data = data;
  event_ptr->next = NULL;
  if (callback_list.first == NULL)
    callback_list.first = event_ptr;
  if (callback_list.last != NULL)
    callback_list.last->next = event_ptr;
  callback_list.last = event_ptr;
  return event_ptr->id;
}

/* Delete callback ID.
   It is not an error callback ID doesn't exist.  */

void
delete_callback_event (int id)
{
  struct callback_event **p;

  for (p = &callback_list.first; *p != NULL; p = &(*p)->next)
    {
      struct callback_event *event_ptr = *p;

      if (event_ptr->id == id)
	{
	  *p = event_ptr->next;
	  if (event_ptr == callback_list.last)
	    callback_list.last = NULL;
	  free (event_ptr);
	  break;
	}
    }
}

/* Run the next callback.
   The result is 1 if a callback was called and event processing
   should continue, -1 if the callback wants the event loop to exit,
   and 0 if there are no more callbacks.  */

static int
process_callback (void)
{
  struct callback_event *event_ptr;

  event_ptr = callback_list.first;
  if (event_ptr != NULL)
    {
      callback_handler_func *proc = event_ptr->proc;
      gdb_client_data *data = event_ptr->data;

      /* Remove the event before calling PROC,
	 more events may get added by PROC.  */
      callback_list.first = event_ptr->next;
      if (callback_list.first == NULL)
	callback_list.last = NULL;
      free  (event_ptr);
      if ((*proc) (data))
	return -1;
      return 1;
    }

  return 0;
}

/* Add a file handler/descriptor to the list of descriptors we are
   interested in.  FD is the file descriptor for the file/stream to be
   listened to.  MASK is a combination of READABLE, WRITABLE,
   EXCEPTION.  PROC is the procedure that will be called when an event
   occurs for FD.  CLIENT_DATA is the argument to pass to PROC.  */

static void
create_file_handler (gdb_fildes_t fd, int mask, handler_func *proc,
		     gdb_client_data client_data)
{
  file_handler *file_ptr;

  /* Do we already have a file handler for this file? (We may be
     changing its associated procedure).  */
  for (file_ptr = gdb_notifier.first_file_handler;
       file_ptr != NULL;
       file_ptr = file_ptr->next_file)
    if (file_ptr->fd == fd)
      break;

  /* It is a new file descriptor.  Add it to the list.  Otherwise,
     just change the data associated with it.  */
  if (file_ptr == NULL)
    {
      file_ptr = xmalloc (sizeof (*file_ptr));
      file_ptr->fd = fd;
      file_ptr->ready_mask = 0;
      file_ptr->next_file = gdb_notifier.first_file_handler;
      gdb_notifier.first_file_handler = file_ptr;

      if (mask & GDB_READABLE)
	FD_SET (fd, &gdb_notifier.check_masks[0]);
      else
	FD_CLR (fd, &gdb_notifier.check_masks[0]);

      if (mask & GDB_WRITABLE)
	FD_SET (fd, &gdb_notifier.check_masks[1]);
      else
	FD_CLR (fd, &gdb_notifier.check_masks[1]);

      if (mask & GDB_EXCEPTION)
	FD_SET (fd, &gdb_notifier.check_masks[2]);
      else
	FD_CLR (fd, &gdb_notifier.check_masks[2]);

      if (gdb_notifier.num_fds <= fd)
	gdb_notifier.num_fds = fd + 1;
    }

  file_ptr->proc = proc;
  file_ptr->client_data = client_data;
  file_ptr->mask = mask;
}

/* Wrapper function for create_file_handler.  */

void
add_file_handler (gdb_fildes_t fd,
		  handler_func *proc, gdb_client_data client_data)
{
  create_file_handler (fd, GDB_READABLE | GDB_EXCEPTION, proc, client_data);
}

/* Remove the file descriptor FD from the list of monitored fd's:
   i.e. we don't care anymore about events on the FD.  */

void
delete_file_handler (gdb_fildes_t fd)
{
  file_handler *file_ptr, *prev_ptr = NULL;
  int i;

  /* Find the entry for the given file. */

  for (file_ptr = gdb_notifier.first_file_handler;
       file_ptr != NULL;
       file_ptr = file_ptr->next_file)
    if (file_ptr->fd == fd)
      break;

  if (file_ptr == NULL)
    return;

  if (file_ptr->mask & GDB_READABLE)
    FD_CLR (fd, &gdb_notifier.check_masks[0]);
  if (file_ptr->mask & GDB_WRITABLE)
    FD_CLR (fd, &gdb_notifier.check_masks[1]);
  if (file_ptr->mask & GDB_EXCEPTION)
    FD_CLR (fd, &gdb_notifier.check_masks[2]);

  /* Find current max fd.  */

  if ((fd + 1) == gdb_notifier.num_fds)
    {
      gdb_notifier.num_fds--;
      for (i = gdb_notifier.num_fds; i; i--)
	{
	  if (FD_ISSET (i - 1, &gdb_notifier.check_masks[0])
	      || FD_ISSET (i - 1, &gdb_notifier.check_masks[1])
	      || FD_ISSET (i - 1, &gdb_notifier.check_masks[2]))
	    break;
	}
      gdb_notifier.num_fds = i;
    }

  /* Deactivate the file descriptor, by clearing its mask, so that it
     will not fire again.  */

  file_ptr->mask = 0;

  /* Get rid of the file handler in the file handler list.  */
  if (file_ptr == gdb_notifier.first_file_handler)
    gdb_notifier.first_file_handler = file_ptr->next_file;
  else
    {
      for (prev_ptr = gdb_notifier.first_file_handler;
	   prev_ptr->next_file != file_ptr;
	   prev_ptr = prev_ptr->next_file)
	;
      prev_ptr->next_file = file_ptr->next_file;
    }
  free (file_ptr);
}

/* Handle the given event by calling the procedure associated to the
   corresponding file handler.  Called by process_event indirectly,
   through event_ptr->proc.  EVENT_FILE_DESC is file descriptor of the
   event in the front of the event queue.  */

static int
handle_file_event (gdb_fildes_t event_file_desc)
{
  file_handler *file_ptr;
  int mask;

  /* Search the file handler list to find one that matches the fd in
     the event.  */
  for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL;
       file_ptr = file_ptr->next_file)
    {
      if (file_ptr->fd == event_file_desc)
	{
	  /* See if the desired events (mask) match the received
	     events (ready_mask).  */

	  if (file_ptr->ready_mask & GDB_EXCEPTION)
	    {
	      fprintf (stderr, "Exception condition detected on fd %s\n",
		       pfildes (file_ptr->fd));
	      file_ptr->error = 1;
	    }
	  else
	    file_ptr->error = 0;
	  mask = file_ptr->ready_mask & file_ptr->mask;

	  /* Clear the received events for next time around.  */
	  file_ptr->ready_mask = 0;

	  /* If there was a match, then call the handler.  */
	  if (mask != 0)
	    {
	      if ((*file_ptr->proc) (file_ptr->error,
				     file_ptr->client_data) < 0)
		return -1;
	    }
	  break;
	}
    }

  return 0;
}

/* Create a file event, to be enqueued in the event queue for
   processing.  The procedure associated to this event is always
   handle_file_event, which will in turn invoke the one that was
   associated to FD when it was registered with the event loop.  */

static gdb_event *
create_file_event (gdb_fildes_t fd)
{
  gdb_event *file_event_ptr;

  file_event_ptr = xmalloc (sizeof (gdb_event));
  file_event_ptr->proc = handle_file_event;
  file_event_ptr->fd = fd;
  return file_event_ptr;
}

/* Called by do_one_event to wait for new events on the monitored file
   descriptors.  Queue file events as they are detected by the poll.
   If there are no events, this function will block in the call to
   select.  Return -1 if there are no files descriptors to monitor,
   otherwise return 0.  */

static int
wait_for_event (void)
{
  file_handler *file_ptr;
  int num_found = 0;

  /* Make sure all output is done before getting another event.  */
  fflush (stdout);
  fflush (stderr);

  if (gdb_notifier.num_fds == 0)
    return -1;

  gdb_notifier.ready_masks[0] = gdb_notifier.check_masks[0];
  gdb_notifier.ready_masks[1] = gdb_notifier.check_masks[1];
  gdb_notifier.ready_masks[2] = gdb_notifier.check_masks[2];
  num_found = select (gdb_notifier.num_fds,
		      &gdb_notifier.ready_masks[0],
		      &gdb_notifier.ready_masks[1],
		      &gdb_notifier.ready_masks[2],
		      NULL);

  /* Clear the masks after an error from select.  */
  if (num_found == -1)
    {
      FD_ZERO (&gdb_notifier.ready_masks[0]);
      FD_ZERO (&gdb_notifier.ready_masks[1]);
      FD_ZERO (&gdb_notifier.ready_masks[2]);
#ifdef EINTR
      /* Dont print anything if we got a signal, let gdb handle
	 it.  */
      if (errno != EINTR)
	perror_with_name ("select");
#endif
    }

  /* Enqueue all detected file events.  */

  for (file_ptr = gdb_notifier.first_file_handler;
       file_ptr != NULL && num_found > 0;
       file_ptr = file_ptr->next_file)
    {
      int mask = 0;

      if (FD_ISSET (file_ptr->fd, &gdb_notifier.ready_masks[0]))
	mask |= GDB_READABLE;
      if (FD_ISSET (file_ptr->fd, &gdb_notifier.ready_masks[1]))
	mask |= GDB_WRITABLE;
      if (FD_ISSET (file_ptr->fd, &gdb_notifier.ready_masks[2]))
	mask |= GDB_EXCEPTION;

      if (!mask)
	continue;
      else
	num_found--;

      /* Enqueue an event only if this is still a new event for this
	 fd.  */

      if (file_ptr->ready_mask == 0)
	{
	  gdb_event *file_event_ptr = create_file_event (file_ptr->fd);

	  QUEUE_enque (gdb_event_p, event_queue, file_event_ptr);
	}
      file_ptr->ready_mask = mask;
    }

  return 0;
}

/* Start up the event loop.  This is the entry point to the event
   loop.  */

void
start_event_loop (void)
{
  /* Loop until there is nothing to do.  This is the entry point to
     the event loop engine.  If nothing is ready at this time, wait
     for something to happen (via wait_for_event), then process it.
     Return when there are no longer event sources to wait for.  */

  while (1)
    {
      /* Any events already waiting in the queue?  */
      int res = process_event ();

      /* Did the event handler want the event loop to stop?  */
      if (res == -1)
	return;

      if (res)
	continue;

      /* Process any queued callbacks before we go to sleep.  */
      res = process_callback ();

      /* Did the callback want the event loop to stop?  */
      if (res == -1)
	return;

      if (res)
	continue;

      /* Wait for a new event.  If wait_for_event returns -1, we
	 should get out because this means that there are no event
	 sources left.  This will make the event loop stop, and the
	 application exit.  */

      if (wait_for_event () < 0)
	return;
    }

  /* We are done with the event loop.  There are no more event sources
     to listen to.  So we exit gdbserver.  */
}
