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:
parent
d5ad6aa5ce
commit
ddefb60ff8
4 changed files with 88 additions and 11 deletions
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
27
gdb/serial.c
27
gdb/serial.c
|
@ -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)
|
||||
{
|
||||
|
|
27
gdb/serial.h
27
gdb/serial.h
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue