freertos-service.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to
  8. * deal in the Software without restriction, including without limitation the
  9. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  10. * sell copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  22. * IN THE SOFTWARE.
  23. */
  24. #include "private-lib-core.h"
  25. int
  26. lws_plat_service(struct lws_context *context, int timeout_ms)
  27. {
  28. int n = _lws_plat_service_tsi(context, timeout_ms, 0);
  29. #if !defined(LWS_AMAZON_RTOS)
  30. esp_task_wdt_reset();
  31. #endif
  32. return n;
  33. }
  34. int
  35. _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
  36. {
  37. struct lws_context_per_thread *pt;
  38. lws_usec_t timeout_us;
  39. int n = -1, m, c, a = 0;
  40. /* stay dead once we are dead */
  41. if (!context)
  42. return 1;
  43. pt = &context->pt[tsi];
  44. lws_stats_bump(pt, LWSSTATS_C_SERVICE_ENTRY, 1);
  45. {
  46. unsigned long m = lws_now_secs();
  47. if (m > context->time_last_state_dump) {
  48. context->time_last_state_dump = m;
  49. #if defined(LWS_ESP_PLATFORM)
  50. n = esp_get_free_heap_size();
  51. #else
  52. n = xPortGetFreeHeapSize();
  53. #endif
  54. if ((unsigned int)n != context->last_free_heap) {
  55. if ((unsigned int)n > context->last_free_heap)
  56. lwsl_debug(" heap :%ld (+%ld)\n",
  57. (unsigned long)n,
  58. (unsigned long)(n -
  59. context->last_free_heap));
  60. else
  61. lwsl_debug(" heap :%ld (-%ld)\n",
  62. (unsigned long)n,
  63. (unsigned long)(
  64. context->last_free_heap -
  65. n));
  66. context->last_free_heap = n;
  67. }
  68. }
  69. }
  70. if (timeout_ms < 0)
  71. timeout_ms = 0;
  72. else
  73. /* force a default timeout of 23 days */
  74. timeout_ms = 2000000000;
  75. timeout_us = ((lws_usec_t)timeout_ms) * LWS_US_PER_MS;
  76. if (!pt->service_tid_detected && context->vhost_list) {
  77. lws_fakewsi_def_plwsa(pt);
  78. lws_fakewsi_prep_plwsa_ctx(context);
  79. pt->service_tid = context->vhost_list->protocols[0].callback(
  80. (struct lws *)plwsa, LWS_CALLBACK_GET_THREAD_ID,
  81. NULL, NULL, 0);
  82. pt->service_tid_detected = 1;
  83. }
  84. /*
  85. * is there anybody with pending stuff that needs service forcing?
  86. */
  87. if (lws_service_adjust_timeout(context, 1, tsi)) {
  88. again:
  89. a = 0;
  90. if (timeout_us) {
  91. lws_usec_t us;
  92. lws_pt_lock(pt, __func__);
  93. /* don't stay in poll wait longer than next hr timeout */
  94. us = __lws_sul_service_ripe(pt->pt_sul_owner,
  95. LWS_COUNT_PT_SUL_OWNERS,
  96. lws_now_usecs());
  97. if (us && us < timeout_us)
  98. timeout_us = us;
  99. lws_pt_unlock(pt);
  100. }
  101. // n = poll(pt->fds, pt->fds_count, timeout_ms);
  102. {
  103. fd_set readfds, writefds, errfds;
  104. struct timeval tv = { timeout_us / LWS_US_PER_SEC,
  105. timeout_us % LWS_US_PER_SEC }, *ptv = &tv;
  106. int max_fd = 0;
  107. FD_ZERO(&readfds);
  108. FD_ZERO(&writefds);
  109. FD_ZERO(&errfds);
  110. for (n = 0; n < (int)pt->fds_count; n++) {
  111. pt->fds[n].revents = 0;
  112. if (pt->fds[n].fd >= max_fd)
  113. max_fd = pt->fds[n].fd;
  114. if (pt->fds[n].events & LWS_POLLIN)
  115. FD_SET(pt->fds[n].fd, &readfds);
  116. if (pt->fds[n].events & LWS_POLLOUT)
  117. FD_SET(pt->fds[n].fd, &writefds);
  118. FD_SET(pt->fds[n].fd, &errfds);
  119. }
  120. n = select(max_fd + 1, &readfds, &writefds, &errfds, ptv);
  121. n = 0;
  122. #if defined(LWS_WITH_DETAILED_LATENCY)
  123. /*
  124. * so we can track how long it took before we actually read a POLLIN
  125. * that was signalled when we last exited poll()
  126. */
  127. if (context->detailed_latency_cb)
  128. pt->ust_left_poll = lws_now_usecs();
  129. #endif
  130. for (m = 0; m < (int)pt->fds_count; m++) {
  131. c = 0;
  132. if (FD_ISSET(pt->fds[m].fd, &readfds)) {
  133. pt->fds[m].revents |= LWS_POLLIN;
  134. c = 1;
  135. }
  136. if (FD_ISSET(pt->fds[m].fd, &writefds)) {
  137. pt->fds[m].revents |= LWS_POLLOUT;
  138. c = 1;
  139. }
  140. if (FD_ISSET(pt->fds[m].fd, &errfds)) {
  141. // lwsl_notice("errfds %d\n", pt->fds[m].fd);
  142. pt->fds[m].revents |= LWS_POLLHUP;
  143. c = 1;
  144. }
  145. if (c)
  146. n++;
  147. }
  148. }
  149. m = 0;
  150. #if defined(LWS_ROLE_WS) && !defined(LWS_WITHOUT_EXTENSIONS)
  151. m |= !!pt->ws.rx_draining_ext_list;
  152. #endif
  153. #if defined(LWS_WITH_TLS)
  154. if (pt->context->tls_ops &&
  155. pt->context->tls_ops->fake_POLLIN_for_buffered)
  156. m |= pt->context->tls_ops->fake_POLLIN_for_buffered(pt);
  157. #endif
  158. if (!m && !n)
  159. return 0;
  160. } else
  161. a = 1;
  162. m = lws_service_flag_pending(context, tsi);
  163. if (m)
  164. c = -1; /* unknown limit */
  165. else
  166. if (n < 0) {
  167. if (LWS_ERRNO != LWS_EINTR)
  168. return -1;
  169. return 0;
  170. } else
  171. c = n;
  172. /* any socket with events to service? */
  173. for (n = 0; n < (int)pt->fds_count && c; n++) {
  174. if (!pt->fds[n].revents)
  175. continue;
  176. c--;
  177. m = lws_service_fd_tsi(context, &pt->fds[n], tsi);
  178. if (m < 0)
  179. return -1;
  180. /* if something closed, retry this slot */
  181. if (m)
  182. n--;
  183. }
  184. if (a)
  185. goto again;
  186. return 0;
  187. }