diff options
author | Doug Evans <dje@google.com> | 2010-05-03 20:53:21 +0000 |
---|---|---|
committer | Doug Evans <dje@google.com> | 2010-05-03 20:53:21 +0000 |
commit | 24b066ba2b90ef215c6c414ae1d15f79a8addefc (patch) | |
tree | f27d08952131519af6cbcb930aefad2ff9cd3496 /gdb/gdbserver/event-loop.c | |
parent | 1ac77ea1639caba28809b36835f0c97c29a32378 (diff) | |
download | gdb-24b066ba2b90ef215c6c414ae1d15f79a8addefc.zip gdb-24b066ba2b90ef215c6c414ae1d15f79a8addefc.tar.gz gdb-24b066ba2b90ef215c6c414ae1d15f79a8addefc.tar.bz2 |
* event-loop.c (struct callback_event): New struct.
(callback_list): New global.
(append_callback_event, delete_callback_event): New functions.
(process_callback): New function.
(start_event_loop): Call it.
* remote-utils.c (NOT_SCHEDULED): Define.
(readchar_buf, readchar_bufcnt, readchar_bufp): New static globals,
moved out of readchar.
(readchar): Rewrite. Call reschedule before returning.
(reset_readchar): New function.
(remote_close): Call it.
(process_remaining, reschedule): New functions.
* server.h (callback_handler_func): New typedef.
(append_callback_event, delete_callback_event): Declare.
Diffstat (limited to 'gdb/gdbserver/event-loop.c')
-rw-r--r-- | gdb/gdbserver/event-loop.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/gdb/gdbserver/event-loop.c b/gdb/gdbserver/event-loop.c index 6471772..bc5c1f7 100644 --- a/gdb/gdbserver/event-loop.c +++ b/gdb/gdbserver/event-loop.c @@ -141,6 +141,36 @@ static struct } 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; + /* Insert an event object into the gdb event queue. EVENT_PTR points to the event to be inserted into the queue. The @@ -220,6 +250,81 @@ process_event (void) 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, @@ -507,6 +612,16 @@ start_event_loop (void) 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 |