2323#include <errno.h>
2424#include <fcntl.h>
2525#include <assert.h>
26+ #include <sys/epoll.h>
2627#include <sys/time.h>
2728#include <sys/types.h>
2829#include <sys/syscall.h>
@@ -34,6 +35,8 @@ struct thread_data {
3435 int nr ;
3536 int pipe_read ;
3637 int pipe_write ;
38+ struct epoll_event epoll_ev ;
39+ int epoll_fd ;
3740 bool cgroup_failed ;
3841 pthread_t pthread ;
3942};
@@ -44,6 +47,7 @@ static int loops = LOOPS_DEFAULT;
4447/* Use processes by default: */
4548static bool threaded ;
4649
50+ static bool nonblocking ;
4751static char * cgrp_names [2 ];
4852static struct cgroup * cgrps [2 ];
4953
@@ -81,6 +85,7 @@ static int parse_two_cgroups(const struct option *opt __maybe_unused,
8185}
8286
8387static const struct option options [] = {
88+ OPT_BOOLEAN ('n' , "nonblocking" , & nonblocking , "Use non-blocking operations" ),
8489 OPT_INTEGER ('l' , "loop" , & loops , "Specify number of loops" ),
8590 OPT_BOOLEAN ('T' , "threaded" , & threaded , "Specify threads/process based task setup" ),
8691 OPT_CALLBACK ('G' , "cgroups" , NULL , "SEND,RECV" ,
@@ -165,28 +170,49 @@ static void exit_cgroup(int nr)
165170 free (cgrp_names [nr ]);
166171}
167172
173+ static inline int read_pipe (struct thread_data * td )
174+ {
175+ int ret , m ;
176+ retry :
177+ if (nonblocking ) {
178+ ret = epoll_wait (td -> epoll_fd , & td -> epoll_ev , 1 , -1 );
179+ if (ret < 0 )
180+ return ret ;
181+ }
182+ ret = read (td -> pipe_read , & m , sizeof (int ));
183+ if (nonblocking && ret < 0 && errno == EWOULDBLOCK )
184+ goto retry ;
185+ return ret ;
186+ }
187+
168188static void * worker_thread (void * __tdata )
169189{
170190 struct thread_data * td = __tdata ;
171- int m = 0 , i ;
172- int ret ;
191+ int i , ret , m = 0 ;
173192
174193 ret = enter_cgroup (td -> nr );
175194 if (ret < 0 ) {
176195 td -> cgroup_failed = true;
177196 return NULL ;
178197 }
179198
199+ if (nonblocking ) {
200+ td -> epoll_ev .events = EPOLLIN ;
201+ td -> epoll_fd = epoll_create (1 );
202+ BUG_ON (td -> epoll_fd < 0 );
203+ BUG_ON (epoll_ctl (td -> epoll_fd , EPOLL_CTL_ADD , td -> pipe_read , & td -> epoll_ev ) < 0 );
204+ }
205+
180206 for (i = 0 ; i < loops ; i ++ ) {
181207 if (!td -> nr ) {
182- ret = read (td -> pipe_read , & m , sizeof ( int ) );
208+ ret = read_pipe (td );
183209 BUG_ON (ret != sizeof (int ));
184210 ret = write (td -> pipe_write , & m , sizeof (int ));
185211 BUG_ON (ret != sizeof (int ));
186212 } else {
187213 ret = write (td -> pipe_write , & m , sizeof (int ));
188214 BUG_ON (ret != sizeof (int ));
189- ret = read (td -> pipe_read , & m , sizeof ( int ) );
215+ ret = read_pipe (td );
190216 BUG_ON (ret != sizeof (int ));
191217 }
192218 }
@@ -209,13 +235,16 @@ int bench_sched_pipe(int argc, const char **argv)
209235 * discarding returned value of read(), write()
210236 * causes error in building environment for perf
211237 */
212- int __maybe_unused ret , wait_stat ;
238+ int __maybe_unused ret , wait_stat , flags = 0 ;
213239 pid_t pid , retpid __maybe_unused ;
214240
215241 argc = parse_options (argc , argv , options , bench_sched_pipe_usage , 0 );
216242
217- BUG_ON (pipe (pipe_1 ));
218- BUG_ON (pipe (pipe_2 ));
243+ if (nonblocking )
244+ flags |= O_NONBLOCK ;
245+
246+ BUG_ON (pipe2 (pipe_1 , flags ));
247+ BUG_ON (pipe2 (pipe_2 , flags ));
219248
220249 gettimeofday (& start , NULL );
221250
0 commit comments