1 /* Serial interface for a selectable event. 2 Copyright (C) 2016-2023 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 #include "defs.h" 20 #include "ser-event.h" 21 #include "serial.h" 22 #include "gdbsupport/filestuff.h" 23 24 /* On POSIX hosts, a serial_event is basically an abstraction for the 25 classical self-pipe trick. 26 27 On Windows, a serial_event is a wrapper around a native Windows 28 event object. Because we want to interface with gdb_select, which 29 takes file descriptors, we need to wrap that Windows event object 30 in a file descriptor. As _open_osfhandle can not be used with 31 event objects, we instead create a dummy file wrap that in a file 32 descriptor with _open_osfhandle, and pass that as selectable 33 descriptor to callers. As Windows' gdb_select converts file 34 descriptors back to Windows handles by calling serial->wait_handle, 35 nothing ever actually waits on that file descriptor. */ 36 37 struct serial_event_state 38 { 39 #ifdef USE_WIN32API 40 /* The Windows event object, created with CreateEvent. */ 41 HANDLE event; 42 #else 43 /* The write side of the pipe. The read side is in 44 serial->fd. */ 45 int write_fd; 46 #endif 47 }; 48 49 /* Open a new serial event. */ 50 51 static int 52 serial_event_open (struct serial *scb, const char *name) 53 { 54 struct serial_event_state *state; 55 56 state = XNEW (struct serial_event_state); 57 scb->state = state; 58 59 #ifndef USE_WIN32API 60 { 61 int fds[2]; 62 63 if (gdb_pipe_cloexec (fds) == -1) 64 internal_error ("creating serial event pipe failed."); 65 66 fcntl (fds[0], F_SETFL, O_NONBLOCK); 67 fcntl (fds[1], F_SETFL, O_NONBLOCK); 68 69 scb->fd = fds[0]; 70 state->write_fd = fds[1]; 71 } 72 #else 73 { 74 /* A dummy file object that can be wrapped in a file descriptor. 75 We don't need to store this handle because closing the file 76 descriptor automatically closes this. */ 77 HANDLE dummy_file; 78 79 /* A manual-reset event. */ 80 state->event = CreateEvent (0, TRUE, FALSE, 0); 81 82 /* The dummy file handle. Created just so we have something 83 wrappable in a file descriptor. */ 84 dummy_file = CreateFile ("nul", 0, 0, NULL, OPEN_EXISTING, 0, NULL); 85 scb->fd = _open_osfhandle ((intptr_t) dummy_file, 0); 86 } 87 #endif 88 89 return 0; 90 } 91 92 static void 93 serial_event_close (struct serial *scb) 94 { 95 struct serial_event_state *state = (struct serial_event_state *) scb->state; 96 97 close (scb->fd); 98 #ifndef USE_WIN32API 99 close (state->write_fd); 100 #else 101 CloseHandle (state->event); 102 #endif 103 104 scb->fd = -1; 105 106 xfree (state); 107 scb->state = NULL; 108 } 109 110 #ifdef USE_WIN32API 111 112 /* Implementation of the wait_handle method. Returns the native 113 Windows event object handle. */ 114 115 static void 116 serial_event_wait_handle (struct serial *scb, HANDLE *read, HANDLE *except) 117 { 118 struct serial_event_state *state = (struct serial_event_state *) scb->state; 119 120 *read = state->event; 121 } 122 123 #endif 124 125 /* The serial_ops for struct serial_event objects. Note we never 126 register this serial type with serial_add_interface, because this 127 is internal implementation detail never to be used by remote 128 targets for protocol transport. */ 129 130 static const struct serial_ops serial_event_ops = 131 { 132 "event", 133 serial_event_open, 134 serial_event_close, 135 NULL, /* fdopen */ 136 NULL, /* readchar */ 137 NULL, /* write */ 138 NULL, /* flush_output */ 139 NULL, /* flush_input */ 140 NULL, /* send_break */ 141 NULL, /* go_raw */ 142 NULL, /* get_tty_state */ 143 NULL, /* copy_tty_state */ 144 NULL, /* set_tty_state */ 145 NULL, /* print_tty_state */ 146 NULL, /* setbaudrate */ 147 NULL, /* setstopbits */ 148 NULL, /* setparity */ 149 NULL, /* drain_output */ 150 NULL, /* async */ 151 NULL, /* read_prim */ 152 NULL, /* write_prim */ 153 NULL, /* avail */ 154 #ifdef USE_WIN32API 155 serial_event_wait_handle, 156 #endif 157 }; 158 159 /* See ser-event.h. */ 160 161 struct serial_event * 162 make_serial_event (void) 163 { 164 return (struct serial_event *) serial_open_ops (&serial_event_ops); 165 } 166 167 /* See ser-event.h. */ 168 169 int 170 serial_event_fd (struct serial_event *event) 171 { 172 struct serial *ser = (struct serial *) event; 173 174 return ser->fd; 175 } 176 177 /* See ser-event.h. */ 178 179 void 180 serial_event_set (struct serial_event *event) 181 { 182 struct serial *ser = (struct serial *) event; 183 struct serial_event_state *state = (struct serial_event_state *) ser->state; 184 #ifndef USE_WIN32API 185 int r; 186 char c = '+'; /* Anything. */ 187 188 do 189 { 190 r = write (state->write_fd, &c, 1); 191 } 192 while (r < 0 && errno == EINTR); 193 #else 194 SetEvent (state->event); 195 #endif 196 } 197 198 /* See ser-event.h. */ 199 200 void 201 serial_event_clear (struct serial_event *event) 202 { 203 struct serial *ser = (struct serial *) event; 204 #ifndef USE_WIN32API 205 int r; 206 207 do 208 { 209 char c; 210 211 r = read (ser->fd, &c, 1); 212 } 213 while (r > 0 || (r < 0 && errno == EINTR)); 214 #else 215 struct serial_event_state *state = (struct serial_event_state *) ser->state; 216 ResetEvent (state->event); 217 #endif 218 } 219