OpenOCD
replacements.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * Copyright (C) 2006 by Dominic Rath *
5  * Dominic.Rath@gmx.de *
6  * *
7  * Copyright (C) 2007,2008 Øyvind Harboe *
8  * oyvind.harboe@zylin.com *
9  * *
10  * Copyright (C) 2008 by Spencer Oliver *
11  * spen@spen-soft.co.uk *
12  ***************************************************************************/
13 
14 #ifdef HAVE_CONFIG_H
15 #include "config.h"
16 #endif
17 
18 /* define IN_REPLACEMENTS_C before include replacements.h */
19 #define IN_REPLACEMENTS_C
20 #include "replacements.h"
21 
22 #include <stdbool.h>
23 #include <stdlib.h>
24 #include <string.h>
25 
26 /*
27  * clear_malloc
28  *
29  * will alloc memory and clear it
30  */
31 void *clear_malloc(size_t size)
32 {
33  void *t = malloc(size);
34  if (t)
35  memset(t, 0x00, size);
36  return t;
37 }
38 
39 void *fill_malloc(size_t size)
40 {
41  void *t = malloc(size);
42  if (t) {
43  /* We want to initialize memory to some known bad state.
44  * 0 and 0xff yields 0 and -1 as integers, which often
45  * have meaningful values. 0x5555... is not often a valid
46  * integer and is quite easily spotted in the debugger
47  * also it is almost certainly an invalid address */
48  memset(t, 0x55, size);
49  }
50  return t;
51 }
52 
53 #ifdef HAVE_STRINGS_H
54 #include <strings.h>
55 #endif
56 
57 #ifdef _WIN32
58 #include <io.h>
59 #include <winsock2.h>
60 #endif
61 
62 #ifndef HAVE_STRNLEN
63 size_t strnlen(const char *s, size_t maxlen)
64 {
65  const char *end = (const char *)memchr(s, '\0', maxlen);
66  return end ? (size_t) (end - s) : maxlen;
67 }
68 #endif
69 
70 #ifndef HAVE_STRNDUP
71 char *strndup(const char *s, size_t n)
72 {
73  size_t len = strnlen(s, n);
74  char *new = malloc(len + 1);
75 
76  if (!new)
77  return NULL;
78 
79  new[len] = '\0';
80  return (char *) memcpy(new, s, len);
81 }
82 #endif
83 
84 #ifdef _WIN32
85 
86 static bool safe_fd_isset(int fd, fd_set *set)
87 {
88  return set && OCD_FD_ISSET(fd, set);
89 }
90 
91 int win_select(int max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv)
92 {
93  DWORD ms_total, limit;
94  HANDLE handles[MAXIMUM_WAIT_OBJECTS];
95  int handle_slot_to_fd[MAXIMUM_WAIT_OBJECTS];
96  int n_handles = 0, i;
97  fd_set sock_read, sock_write, sock_except;
98  fd_set aread, awrite, aexcept;
99  int sock_max_fd = -1;
100  struct timeval tvslice;
101  int retcode;
102 
103  /* calculate how long we need to wait in milliseconds */
104  if (!tv)
105  ms_total = INFINITE;
106  else {
107  ms_total = tv->tv_sec * 1000;
108  ms_total += tv->tv_usec / 1000;
109  }
110 
111  FD_ZERO(&sock_read);
112  FD_ZERO(&sock_write);
113  FD_ZERO(&sock_except);
114 
115  /* On Windows, if all provided sets are empty/NULL an error code of -1 is returned
116  * and WSAGetLastError() returns WSAEINVAL instead of delaying.
117  * We check for this case, delay and return 0 instead of calling select(). */
118  if (rfds && rfds->fd_count == 0)
119  rfds = NULL;
120  if (wfds && wfds->fd_count == 0)
121  wfds = NULL;
122  if (efds && efds->fd_count == 0)
123  efds = NULL;
124  if (!rfds && !wfds && !efds && tv) {
125  sleep(tv->tv_sec);
126  usleep(tv->tv_usec);
127  return 0;
128  }
129 
130  /* build an array of handles for non-sockets */
131  for (i = 0; i < max_fd; i++) {
132  if (safe_fd_isset(i, rfds) || safe_fd_isset(i, wfds) || safe_fd_isset(i, efds)) {
133  intptr_t handle = (intptr_t) _get_osfhandle(i);
134  handles[n_handles] = (HANDLE)handle;
135  if (handles[n_handles] == INVALID_HANDLE_VALUE) {
136  /* socket */
137  if (safe_fd_isset(i, rfds))
138  OCD_FD_SET(i, &sock_read);
139  if (safe_fd_isset(i, wfds))
140  OCD_FD_SET(i, &sock_write);
141  if (safe_fd_isset(i, efds))
142  OCD_FD_SET(i, &sock_except);
143  if (i > sock_max_fd)
144  sock_max_fd = i;
145  } else {
146  handle_slot_to_fd[n_handles] = i;
147  n_handles++;
148  }
149  }
150  }
151 
152  if (n_handles == 0) {
153  /* plain sockets only - let winsock handle the whole thing */
154  return select(max_fd, rfds, wfds, efds, tv);
155  }
156 
157  /* mixture of handles and sockets; lets multiplex between
158  * winsock and waiting on the handles */
159 
160  FD_ZERO(&aread);
161  FD_ZERO(&awrite);
162  FD_ZERO(&aexcept);
163 
164  limit = GetTickCount() + ms_total;
165  do {
166  retcode = 0;
167 
168  if (sock_max_fd >= 0) {
169  /* overwrite the zero'd sets here; the select call
170  * will clear those that are not active */
171  aread = sock_read;
172  awrite = sock_write;
173  aexcept = sock_except;
174 
175  tvslice.tv_sec = 0;
176  tvslice.tv_usec = 1000;
177 
178  retcode = select(sock_max_fd + 1, &aread, &awrite, &aexcept, &tvslice);
179  }
180 
181  if (n_handles > 0) {
182  /* check handles */
183  DWORD wret;
184 
185  wret = MsgWaitForMultipleObjects(n_handles,
186  handles,
187  FALSE,
188  retcode > 0 ? 0 : 1,
189  QS_ALLEVENTS);
190 
191  if (wret == WAIT_TIMEOUT) {
192  /* set retcode to 0; this is the default.
193  * select() may have set it to something else,
194  * in which case we leave it alone, so this branch
195  * does nothing */
196  ;
197  } else if (wret == WAIT_FAILED) {
198  if (retcode == 0)
199  retcode = -1;
200  } else {
201  if (retcode < 0)
202  retcode = 0;
203  for (i = 0; i < n_handles; i++) {
204  if (WaitForSingleObject(handles[i], 0) == WAIT_OBJECT_0) {
205  if (safe_fd_isset(handle_slot_to_fd[i], rfds)) {
206  DWORD bytes;
207  intptr_t handle = (intptr_t) _get_osfhandle(
208  handle_slot_to_fd[i]);
209 
210  if (PeekNamedPipe((HANDLE)handle, NULL, 0,
211  NULL, &bytes, NULL)) {
212  /* check to see if gdb pipe has data available */
213  if (bytes) {
214  OCD_FD_SET(handle_slot_to_fd[i], &aread);
215  retcode++;
216  }
217  } else {
218  OCD_FD_SET(handle_slot_to_fd[i], &aread);
219  retcode++;
220  }
221  }
222  if (safe_fd_isset(handle_slot_to_fd[i], wfds)) {
223  OCD_FD_SET(handle_slot_to_fd[i], &awrite);
224  retcode++;
225  }
226  if (safe_fd_isset(handle_slot_to_fd[i], efds)) {
227  OCD_FD_SET(handle_slot_to_fd[i], &aexcept);
228  retcode++;
229  }
230  }
231  }
232  }
233  }
234  } while (retcode == 0 && (ms_total == INFINITE || GetTickCount() < limit));
235 
236  if (rfds)
237  *rfds = aread;
238  if (wfds)
239  *wfds = awrite;
240  if (efds)
241  *efds = aexcept;
242 
243  return retcode;
244 }
245 #endif
uint32_t size
Size of dw_spi_transaction::buffer.
Definition: dw-spi-helper.h:4
char * strndup(const char *s, size_t n)
Definition: replacements.c:71
void * clear_malloc(size_t size)
Definition: replacements.c:31
void * fill_malloc(size_t size)
Definition: replacements.c:39
size_t strnlen(const char *s, size_t maxlen)
Definition: replacements.c:63
#define OCD_FD_SET(fd, set)
Definition: replacements.h:159
#define OCD_FD_ISSET(fd, set)
Definition: replacements.h:161
long tv_sec
Definition: replacements.h:46
long tv_usec
Definition: replacements.h:47
#define NULL
Definition: usb.h:16
#define DWORD
Definition: x86_32_common.h:33