1 /* Notification to GDB. 2 Copyright (C) 1989-2024 Free Software Foundation, Inc. 3 4 This file is part of GDB. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 18 19 /* Async notifications to GDB. When the state of remote target is 20 changed or something interesting to GDB happened, async 21 notifications are used to tell GDB. 22 23 Each type of notification is represented by an object 24 'struct notif_server', in which there is a queue for events to GDB 25 represented by 'struct notif_event'. GDBserver writes (by means of 26 'write' field) each event in the queue into the buffer and send the 27 contents in buffer to GDB. The contents in buffer is specified in 28 RSP. See more in the comments to field 'queue' of 29 'struct notif_server'. 30 31 Here is the workflow of sending events and managing queue: 32 1. At any time, when something interesting FOO happens, a object 33 of 'struct notif_event' or its sub-class EVENT is created for FOO. 34 35 2. Enque EVENT to the 'queue' field of 'struct notif_server' for 36 FOO and send corresponding notification packet to GDB if EVENT is 37 the first one. 38 #1 and #2 are done by function 'notif_push'. 39 40 3. EVENT is not deque'ed until the ack of FOO from GDB arrives. 41 Before ack of FOO arrives, FOO happens again, a new object of 42 EVENT is created and enque EVENT silently. 43 Once GDB has a chance to ack to FOO, it sends an ack to GDBserver, 44 and GDBserver repeatedly sends events to GDB and gets ack of FOO, 45 until queue is empty. Then, GDBserver sends 'OK' to GDB that all 46 queued notification events are done. 47 48 # 3 is done by function 'handle_notif_ack'. */ 49 50 #include "notif.h" 51 52 static struct notif_server *notifs[] = 53 { 54 ¬if_stop, 55 }; 56 57 /* Write another event or an OK, if there are no more left, to 58 OWN_BUF. */ 59 60 void 61 notif_write_event (struct notif_server *notif, char *own_buf) 62 { 63 if (!notif->queue.empty ()) 64 { 65 struct notif_event *event = notif->queue.front (); 66 67 notif->write (event, own_buf); 68 } 69 else 70 write_ok (own_buf); 71 } 72 73 /* Handle the ack in buffer OWN_BUF,and packet length is PACKET_LEN. 74 Return 1 if the ack is handled, and return 0 if the contents 75 in OWN_BUF is not a ack. */ 76 77 int 78 handle_notif_ack (char *own_buf, int packet_len) 79 { 80 size_t i; 81 struct notif_server *np; 82 83 for (i = 0; i < ARRAY_SIZE (notifs); i++) 84 { 85 const char *ack_name = notifs[i]->ack_name; 86 87 if (startswith (own_buf, ack_name) 88 && packet_len == strlen (ack_name)) 89 break; 90 } 91 92 if (i == ARRAY_SIZE (notifs)) 93 return 0; 94 95 np = notifs[i]; 96 97 /* If we're waiting for GDB to acknowledge a pending event, 98 consider that done. */ 99 if (!np->queue.empty ()) 100 { 101 struct notif_event *head = np->queue.front (); 102 np->queue.pop_front (); 103 104 remote_debug_printf ("%s: acking %d", np->ack_name, 105 (int) np->queue.size ()); 106 107 delete head; 108 } 109 110 notif_write_event (np, own_buf); 111 112 return 1; 113 } 114 115 /* Put EVENT to the queue of NOTIF. */ 116 117 void 118 notif_event_enque (struct notif_server *notif, 119 struct notif_event *event) 120 { 121 notif->queue.push_back (event); 122 123 remote_debug_printf ("pending events: %s %d", notif->notif_name, 124 (int) notif->queue.size ()); 125 126 } 127 128 /* Push one event NEW_EVENT of notification NP into NP->queue. */ 129 130 void 131 notif_push (struct notif_server *np, struct notif_event *new_event) 132 { 133 bool is_first_event = np->queue.empty (); 134 135 /* Something interesting. Tell GDB about it. */ 136 notif_event_enque (np, new_event); 137 138 /* If this is the first stop reply in the queue, then inform GDB 139 about it, by sending a corresponding notification. */ 140 if (is_first_event) 141 { 142 char buf[PBUFSIZ]; 143 char *p = buf; 144 145 xsnprintf (p, PBUFSIZ, "%s:", np->notif_name); 146 p += strlen (p); 147 148 np->write (new_event, p); 149 putpkt_notif (buf); 150 } 151 } 152