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 vcom_ioctl_va (int __fd, unsigned long int __cmd, va_list __ap)
432 if (vcom_init () != 0)
437 return vcom_socket_ioctl_va (__fd, __cmd, __ap);
441 vcom_ioctl (int __fd, unsigned long int __cmd, ...)
446 if (is_vcom_socket_fd (__fd))
448 va_start (ap, __cmd);
449 rv = vcom_ioctl_va (__fd, __cmd, ap);
456 ioctl (int __fd, unsigned long int __cmd, ...)
460 pid_t pid = getpid ();
462 va_start (ap, __cmd);
463 if (is_vcom_socket_fd (__fd))
465 rv = vcom_ioctl_va (__fd, __cmd, ap);
469 "'%04d'='%04d', '%04ld'\n", pid, rv, __fd, __cmd);
477 rv = libc_vioctl (__fd, __cmd, ap);
485 * Check the first NFDS descriptors each in READFDS (if not NULL) for
486 * read readiness, in WRITEFDS (if not NULL) for write readiness,
487 * and in EXCEPTFDS (if not NULL) for exceptional conditions.
488 * If TIMEOUT is not NULL, time out after waiting the interval
489 * specified therein. Returns the number of ready descriptors,
492 * This function is a cancellation point and therefore not marked
497 * clear all vcom FDs from fd_sets __readfds, __writefds and
498 * __exceptfds and update the new nfds
500 * new nfds is the highest-numbered file descriptor
501 * in any of the three sets, plus 1
503 * Return the number of file descriptors contained in the
504 * three descriptor sets. ie. the total number of the bits
505 * that are set in __readfds, __writefds and __exceptfds
508 vcom_fd_clear (int __nfds,
510 fd_set * __restrict __readfds,
511 fd_set * __restrict __writefds,
512 fd_set * __restrict __exceptfds)
515 /* invalid max_fd is -1 */
520 /* clear all vcom fd from the sets */
521 for (fd = 0; fd < __nfds; fd++)
524 /* clear vcom fd from set */
529 if ((F) && FD_ISSET (fd, (F))) \
531 if (is_vcom_socket_fd (fd)) \
545 * compute nfd and __new_nfds
547 for (fd = 0; fd < __nfds; fd++)
554 if ((F) && FD_ISSET (fd, (F))) \
570 *__new_nfds = max_fd != -1 ? max_fd + 1 : 0;
575 * Return the number of file descriptors contained in the
576 * three descriptor sets. ie. the total number of the bits
577 * that are set in __readfds, __writefds and __exceptfds
580 vcom_fd_set (int __nfds,
583 fd_set * __restrict __readfds,
584 fd_set * __restrict __writefds, fd_set * __restrict __exceptfds,
586 fd_set * __restrict __saved_readfds,
587 fd_set * __restrict __saved_writefds,
588 fd_set * __restrict __saved_exceptfds)
591 /* invalid max_fd is -1 */
595 for (fd = 0; fd < __nfds; fd++)
602 if ((F) && (S) && FD_ISSET (fd, (S))) \
604 if (is_vcom_socket_fd (fd)) \
611 _(__saved_readfds, __readfds);
612 _(__saved_writefds, __writefds);
618 * compute nfd and __new_nfds
620 for (fd = 0; fd < __nfds; fd++)
627 if ((F) && FD_ISSET (fd, (F))) \
643 *__new_nfds = max_fd != -1 ? max_fd + 1 : 0;
648 * split select sets(src) into
649 * vcom sets(dest1) and libc sets(dest2)
653 /* src, select sets */
655 fd_set * __restrict readfds,
656 fd_set * __restrict writefds,
657 fd_set * __restrict exceptfds,
658 /* dest1, vcom sets */
660 fd_set * __restrict vcom_readfds,
661 fd_set * __restrict vcom_writefds,
662 fd_set * __restrict vcom_exceptfds, int *vcom_nfd,
663 /* dest2, libc sets */
665 fd_set * __restrict libc_readfds,
666 fd_set * __restrict libc_writefds,
667 fd_set * __restrict libc_exceptfds, int *libc_nfd)
672 /* invalid max_fd is -1 */
673 int vcom_max_fd = -1;
677 /* invalid max_fd is -1 */
678 int libc_max_fd = -1;
682 for (fd = 0; fd < nfds; fd++)
690 if ((S) && FD_ISSET (fd, (S))) \
692 if (is_vcom_socket_fd (fd)) \
697 if (fd > vcom_max_fd) \
709 if (fd > libc_max_fd) \
719 _(readfds, vcom_readfds, libc_readfds);
720 _(writefds, vcom_writefds, libc_writefds);
721 _(exceptfds, vcom_exceptfds, libc_exceptfds);
726 *vcom_nfds = vcom_max_fd != -1 ? vcom_max_fd + 1 : 0;
728 *vcom_nfd = vcom_nfd2;
730 *libc_nfds = libc_max_fd != -1 ? libc_max_fd + 1 : 0;
732 *libc_nfd = libc_nfd2;
736 * merge vcom sets(src1) and libc sets(src2)
737 * into select sets(dest)
741 /* dest, select sets */
743 fd_set * __restrict readfds,
744 fd_set * __restrict writefds,
745 fd_set * __restrict exceptfds, int *nfd,
746 /* src1, vcom sets */
748 fd_set * __restrict vcom_readfds,
749 fd_set * __restrict vcom_writefds,
750 fd_set * __restrict vcom_exceptfds, int vcom_nfd,
751 /* src2, libc sets */
753 fd_set * __restrict libc_readfds,
754 fd_set * __restrict libc_writefds,
755 fd_set * __restrict libc_exceptfds, int libc_nfd)
758 /* invalid max_fd is -1 */
765 * dest |= src at current bit index
766 * update MAX and NFD of dest fd set
772 * MAX current max_fd of dest fd sets
773 * NFD current nfd of dest fd sets
774 * N nfds of source fd set
776 #define FD_BIT_OR(FD,FS,BI, \
778 if ((FS) && (FD) && FD_ISSET ((BI), (FS))) \
780 FD_SET ((BI), (FD)); \
791 * SR,SW,SE source RWE fd sets
792 * DR,DW,DE dest RWE fd sets
794 * NFDS nfds of source fd sets
795 * MAX current max_fd of dest fd sets
796 * NFD current nfd of dest fd sets
798 #define FD_RWE_SETS_OR(DR,DW,DE, \
804 for ((BI) = 0; (BI) < (NFDS); (BI)++) \
806 FD_BIT_OR((DR), (SR), (BI), (MAX), (NFD)); \
807 FD_BIT_OR((DW), (SW), (BI), (MAX), (NFD)); \
808 FD_BIT_OR((DE), (SE), (BI), (MAX), (NFD)); \
814 /* source(vcom) to dest(select) rwe fd sets */
815 FD_RWE_SETS_OR (readfds, writefds, exceptfds,
816 vcom_readfds, vcom_writefds, vcom_exceptfds,
817 fd, vcom_nfds, max_fd, nfd2);
819 /* source(libc) to dest(select) rwe fd sets */
820 FD_RWE_SETS_OR (readfds, writefds, exceptfds,
821 libc_readfds, libc_writefds, libc_exceptfds,
822 fd, libc_nfds, max_fd, nfd2);
824 #undef FD_RWE_SETS_OR
828 *nfds = max_fd != -1 ? max_fd + 1 : 0;
834 * RETURN 1 if fds is NULL or empty. 0 otherwise
837 fd_set_iszero (fd_set * __restrict fds)
845 for (fd = 0; fd < FD_SETSIZE; fd++)
847 if (FD_ISSET (fd, fds))
863 typedef long int s64;
864 typedef unsigned long int u64;
866 typedef long long int __s64;
867 typedef unsigned long long int __u64;
869 typedef __s64 time64_t;
870 typedef __u64 timeu64_t;
872 /* Parameters used to convert the timespec values: */
873 #define MSEC_PER_SEC 1000L
874 #define USEC_PER_MSEC 1000L
875 #define NSEC_PER_USEC 1000L
876 #define NSEC_PER_MSEC 1000000L
877 #define USEC_PER_SEC 1000000L
878 #define NSEC_PER_SEC 1000000000L
879 #define FSEC_PER_SEC 1000000000000000LL
889 #define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
892 timespec_equal (const struct timespec *a, const struct timespec *b)
894 return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
898 * lhs < rhs: return <0
899 * lhs == rhs: return 0
900 * lhs > rhs: return >0
903 timespec_compare (const struct timespec *lhs, const struct timespec *rhs)
905 if (lhs->tv_sec < rhs->tv_sec)
907 if (lhs->tv_sec > rhs->tv_sec)
909 return lhs->tv_nsec - rhs->tv_nsec;
913 timeval_compare (const struct timeval *lhs, const struct timeval *rhs)
915 if (lhs->tv_sec < rhs->tv_sec)
917 if (lhs->tv_sec > rhs->tv_sec)
919 return lhs->tv_usec - rhs->tv_usec;
922 extern void set_normalized_timespec (struct timespec *ts, time_t sec,
926 static inline struct timespec
927 timespec_add (struct timespec lhs, struct timespec rhs)
929 struct timespec ts_delta;
930 set_normalized_timespec (&ts_delta, lhs.tv_sec + rhs.tv_sec,
931 lhs.tv_nsec + rhs.tv_nsec);
936 * sub = lhs - rhs, in normalized form
938 static inline struct timespec
939 timespec_sub (struct timespec lhs, struct timespec rhs)
941 struct timespec ts_delta;
942 set_normalized_timespec (&ts_delta, lhs.tv_sec - rhs.tv_sec,
943 lhs.tv_nsec - rhs.tv_nsec);
955 * set_normalized_timespec - set timespec sec and nsec parts and normalize
957 * @ts: pointer to timespec variable to be set
958 * @sec: seconds to set
959 * @nsec: nanoseconds to set
961 * Set seconds and nanoseconds field of a timespec variable and
962 * normalize to the timespec storage format
964 * Note: The tv_nsec part is always in the range of
965 * 0 <= tv_nsec < NSEC_PER_SEC
966 * For negative values only the tv_sec field is negative !
969 set_normalized_timespec (struct timespec *ts, time_t sec, s64 nsec)
971 while (nsec >= NSEC_PER_SEC)
974 * The following asm() prevents the compiler from
975 * optimising this loop into a modulo operation. See
976 * also __iter_div_u64_rem() in include/linux/time.h
978 asm ("":"+rm" (nsec));
979 nsec -= NSEC_PER_SEC;
984 asm ("":"+rm" (nsec));
985 nsec += NSEC_PER_SEC;
992 #define vcom_timerisvalid(tvp) (!((tvp)->tv_sec < 0 || (tvp)->tv_usec < 0))
994 /* Macros for converting between `struct timeval' and `struct timespec'. */
995 #define VCOM_TIMEVAL_TO_TIMESPEC(tv, ts) { \
996 (ts)->tv_sec = (tv)->tv_sec; \
997 (ts)->tv_nsec = (tv)->tv_usec * 1000; \
999 #define VCOM_TIMESPEC_TO_TIMEVAL(tv, ts) { \
1000 (tv)->tv_sec = (ts)->tv_sec; \
1001 (tv)->tv_usec = (ts)->tv_nsec / 1000; \
1005 vcom_select_impl (int vcom_nfds, fd_set * __restrict vcom_readfds,
1006 fd_set * __restrict vcom_writefds,
1007 fd_set * __restrict vcom_exceptfds,
1008 struct timeval *__restrict timeout)
1010 return vcom_socket_select (vcom_nfds, vcom_readfds,
1011 vcom_writefds, vcom_exceptfds, timeout);
1015 vcom_select (int __nfds, fd_set * __restrict __readfds,
1016 fd_set * __restrict __writefds,
1017 fd_set * __restrict __exceptfds,
1018 struct timeval *__restrict __timeout)
1022 pid_t pid = getpid ();
1025 /* block indefinitely */
1027 int first_clock_gettime_failed = 0;
1028 /* timeout value in units of timespec */
1029 struct timespec timeout_ts;
1030 struct timespec start_time, now, end_time;
1032 /* select sets attributes - after merge */
1038 fd_set vcom_readfds;
1039 fd_set vcom_writefds;
1040 fd_set vcom_exceptfds;
1045 fd_set libc_readfds;
1046 fd_set libc_writefds;
1047 fd_set libc_exceptfds;
1051 struct timeval tv = {.tv_sec = 0,.tv_usec = 0 };
1053 /* validate __timeout */
1056 /* validate tv_sec */
1058 if (!vcom_timerisvalid (__timeout))
1064 /* validate tv_usec */
1066 /* init timeout_ts */
1067 VCOM_TIMEVAL_TO_TIMESPEC (__timeout, &timeout_ts);
1068 set_normalized_timespec (&timeout_ts,
1069 timeout_ts.tv_sec, timeout_ts.tv_nsec);
1072 rv = clock_gettime (CLOCK_MONOTONIC, &start_time);
1076 first_clock_gettime_failed = 1;
1083 if (timerisset (__timeout))
1085 end_time = timespec_add (start_time, timeout_ts);
1090 * if both fields of the timeout structure are zero,
1091 * then select returns immediately
1093 end_time = start_time;
1098 /* block indefinitely */
1104 if (vcom_init () != 0)
1110 /* validate __nfds */
1111 if (__nfds < 0 || __nfds > FD_SETSIZE)
1119 * usleep(3) emulation
1122 /* call libc_select() with a finite timeout and
1123 * no file descriptors or empty fd sets and
1126 (!__readfds || fd_set_iszero (__readfds)) &&
1127 (!__writefds || fd_set_iszero (__writefds)) &&
1128 (!__exceptfds || fd_set_iszero (__exceptfds)))
1132 rv = libc_select (__nfds,
1133 __readfds, __writefds, __exceptfds, __timeout);
1139 /* TBD: block indefinitely or return -EINVAL */
1145 /* init once before the polling loop */
1147 /* zero vcom and libc fd sets */
1161 _(__readfds, &vcom_readfds, &libc_readfds);
1162 _(__writefds, &vcom_writefds, &libc_writefds);
1163 _(__exceptfds, &vcom_exceptfds, &libc_exceptfds);
1174 /* src, select sets */
1175 __nfds, __readfds, __writefds, __exceptfds,
1176 /* dest1, vcom sets */
1177 __readfds || __writefds || __exceptfds ?
1179 __readfds ? &vcom_readfds : NULL,
1180 __writefds ? &vcom_writefds : NULL,
1181 __exceptfds ? &vcom_exceptfds : NULL,
1182 __readfds || __writefds || __exceptfds ?
1184 /* dest2, libc sets */
1185 __readfds || __writefds || __exceptfds ?
1187 __readfds ? &libc_readfds : NULL,
1188 __writefds ? &libc_writefds : NULL,
1189 __exceptfds ? &libc_exceptfds : NULL,
1190 __readfds || __writefds || __exceptfds ?
1203 * if both fields of timeval structure are zero,
1204 * vcom_select_impl and libc_select returns immediately.
1205 * useful for polling and ensure fairness among
1206 * file descriptors watched.
1213 /* select on vcom fds */
1216 vcom_nfd = vcom_select_impl (vcom_nfds,
1217 __readfds ? &vcom_readfds : NULL,
1218 __writefds ? &vcom_writefds : NULL,
1219 __exceptfds ? &vcom_exceptfds : NULL,
1223 "[%d] select vcom: "
1224 "'%04d'='%04d'\n", pid, vcom_nfd, vcom_nfds);
1232 /* select on libc fds */
1235 libc_nfd = libc_select (libc_nfds,
1236 __readfds ? &libc_readfds : NULL,
1237 __writefds ? &libc_writefds : NULL,
1238 __exceptfds ? &libc_exceptfds : NULL, &tv);
1241 "[%d] select libc: "
1242 "'%04d'='%04d'\n", pid, libc_nfd, libc_nfds);
1246 /* tv becomes undefined */
1253 /* check if any file descriptors changed status */
1254 if ((vcom_nfds && vcom_nfd > 0) || (libc_nfds && libc_nfd > 0))
1256 /* zero the sets before merge and exit */
1276 * on exit, sets are modified in place to indicate which
1277 * file descriptors actually changed status
1280 /* dest, select sets */
1281 __readfds || __writefds || __exceptfds ?
1286 __readfds || __writefds || __exceptfds ?
1288 /* src1, vcom sets */
1290 __readfds ? &vcom_readfds : NULL,
1291 __writefds ? &vcom_writefds : NULL,
1292 __exceptfds ? &vcom_exceptfds : NULL, vcom_nfd,
1293 /* src2, libc sets */
1295 __readfds ? &libc_readfds : NULL,
1296 __writefds ? &libc_writefds : NULL,
1297 __exceptfds ? &libc_exceptfds : NULL, libc_nfd);
1299 * return the number of file descriptors contained in the
1300 * three returned sets
1312 rv = new_nfd == -1 ? 0 : new_nfd;
1316 rv = clock_gettime (CLOCK_MONOTONIC, &now);
1323 while (no_timeout || timespec_compare (&now, &end_time) < 0);
1325 /* timeout expired before anything interesting happened */
1331 fprintf (stderr, "[%d] vselect1: " "'%04d'='%04d'\n", pid, rv, __nfds);
1333 * modify timeout parameter to reflect the amount of time not slept
1337 if (vcom_timerisvalid (__timeout))
1339 /* timeout expired */
1342 timerclear (__timeout);
1344 else if (!first_clock_gettime_failed)
1346 rv2 = clock_gettime (CLOCK_MONOTONIC, &now);
1353 struct timespec ts_delta;
1354 ts_delta = timespec_sub (end_time, now);
1355 VCOM_TIMESPEC_TO_TIMEVAL (__timeout, &ts_delta);
1361 fprintf (stderr, "[%d] vselect2: " "'%04d',='%04d'\n", pid, rv, __nfds);
1367 vcom_select_internal (int __nfds, fd_set * __restrict __readfds,
1368 fd_set * __restrict __writefds,
1369 fd_set * __restrict __exceptfds,
1370 struct timeval *__restrict __timeout)
1375 pid_t pid = getpid ();
1377 fd_set saved_readfds;
1378 fd_set saved_writefds;
1379 fd_set saved_exceptfds;
1381 /* validate __nfds */
1388 /* validate __timeout */
1391 /* validate tv_sec */
1393 if (__timeout->tv_sec < 0 || __timeout->tv_usec < 0)
1399 /* validate tv_usec */
1403 /* init saved_x fds */
1406 saved_readfds = *__readfds;
1408 memcpy (&saved_readfds, __readfds, sizeof (*__readfds));
1413 FD_ZERO (&saved_readfds);
1418 saved_writefds = *__writefds;
1420 memcpy (&saved_writefds, __writefds, sizeof (*__writefds));
1426 FD_ZERO (&saved_writefds);
1431 saved_exceptfds = *__exceptfds;
1433 memcpy (&saved_exceptfds, __exceptfds, sizeof (*__exceptfds));
1439 FD_ZERO (&saved_exceptfds);
1442 /* clear vcom fds */
1443 nfd = vcom_fd_clear (__nfds, &new_nfds, __readfds, __writefds, __exceptfds);
1445 /* set to an invalid value */
1447 /* have kernel fds */
1449 rv = libc_select (new_nfds, __readfds,
1450 __writefds, __exceptfds, __timeout);
1452 if (new_nfds && rv == -1)
1454 /* on error, the file descriptor sets are unmodified */
1456 *__readfds = saved_readfds;
1458 *__writefds = saved_writefds;
1460 *__exceptfds = saved_exceptfds;
1463 else if ((new_nfds && rv != -1) || (rv == -2))
1465 /* restore vcom fds */
1466 nfd = vcom_fd_set (__nfds,
1471 &saved_readfds, &saved_writefds, &saved_exceptfds);
1476 fprintf (stderr, "[%d] select: " "'%04d'='%04d'\n", pid, rv, __nfds);
1481 select (int __nfds, fd_set * __restrict __readfds,
1482 fd_set * __restrict __writefds,
1483 fd_set * __restrict __exceptfds, struct timeval *__restrict __timeout)
1486 pid_t pid = getpid ();
1489 fprintf (stderr, "[%d] select1: " "'%04d'='%04d'\n", pid, rv, __nfds);
1490 rv = vcom_select (__nfds, __readfds, __writefds, __exceptfds, __timeout);
1492 fprintf (stderr, "[%d] select2: " "'%04d'='%04d'\n", pid, rv, __nfds);
1501 #ifdef __USE_XOPEN2K
1503 * Same as above only that the TIMEOUT value is given with higher
1504 * resolution and a sigmask which is been set temporarily. This
1505 * version should be used.
1507 * This function is a cancellation point and therefore not marked
1511 vcom_pselect (int __nfds, fd_set * __restrict __readfds,
1512 fd_set * __restrict __writefds,
1513 fd_set * __restrict __exceptfds,
1514 const struct timespec *__restrict __timeout,
1515 const __sigset_t * __restrict __sigmask)
1520 for (fd = 0; fd < __nfds; fd++)
1522 if (__readfds && FD_ISSET (fd, __readfds))
1524 if (is_vcom_socket_fd (fd))
1530 if (__writefds && FD_ISSET (fd, __writefds))
1532 if (is_vcom_socket_fd (fd))
1537 if (__exceptfds && FD_ISSET (fd, __exceptfds))
1539 if (is_vcom_socket_fd (fd))
1541 FD_CLR (fd, __exceptfds);
1549 pselect (int __nfds, fd_set * __restrict __readfds,
1550 fd_set * __restrict __writefds,
1551 fd_set * __restrict __exceptfds,
1552 const struct timespec *__restrict __timeout,
1553 const __sigset_t * __restrict __sigmask)
1558 pid_t pid = getpid ();
1560 fd_set saved_readfds;
1561 fd_set saved_writefds;
1562 fd_set saved_exceptfds;
1564 /* validate __nfds */
1571 /* validate __timeout */
1574 /* validate tv_sec */
1576 if (__timeout->tv_sec < 0 || __timeout->tv_nsec < 0)
1582 /* validate tv_usec */
1586 /* init saved fds */
1589 saved_readfds = *__readfds;
1591 memcpy (&saved_readfds, __readfds, sizeof (*__readfds));
1596 FD_ZERO (&saved_readfds);
1601 saved_writefds = *__writefds;
1603 memcpy (&saved_writefds, __writefds, sizeof (*__writefds));
1609 FD_ZERO (&saved_writefds);
1614 saved_exceptfds = *__exceptfds;
1616 memcpy (&saved_exceptfds, __exceptfds, sizeof (*__exceptfds));
1622 FD_ZERO (&saved_exceptfds);
1625 /* clear vcom fds */
1626 nfd = vcom_fd_clear (__nfds, &new_nfds, __readfds, __writefds, __exceptfds);
1628 /* set to an invalid value */
1631 rv = libc_pselect (new_nfds,
1633 __writefds, __exceptfds, __timeout, __sigmask);
1635 if (new_nfds && rv == -1)
1637 /* on error, the file descriptor sets are unmodified */
1639 *__readfds = saved_readfds;
1641 *__writefds = saved_writefds;
1643 *__exceptfds = saved_exceptfds;
1646 else if ((new_nfds && rv != -1) || (rv == -2))
1648 /* restore vcom fds */
1649 nfd = vcom_fd_set (__nfds,
1654 &saved_readfds, &saved_writefds, &saved_exceptfds);
1659 fprintf (stderr, "[%d] pselect: " "'%04d'='%04d'\n", pid, rv, __nfds);
1666 * Socket specific glibc api
1670 /* Create a new socket of type TYPE in domain DOMAIN, using
1671 * protocol PROTOCOL. If PROTOCOL is zero, one is chosen
1672 * automatically. Returns a file descriptor for the new socket,
1674 * RETURN: a valid file descriptor for the new socket,
1679 vcom_socket (int __domain, int __type, int __protocol)
1681 if (vcom_init () != 0)
1686 return vcom_socket_socket (__domain, __type, __protocol);
1690 socket (int __domain, int __type, int __protocol)
1693 pid_t pid = getpid ();
1694 pthread_t tid = pthread_self ();
1696 /* handle domains implemented by vpp */
1701 /* handle types implemented by vpp */
1702 switch (__type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1707 vcom_socket_main_show ();
1708 rv = vcom_socket (__domain, __type, __protocol);
1711 "[%d][%lu (0x%lx)] socket: "
1712 "'%04d'= D='%04d', T='%04d', P='%04d'\n",
1713 pid, (unsigned long) tid, (unsigned long) tid,
1714 rv, __domain, __type, __protocol);
1716 vcom_socket_main_show ();
1726 goto CALL_GLIBC_SOCKET_API;
1733 goto CALL_GLIBC_SOCKET_API;
1737 CALL_GLIBC_SOCKET_API:
1738 return libc_socket (__domain, __type, __protocol);
1742 * Create two new sockets, of type TYPE in domain DOMAIN and using
1743 * protocol PROTOCOL, which are connected to each other, and put file
1744 * descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero,
1745 * one will be chosen automatically.
1746 * Returns 0 on success, -1 for errors.
1749 vcom_socketpair (int __domain, int __type, int __protocol, int __fds[2])
1751 if (vcom_init () != 0)
1756 return vcom_socket_socketpair (__domain, __type, __protocol, __fds);
1760 socketpair (int __domain, int __type, int __protocol, int __fds[2])
1763 pid_t pid = getpid ();
1765 /* handle domains implemented by vpp */
1770 /* handle types implemented by vpp */
1775 rv = vcom_socketpair (__domain, __type, __protocol, __fds);
1779 "'%04d'= D='%04d', T='%04d', P='%04d'\n",
1780 pid, rv, __domain, __type, __protocol);
1790 goto CALL_GLIBC_SOCKET_API;
1797 goto CALL_GLIBC_SOCKET_API;
1801 CALL_GLIBC_SOCKET_API:
1802 return libc_socketpair (__domain, __type, __protocol, __fds);
1806 * Give the socket FD the local address ADDR
1807 * (which is LEN bytes long).
1810 vcom_bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
1814 if (vcom_init () != 0)
1819 /* validate __len */
1820 switch (__addr->sa_family)
1823 if (__len != sizeof (struct sockaddr_in))
1827 if (__len != sizeof (struct sockaddr_in6))
1836 /* handle domains implemented by vpp */
1837 switch (__addr->sa_family)
1841 rv = vcom_socket_bind (__fd, __addr, __len);
1854 bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
1857 pid_t pid = getpid ();
1859 if (is_vcom_socket_fd (__fd))
1862 rv = vcom_bind (__fd, __addr, __len);
1866 "'%04d'='%04d', '%p', '%04d'\n",
1867 pid, rv, __fd, __addr, __len);
1875 return libc_bind (__fd, __addr, __len);
1879 * Put the local address of FD into *ADDR and its length in *LEN.
1882 vcom_getsockname (int __fd, __SOCKADDR_ARG __addr,
1883 socklen_t * __restrict __len)
1885 if (vcom_init () != 0)
1890 return vcom_socket_getsockname (__fd, __addr, __len);
1894 getsockname (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __len)
1897 pid_t pid = getpid ();
1899 if (is_vcom_socket_fd (__fd))
1901 rv = vcom_getsockname (__fd, __addr, __len);
1904 "[%d] getsockname: "
1905 "'%04d'='%04d', '%p', '%p'\n", pid, rv, __fd, __addr, __len);
1913 return libc_getsockname (__fd, __addr, __len);
1917 * Open a connection on socket FD to peer at ADDR
1918 * (which LEN bytes long). For connectionless socket types, just set
1919 * the default address to send to and the only address from which to
1920 * accept transmissions. Return 0 on success, -1 for errors.
1921 * This function is a cancellation point and therefore not marked
1925 vcom_connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
1929 if (vcom_init () != 0)
1934 /* validate __len */
1935 switch (__addr->sa_family)
1938 if (__len != INET_ADDRSTRLEN)
1942 if (__len != INET6_ADDRSTRLEN)
1951 /* handle domains implemented by vpp */
1952 switch (__addr->sa_family)
1956 rv = vcom_socket_connect (__fd, __addr, __len);
1968 connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
1971 pid_t pid = getpid ();
1972 pthread_t tid = pthread_self ();
1974 if (is_vcom_socket_fd (__fd))
1976 rv = vcom_connect (__fd, __addr, __len);
1979 "[%d][%lu (0x%lx)] connect: "
1980 "'%04d'='%04d', '%p', '%04d'\n",
1981 pid, (unsigned long) tid, (unsigned long) tid,
1982 rv, __fd, __addr, __len);
1991 return libc_connect (__fd, __addr, __len);
1995 * Put the address of the peer connected to socket FD into *ADDR
1996 * (which is *LEN bytes long), and its actual length into *LEN.
1999 vcom_getpeername (int __fd, __SOCKADDR_ARG __addr,
2000 socklen_t * __restrict __len)
2002 if (vcom_init () != 0)
2007 return vcom_socket_getpeername (__fd, __addr, __len);
2011 getpeername (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __len)
2014 pid_t pid = getpid ();
2016 if (is_vcom_socket_fd (__fd))
2018 rv = vcom_getpeername (__fd, __addr, __len);
2021 "[%d] getpeername: "
2022 "'%04d'='%04d', '%p', '%p'\n", pid, rv, __fd, __addr, __len);
2030 return libc_getpeername (__fd, __addr, __len);
2034 * Send N bytes of BUF to socket FD. Returns the number sent or -1.
2035 * This function is a cancellation point and therefore not marked
2039 vcom_send (int __fd, const void *__buf, size_t __n, int __flags)
2042 if (vcom_init () != 0)
2047 return vcom_socket_send (__fd, (void *) __buf, (int) __n, __flags);
2051 send (int __fd, const void *__buf, size_t __n, int __flags)
2054 pid_t pid = getpid ();
2056 if (is_vcom_socket_fd (__fd))
2058 size = vcom_send (__fd, __buf, __n, __flags);
2062 "'%04d'='%04d', '%p', '%04d', '%04x'\n",
2063 pid, (int) size, __fd, __buf, (int) __n, __flags);
2071 return libc_send (__fd, __buf, __n, __flags);
2075 * Read N bytes into BUF from socket FD.
2076 * Returns the number read or -1 for errors.
2077 * This function is a cancellation point and therefore not marked
2081 vcom_recv (int __fd, void *__buf, size_t __n, int __flags)
2083 if (vcom_init () != 0)
2088 return vcom_socket_recv (__fd, __buf, __n, __flags);
2092 recv (int __fd, void *__buf, size_t __n, int __flags)
2095 pid_t pid = getpid ();
2097 if (is_vcom_socket_fd (__fd))
2099 size = vcom_recv (__fd, __buf, __n, __flags);
2103 "'%04d'='%04d', '%p', '%04d', '%04x'\n",
2104 pid, (int) size, __fd, __buf, (int) __n, __flags);
2112 return libc_recv (__fd, __buf, __n, __flags);
2116 * Send N bytes of BUF on socket FD to peer at address ADDR (which is
2117 * ADDR_LEN bytes long). Returns the number sent, or -1 for errors.
2118 * This function is a cancellation point and therefore not marked
2122 vcom_sendto (int __fd, const void *__buf, size_t __n, int __flags,
2123 __CONST_SOCKADDR_ARG __addr, socklen_t __addr_len)
2125 if (vcom_init () != 0)
2130 return vcom_socket_sendto (__fd, __buf, __n, __flags, __addr, __addr_len);
2134 sendto (int __fd, const void *__buf, size_t __n, int __flags,
2135 __CONST_SOCKADDR_ARG __addr, socklen_t __addr_len)
2138 pid_t pid = getpid ();
2140 if (is_vcom_socket_fd (__fd))
2142 size = vcom_sendto (__fd, __buf, __n, __flags, __addr, __addr_len);
2146 "'%04d'='%04d', '%p', '%04d', '%04x', "
2148 pid, (int) size, __fd, __buf, (int) __n, __flags,
2149 __addr, __addr_len);
2157 return libc_sendto (__fd, __buf, __n, __flags, __addr, __addr_len);
2161 * Read N bytes into BUF through socket FD.
2162 * If ADDR is not NULL, fill in *ADDR_LEN bytes of it with the
2163 * address of the sender, and store the actual size of the address
2165 * Returns the number of bytes read or -1 for errors.
2166 * This function is a cancellation point and therefore not marked
2170 vcom_recvfrom (int __fd, void *__restrict __buf, size_t __n,
2172 __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len)
2174 if (vcom_init () != 0)
2179 return vcom_socket_recvfrom (__fd, __buf, __n, __flags, __addr, __addr_len);
2183 recvfrom (int __fd, void *__restrict __buf, size_t __n,
2185 __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len)
2188 pid_t pid = getpid ();
2190 if (is_vcom_socket_fd (__fd))
2192 size = vcom_recvfrom (__fd, __buf, __n, __flags, __addr, __addr_len);
2196 "'%04d'='%04d', '%p', '%04d', '%04x', "
2198 pid, (int) size, __fd, __buf, (int) __n, __flags,
2199 __addr, __addr_len);
2207 return libc_recvfrom (__fd, __buf, __n, __flags, __addr, __addr_len);
2211 * Send a message described MESSAGE on socket FD.
2212 * Returns the number of bytes sent, or -1 for errors.
2213 * This function is a cancellation point and therefore not marked
2217 vcom_sendmsg (int __fd, const struct msghdr * __message, int __flags)
2219 if (vcom_init () != 0)
2224 return vcom_socket_sendmsg (__fd, __message, __flags);
2228 sendmsg (int __fd, const struct msghdr * __message, int __flags)
2231 pid_t pid = getpid ();
2233 if (is_vcom_socket_fd (__fd))
2235 size = vcom_sendmsg (__fd, __message, __flags);
2239 "'%04d'='%04d', '%p', '%04x'\n",
2240 pid, (int) size, __fd, __message, __flags);
2248 return libc_sendmsg (__fd, __message, __flags);
2253 * Send a VLEN messages as described by VMESSAGES to socket FD.
2254 * Returns the number of datagrams successfully written
2256 * This function is a cancellation point and therefore not marked
2260 vcom_sendmmsg (int __fd, struct mmsghdr *__vmessages,
2261 unsigned int __vlen, int __flags)
2263 if (vcom_init () != 0)
2268 return vcom_socket_sendmmsg (__fd, __message, __vlen, __flags);
2272 sendmmsg (int __fd, struct mmsghdr *__vmessages,
2273 unsigned int __vlen, int __flags)
2276 pid_t pid = getpid ();
2278 if (is_vcom_socket_fd (__fd))
2280 size = vcom_sendmmsg (__fd, __message, __vlen, __flags);
2284 "'%04d'='%04d', '%p', '%04d', '%04x'\n",
2285 pid, (int) size, __fd, __vmessages, __vlen, __flags);
2293 return libc_sendmmsg (__fd, __message, __vlen, __flags);
2299 * Receive a message as described by MESSAGE from socket FD.
2300 * Returns the number of bytes read or -1 for errors.
2301 * This function is a cancellation point and therefore not marked
2305 vcom_recvmsg (int __fd, struct msghdr * __message, int __flags)
2307 if (vcom_init () != 0)
2312 return vcom_socket_recvmsg (__fd, __message, __flags);
2316 recvmsg (int __fd, struct msghdr * __message, int __flags)
2319 pid_t pid = getpid ();
2321 if (is_vcom_socket_fd (__fd))
2323 size = vcom_recvmsg (__fd, __message, __flags);
2327 "'%04d'='%04d', '%p', '%04x'\n",
2328 pid, (int) size, __fd, __message, __flags);
2336 return libc_recvmsg (__fd, __message, __flags);
2341 * Receive up to VLEN messages as described by VMESSAGES from socket FD.
2342 * Returns the number of messages received or -1 for errors.
2343 * This function is a cancellation point and therefore not marked
2347 vcom_recvmmsg (int __fd, struct mmsghdr *__vmessages,
2348 unsigned int __vlen, int __flags, struct timespec *__tmo)
2350 if (vcom_init () != 0)
2355 return vcom_socket_recvmmsg (__fd, __message, __vlen, __flags, __tmo);
2359 recvmmsg (int __fd, struct mmsghdr *__vmessages,
2360 unsigned int __vlen, int __flags, struct timespec *__tmo)
2363 pid_t pid = getpid ();
2365 if (is_vcom_socket_fd (__fd))
2367 size = vcom_recvmmsg (__fd, __message, __vlen, __flags, __tmo);
2371 "'%04d'='%04d', '%p', "
2372 "'%04d', '%04x', '%p'\n",
2373 pid, (int) size, __fd, __vmessages, __vlen, __flags, __tmo);
2381 return libc_recvmmsg (__fd, __message, __vlen, __flags, __tmo);
2387 * Put the current value for socket FD's option OPTNAME
2388 * at protocol level LEVEL into OPTVAL (which is *OPTLEN bytes long),
2389 * and set *OPTLEN to the value's actual length.
2390 * Returns 0 on success, -1 for errors.
2393 vcom_getsockopt (int __fd, int __level, int __optname,
2394 void *__restrict __optval, socklen_t * __restrict __optlen)
2396 if (vcom_init () != 0)
2401 return vcom_socket_getsockopt (__fd, __level, __optname,
2402 __optval, __optlen);
2406 getsockopt (int __fd, int __level, int __optname,
2407 void *__restrict __optval, socklen_t * __restrict __optlen)
2410 pid_t pid = getpid ();
2412 if (is_vcom_socket_fd (__fd))
2414 rv = vcom_getsockopt (__fd, __level, __optname, __optval, __optlen);
2418 "'%04d'='%04d', '%04d', '%04d', "
2420 pid, rv, __fd, __level, __optname, __optval, __optlen);
2428 return libc_getsockopt (__fd, __level, __optname, __optval, __optlen);
2432 * Set socket FD's option OPTNAME at protocol level LEVEL
2433 * to *OPTVAL (which is OPTLEN bytes long).
2434 * Returns 0 on success, -1 for errors.
2437 vcom_setsockopt (int __fd, int __level, int __optname,
2438 const void *__optval, socklen_t __optlen)
2440 if (vcom_init () != 0)
2445 return vcom_socket_setsockopt (__fd, __level, __optname,
2446 __optval, __optlen);
2450 setsockopt (int __fd, int __level, int __optname,
2451 const void *__optval, socklen_t __optlen)
2454 pid_t pid = getpid ();
2456 if (is_vcom_socket_fd (__fd))
2458 rv = vcom_setsockopt (__fd, __level, __optname, __optval, __optlen);
2462 "'%04d'='%04d', '%04d', '%04d', "
2464 pid, rv, __fd, __level, __optname, __optval, __optlen);
2472 return libc_setsockopt (__fd, __level, __optname, __optval, __optlen);
2476 * Prepare to accept connections on socket FD.
2477 * N connection requests will be queued before further
2478 * requests are refused.
2479 * Returns 0 on success, -1 for errors.
2482 vcom_listen (int __fd, int __n)
2484 if (vcom_init () != 0)
2489 return vcom_socket_listen (__fd, __n);
2493 listen (int __fd, int __n)
2496 pid_t pid = getpid ();
2498 if (is_vcom_socket_fd (__fd))
2500 rv = vcom_listen (__fd, __n);
2504 "'%04d'='%04d', '%04d'\n", pid, rv, __fd, __n);
2512 return libc_listen (__fd, __n);
2516 * Await a connection on socket FD.
2517 * When a connection arrives, open a new socket to communicate
2518 * with it, set *ADDR (which is *ADDR_LEN bytes long) to the address
2519 * of the connecting peer and *ADDR_LEN to the address's actual
2520 * length, and return the new socket's descriptor, or -1 for errors.
2521 * This function is a cancellation point and therefore not marked
2525 vcom_accept (int __fd, __SOCKADDR_ARG __addr,
2526 socklen_t * __restrict __addr_len)
2529 if (vcom_init () != 0)
2533 return vcom_socket_accept (__fd, __addr, __addr_len);
2537 accept (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len)
2540 pid_t pid = getpid ();
2541 pthread_t tid = pthread_self ();
2543 if (is_vcom_socket_fd (__fd))
2546 vcom_socket_main_show ();
2549 "[%d][%lu (0x%lx)] accept1: "
2550 "'%04d'='%04d', '%p', '%p'\n",
2551 pid, (unsigned long) tid, (unsigned long) tid,
2552 rv, __fd, __addr, __addr_len);
2553 rv = vcom_accept (__fd, __addr, __addr_len);
2556 "[%d][%lu (0x%lx)] accept2: "
2557 "'%04d'='%04d', '%p', '%p'\n",
2558 pid, (unsigned long) tid, (unsigned long) tid,
2559 rv, __fd, __addr, __addr_len);
2561 vcom_socket_main_show ();
2569 return libc_accept (__fd, __addr, __addr_len);
2574 * Similar to 'accept' but takes an additional parameter to specify
2576 * This function is a cancellation point and therefore not marked
2580 vcom_accept4 (int __fd, __SOCKADDR_ARG __addr,
2581 socklen_t * __restrict __addr_len, int __flags)
2584 if (vcom_init () != 0)
2589 return vcom_socket_accept4 (__fd, __addr, __addr_len, __flags);
2593 accept4 (int __fd, __SOCKADDR_ARG __addr,
2594 socklen_t * __restrict __addr_len, int __flags)
2597 pid_t pid = getpid ();
2599 if (is_vcom_socket_fd (__fd))
2602 vcom_socket_main_show ();
2603 rv = vcom_accept4 (__fd, __addr, __addr_len, __flags);
2607 "'%04d'='%04d', '%p', '%p', '%04x'\n",
2608 pid, rv, __fd, __addr, __addr_len, __flags);
2610 vcom_socket_main_show ();
2618 return libc_accept4 (__fd, __addr, __addr_len, __flags);
2624 * Shut down all or part of the connection open on socket FD.
2625 * HOW determines what to shut down:
2626 * SHUT_RD = No more receptions;
2627 * SHUT_WR = No more transmissions;
2628 * SHUT_RDWR = No more receptions or transmissions.
2629 * Returns 0 on success, -1 for errors.
2632 vcom_shutdown (int __fd, int __how)
2634 if (vcom_init () != 0)
2638 return vcom_socket_shutdown (__fd, __how);
2642 shutdown (int __fd, int __how)
2645 pid_t pid = getpid ();
2647 if (is_vcom_socket_fd (__fd))
2649 rv = vcom_shutdown (__fd, __how);
2653 "'%04d'='%04d', '%04d'\n", pid, rv, __fd, __how);
2661 return libc_shutdown (__fd, __how);
2665 vcom_epoll_create (int __size)
2668 if (vcom_init () != 0)
2678 /* __size argument is ignored "thereafter" */
2679 return vcom_epoll_create1 (0);
2683 * __size argument is ignored, but must be greater than zero
2686 epoll_create (int __size)
2689 pid_t pid = getpid ();
2691 rv = vcom_epoll_create (__size);
2694 "[%d] epoll_create: " "'%04d'='%04d'\n", pid, rv, __size);
2704 vcom_epoll_create1 (int __flags)
2706 if (vcom_init () != 0)
2715 if (__flags & ~EPOLL_CLOEXEC)
2719 /* __flags can be either zero or EPOLL_CLOEXEC */
2720 /* implementation */
2721 return vcom_socket_epoll_create1 (__flags);
2725 * __flags can be either zero or EPOLL_CLOEXEC
2728 epoll_create1 (int __flags)
2731 pid_t pid = getpid ();
2733 rv = vcom_epoll_create1 (__flags);
2736 "[%d] epoll_create: " "'%04d'='%08x'\n", pid, rv, __flags);
2746 ep_op_has_event (int op)
2748 return op != EPOLL_CTL_DEL;
2752 vcom_epoll_ctl (int __epfd, int __op, int __fd, struct epoll_event *__event)
2754 if (vcom_init () != 0)
2760 * the requested operation __op is not supported
2761 * by this interface */
2762 if (!((__op == EPOLL_CTL_ADD) ||
2763 (__op == EPOLL_CTL_MOD) || (__op == EPOLL_CTL_DEL)))
2768 /* op is ADD or MOD but event parameter is NULL */
2769 if ((ep_op_has_event (__op) && !__event))
2774 /* fd is same as epfd */
2775 /* do not permit adding an epoll file descriptor inside itself */
2781 /* implementation */
2782 return vcom_socket_epoll_ctl (__epfd, __op, __fd, __event);
2786 * implement the controller interface for epoll
2787 * that enables the insertion/removal/change of
2788 * file descriptors inside the interest set.
2791 epoll_ctl (int __epfd, int __op, int __fd, struct epoll_event *__event)
2794 pid_t pid = getpid ();
2796 if (is_vcom_epfd (__epfd))
2798 /* TBD: currently limiting epoll to support only vcom fds */
2799 if (is_vcom_socket_fd (__fd))
2801 rv = vcom_epoll_ctl (__epfd, __op, __fd, __event);
2805 "'%04d'='%04d', '%04d', '%04d'\n",
2806 pid, rv, __epfd, __op, __fd);
2817 * TBD: currently epoll does not support kernel fds
2825 /* epfd is not an epoll file descriptor */
2833 vcom_epoll_wait (int __epfd, struct epoll_event *__events,
2834 int __maxevents, int __timeout)
2836 if (vcom_init () != 0)
2841 return vcom_epoll_pwait (__epfd, __events, __maxevents, __timeout, NULL);
2845 epoll_wait (int __epfd, struct epoll_event *__events,
2846 int __maxevents, int __timeout)
2849 pid_t pid = getpid ();
2851 if (__maxevents <= 0 || __maxevents > EP_MAX_EVENTS)
2857 if (is_vcom_epfd (__epfd))
2859 rv = vcom_epoll_wait (__epfd, __events, __maxevents, __timeout);
2863 "'%04d'='%04d', '%p', "
2865 pid, rv, __epfd, __events, __maxevents, __timeout);
2883 vcom_epoll_pwait (int __epfd, struct epoll_event *__events,
2884 int __maxevents, int __timeout, const __sigset_t * __ss)
2886 if (vcom_init () != 0)
2891 /* implementation */
2892 return vcom_socket_epoll_pwait (__epfd, __events,
2893 __maxevents, __timeout, __ss);
2897 epoll_pwait (int __epfd, struct epoll_event *__events,
2898 int __maxevents, int __timeout, const __sigset_t * __ss)
2901 pid_t pid = getpid ();
2903 if (__maxevents <= 0 || __maxevents > EP_MAX_EVENTS)
2909 if (is_vcom_epfd (__epfd))
2911 rv = vcom_epoll_pwait (__epfd, __events, __maxevents, __timeout, __ss);
2914 "[%d] epoll_pwait: "
2915 "'%04d'='%04d', '%p', "
2918 pid, rv, __epfd, __events, __maxevents, __timeout, __ss);
2935 /* Poll the file descriptors described by the NFDS structures starting at
2936 FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for
2937 an event to occur; if TIMEOUT is -1, block until an event occurs.
2938 Returns the number of file descriptors with events, zero if timed out,
2941 This function is a cancellation point and therefore not marked with
2944 vcom_poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
2946 if (vcom_init () != 0)
2955 poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
2965 /* Like poll, but before waiting the threads signal mask is replaced
2966 with that specified in the fourth parameter. For better usability,
2967 the timeout value is specified using a TIMESPEC object.
2969 This function is a cancellation point and therefore not marked with
2972 vcom_ppoll (struct pollfd *__fds, nfds_t __nfds,
2973 const struct timespec *__timeout, const __sigset_t * __ss)
2975 if (vcom_init () != 0)
2984 ppoll (struct pollfd *__fds, nfds_t __nfds,
2985 const struct timespec *__timeout, const __sigset_t * __ss)
2995 void CONSTRUCTOR_ATTRIBUTE vcom_constructor (void);
2997 void DESTRUCTOR_ATTRIBUTE vcom_destructor (void);
3000 vcom_constructor (void)
3002 pid_t pid = getpid ();
3004 swrap_constructor ();
3005 if (vcom_init () != 0)
3007 printf ("\n[%d] vcom_constructor...failed!\n", pid);
3011 printf ("\n[%d] vcom_constructor...done!\n", pid);
3016 * This function is called when the library is unloaded
3019 vcom_destructor (void)
3021 pid_t pid = getpid ();
3024 swrap_destructor ();
3025 printf ("\n[%d] vcom_destructor...done!\n", pid);
3030 * fd.io coding-style-patch-verification: ON
3033 * eval: (c-set-style "gnu")