add to, and prioritize the TODO a little.
[trinity.git] / fds.c
blobd56addbc175c6a556cef60821a713c73e70ac685
1 #include <errno.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <sys/epoll.h>
7 #include <sys/eventfd.h>
9 #include "files.h"
10 #include "log.h"
11 #include "net.h"
12 #include "params.h"
13 #include "perf.h"
14 #include "pids.h"
15 #include "random.h"
16 #include "sanitise.h"
17 #include "shm.h"
18 #include "trinity.h"
20 /* Pipe FD related functions. */
21 static void open_pipes(void)
23 int pipes[2];
24 unsigned int i;
26 for (i = 0; i < MAX_PIPE_FDS; i+=2) {
27 if (pipe(pipes) < 0) {
28 perror("pipe fail.\n");
29 exit(EXIT_FAILURE);
31 shm->pipe_fds[i] = pipes[0];
32 shm->pipe_fds[i+1] = pipes[1];
34 output(2, "fd[%d] = pipe\n", shm->pipe_fds[i]);
35 output(2, "fd[%d] = pipe\n", shm->pipe_fds[i+1]);
39 static int rand_pipe_fd(void)
41 return shm->pipe_fds[rand() % MAX_PIPE_FDS];
44 /* perf related fds (see also perf.c & syscalls/perf_event_open.c) */
45 static int rand_perf_fd(void)
47 return shm->perf_fds[rand() % MAX_PERF_FDS];
50 /* epoll related fds */
51 static void open_epoll_fds(void)
53 unsigned int i = 0;
54 int fd = -1;
56 while (i < MAX_EPOLL_FDS) {
58 if (rand_bool())
59 fd = epoll_create(1);
60 else
61 fd = epoll_create1(EPOLL_CLOEXEC);
63 if (fd != -1) {
64 shm->epoll_fds[i] = fd;
65 output(2, "fd[%d] = epoll\n", shm->epoll_fds[i]);
66 i++;
71 static int rand_epoll_fd(void)
73 return shm->epoll_fds[rand() % MAX_EPOLL_FDS];
76 /* eventfd FDs */
77 static void open_eventfd_fds(void)
79 unsigned int i;
81 shm->eventfd_fds[0] = eventfd(rand32(), 0);
82 shm->eventfd_fds[1] = eventfd(rand32(), EFD_CLOEXEC);
83 shm->eventfd_fds[2] = eventfd(rand32(), EFD_NONBLOCK);
84 shm->eventfd_fds[3] = eventfd(rand32(), EFD_SEMAPHORE);
85 shm->eventfd_fds[4] = eventfd(rand32(), EFD_CLOEXEC | EFD_NONBLOCK);
86 shm->eventfd_fds[5] = eventfd(rand32(), EFD_CLOEXEC | EFD_SEMAPHORE);
87 shm->eventfd_fds[6] = eventfd(rand32(), EFD_NONBLOCK | EFD_SEMAPHORE);
88 shm->eventfd_fds[7] = eventfd(rand32(), EFD_CLOEXEC | EFD_NONBLOCK | EFD_SEMAPHORE);
90 for (i = 0; i < MAX_EVENTFD_FDS; i++)
91 output(2, "fd[%d] = eventfd\n", shm->eventfd_fds[i]);
94 static int rand_eventfd_fd(void)
96 return shm->eventfd_fds[rand() % MAX_EVENTFD_FDS];
99 /* regular file FDs */
100 unsigned int nr_file_fds = 0;
102 static int rand_file_fd(void)
104 unsigned int fd_index;
106 fd_index = rand() % nr_file_fds;
107 return shm->file_fds[fd_index];
111 static int get_new_random_fd(void)
113 unsigned int i;
114 int fd = 0;
116 retry:
117 i = rand() % 6;
119 if (do_specific_proto == TRUE)
120 i = 1;
122 if (no_files == TRUE)
123 i = 1;
125 /* Ugly special case.
126 * Sometimes, we can get here without any fd's setup.
127 * If this happens, we divide by zero if we pick case 0 because
128 * nr_file_fds is zero
130 * When this circumstance occurs, we just force it to use another network socket.
132 * FIXME: A better solution would be to like, actually open an fd. duh.
134 if (nr_file_fds == 0)
135 i = 1;
137 switch (i) {
138 case 0:
139 fd = rand_file_fd();
140 break;
142 case 1:
143 /* When using victim files, sockets can be 0.
144 * Use files as a fallback, or pipes if no files are open.
146 if (nr_sockets == 0) {
147 if (nr_file_fds > 0)
148 fd = rand_file_fd();
149 else
150 fd = rand_pipe_fd();
151 return fd;
153 fd = shm->sockets[rand() % nr_sockets].fd;
154 break;
156 case 2:
157 fd = rand_pipe_fd();
158 break;
160 case 3:
161 if (shm->perf_fds[0] == 0) /* perf unavailable/disabled. */
162 goto retry;
164 fd = rand_perf_fd();
165 break;
167 case 4:
168 fd = rand_epoll_fd();
169 break;
171 case 5:
172 fd = rand_eventfd_fd();
173 break;
177 return fd;
180 int get_random_fd(void)
182 /* 25% chance of returning something new. */
183 if ((rand() % 4) == 0)
184 return get_new_random_fd();
186 /* the rest of the time, return the same fd as last time. */
187 regen:
188 if (shm->fd_lifetime == 0) {
189 shm->current_fd = get_new_random_fd();
190 shm->fd_lifetime = (rand() % max_children) + 5;
191 } else
192 shm->fd_lifetime--;
194 if (shm->current_fd == 0) {
195 shm->fd_lifetime = 0;
196 goto regen;
199 return shm->current_fd;
202 unsigned int setup_fds(void)
204 /* If we have victim files, don't worry about sockets. */
205 if (victim_path == NULL) {
206 int ret;
208 ret = open_sockets();
209 if (ret == FALSE)
210 return FALSE;
213 open_pipes();
215 open_perf_fds();
217 open_epoll_fds();
219 open_eventfd_fds();
221 if (no_files == FALSE) {
222 generate_filelist();
223 if (files_in_index == 0) /* Something bad happened. Crappy -V maybe? */
224 return FALSE; // FIXME: We should log something here probably.
226 open_files();
229 return TRUE;
232 void regenerate_fds(void)
234 if (no_files == TRUE)
235 return;
237 close_files();
238 open_files();