comparison seobeo/os/s_linux_edge.c @ 183:a8976a008a9d

[BenchMark] Added bun bench mark to test seoboe vs other popular benchmarks.
author MrJuneJune <me@mrjunejune.com>
date Fri, 23 Jan 2026 21:19:08 -0800
parents 48f260576059
children
comparison
equal deleted inserted replaced
179:8d17f6e6e290 183:a8976a008a9d
1 #include <sys/epoll.h> 1 #include <sys/epoll.h>
2 #include <netinet/tcp.h>
2 #include "seobeo/seobeo.h" 3 #include "seobeo/seobeo.h"
3 4
5 // TCP keep-alive settings
6 #define KEEP_ALIVE_IDLE_SEC 30 // Start probes after 30s idle
7 #define KEEP_ALIVE_INTERVAL 5 // Probe every 5 seconds
8 #define KEEP_ALIVE_COUNT 3 // Close after 3 failed probes
9
10 // Configure TCP keep-alive on socket (kernel handles timeout)
11 static void configure_keep_alive(int socket)
12 {
13 int enable = 1;
14 setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable));
15
16 int idle = KEEP_ALIVE_IDLE_SEC;
17 setsockopt(socket, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(idle));
18
19 int interval = KEEP_ALIVE_INTERVAL;
20 setsockopt(socket, IPPROTO_TCP, TCP_KEEPINTVL, &interval, sizeof(interval));
21
22 int count = KEEP_ALIVE_COUNT;
23 setsockopt(socket, IPPROTO_TCP, TCP_KEEPCNT, &count, sizeof(count));
24 }
4 25
5 void *Seobeo_Web_Edge_Worker(void *vargs) 26 void *Seobeo_Web_Edge_Worker(void *vargs)
6 { 27 {
7 WorkerArgs *args = vargs; 28 WorkerArgs *args = vargs;
8 const int max_events = 64; 29 const int max_events = 64;
9 struct epoll_event events[max_events]; 30 struct epoll_event events[max_events];
10 31
11 // Each thread creates its own epoll to avoid race conditions
12 int epfd = epoll_create1(0); 32 int epfd = epoll_create1(0);
13 if (epfd < 0) { 33 if (epfd < 0)
34 {
14 perror("epoll_create1"); 35 perror("epoll_create1");
15 return NULL; 36 return NULL;
16 } 37 }
17 38
18 // Add server socket to this thread's epoll
19 struct epoll_event ev = { 39 struct epoll_event ev = {
20 .events = EPOLLIN | EPOLLET, 40 .events = EPOLLIN | EPOLLET,
21 .data.ptr = args->srv 41 .data.ptr = args->srv
22 }; 42 };
23 if (epoll_ctl(epfd, EPOLL_CTL_ADD, args->srv->socket, &ev) < 0) { 43 if (epoll_ctl(epfd, EPOLL_CTL_ADD, args->srv->socket, &ev) < 0)
44 {
24 perror("epoll_ctl ADD server"); 45 perror("epoll_ctl ADD server");
25 close(epfd); 46 close(epfd);
26 return NULL; 47 return NULL;
27 } 48 }
28 49
29 while (1) { 50 while (1)
30 int n = epoll_wait(epfd, events, max_events, -1); 51 {
31 if (n < 0) { 52 int n = epoll_wait(epfd, events, max_events, -1); // Block indefinitely, kernel handles timeouts
32 if (errno == EINTR) continue; 53 if (n < 0)
54 {
55 if (errno == EINTR)
56 continue;
33 perror("epoll_wait"); 57 perror("epoll_wait");
34 continue; 58 continue;
35 } 59 }
36 60
37 for (int i = 0; i < n; i++) { 61 for (int i = 0; i < n; i++)
38 Seobeo_Handle *phandle = events[i].data.ptr; 62 {
63 Seobeo_Handle *p_handle = events[i].data.ptr;
39 64
40 if (phandle == args->srv) { 65 // Server socket - accept new connections
41 // Accept all pending connections (edge-triggered mode) 66 if (p_handle == args->srv)
42 while (1) { 67 {
68 while (1)
69 {
43 Seobeo_Handle *p_cli_handle = Seobeo_Stream_Handle_Server_Accept(args->srv); 70 Seobeo_Handle *p_cli_handle = Seobeo_Stream_Handle_Server_Accept(args->srv);
44 if (!p_cli_handle) break; 71 if (!p_cli_handle) break;
72
73 // Let kernel handle keep-alive timeout
74 configure_keep_alive(p_cli_handle->socket);
45 75
46 struct epoll_event client_ev = { 76 struct epoll_event client_ev = {
47 .events = EPOLLIN | EPOLLET, 77 .events = EPOLLIN | EPOLLET,
48 .data.ptr = p_cli_handle 78 .data.ptr = p_cli_handle
49 }; 79 };
80
50 if (epoll_ctl(epfd, EPOLL_CTL_ADD, p_cli_handle->socket, &client_ev) < 0) 81 if (epoll_ctl(epfd, EPOLL_CTL_ADD, p_cli_handle->socket, &client_ev) < 0)
51 { 82 {
52 perror("epoll_ctl ADD client"); 83 perror("epoll_ctl ADD client");
53 Seobeo_Handle_Destroy(p_cli_handle); 84 Seobeo_Handle_Destroy(p_cli_handle);
54 } 85 }
55 } 86 }
56 } else { 87 }
57 // Remove from epoll first 88 // Client socket - handle request
58 epoll_ctl(epfd, EPOLL_CTL_DEL, phandle->socket, NULL); 89 else
90 {
91 Seobeo_Handle *p_client_handle = p_handle;
59 92
60 // Handle request (this function destroys the handle internally) 93 // Connection error or hangup - clean up
61 Seobeo_Web_HandleClientRequest(phandle, args->cache); 94 if (events[i].events & (EPOLLERR | EPOLLHUP))
95 {
96 epoll_ctl(epfd, EPOLL_CTL_DEL, p_client_handle->socket, NULL);
97 Seobeo_Handle_Destroy(p_client_handle);
98 continue;
99 }
100
101 // Handle requests (loop for pipelined requests)
102 boolean keep_alive = TRUE;
103 while (keep_alive)
104 {
105 keep_alive = Seobeo_Web_ClientHandle_Request(p_client_handle, args->cache, TRUE);
106
107 // No more data in buffer, wait for next epoll event
108 if (keep_alive && p_client_handle->read_buffer_len == 0)
109 break;
110 }
111
112 // Client wants to close
113 if (!keep_alive)
114 {
115 epoll_ctl(epfd, EPOLL_CTL_DEL, p_client_handle->socket, NULL);
116 Seobeo_Handle_Destroy(p_client_handle);
117 }
118 // Connection stays open, kernel will timeout if idle
62 } 119 }
63 } 120 }
64 } 121 }
65 122
66 close(epfd); 123 close(epfd);