Package: dvbstream Version: 0.5-2 Whilst looking at a kernel memory leak, I found out that dvbstream is calling poll() ~ 1500 times a second on my machine.
I've attached a patch which replaces poll() with select(). This also leads to a 15% reduction in CPU usage in my testing. Adrian -- Email: [EMAIL PROTECTED] -*- GPG key available on public key servers Debian GNU/Linux - the maintainable distribution -*- www.debian.org Avoid working with children, animals and Microsoft "operating" systems
diff -Naur dvbstream-0.5-orig/CHANGES dvbstream-0.5/CHANGES --- dvbstream-0.5-orig/CHANGES 2002-05-15 17:39:58.000000000 +0100 +++ dvbstream-0.5/CHANGES 2006-04-01 00:02:05.000000000 +0100 @@ -1,3 +1,14 @@ +v0.5.1 - 31st March 2006: +------------------------- +Changed by Adrian Bridgett from poll() to select(). +Saves ~1500 accept() calls/second which translates into approx 15% CPU saving. + + +v0.5 - ?? +--------- +Unknown + + V0.4 - 29th October 2001: ------------------------- diff -Naur dvbstream-0.5-orig/dvbstream.c dvbstream-0.5/dvbstream.c --- dvbstream-0.5-orig/dvbstream.c 2004-02-11 15:34:21.000000000 +0000 +++ dvbstream-0.5/dvbstream.c 2006-03-31 23:55:47.000000000 +0100 @@ -30,7 +30,7 @@ #include <ctype.h> #include <sys/ioctl.h> #include <sys/time.h> -#include <sys/poll.h> +#include <sys/select.h> #include <sys/stat.h> #include <resolv.h> #include <fcntl.h> @@ -174,22 +174,10 @@ } } -void make_nonblock(int f) { - int oldflags; - - if ((oldflags=fcntl(f,F_GETFL,0)) < 0) { - perror("F_GETFL"); - } - oldflags|=O_NONBLOCK; - if (fcntl(f,F_SETFL,oldflags) < 0) { - perror("F_SETFL"); - } -} - typedef enum {STREAM_ON,STREAM_OFF} state_t; - int socketIn, ns; + int socketIn, ns = -1; int pids[MAX_CHANNELS]; int pestypes[MAX_CHANNELS]; unsigned char hi_mappids[8192]; @@ -197,7 +185,6 @@ int fd_sec; int fd_frontend; int pid,pid2; - int connectionOpen; int fromlen; char hostname[64]; char in_ch; @@ -220,33 +207,31 @@ #define TS_SIZE 188 #define IN_SIZE TS_SIZE +int accept_telnet() { + /* Open a new telnet session if a client is trying to connect */ + if ((ns = accept(socketIn, (struct sockaddr *)&fsin, &fromlen)) < 0) { + perror ("server: accept"); + return -1; + } + + printf("Opened connection\n"); + writes(ns,"220-DVBSTREAM - "); + writes(ns,hostname); + writes(ns,"\r\nDONE\r\n"); + return 1; +} + int process_telnet() { - char cmd[1024]; - int cmd_i=0; + static char cmd[1024] = "\0"; + static int cmd_i=0; int i; char* ch; dmx_pes_type_t pestype; unsigned long freq=0; unsigned long srate=0; - /* Open a new telnet session if a client is trying to connect */ - if (ns==-1) { - if ((ns = accept(socketIn, (struct sockaddr *)&fsin, &fromlen)) > 0) { - make_nonblock(ns); - cmd_i=0; - cmd[0]=0; - printf("Opened connection\n"); - writes(ns,"220-DVBSTREAM - "); - writes(ns,hostname); - writes(ns,"\r\nDONE\r\n"); - connectionOpen=1; - } - } - - /* If a telnet session is open, receive and process any input */ - if (connectionOpen) { /* Read in at most a line of text - any ctrl character ends the line */ - while (read(ns,&in_ch,1)>0) { + while (recv(ns,&in_ch,1,MSG_DONTWAIT)>0) { if (in_ch < 32) break; /* Prevent buffer overflows */ if (cmd_i < 1024-1) { @@ -261,7 +246,6 @@ writes(ns,"DONE\r\n"); close(ns); ns=-1; - connectionOpen=0; printf("Closed connection\n"); } else if (strcasecmp(cmd,"STOP")==0) { writes(ns,"STOP\n"); @@ -352,7 +336,6 @@ writes(ns,"DONE\r\n"); } } - } return(0); } @@ -444,7 +427,8 @@ int fd_dvr; int i,j; unsigned char buf[MTU]; - struct pollfd pfds[2]; // DVR device and Telnet connection + fd_set select_fds; // DVR device, telnet socket and connection + int num_fds; unsigned int secs = 0; unsigned long freq=0; unsigned long srate=0; @@ -691,7 +675,6 @@ f = fopen(pids_map[map_cnt-1].filename, "w+b"); if (f != NULL) { pids_map[map_cnt-1].fd = fileno(f); - make_nonblock(pids_map[map_cnt-1].fd); fprintf(stderr, "Open file %s\n", pids_map[map_cnt-1].filename); } else { pids_map[map_cnt-1].fd = -1; @@ -729,7 +712,7 @@ if ((output_type==RTP_PS) && (npids!=2)) { fprintf(stderr,"ERROR: PS requires exactly two PIDS - video and audio.\n"); - exit; + exit(1); } if (signal(SIGHUP, SignalHandler) == SIG_IGN) signal(SIGHUP, SIG_IGN); @@ -823,32 +806,53 @@ exit(1); } - make_nonblock(socketIn); - if (listen(socketIn, 1) < 0) { perror("server: listen"); exit(1); } - connectionOpen=0; - ns=-1; - pfds[0].fd=fd_dvr; - pfds[0].events=POLLIN|POLLPRI; - pfds[1].events=POLLIN|POLLPRI; - /* Set up timer */ // if (secs > 0) alarm(secs); while ( !Interrupted) { - /* Poll the open file descriptors */ - if (ns==-1) { - poll(pfds,1,500); + // setup select descriptor set + // we always wait on DVR device and + // either the socket or telnet session + // only one session at a time ATM + // in fact, process_telnet can only handle one session + FD_ZERO(&select_fds); + FD_SET(fd_dvr,&select_fds); + if (ns == -1) { + FD_SET(socketIn,&select_fds); } else { - pfds[1].fd=ns; // This can change - poll(pfds,2,500); + FD_SET(ns,&select_fds); + } + + num_fds = (socketIn >= ns) ? socketIn : ns; + num_fds++; + if (select(num_fds, &select_fds, NULL, NULL, NULL) < 0) { + if (errno == EINTR) { + continue; + } + perror("server: select"); + exit(1); + } + + if (FD_ISSET(socketIn, &select_fds)) { + if (ns != -1) { + fprintf(stderr,"Multiple telnets not supported"); + } else { + accept_telnet(); + } } - process_telnet(); // See if there is an incoming telnet connection + if ((ns != -1) && FD_ISSET(ns, &select_fds)) { + process_telnet(); + } + if (! FD_ISSET(fd_dvr, &select_fds)) { + continue; + } + if (output_type==RTP_TS) { /* Attempt to read 188 bytes from /dev/ost/dvr */ if ((bytes_read = read(fd_dvr,free_bytes,PACKET_SIZE)) > 0) {