worker.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /* shttpd - functions for workers
  2. Copyright (C) 2018 Ariadne Devos
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  13. /* # High-level architecture
  14. There are multiple processes.
  15. In a process, there are multiple workers.
  16. Each worker has its own file descriptor table.
  17. This table can have the following format:
  18. 0: unix socket (control lifecycle)
  19. 1: /dev/null (for now)
  20. 2: /dev/null (for now)
  21. 3: epollfd
  22. ???: asynchronous IO?
  23. ...: accept sockets, read/write sockets, open files,
  24. connections to external services ...
  25. The unix socket is for controlling when the worker should stop.
  26. The worker polls for changes in file descriptor readyness and reacts
  27. to those and asynchronous IO events.
  28. Everything is mutually distrusting.
  29. # Seperation of knowledge
  30. Use case: a HTTPS server. A HTTPS server conceptually is TLS encryption
  31. after a HTTP server encrypted connections. The HTTP code and TLS code
  32. (or even HTTPS code and encryption and signing) can live in different
  33. workers or processes.
  34. TODO: an intra-shttpd communication system (passing around and transcribing
  35. paper).
  36. # Paper
  37. A character buffer that can be passed around.
  38. # The control thread
  39. - Control thread creates worker.
  40. - Control thread -> asks worker to perform apoptosis
  41. - Control thread -> sends tasks to worker
  42. - Control thread -> asks tasks from worker -> sends tasks to control thread
  43. - Worker thread -> reports hard errors to control thread
  44. - Kernel -> notifies worker -> asks kernel to do stuff
  45. */
  46. #include <stdint.h>
  47. #include <sys/epoll.h>
  48. /* Don't change this group! control.c relies upon these values. */
  49. #define sHT_FD_CONTROL 0
  50. #define sHT_FD_STDOUT 1
  51. #define sHT_FD_STDERR 2
  52. /* Only for sHT_start_worker. Points to a worker executable. */
  53. #define sHT_FD_WORKEREXE 4
  54. #include <sHT/paper.h>
  55. #include <sHT/task.h>
  56. #include <sHT/taskset.h>
  57. #include <sHT/scheduling.h>
  58. typedef unsigned int sHT_worker_flags;
  59. #define sHT_WORKER_OOM 1
  60. #define sHT_WORKER_LIMIT_TASKS 2
  61. #define sHT_WORKER_LIMIT_PAPER 4
  62. #define sHT_WORKER_LIMIT_WATCHES 8
  63. /* file descriptor */
  64. #define sHT_WORKER_LIMIT_FDS 16
  65. /* file descriptor */
  66. #define sHT_WORKER_SYSTEM_FDS 32
  67. struct sHT_objcache;
  68. struct sHT_worker
  69. {
  70. struct sHT_objcache *papers;
  71. /* Use sHT_deschedule_rr, sHT_schedule_rr */
  72. struct sHT_taskset todo;
  73. struct sHT_objcache *free_streams;
  74. /* length: todo->n */
  75. struct epoll_event *epoll_events;
  76. /* indexed by fd, length: todo->capacity */
  77. struct sHT_task *tasks;
  78. /* The control thread is notified if any is set. */
  79. sHT_worker_flags flags;
  80. sHT_watch_set watches;
  81. };
  82. /* epoll_wait(2) returned n events. Schedule corresponding tasks, setting
  83. task->epollflags. */
  84. __attribute__((nonnull (1)))
  85. void
  86. sHT_schedule_events(struct sHT_worker *worker, int n);
  87. /* _logic$ is defined by worker-specific code */
  88. __attribute__((nonnull (1, 2)))
  89. void
  90. sHT_diy_logic(struct sHT_worker *worker, struct sHT_task *task);
  91. __attribute__((nonnull (1, 2)))
  92. void
  93. sHT_aio_logic(struct sHT_worker *worker, struct sHT_task *task);
  94. /* Send information about resource utilisation to the control thread.
  95. More specifically,
  96. send and clear task->flags.
  97. Doesn't allocate any resources.
  98. (May be extended) */
  99. __attribute__((nonnull (1, 2)))
  100. void
  101. sHT_sendstatus_task(struct sHT_worker *worker, struct sHT_task *task);
  102. /* Perform the IO actions of worker->io_type.
  103. Then, call sHT_diy_logic, sHT_socket_logic, sHT_aio_logic or
  104. sHT_accept_logic, depending on the io type.
  105. task must reschedule itself if it:
  106. - it has some things to do, even if no IO is possible
  107. */
  108. __attribute__((nonnull (1, 2)))
  109. void
  110. sHT_perform_task(struct sHT_worker *worker, struct sHT_task *task);
  111. __attribute__((nonnull (1)))
  112. _Noreturn void
  113. sHT_worker(struct sHT_worker *worker);