2012-06-11 Pedro Alves <palves@redhat.com>

* ser-base.c (run_async_handler_and_reschedule): New.
	(fd_event, push_event): Use it.
	* serial.c (serial_open, serial_fdopen_ops): Set the initial
	reference count to 1.
	(do_serial_close): Set the bufp field to NULL.  Use serial_unref
	instead of xfree.
	(serial_is_open, serial_ref, serial_unref): New.
	* serial.h (serial_open): Adjust comment.
	(serial_is_open): Declare.
	(serial_close): Adjust comment.
	(serial_ref, serial_unref) Declare.
	(struct serial): New field 'refcnt'.
This commit is contained in:
Pedro Alves 2012-06-11 20:36:53 +00:00
parent d5ad6aa5ce
commit ddefb60ff8
4 changed files with 88 additions and 11 deletions

View File

@ -1,3 +1,18 @@
2012-06-11 Pedro Alves <palves@redhat.com>
* ser-base.c (run_async_handler_and_reschedule): New.
(fd_event, push_event): Use it.
* serial.c (serial_open, serial_fdopen_ops): Set the initial
reference count to 1.
(do_serial_close): Set the bufp field to NULL. Use serial_unref
instead of xfree.
(serial_is_open, serial_ref, serial_unref): New.
* serial.h (serial_open): Adjust comment.
(serial_is_open): Declare.
(serial_close): Adjust comment.
(serial_ref, serial_unref) Declare.
(struct serial): New field 'refcnt'.
2012-06-11 Pedro Alves <palves@redhat.com>
Remove #if 0'd "connect" command, and unnecessary associated

View File

@ -123,6 +123,29 @@ reschedule (struct serial *scb)
}
}
/* Run the SCB's async handle, and reschedule, if the handler doesn't
close SCB. */
static void
run_async_handler_and_reschedule (struct serial *scb)
{
int is_open;
/* Take a reference, so a serial_close call within the handler
doesn't make SCB a dangling pointer. */
serial_ref (scb);
/* Run the handler. */
scb->async_handler (scb, scb->async_context);
is_open = serial_is_open (scb);
serial_unref (scb);
/* Get ready for more, if not already closed. */
if (is_open)
reschedule (scb);
}
/* FD_EVENT: This is scheduled when the input FIFO is empty (and there
is no pending error). As soon as data arrives, it is read into the
input FIFO and the client notified. The client should then drain
@ -158,8 +181,7 @@ fd_event (int error, void *context)
scb->bufcnt = SERIAL_ERROR;
}
}
scb->async_handler (scb, scb->async_context);
reschedule (scb);
run_async_handler_and_reschedule (scb);
}
/* PUSH_EVENT: The input FIFO is non-empty (or there is a pending
@ -173,9 +195,7 @@ push_event (void *context)
struct serial *scb = context;
scb->async_state = NOTHING_SCHEDULED; /* Timers are one-off */
scb->async_handler (scb, scb->async_context);
/* re-schedule */
reschedule (scb);
run_async_handler_and_reschedule (scb);
}
/* Wait for input on scb, with timeout seconds. Returns 0 on success,

View File

@ -196,6 +196,7 @@ serial_open (const char *name)
scb->bufcnt = 0;
scb->bufp = scb->buf;
scb->error_fd = -1;
scb->refcnt = 1;
/* `...->open (...)' would get expanded by the open(2) syscall macro. */
if ((*scb->ops->open) (scb, open_name))
@ -245,6 +246,7 @@ serial_fdopen_ops (const int fd, struct serial_ops *ops)
scb->bufcnt = 0;
scb->bufp = scb->buf;
scb->error_fd = -1;
scb->refcnt = 1;
scb->name = NULL;
scb->debug_p = 0;
@ -291,7 +293,10 @@ do_serial_close (struct serial *scb, int really_close)
if (scb->name)
xfree (scb->name);
xfree (scb);
/* For serial_is_open. */
scb->bufp = NULL;
serial_unref (scb);
}
void
@ -306,6 +311,26 @@ serial_un_fdopen (struct serial *scb)
do_serial_close (scb, 0);
}
int
serial_is_open (struct serial *scb)
{
return scb->bufp != NULL;
}
void
serial_ref (struct serial *scb)
{
scb->refcnt++;
}
void
serial_unref (struct serial *scb)
{
--scb->refcnt;
if (scb->refcnt == 0)
xfree (scb);
}
int
serial_readchar (struct serial *scb, int timeout)
{

View File

@ -37,13 +37,18 @@ typedef void *serial_ttystate;
struct serial;
/* Try to open NAME. Returns a new `struct serial *' on success, NULL
on failure. Note that some open calls can block and, if possible,
should be written to be non-blocking, with calls to ui_look_hook
so they can be cancelled. An async interface for open could be
added to GDB if necessary. */
on failure. The new serial object has a reference count of 1.
Note that some open calls can block and, if possible, should be
written to be non-blocking, with calls to ui_look_hook so they can
be cancelled. An async interface for open could be added to GDB if
necessary. */
extern struct serial *serial_open (const char *name);
/* Returns true if SCB is open. */
extern int serial_is_open (struct serial *scb);
/* Find an already opened serial stream using a file handle. */
extern struct serial *serial_for_fd (int fd);
@ -52,10 +57,18 @@ extern struct serial *serial_for_fd (int fd);
extern struct serial *serial_fdopen (const int fd);
/* Push out all buffers, close the device and destroy SCB. */
/* Push out all buffers, close the device and unref SCB. */
extern void serial_close (struct serial *scb);
/* Increment reference count of SCB. */
extern void serial_ref (struct serial *scb);
/* Decrement reference count of SCB. */
extern void serial_unref (struct serial *scb);
/* Create a pipe, and put the read end in files[0], and the write end
in filde[1]. Returns 0 for success, negative value for error (in
which case errno contains the error). */
@ -213,6 +226,10 @@ extern int serial_debug_p (struct serial *scb);
struct serial
{
/* serial objects are ref counted (but not the underlying
connection, just the object's lifetime in memory). */
int refcnt;
int fd; /* File descriptor */
/* File descriptor for a separate error stream that should be
immediately forwarded to gdb_stderr. This may be -1.