1 /* Serial interface for a selectable event. 2 Copyright (C) 2016-2020 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 (__FILE__, __LINE__, 65 "creating serial event pipe failed."); 66 67 fcntl (fds[0], F_SETFL, O_NONBLOCK); 68 fcntl (fds[1], F_SETFL, O_NONBLOCK); 69 70 scb->fd = fds[0]; 71 state->write_fd = fds[1]; 72 } 73 #else 74 { 75 /* A dummy file object that can be wrapped in a file descriptor. 76 We don't need to store this handle because closing the file 77 descriptor automatically closes this. */ 78 HANDLE dummy_file; 79 80 /* A manual-reset event. */ 81 state->event = CreateEvent (0, TRUE, FALSE, 0); 82 83 /* The dummy file handle. Created just so we have something 84 wrappable in a file descriptor. */ 85 dummy_file = CreateFile ("nul", 0, 0, NULL, OPEN_EXISTING, 0, NULL); 86 scb->fd = _open_osfhandle ((intptr_t) dummy_file, 0); 87 } 88 #endif 89 90 return 0; 91 } 92 93 static void 94 serial_event_close (struct serial *scb) 95 { 96 struct serial_event_state *state = (struct serial_event_state *) scb->state; 97 98 close (scb->fd); 99 #ifndef USE_WIN32API 100 close (state->write_fd); 101 #else 102 CloseHandle (state->event); 103 #endif 104 105 scb->fd = -1; 106 107 xfree (state); 108 scb->state = NULL; 109 } 110 111 #ifdef USE_WIN32API 112 113 /* Implementation of the wait_handle method. Returns the native 114 Windows event object handle. */ 115 116 static void 117 serial_event_wait_handle (struct serial *scb, HANDLE *read, HANDLE *except) 118 { 119 struct serial_event_state *state = (struct serial_event_state *) scb->state; 120 121 *read = state->event; 122 } 123 124 #endif 125 126 /* The serial_ops for struct serial_event objects. Note we never 127 register this serial type with serial_add_interface, because this 128 is internal implementation detail never to be used by remote 129 targets for protocol transport. */ 130 131 static const struct serial_ops serial_event_ops = 132 { 133 "event", 134 serial_event_open, 135 serial_event_close, 136 NULL, /* fdopen */ 137 NULL, /* readchar */ 138 NULL, /* write */ 139 NULL, /* flush_output */ 140 NULL, /* flush_input */ 141 NULL, /* send_break */ 142 NULL, /* go_raw */ 143 NULL, /* get_tty_state */ 144 NULL, /* copy_tty_state */ 145 NULL, /* set_tty_state */ 146 NULL, /* print_tty_state */ 147 NULL, /* setbaudrate */ 148 NULL, /* setstopbits */ 149 NULL, /* setparity */ 150 NULL, /* drain_output */ 151 NULL, /* async */ 152 NULL, /* read_prim */ 153 NULL, /* write_prim */ 154 NULL, /* avail */ 155 #ifdef USE_WIN32API 156 serial_event_wait_handle, 157 #endif 158 }; 159 160 /* See ser-event.h. */ 161 162 struct serial_event * 163 make_serial_event (void) 164 { 165 return (struct serial_event *) serial_open_ops (&serial_event_ops); 166 } 167 168 /* See ser-event.h. */ 169 170 int 171 serial_event_fd (struct serial_event *event) 172 { 173 struct serial *ser = (struct serial *) event; 174 175 return ser->fd; 176 } 177 178 /* See ser-event.h. */ 179 180 void 181 serial_event_set (struct serial_event *event) 182 { 183 struct serial *ser = (struct serial *) event; 184 struct serial_event_state *state = (struct serial_event_state *) ser->state; 185 #ifndef USE_WIN32API 186 int r; 187 char c = '+'; /* Anything. */ 188 189 do 190 { 191 r = write (state->write_fd, &c, 1); 192 } 193 while (r < 0 && errno == EINTR); 194 #else 195 SetEvent (state->event); 196 #endif 197 } 198 199 /* See ser-event.h. */ 200 201 void 202 serial_event_clear (struct serial_event *event) 203 { 204 struct serial *ser = (struct serial *) event; 205 #ifndef USE_WIN32API 206 int r; 207 208 do 209 { 210 char c; 211 212 r = read (ser->fd, &c, 1); 213 } 214 while (r > 0 || (r < 0 && errno == EINTR)); 215 #else 216 struct serial_event_state *state = (struct serial_event_state *) ser->state; 217 ResetEvent (state->event); 218 #endif 219 } 220