2 * Copyright (c) 2016 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
23 #include <libvcl-ldpreload/vcom_socket_wrapper.h>
24 #include <libvcl-ldpreload/vcom.h>
27 #include <uri/vppcom.h>
28 #include <libvcl-ldpreload/vcom_socket.h>
30 /* GCC have printf type attribute check. */
31 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
32 #define PRINTF_ATTRIBUTE(a,b) \
33 __attribute__ ((__format__ (__printf__, a, b)))
35 #define PRINTF_ATTRIBUTE(a,b)
36 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
38 #define HAVE_CONSTRUCTOR_ATTRIBUTE
39 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
40 #define CONSTRUCTOR_ATTRIBUTE \
41 __attribute__ ((constructor))
43 #define CONSTRUCTOR_ATTRIBUTE
44 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
46 #define HAVE_DESTRUCTOR_ATTRIBUTE
47 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
48 #define DESTRUCTOR_ATTRIBUTE \
49 __attribute__ ((destructor))
51 #define DESTRUCTOR_ATTRIBUTE
54 #define HAVE_ADDRESS_SANITIZER_ATTRIBUTE
55 #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
56 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE \
57 __attribute__((no_sanitize_address))
59 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
62 #define VCOM_SOCKET_FD_MAX 0x10000
64 static char vcom_app_name[MAX_VCOM_APP_NAME];
67 * RETURN: 0 on success or -1 on error.
70 vcom_set_app_name (char *__app_name)
72 return snprintf (vcom_app_name, MAX_VCOM_APP_NAME, "vcom-%s-%d",
73 __app_name, getpid ()) < 0 ? -1 : 0;
79 if (vcom_app_name[0] == '\0')
81 snprintf (vcom_app_name, MAX_VCOM_APP_NAME, "vcom-app-%d", getpid ());
87 * 1 if init, 0 otherwise
89 static int is_vcom_init;
92 * TBD: Make it thread safe
96 * constructor function called before main is called
97 * RETURN: 0 on success -1 on failure
102 pid_t pid = getpid ();
106 if (vppcom_app_create (vcom_get_app_name ()) != 0)
108 printf ("\n[%d] vcom_init...failed!\n", pid);
111 "[%d] vcom_init: vppcom_app_create failed!\n", pid);
114 if (vcom_socket_main_init () != 0)
116 printf ("\n[%d] vcom_init...failed!\n", pid);
119 "[%d] vcom_init: vcom_socket_main_init failed!\n", pid);
124 printf ("\n[%d] vcom_init...done!\n", pid);
132 pid_t pid = getpid ();
136 vcom_socket_main_destroy ();
137 vppcom_app_destroy ();
139 fprintf (stderr, "\n[%d] vcom_destroy...done!\n", pid);
144 is_vcom_socket_fd (int fd)
146 return vcom_socket_is_vcom_fd (fd);
150 is_vcom_epfd (int epfd)
152 return vcom_socket_is_vcom_epfd (epfd);
158 * Generic glibc fd api
162 /* Close the file descriptor FD.
164 This function is a cancellation point and therefore
165 not marked with __THROW. */
167 * PRE: is_vcom_socket_fd(__fd) == 1
168 * RETURN: 0 on success and -1 for errors.
171 vcom_close (int __fd)
173 if (vcom_init () != 0)
178 if (vcom_socket_close (__fd) != 0)
187 * RETURN: 0 on success, or -1 on error
193 pid_t pid = getpid ();
195 if (is_vcom_socket_fd (__fd) || is_vcom_epfd (__fd))
198 vcom_socket_main_show ();
199 rv = vcom_close (__fd);
201 fprintf (stderr, "[%d] close: " "'%04d'='%04d'\n", pid, rv, __fd);
203 vcom_socket_main_show ();
211 return libc_close (__fd);
214 /* Read NBYTES into BUF from FD. Return the
215 number read, -1 for errors or 0 for EOF.
217 This function is a cancellation point and therefore
218 not marked with __THROW. */
220 vcom_read (int __fd, void *__buf, size_t __nbytes)
222 if (vcom_init () != 0)
227 return vcom_socket_read (__fd, __buf, __nbytes);
231 read (int __fd, void *__buf, size_t __nbytes)
234 pid_t pid = getpid ();
235 pthread_t tid = pthread_self ();
237 if (is_vcom_socket_fd (__fd))
241 "[%d][%lu (0x%lx)] read:1 "
242 "'%04d'='%04d', '%p', '%04d'\n",
243 pid, (unsigned long) tid, (unsigned long) tid,
244 (int) size, __fd, __buf, (int) __nbytes);
245 size = vcom_read (__fd, __buf, __nbytes);
248 "[%d][%lu (0x%lx)] read:2 "
249 "'%04d'='%04d', '%p', '%04d'\n",
250 pid, (unsigned long) tid, (unsigned long) tid,
251 (int) size, __fd, __buf, (int) __nbytes);
259 return libc_read (__fd, __buf, __nbytes);
263 vcom_readv (int __fd, const struct iovec * __iov, int __iovcnt)
265 if (vcom_init () != 0)
270 return vcom_socket_readv (__fd, __iov, __iovcnt);
274 readv (int __fd, const struct iovec * __iov, int __iovcnt)
278 if (is_vcom_socket_fd (__fd))
280 size = vcom_readv (__fd, __iov, __iovcnt);
289 return libc_readv (__fd, __iov, __iovcnt);
292 /* Write N bytes of BUF to FD. Return the number written, or -1.
294 This function is a cancellation point and therefore
295 not marked with __THROW. */
297 vcom_write (int __fd, const void *__buf, size_t __n)
299 if (vcom_init () != 0)
304 return vcom_socket_write (__fd, (void *) __buf, __n);
308 write (int __fd, const void *__buf, size_t __n)
311 pid_t pid = getpid ();
312 pthread_t tid = pthread_self ();
314 if (is_vcom_socket_fd (__fd))
318 "[%d][%lu (0x%lx)] write:1 "
319 "'%04d'='%04d', '%p', '%04d'\n",
320 pid, (unsigned long) tid, (unsigned long) tid,
321 (int) size, __fd, __buf, (int) __n);
322 size = vcom_write (__fd, __buf, __n);
325 "[%d][%lu (0x%lx)] write:2 "
326 "'%04d'='%04d', '%p', '%04d'\n",
327 pid, (unsigned long) tid, (unsigned long) tid,
328 (int) size, __fd, __buf, (int) __n);
336 return libc_write (__fd, __buf, __n);
340 vcom_writev (int __fd, const struct iovec * __iov, int __iovcnt)
342 if (vcom_init () != 0)
347 return vcom_socket_writev (__fd, __iov, __iovcnt);
351 writev (int __fd, const struct iovec * __iov, int __iovcnt)
355 if (is_vcom_socket_fd (__fd))
357 size = vcom_writev (__fd, __iov, __iovcnt);
366 return libc_writev (__fd, __iov, __iovcnt);
369 /* Do the file control operation described by CMD on FD.
370 The remaining arguments are interpreted depending on CMD.
372 This function is a cancellation point and therefore
373 not marked with __THROW. */
375 vcom_fcntl_va (int __fd, int __cmd, va_list __ap)
377 if (vcom_init () != 0)
382 return vcom_socket_fcntl_va (__fd, __cmd, __ap);
386 vcom_fcntl (int __fd, int __cmd, ...)
391 if (is_vcom_socket_fd (__fd))
393 va_start (ap, __cmd);
394 rv = vcom_fcntl_va (__fd, __cmd, ap);
401 fcntl (int __fd, int __cmd, ...)
405 pid_t pid = getpid ();
407 va_start (ap, __cmd);
408 if (is_vcom_socket_fd (__fd))
410 rv = vcom_fcntl_va (__fd, __cmd, ap);
414 "'%04d'='%04d', '%04d'\n", pid, rv, __fd, __cmd);
422 rv = libc_vfcntl (__fd, __cmd, ap);
430 * Check the first NFDS descriptors each in READFDS (if not NULL) for
431 * read readiness, in WRITEFDS (if not NULL) for write readiness,
432 * and in EXCEPTFDS (if not NULL) for exceptional conditions.
433 * If TIMEOUT is not NULL, time out after waiting the interval
434 * specified therein. Returns the number of ready descriptors,
437 * This function is a cancellation point and therefore not marked
442 * clear all vcom FDs from fd_sets __readfds, __writefds and
443 * __exceptfds and update the new nfds
445 * new nfds is the highest-numbered file descriptor
446 * in any of the three sets, plus 1
448 * Return the number of file descriptors contained in the
449 * three descriptor sets. ie. the total number of the bits
450 * that are set in __readfds, __writefds and __exceptfds
453 vcom_fd_clear (int __nfds,
455 fd_set * __restrict __readfds,
456 fd_set * __restrict __writefds,
457 fd_set * __restrict __exceptfds)
460 /* invalid max_fd is -1 */
465 /* clear all vcom fd from the sets */
466 for (fd = 0; fd < __nfds; fd++)
469 /* clear vcom fd from set */
474 if ((F) && FD_ISSET (fd, (F))) \
476 if (is_vcom_socket_fd (fd)) \
490 * compute nfd and __new_nfds
492 for (fd = 0; fd < __nfds; fd++)
499 if ((F) && FD_ISSET (fd, (F))) \
515 *__new_nfds = max_fd != -1 ? max_fd + 1 : 0;
520 * Return the number of file descriptors contained in the
521 * three descriptor sets. ie. the total number of the bits
522 * that are set in __readfds, __writefds and __exceptfds
525 vcom_fd_set (int __nfds,
528 fd_set * __restrict __readfds,
529 fd_set * __restrict __writefds, fd_set * __restrict __exceptfds,
531 fd_set * __restrict __saved_readfds,
532 fd_set * __restrict __saved_writefds,
533 fd_set * __restrict __saved_exceptfds)
536 /* invalid max_fd is -1 */
540 for (fd = 0; fd < __nfds; fd++)
547 if ((F) && (S) && FD_ISSET (fd, (S))) \
549 if (is_vcom_socket_fd (fd)) \
556 _(__saved_readfds, __readfds);
557 _(__saved_writefds, __writefds);
563 * compute nfd and __new_nfds
565 for (fd = 0; fd < __nfds; fd++)
572 if ((F) && FD_ISSET (fd, (F))) \
588 *__new_nfds = max_fd != -1 ? max_fd + 1 : 0;
593 * split select sets(src) into
594 * vcom sets(dest1) and libc sets(dest2)
598 /* src, select sets */
600 fd_set * __restrict readfds,
601 fd_set * __restrict writefds,
602 fd_set * __restrict exceptfds,
603 /* dest1, vcom sets */
605 fd_set * __restrict vcom_readfds,
606 fd_set * __restrict vcom_writefds,
607 fd_set * __restrict vcom_exceptfds, int *vcom_nfd,
608 /* dest2, libc sets */
610 fd_set * __restrict libc_readfds,
611 fd_set * __restrict libc_writefds,
612 fd_set * __restrict libc_exceptfds, int *libc_nfd)
617 /* invalid max_fd is -1 */
618 int vcom_max_fd = -1;
622 /* invalid max_fd is -1 */
623 int libc_max_fd = -1;
627 for (fd = 0; fd < nfds; fd++)
635 if ((S) && FD_ISSET (fd, (S))) \
637 if (is_vcom_socket_fd (fd)) \
642 if (fd > vcom_max_fd) \
654 if (fd > libc_max_fd) \
664 _(readfds, vcom_readfds, libc_readfds);
665 _(writefds, vcom_writefds, libc_writefds);
666 _(exceptfds, vcom_exceptfds, libc_exceptfds);
671 *vcom_nfds = vcom_max_fd != -1 ? vcom_max_fd + 1 : 0;
673 *vcom_nfd = vcom_nfd2;
675 *libc_nfds = libc_max_fd != -1 ? libc_max_fd + 1 : 0;
677 *libc_nfd = libc_nfd2;
681 * merge vcom sets(src1) and libc sets(src2)
682 * into select sets(dest)
686 /* dest, select sets */
688 fd_set * __restrict readfds,
689 fd_set * __restrict writefds,
690 fd_set * __restrict exceptfds, int *nfd,
691 /* src1, vcom sets */
693 fd_set * __restrict vcom_readfds,
694 fd_set * __restrict vcom_writefds,
695 fd_set * __restrict vcom_exceptfds, int vcom_nfd,
696 /* src2, libc sets */
698 fd_set * __restrict libc_readfds,
699 fd_set * __restrict libc_writefds,
700 fd_set * __restrict libc_exceptfds, int libc_nfd)
703 /* invalid max_fd is -1 */
710 * dest |= src at current bit index
711 * update MAX and NFD of dest fd set
717 * MAX current max_fd of dest fd sets
718 * NFD current nfd of dest fd sets
719 * N nfds of source fd set
721 #define FD_BIT_OR(FD,FS,BI, \
723 if ((FS) && (FD) && FD_ISSET ((BI), (FS))) \
725 FD_SET ((BI), (FD)); \
736 * SR,SW,SE source RWE fd sets
737 * DR,DW,DE dest RWE fd sets
739 * NFDS nfds of source fd sets
740 * MAX current max_fd of dest fd sets
741 * NFD current nfd of dest fd sets
743 #define FD_RWE_SETS_OR(DR,DW,DE, \
749 for ((BI) = 0; (BI) < (NFDS); (BI)++) \
751 FD_BIT_OR((DR), (SR), (BI), (MAX), (NFD)); \
752 FD_BIT_OR((DW), (SW), (BI), (MAX), (NFD)); \
753 FD_BIT_OR((DE), (SE), (BI), (MAX), (NFD)); \
759 /* source(vcom) to dest(select) rwe fd sets */
760 FD_RWE_SETS_OR (readfds, writefds, exceptfds,
761 vcom_readfds, vcom_writefds, vcom_exceptfds,
762 fd, vcom_nfds, max_fd, nfd2);
764 /* source(libc) to dest(select) rwe fd sets */
765 FD_RWE_SETS_OR (readfds, writefds, exceptfds,
766 libc_readfds, libc_writefds, libc_exceptfds,
767 fd, libc_nfds, max_fd, nfd2);
769 #undef FD_RWE_SETS_OR
773 *nfds = max_fd != -1 ? max_fd + 1 : 0;
779 * RETURN 1 if fds is NULL or empty. 0 otherwise
782 fd_set_iszero (fd_set * __restrict fds)
790 for (fd = 0; fd < FD_SETSIZE; fd++)
792 if (FD_ISSET (fd, fds))
808 typedef long int s64;
809 typedef unsigned long int u64;
811 typedef long long int __s64;
812 typedef unsigned long long int __u64;
814 typedef __s64 time64_t;
815 typedef __u64 timeu64_t;
817 /* Parameters used to convert the timespec values: */
818 #define MSEC_PER_SEC 1000L
819 #define USEC_PER_MSEC 1000L
820 #define NSEC_PER_USEC 1000L
821 #define NSEC_PER_MSEC 1000000L
822 #define USEC_PER_SEC 1000000L
823 #define NSEC_PER_SEC 1000000000L
824 #define FSEC_PER_SEC 1000000000000000LL
834 #define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
837 timespec_equal (const struct timespec *a, const struct timespec *b)
839 return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
843 * lhs < rhs: return <0
844 * lhs == rhs: return 0
845 * lhs > rhs: return >0
848 timespec_compare (const struct timespec *lhs, const struct timespec *rhs)
850 if (lhs->tv_sec < rhs->tv_sec)
852 if (lhs->tv_sec > rhs->tv_sec)
854 return lhs->tv_nsec - rhs->tv_nsec;
858 timeval_compare (const struct timeval *lhs, const struct timeval *rhs)
860 if (lhs->tv_sec < rhs->tv_sec)
862 if (lhs->tv_sec > rhs->tv_sec)
864 return lhs->tv_usec - rhs->tv_usec;
867 extern void set_normalized_timespec (struct timespec *ts, time_t sec,
871 static inline struct timespec
872 timespec_add (struct timespec lhs, struct timespec rhs)
874 struct timespec ts_delta;
875 set_normalized_timespec (&ts_delta, lhs.tv_sec + rhs.tv_sec,
876 lhs.tv_nsec + rhs.tv_nsec);
881 * sub = lhs - rhs, in normalized form
883 static inline struct timespec
884 timespec_sub (struct timespec lhs, struct timespec rhs)
886 struct timespec ts_delta;
887 set_normalized_timespec (&ts_delta, lhs.tv_sec - rhs.tv_sec,
888 lhs.tv_nsec - rhs.tv_nsec);
900 * set_normalized_timespec - set timespec sec and nsec parts and normalize
902 * @ts: pointer to timespec variable to be set
903 * @sec: seconds to set
904 * @nsec: nanoseconds to set
906 * Set seconds and nanoseconds field of a timespec variable and
907 * normalize to the timespec storage format
909 * Note: The tv_nsec part is always in the range of
910 * 0 <= tv_nsec < NSEC_PER_SEC
911 * For negative values only the tv_sec field is negative !
914 set_normalized_timespec (struct timespec *ts, time_t sec, s64 nsec)
916 while (nsec >= NSEC_PER_SEC)
919 * The following asm() prevents the compiler from
920 * optimising this loop into a modulo operation. See
921 * also __iter_div_u64_rem() in include/linux/time.h
923 asm ("":"+rm" (nsec));
924 nsec -= NSEC_PER_SEC;
929 asm ("":"+rm" (nsec));
930 nsec += NSEC_PER_SEC;
937 #define vcom_timerisvalid(tvp) (!((tvp)->tv_sec < 0 || (tvp)->tv_usec < 0))
939 /* Macros for converting between `struct timeval' and `struct timespec'. */
940 #define VCOM_TIMEVAL_TO_TIMESPEC(tv, ts) { \
941 (ts)->tv_sec = (tv)->tv_sec; \
942 (ts)->tv_nsec = (tv)->tv_usec * 1000; \
944 #define VCOM_TIMESPEC_TO_TIMEVAL(tv, ts) { \
945 (tv)->tv_sec = (ts)->tv_sec; \
946 (tv)->tv_usec = (ts)->tv_nsec / 1000; \
950 vcom_select_impl (int vcom_nfds, fd_set * __restrict vcom_readfds,
951 fd_set * __restrict vcom_writefds,
952 fd_set * __restrict vcom_exceptfds,
953 struct timeval *__restrict timeout)
955 return vcom_socket_select (vcom_nfds, vcom_readfds,
956 vcom_writefds, vcom_exceptfds, timeout);
960 vcom_select (int __nfds, fd_set * __restrict __readfds,
961 fd_set * __restrict __writefds,
962 fd_set * __restrict __exceptfds,
963 struct timeval *__restrict __timeout)
967 pid_t pid = getpid ();
970 /* block indefinitely */
972 int first_clock_gettime_failed = 0;
973 /* timeout value in units of timespec */
974 struct timespec timeout_ts;
975 struct timespec start_time, now, end_time;
977 /* select sets attributes - after merge */
984 fd_set vcom_writefds;
985 fd_set vcom_exceptfds;
991 fd_set libc_writefds;
992 fd_set libc_exceptfds;
996 struct timeval tv = {.tv_sec = 0,.tv_usec = 0 };
998 /* validate __timeout */
1001 /* validate tv_sec */
1003 if (!vcom_timerisvalid (__timeout))
1009 /* validate tv_usec */
1011 /* init timeout_ts */
1012 VCOM_TIMEVAL_TO_TIMESPEC (__timeout, &timeout_ts);
1013 set_normalized_timespec (&timeout_ts,
1014 timeout_ts.tv_sec, timeout_ts.tv_nsec);
1017 rv = clock_gettime (CLOCK_MONOTONIC, &start_time);
1021 first_clock_gettime_failed = 1;
1028 if (timerisset (__timeout))
1030 end_time = timespec_add (start_time, timeout_ts);
1035 * if both fields of the timeout structure are zero,
1036 * then select returns immediately
1038 end_time = start_time;
1043 /* block indefinitely */
1049 if (vcom_init () != 0)
1055 /* validate __nfds */
1056 if (__nfds < 0 || __nfds > FD_SETSIZE)
1064 * usleep(3) emulation
1067 /* call libc_select() with a finite timeout and
1068 * no file descriptors or empty fd sets and
1071 (!__readfds || fd_set_iszero (__readfds)) &&
1072 (!__writefds || fd_set_iszero (__writefds)) &&
1073 (!__exceptfds || fd_set_iszero (__exceptfds)))
1077 rv = libc_select (__nfds,
1078 __readfds, __writefds, __exceptfds, __timeout);
1084 /* TBD: block indefinitely or return -EINVAL */
1090 /* init once before the polling loop */
1092 /* zero vcom and libc fd sets */
1106 _(__readfds, &vcom_readfds, &libc_readfds);
1107 _(__writefds, &vcom_writefds, &libc_writefds);
1108 _(__exceptfds, &vcom_exceptfds, &libc_exceptfds);
1119 /* src, select sets */
1120 __nfds, __readfds, __writefds, __exceptfds,
1121 /* dest1, vcom sets */
1122 __readfds || __writefds || __exceptfds ?
1124 __readfds ? &vcom_readfds : NULL,
1125 __writefds ? &vcom_writefds : NULL,
1126 __exceptfds ? &vcom_exceptfds : NULL,
1127 __readfds || __writefds || __exceptfds ?
1129 /* dest2, libc sets */
1130 __readfds || __writefds || __exceptfds ?
1132 __readfds ? &libc_readfds : NULL,
1133 __writefds ? &libc_writefds : NULL,
1134 __exceptfds ? &libc_exceptfds : NULL,
1135 __readfds || __writefds || __exceptfds ?
1148 * if both fields of timeval structure are zero,
1149 * vcom_select_impl and libc_select returns immediately.
1150 * useful for polling and ensure fairness among
1151 * file descriptors watched.
1158 /* select on vcom fds */
1161 vcom_nfd = vcom_select_impl (vcom_nfds,
1162 __readfds ? &vcom_readfds : NULL,
1163 __writefds ? &vcom_writefds : NULL,
1164 __exceptfds ? &vcom_exceptfds : NULL,
1168 "[%d] select vcom: "
1169 "'%04d'='%04d'\n", pid, vcom_nfd, vcom_nfds);
1177 /* select on libc fds */
1180 libc_nfd = libc_select (libc_nfds,
1181 __readfds ? &libc_readfds : NULL,
1182 __writefds ? &libc_writefds : NULL,
1183 __exceptfds ? &libc_exceptfds : NULL, &tv);
1186 "[%d] select libc: "
1187 "'%04d'='%04d'\n", pid, libc_nfd, libc_nfds);
1191 /* tv becomes undefined */
1198 /* check if any file descriptors changed status */
1199 if ((vcom_nfds && vcom_nfd > 0) || (libc_nfds && libc_nfd > 0))
1201 /* zero the sets before merge and exit */
1221 * on exit, sets are modified in place to indicate which
1222 * file descriptors actually changed status
1225 /* dest, select sets */
1226 __readfds || __writefds || __exceptfds ?
1231 __readfds || __writefds || __exceptfds ?
1233 /* src1, vcom sets */
1235 __readfds ? &vcom_readfds : NULL,
1236 __writefds ? &vcom_writefds : NULL,
1237 __exceptfds ? &vcom_exceptfds : NULL, vcom_nfd,
1238 /* src2, libc sets */
1240 __readfds ? &libc_readfds : NULL,
1241 __writefds ? &libc_writefds : NULL,
1242 __exceptfds ? &libc_exceptfds : NULL, libc_nfd);
1244 * return the number of file descriptors contained in the
1245 * three returned sets
1257 rv = new_nfd == -1 ? 0 : new_nfd;
1261 rv = clock_gettime (CLOCK_MONOTONIC, &now);
1268 while (no_timeout || timespec_compare (&now, &end_time) < 0);
1270 /* timeout expired before anything interesting happened */
1276 fprintf (stderr, "[%d] vselect1: " "'%04d'='%04d'\n", pid, rv, __nfds);
1278 * modify timeout parameter to reflect the amount of time not slept
1282 if (vcom_timerisvalid (__timeout))
1284 /* timeout expired */
1287 timerclear (__timeout);
1289 else if (!first_clock_gettime_failed)
1291 rv2 = clock_gettime (CLOCK_MONOTONIC, &now);
1298 struct timespec ts_delta;
1299 ts_delta = timespec_sub (end_time, now);
1300 VCOM_TIMESPEC_TO_TIMEVAL (__timeout, &ts_delta);
1306 fprintf (stderr, "[%d] vselect2: " "'%04d',='%04d'\n", pid, rv, __nfds);
1312 vcom_select_internal (int __nfds, fd_set * __restrict __readfds,
1313 fd_set * __restrict __writefds,
1314 fd_set * __restrict __exceptfds,
1315 struct timeval *__restrict __timeout)
1320 pid_t pid = getpid ();
1322 fd_set saved_readfds;
1323 fd_set saved_writefds;
1324 fd_set saved_exceptfds;
1326 /* validate __nfds */
1333 /* validate __timeout */
1336 /* validate tv_sec */
1338 if (__timeout->tv_sec < 0 || __timeout->tv_usec < 0)
1344 /* validate tv_usec */
1348 /* init saved_x fds */
1351 saved_readfds = *__readfds;
1353 memcpy (&saved_readfds, __readfds, sizeof (*__readfds));
1358 FD_ZERO (&saved_readfds);
1363 saved_writefds = *__writefds;
1365 memcpy (&saved_writefds, __writefds, sizeof (*__writefds));
1371 FD_ZERO (&saved_writefds);
1376 saved_exceptfds = *__exceptfds;
1378 memcpy (&saved_exceptfds, __exceptfds, sizeof (*__exceptfds));
1384 FD_ZERO (&saved_exceptfds);
1387 /* clear vcom fds */
1388 nfd = vcom_fd_clear (__nfds, &new_nfds, __readfds, __writefds, __exceptfds);
1390 /* set to an invalid value */
1392 /* have kernel fds */
1394 rv = libc_select (new_nfds, __readfds,
1395 __writefds, __exceptfds, __timeout);
1397 if (new_nfds && rv == -1)
1399 /* on error, the file descriptor sets are unmodified */
1401 *__readfds = saved_readfds;
1403 *__writefds = saved_writefds;
1405 *__exceptfds = saved_exceptfds;
1408 else if ((new_nfds && rv != -1) || (rv == -2))
1410 /* restore vcom fds */
1411 nfd = vcom_fd_set (__nfds,
1416 &saved_readfds, &saved_writefds, &saved_exceptfds);
1421 fprintf (stderr, "[%d] select: " "'%04d'='%04d'\n", pid, rv, __nfds);
1426 select (int __nfds, fd_set * __restrict __readfds,
1427 fd_set * __restrict __writefds,
1428 fd_set * __restrict __exceptfds, struct timeval *__restrict __timeout)
1431 pid_t pid = getpid ();
1434 fprintf (stderr, "[%d] select1: " "'%04d'='%04d'\n", pid, rv, __nfds);
1435 rv = vcom_select (__nfds, __readfds, __writefds, __exceptfds, __timeout);
1437 fprintf (stderr, "[%d] select2: " "'%04d'='%04d'\n", pid, rv, __nfds);
1446 #ifdef __USE_XOPEN2K
1448 * Same as above only that the TIMEOUT value is given with higher
1449 * resolution and a sigmask which is been set temporarily. This
1450 * version should be used.
1452 * This function is a cancellation point and therefore not marked
1456 vcom_pselect (int __nfds, fd_set * __restrict __readfds,
1457 fd_set * __restrict __writefds,
1458 fd_set * __restrict __exceptfds,
1459 const struct timespec *__restrict __timeout,
1460 const __sigset_t * __restrict __sigmask)
1465 for (fd = 0; fd < __nfds; fd++)
1467 if (__readfds && FD_ISSET (fd, __readfds))
1469 if (is_vcom_socket_fd (fd))
1475 if (__writefds && FD_ISSET (fd, __writefds))
1477 if (is_vcom_socket_fd (fd))
1482 if (__exceptfds && FD_ISSET (fd, __exceptfds))
1484 if (is_vcom_socket_fd (fd))
1486 FD_CLR (fd, __exceptfds);
1494 pselect (int __nfds, fd_set * __restrict __readfds,
1495 fd_set * __restrict __writefds,
1496 fd_set * __restrict __exceptfds,
1497 const struct timespec *__restrict __timeout,
1498 const __sigset_t * __restrict __sigmask)
1503 pid_t pid = getpid ();
1505 fd_set saved_readfds;
1506 fd_set saved_writefds;
1507 fd_set saved_exceptfds;
1509 /* validate __nfds */
1516 /* validate __timeout */
1519 /* validate tv_sec */
1521 if (__timeout->tv_sec < 0 || __timeout->tv_nsec < 0)
1527 /* validate tv_usec */
1531 /* init saved fds */
1534 saved_readfds = *__readfds;
1536 memcpy (&saved_readfds, __readfds, sizeof (*__readfds));
1541 FD_ZERO (&saved_readfds);
1546 saved_writefds = *__writefds;
1548 memcpy (&saved_writefds, __writefds, sizeof (*__writefds));
1554 FD_ZERO (&saved_writefds);
1559 saved_exceptfds = *__exceptfds;
1561 memcpy (&saved_exceptfds, __exceptfds, sizeof (*__exceptfds));
1567 FD_ZERO (&saved_exceptfds);
1570 /* clear vcom fds */
1571 nfd = vcom_fd_clear (__nfds, &new_nfds, __readfds, __writefds, __exceptfds);
1573 /* set to an invalid value */
1576 rv = libc_pselect (new_nfds,
1578 __writefds, __exceptfds, __timeout, __sigmask);
1580 if (new_nfds && rv == -1)
1582 /* on error, the file descriptor sets are unmodified */
1584 *__readfds = saved_readfds;
1586 *__writefds = saved_writefds;
1588 *__exceptfds = saved_exceptfds;
1591 else if ((new_nfds && rv != -1) || (rv == -2))
1593 /* restore vcom fds */
1594 nfd = vcom_fd_set (__nfds,
1599 &saved_readfds, &saved_writefds, &saved_exceptfds);
1604 fprintf (stderr, "[%d] pselect: " "'%04d'='%04d'\n", pid, rv, __nfds);
1611 * Socket specific glibc api
1615 /* Create a new socket of type TYPE in domain DOMAIN, using
1616 * protocol PROTOCOL. If PROTOCOL is zero, one is chosen
1617 * automatically. Returns a file descriptor for the new socket,
1619 * RETURN: a valid file descriptor for the new socket,
1624 vcom_socket (int __domain, int __type, int __protocol)
1626 if (vcom_init () != 0)
1631 return vcom_socket_socket (__domain, __type, __protocol);
1635 socket (int __domain, int __type, int __protocol)
1638 pid_t pid = getpid ();
1639 pthread_t tid = pthread_self ();
1641 /* handle domains implemented by vpp */
1646 /* handle types implemented by vpp */
1647 switch (__type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1652 vcom_socket_main_show ();
1653 rv = vcom_socket (__domain, __type, __protocol);
1656 "[%d][%lu (0x%lx)] socket: "
1657 "'%04d'= D='%04d', T='%04d', P='%04d'\n",
1658 pid, (unsigned long) tid, (unsigned long) tid,
1659 rv, __domain, __type, __protocol);
1661 vcom_socket_main_show ();
1671 goto CALL_GLIBC_SOCKET_API;
1678 goto CALL_GLIBC_SOCKET_API;
1682 CALL_GLIBC_SOCKET_API:
1683 return libc_socket (__domain, __type, __protocol);
1687 * Create two new sockets, of type TYPE in domain DOMAIN and using
1688 * protocol PROTOCOL, which are connected to each other, and put file
1689 * descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero,
1690 * one will be chosen automatically.
1691 * Returns 0 on success, -1 for errors.
1694 vcom_socketpair (int __domain, int __type, int __protocol, int __fds[2])
1696 if (vcom_init () != 0)
1701 return vcom_socket_socketpair (__domain, __type, __protocol, __fds);
1705 socketpair (int __domain, int __type, int __protocol, int __fds[2])
1708 pid_t pid = getpid ();
1710 /* handle domains implemented by vpp */
1715 /* handle types implemented by vpp */
1720 rv = vcom_socketpair (__domain, __type, __protocol, __fds);
1724 "'%04d'= D='%04d', T='%04d', P='%04d'\n",
1725 pid, rv, __domain, __type, __protocol);
1735 goto CALL_GLIBC_SOCKET_API;
1742 goto CALL_GLIBC_SOCKET_API;
1746 CALL_GLIBC_SOCKET_API:
1747 return libc_socketpair (__domain, __type, __protocol, __fds);
1751 * Give the socket FD the local address ADDR
1752 * (which is LEN bytes long).
1755 vcom_bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
1759 if (vcom_init () != 0)
1764 /* validate __len */
1765 switch (__addr->sa_family)
1768 if (__len != sizeof (struct sockaddr_in))
1772 if (__len != sizeof (struct sockaddr_in6))
1781 /* handle domains implemented by vpp */
1782 switch (__addr->sa_family)
1786 rv = vcom_socket_bind (__fd, __addr, __len);
1799 bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
1802 pid_t pid = getpid ();
1804 if (is_vcom_socket_fd (__fd))
1807 rv = vcom_bind (__fd, __addr, __len);
1811 "'%04d'='%04d', '%p', '%04d'\n",
1812 pid, rv, __fd, __addr, __len);
1820 return libc_bind (__fd, __addr, __len);
1824 * Put the local address of FD into *ADDR and its length in *LEN.
1827 vcom_getsockname (int __fd, __SOCKADDR_ARG __addr,
1828 socklen_t * __restrict __len)
1830 if (vcom_init () != 0)
1835 return vcom_socket_getsockname (__fd, __addr, __len);
1839 getsockname (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __len)
1842 pid_t pid = getpid ();
1844 if (is_vcom_socket_fd (__fd))
1846 rv = vcom_getsockname (__fd, __addr, __len);
1849 "[%d] getsockname: "
1850 "'%04d'='%04d', '%p', '%p'\n", pid, rv, __fd, __addr, __len);
1858 return libc_getsockname (__fd, __addr, __len);
1862 * Open a connection on socket FD to peer at ADDR
1863 * (which LEN bytes long). For connectionless socket types, just set
1864 * the default address to send to and the only address from which to
1865 * accept transmissions. Return 0 on success, -1 for errors.
1866 * This function is a cancellation point and therefore not marked
1870 vcom_connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
1874 if (vcom_init () != 0)
1879 /* validate __len */
1880 switch (__addr->sa_family)
1883 if (__len != INET_ADDRSTRLEN)
1887 if (__len != INET6_ADDRSTRLEN)
1896 /* handle domains implemented by vpp */
1897 switch (__addr->sa_family)
1901 rv = vcom_socket_connect (__fd, __addr, __len);
1913 connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
1916 pid_t pid = getpid ();
1917 pthread_t tid = pthread_self ();
1919 if (is_vcom_socket_fd (__fd))
1921 rv = vcom_connect (__fd, __addr, __len);
1924 "[%d][%lu (0x%lx)] connect: "
1925 "'%04d'='%04d', '%p', '%04d'\n",
1926 pid, (unsigned long) tid, (unsigned long) tid,
1927 rv, __fd, __addr, __len);
1936 return libc_connect (__fd, __addr, __len);
1940 * Put the address of the peer connected to socket FD into *ADDR
1941 * (which is *LEN bytes long), and its actual length into *LEN.
1944 vcom_getpeername (int __fd, __SOCKADDR_ARG __addr,
1945 socklen_t * __restrict __len)
1947 if (vcom_init () != 0)
1952 return vcom_socket_getpeername (__fd, __addr, __len);
1956 getpeername (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __len)
1959 pid_t pid = getpid ();
1961 if (is_vcom_socket_fd (__fd))
1963 rv = vcom_getpeername (__fd, __addr, __len);
1966 "[%d] getpeername: "
1967 "'%04d'='%04d', '%p', '%p'\n", pid, rv, __fd, __addr, __len);
1975 return libc_getpeername (__fd, __addr, __len);
1979 * Send N bytes of BUF to socket FD. Returns the number sent or -1.
1980 * This function is a cancellation point and therefore not marked
1984 vcom_send (int __fd, const void *__buf, size_t __n, int __flags)
1987 if (vcom_init () != 0)
1992 return vcom_socket_send (__fd, (void *) __buf, (int) __n, __flags);
1996 send (int __fd, const void *__buf, size_t __n, int __flags)
1999 pid_t pid = getpid ();
2001 if (is_vcom_socket_fd (__fd))
2003 size = vcom_send (__fd, __buf, __n, __flags);
2007 "'%04d'='%04d', '%p', '%04d', '%04x'\n",
2008 pid, (int) size, __fd, __buf, (int) __n, __flags);
2016 return libc_send (__fd, __buf, __n, __flags);
2020 * Read N bytes into BUF from socket FD.
2021 * Returns the number read or -1 for errors.
2022 * This function is a cancellation point and therefore not marked
2026 vcom_recv (int __fd, void *__buf, size_t __n, int __flags)
2028 if (vcom_init () != 0)
2033 return vcom_socket_recv (__fd, __buf, __n, __flags);
2037 recv (int __fd, void *__buf, size_t __n, int __flags)
2040 pid_t pid = getpid ();
2042 if (is_vcom_socket_fd (__fd))
2044 size = vcom_recv (__fd, __buf, __n, __flags);
2048 "'%04d'='%04d', '%p', '%04d', '%04x'\n",
2049 pid, (int) size, __fd, __buf, (int) __n, __flags);
2057 return libc_recv (__fd, __buf, __n, __flags);
2061 * Send N bytes of BUF on socket FD to peer at address ADDR (which is
2062 * ADDR_LEN bytes long). Returns the number sent, or -1 for errors.
2063 * This function is a cancellation point and therefore not marked
2067 vcom_sendto (int __fd, const void *__buf, size_t __n, int __flags,
2068 __CONST_SOCKADDR_ARG __addr, socklen_t __addr_len)
2070 if (vcom_init () != 0)
2075 return vcom_socket_sendto (__fd, __buf, __n, __flags, __addr, __addr_len);
2079 sendto (int __fd, const void *__buf, size_t __n, int __flags,
2080 __CONST_SOCKADDR_ARG __addr, socklen_t __addr_len)
2083 pid_t pid = getpid ();
2085 if (is_vcom_socket_fd (__fd))
2087 size = vcom_sendto (__fd, __buf, __n, __flags, __addr, __addr_len);
2091 "'%04d'='%04d', '%p', '%04d', '%04x', "
2093 pid, (int) size, __fd, __buf, (int) __n, __flags,
2094 __addr, __addr_len);
2102 return libc_sendto (__fd, __buf, __n, __flags, __addr, __addr_len);
2106 * Read N bytes into BUF through socket FD.
2107 * If ADDR is not NULL, fill in *ADDR_LEN bytes of it with the
2108 * address of the sender, and store the actual size of the address
2110 * Returns the number of bytes read or -1 for errors.
2111 * This function is a cancellation point and therefore not marked
2115 vcom_recvfrom (int __fd, void *__restrict __buf, size_t __n,
2117 __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len)
2119 if (vcom_init () != 0)
2124 return vcom_socket_recvfrom (__fd, __buf, __n, __flags, __addr, __addr_len);
2128 recvfrom (int __fd, void *__restrict __buf, size_t __n,
2130 __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len)
2133 pid_t pid = getpid ();
2135 if (is_vcom_socket_fd (__fd))
2137 size = vcom_recvfrom (__fd, __buf, __n, __flags, __addr, __addr_len);
2141 "'%04d'='%04d', '%p', '%04d', '%04x', "
2143 pid, (int) size, __fd, __buf, (int) __n, __flags,
2144 __addr, __addr_len);
2152 return libc_recvfrom (__fd, __buf, __n, __flags, __addr, __addr_len);
2156 * Send a message described MESSAGE on socket FD.
2157 * Returns the number of bytes sent, or -1 for errors.
2158 * This function is a cancellation point and therefore not marked
2162 vcom_sendmsg (int __fd, const struct msghdr * __message, int __flags)
2164 if (vcom_init () != 0)
2169 return vcom_socket_sendmsg (__fd, __message, __flags);
2173 sendmsg (int __fd, const struct msghdr * __message, int __flags)
2176 pid_t pid = getpid ();
2178 if (is_vcom_socket_fd (__fd))
2180 size = vcom_sendmsg (__fd, __message, __flags);
2184 "'%04d'='%04d', '%p', '%04x'\n",
2185 pid, (int) size, __fd, __message, __flags);
2193 return libc_sendmsg (__fd, __message, __flags);
2198 * Send a VLEN messages as described by VMESSAGES to socket FD.
2199 * Returns the number of datagrams successfully written
2201 * This function is a cancellation point and therefore not marked
2205 vcom_sendmmsg (int __fd, struct mmsghdr *__vmessages,
2206 unsigned int __vlen, int __flags)
2208 if (vcom_init () != 0)
2213 return vcom_socket_sendmmsg (__fd, __message, __vlen, __flags);
2217 sendmmsg (int __fd, struct mmsghdr *__vmessages,
2218 unsigned int __vlen, int __flags)
2221 pid_t pid = getpid ();
2223 if (is_vcom_socket_fd (__fd))
2225 size = vcom_sendmmsg (__fd, __message, __vlen, __flags);
2229 "'%04d'='%04d', '%p', '%04d', '%04x'\n",
2230 pid, (int) size, __fd, __vmessages, __vlen, __flags);
2238 return libc_sendmmsg (__fd, __message, __vlen, __flags);
2244 * Receive a message as described by MESSAGE from socket FD.
2245 * Returns the number of bytes read or -1 for errors.
2246 * This function is a cancellation point and therefore not marked
2250 vcom_recvmsg (int __fd, struct msghdr * __message, int __flags)
2252 if (vcom_init () != 0)
2257 return vcom_socket_recvmsg (__fd, __message, __flags);
2261 recvmsg (int __fd, struct msghdr * __message, int __flags)
2264 pid_t pid = getpid ();
2266 if (is_vcom_socket_fd (__fd))
2268 size = vcom_recvmsg (__fd, __message, __flags);
2272 "'%04d'='%04d', '%p', '%04x'\n",
2273 pid, (int) size, __fd, __message, __flags);
2281 return libc_recvmsg (__fd, __message, __flags);
2286 * Receive up to VLEN messages as described by VMESSAGES from socket FD.
2287 * Returns the number of messages received or -1 for errors.
2288 * This function is a cancellation point and therefore not marked
2292 vcom_recvmmsg (int __fd, struct mmsghdr *__vmessages,
2293 unsigned int __vlen, int __flags, struct timespec *__tmo)
2295 if (vcom_init () != 0)
2300 return vcom_socket_recvmmsg (__fd, __message, __vlen, __flags, __tmo);
2304 recvmmsg (int __fd, struct mmsghdr *__vmessages,
2305 unsigned int __vlen, int __flags, struct timespec *__tmo)
2308 pid_t pid = getpid ();
2310 if (is_vcom_socket_fd (__fd))
2312 size = vcom_recvmmsg (__fd, __message, __vlen, __flags, __tmo);
2316 "'%04d'='%04d', '%p', "
2317 "'%04d', '%04x', '%p'\n",
2318 pid, (int) size, __fd, __vmessages, __vlen, __flags, __tmo);
2326 return libc_recvmmsg (__fd, __message, __vlen, __flags, __tmo);
2332 * Put the current value for socket FD's option OPTNAME
2333 * at protocol level LEVEL into OPTVAL (which is *OPTLEN bytes long),
2334 * and set *OPTLEN to the value's actual length.
2335 * Returns 0 on success, -1 for errors.
2338 vcom_getsockopt (int __fd, int __level, int __optname,
2339 void *__restrict __optval, socklen_t * __restrict __optlen)
2341 if (vcom_init () != 0)
2346 return vcom_socket_getsockopt (__fd, __level, __optname,
2347 __optval, __optlen);
2351 getsockopt (int __fd, int __level, int __optname,
2352 void *__restrict __optval, socklen_t * __restrict __optlen)
2355 pid_t pid = getpid ();
2357 if (is_vcom_socket_fd (__fd))
2359 rv = vcom_getsockopt (__fd, __level, __optname, __optval, __optlen);
2363 "'%04d'='%04d', '%04d', '%04d', "
2365 pid, rv, __fd, __level, __optname, __optval, __optlen);
2373 return libc_getsockopt (__fd, __level, __optname, __optval, __optlen);
2377 * Set socket FD's option OPTNAME at protocol level LEVEL
2378 * to *OPTVAL (which is OPTLEN bytes long).
2379 * Returns 0 on success, -1 for errors.
2382 vcom_setsockopt (int __fd, int __level, int __optname,
2383 const void *__optval, socklen_t __optlen)
2385 if (vcom_init () != 0)
2390 return vcom_socket_setsockopt (__fd, __level, __optname,
2391 __optval, __optlen);
2395 setsockopt (int __fd, int __level, int __optname,
2396 const void *__optval, socklen_t __optlen)
2399 pid_t pid = getpid ();
2401 if (is_vcom_socket_fd (__fd))
2403 rv = vcom_setsockopt (__fd, __level, __optname, __optval, __optlen);
2407 "'%04d'='%04d', '%04d', '%04d', "
2409 pid, rv, __fd, __level, __optname, __optval, __optlen);
2417 return libc_setsockopt (__fd, __level, __optname, __optval, __optlen);
2421 * Prepare to accept connections on socket FD.
2422 * N connection requests will be queued before further
2423 * requests are refused.
2424 * Returns 0 on success, -1 for errors.
2427 vcom_listen (int __fd, int __n)
2429 if (vcom_init () != 0)
2434 return vcom_socket_listen (__fd, __n);
2438 listen (int __fd, int __n)
2441 pid_t pid = getpid ();
2443 if (is_vcom_socket_fd (__fd))
2445 rv = vcom_listen (__fd, __n);
2449 "'%04d'='%04d', '%04d'\n", pid, rv, __fd, __n);
2457 return libc_listen (__fd, __n);
2461 * Await a connection on socket FD.
2462 * When a connection arrives, open a new socket to communicate
2463 * with it, set *ADDR (which is *ADDR_LEN bytes long) to the address
2464 * of the connecting peer and *ADDR_LEN to the address's actual
2465 * length, and return the new socket's descriptor, or -1 for errors.
2466 * This function is a cancellation point and therefore not marked
2470 vcom_accept (int __fd, __SOCKADDR_ARG __addr,
2471 socklen_t * __restrict __addr_len)
2474 if (vcom_init () != 0)
2478 return vcom_socket_accept (__fd, __addr, __addr_len);
2482 accept (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len)
2485 pid_t pid = getpid ();
2486 pthread_t tid = pthread_self ();
2488 if (is_vcom_socket_fd (__fd))
2491 vcom_socket_main_show ();
2494 "[%d][%lu (0x%lx)] accept1: "
2495 "'%04d'='%04d', '%p', '%p'\n",
2496 pid, (unsigned long) tid, (unsigned long) tid,
2497 rv, __fd, __addr, __addr_len);
2498 rv = vcom_accept (__fd, __addr, __addr_len);
2501 "[%d][%lu (0x%lx)] accept2: "
2502 "'%04d'='%04d', '%p', '%p'\n",
2503 pid, (unsigned long) tid, (unsigned long) tid,
2504 rv, __fd, __addr, __addr_len);
2506 vcom_socket_main_show ();
2514 return libc_accept (__fd, __addr, __addr_len);
2519 * Similar to 'accept' but takes an additional parameter to specify
2521 * This function is a cancellation point and therefore not marked
2525 vcom_accept4 (int __fd, __SOCKADDR_ARG __addr,
2526 socklen_t * __restrict __addr_len, int __flags)
2529 if (vcom_init () != 0)
2534 return vcom_socket_accept4 (__fd, __addr, __addr_len, __flags);
2538 accept4 (int __fd, __SOCKADDR_ARG __addr,
2539 socklen_t * __restrict __addr_len, int __flags)
2542 pid_t pid = getpid ();
2544 if (is_vcom_socket_fd (__fd))
2547 vcom_socket_main_show ();
2548 rv = vcom_accept4 (__fd, __addr, __addr_len, __flags);
2552 "'%04d'='%04d', '%p', '%p', '%04x'\n",
2553 pid, rv, __fd, __addr, __addr_len, __flags);
2555 vcom_socket_main_show ();
2563 return libc_accept4 (__fd, __addr, __addr_len, __flags);
2569 * Shut down all or part of the connection open on socket FD.
2570 * HOW determines what to shut down:
2571 * SHUT_RD = No more receptions;
2572 * SHUT_WR = No more transmissions;
2573 * SHUT_RDWR = No more receptions or transmissions.
2574 * Returns 0 on success, -1 for errors.
2577 vcom_shutdown (int __fd, int __how)
2579 if (vcom_init () != 0)
2583 return vcom_socket_shutdown (__fd, __how);
2587 shutdown (int __fd, int __how)
2590 pid_t pid = getpid ();
2592 if (is_vcom_socket_fd (__fd))
2594 rv = vcom_shutdown (__fd, __how);
2598 "'%04d'='%04d', '%04d'\n", pid, rv, __fd, __how);
2606 return libc_shutdown (__fd, __how);
2610 vcom_epoll_create (int __size)
2613 if (vcom_init () != 0)
2623 /* __size argument is ignored "thereafter" */
2624 return vcom_epoll_create1 (0);
2628 * __size argument is ignored, but must be greater than zero
2631 epoll_create (int __size)
2634 pid_t pid = getpid ();
2636 rv = vcom_epoll_create (__size);
2639 "[%d] epoll_create: " "'%04d'='%04d'\n", pid, rv, __size);
2649 vcom_epoll_create1 (int __flags)
2651 if (vcom_init () != 0)
2660 if (__flags & ~EPOLL_CLOEXEC)
2664 /* __flags can be either zero or EPOLL_CLOEXEC */
2665 /* implementation */
2666 return vcom_socket_epoll_create1 (__flags);
2670 * __flags can be either zero or EPOLL_CLOEXEC
2673 epoll_create1 (int __flags)
2676 pid_t pid = getpid ();
2678 rv = vcom_epoll_create1 (__flags);
2681 "[%d] epoll_create: " "'%04d'='%08x'\n", pid, rv, __flags);
2691 ep_op_has_event (int op)
2693 return op != EPOLL_CTL_DEL;
2697 vcom_epoll_ctl (int __epfd, int __op, int __fd, struct epoll_event *__event)
2699 if (vcom_init () != 0)
2705 * the requested operation __op is not supported
2706 * by this interface */
2707 if (!((__op == EPOLL_CTL_ADD) ||
2708 (__op == EPOLL_CTL_MOD) || (__op == EPOLL_CTL_DEL)))
2713 /* op is ADD or MOD but event parameter is NULL */
2714 if ((ep_op_has_event (__op) && !__event))
2719 /* fd is same as epfd */
2720 /* do not permit adding an epoll file descriptor inside itself */
2726 /* implementation */
2727 return vcom_socket_epoll_ctl (__epfd, __op, __fd, __event);
2731 * implement the controller interface for epoll
2732 * that enables the insertion/removal/change of
2733 * file descriptors inside the interest set.
2736 epoll_ctl (int __epfd, int __op, int __fd, struct epoll_event *__event)
2739 pid_t pid = getpid ();
2741 if (is_vcom_epfd (__epfd))
2743 /* TBD: currently limiting epoll to support only vcom fds */
2744 if (is_vcom_socket_fd (__fd))
2746 rv = vcom_epoll_ctl (__epfd, __op, __fd, __event);
2750 "'%04d'='%04d', '%04d', '%04d'\n",
2751 pid, rv, __epfd, __op, __fd);
2762 * TBD: currently epoll does not support kernel fds
2770 /* epfd is not an epoll file descriptor */
2778 vcom_epoll_wait (int __epfd, struct epoll_event *__events,
2779 int __maxevents, int __timeout)
2781 if (vcom_init () != 0)
2786 return vcom_epoll_pwait (__epfd, __events, __maxevents, __timeout, NULL);
2790 epoll_wait (int __epfd, struct epoll_event *__events,
2791 int __maxevents, int __timeout)
2794 pid_t pid = getpid ();
2796 if (__maxevents <= 0 || __maxevents > EP_MAX_EVENTS)
2802 if (is_vcom_epfd (__epfd))
2804 rv = vcom_epoll_wait (__epfd, __events, __maxevents, __timeout);
2808 "'%04d'='%04d', '%p', "
2810 pid, rv, __epfd, __events, __maxevents, __timeout);
2828 vcom_epoll_pwait (int __epfd, struct epoll_event *__events,
2829 int __maxevents, int __timeout, const __sigset_t * __ss)
2831 if (vcom_init () != 0)
2836 /* implementation */
2837 return vcom_socket_epoll_pwait (__epfd, __events,
2838 __maxevents, __timeout, __ss);
2842 epoll_pwait (int __epfd, struct epoll_event *__events,
2843 int __maxevents, int __timeout, const __sigset_t * __ss)
2846 pid_t pid = getpid ();
2848 if (__maxevents <= 0 || __maxevents > EP_MAX_EVENTS)
2854 if (is_vcom_epfd (__epfd))
2856 rv = vcom_epoll_pwait (__epfd, __events, __maxevents, __timeout, __ss);
2859 "[%d] epoll_pwait: "
2860 "'%04d'='%04d', '%p', "
2863 pid, rv, __epfd, __events, __maxevents, __timeout, __ss);
2880 /* Poll the file descriptors described by the NFDS structures starting at
2881 FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for
2882 an event to occur; if TIMEOUT is -1, block until an event occurs.
2883 Returns the number of file descriptors with events, zero if timed out,
2886 This function is a cancellation point and therefore not marked with
2889 vcom_poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
2891 if (vcom_init () != 0)
2900 poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
2910 /* Like poll, but before waiting the threads signal mask is replaced
2911 with that specified in the fourth parameter. For better usability,
2912 the timeout value is specified using a TIMESPEC object.
2914 This function is a cancellation point and therefore not marked with
2917 vcom_ppoll (struct pollfd *__fds, nfds_t __nfds,
2918 const struct timespec *__timeout, const __sigset_t * __ss)
2920 if (vcom_init () != 0)
2929 ppoll (struct pollfd *__fds, nfds_t __nfds,
2930 const struct timespec *__timeout, const __sigset_t * __ss)
2940 void CONSTRUCTOR_ATTRIBUTE vcom_constructor (void);
2942 void DESTRUCTOR_ATTRIBUTE vcom_destructor (void);
2945 vcom_constructor (void)
2947 pid_t pid = getpid ();
2949 swrap_constructor ();
2950 if (vcom_init () != 0)
2952 printf ("\n[%d] vcom_constructor...failed!\n", pid);
2956 printf ("\n[%d] vcom_constructor...done!\n", pid);
2961 * This function is called when the library is unloaded
2964 vcom_destructor (void)
2966 pid_t pid = getpid ();
2969 swrap_destructor ();
2970 printf ("\n[%d] vcom_destructor...done!\n", pid);
2975 * fd.io coding-style-patch-verification: ON
2978 * eval: (c-set-style "gnu")