FreeRTOSSimulator_wrappers.c 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. /*
  2. * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <pthread.h>
  7. #include "esp_err.h"
  8. #include "errno.h"
  9. /** This module addresses the FreeRTOS simulator's coexistence with linux system calls from user apps.
  10. * It's only included when building without lwIP, so we need to use linux system's select() which would receive
  11. * EINTR event on every FreeRTOS interrupt; we workaround this problem by wrapping select()
  12. * to bypass and silence these events.
  13. */
  14. extern int __real_select (int fd, fd_set * rfds, fd_set * wfds, fd_set *efds, struct timeval *tval);
  15. static inline int64_t get_us(void)
  16. {
  17. struct timespec spec;
  18. clock_gettime(CLOCK_REALTIME, &spec);
  19. return spec.tv_nsec / 1000 + spec.tv_sec * 1000000;
  20. }
  21. int __wrap_select (int fd, fd_set * rfds, fd_set * wfds, fd_set *efds, struct timeval *tval)
  22. {
  23. int ret;
  24. struct timeval *tv = tval;
  25. struct timeval timeval_local = {};
  26. int64_t start = 0;
  27. int64_t timeout_us = 0;
  28. if (tv != NULL) {
  29. start = get_us();
  30. timeout_us = tval->tv_sec * 1000000 + tval->tv_usec;
  31. timeval_local.tv_sec = tval->tv_sec;
  32. timeval_local.tv_usec = tval->tv_usec;
  33. tv = &timeval_local; // this (tv != NULL) indicates that we should handle timeouts
  34. }
  35. while ((ret = __real_select(fd, rfds, wfds, efds, tv)) < 0 && errno == EINTR) {
  36. if (tv != NULL) {
  37. int64_t now = get_us();
  38. timeout_us -= now - start;
  39. if (timeout_us < 0) {
  40. errno = 0;
  41. ret = 0;
  42. break;
  43. }
  44. start = now;
  45. tv->tv_usec = timeout_us % 1000000;
  46. tv->tv_sec = timeout_us / 1000000;
  47. }
  48. }
  49. return ret;
  50. }