[Pkg-uml-pkgs] Bug#628105: uml-utilities: uml-switch eats way more CPU than it should
Anton Ivanov
arivanov at sigsegv.cx
Fri May 27 10:11:00 UTC 2011
Package: uml-utilities
Version: 20070815-1.1
Severity: normal
Tags: patch
UML Switch eats about as much CPU as the VM itself (if not more).
I read the source and noticed that it uses poll() instead of epoll()
in the main loop.
Attached is a diff for an epoll based version. It uses approximately
1/4 of the CPU used by the poll() based one in my test case.
I have tested the basic functionality - VM attach/VM detach, etc. All
seems to work.
*** uml_switch.c.orig 2006-02-27 21:02:36.000000000 +0000
--- uml_switch.c 2011-05-27 11:05:36.000000000 +0100
***************
*** 10,16 ****
#include <stdint.h>
#include <sys/socket.h>
#include <sys/un.h>
! #include <sys/poll.h>
#include <sys/time.h>
#include <unistd.h>
#include "switch.h"
--- 10,16 ----
#include <stdint.h>
#include <sys/socket.h>
#include <sys/un.h>
! #include <sys/epoll.h>
#include <sys/time.h>
#include <unistd.h>
#include "switch.h"
***************
*** 27,32 ****
--- 27,37 ----
static int hub = 0;
static int compat_v0 = 0;
+ // EPOLL FD
+
+ static int epfd;
+ #define MAX_EVENTS 128
+
enum request_type { REQ_NEW_CONTROL };
struct request_v0 {
***************
*** 99,133 ****
static int maxfds = 0;
static int nfds = 0;
static void add_fd(int fd)
{
! struct pollfd *p;
! if(nfds == maxfds){
! maxfds = maxfds ? 2 * maxfds : 4;
! if((fds = realloc(fds, maxfds * sizeof(struct pollfd))) == NULL){
! perror("realloc");
! cleanup();
! exit(1);
! }
! }
! p = &fds[nfds++];
! p->fd = fd;
! p->events = POLLIN;
! }
static void remove_fd(int fd)
{
! int i;
! for(i = 0; i < nfds; i++){
! if(fds[i].fd == fd) break;
! }
! if(i == nfds){
! fprintf(stderr, "remove_fd : Couldn't find descriptor %d\n", fd);
! }
! memmove(&fds[i], &fds[i + 1], (maxfds - i - 1) * sizeof(struct pollfd));
! nfds--;
}
static void sig_handler(int sig)
--- 104,161 ----
static int maxfds = 0;
static int nfds = 0;
+ //static void add_fd(int fd)
+ //{
+ // struct pollfd *p;
+ //
+ // if(nfds == maxfds){
+ // maxfds = maxfds ? 2 * maxfds : 4;
+ // if((fds = realloc(fds, maxfds * sizeof(struct pollfd))) == NULL){
+ // perror("realloc");
+ // cleanup();
+ // exit(1);
+ // }
+ // }
+ // p = &fds[nfds++];
+ // p->fd = fd;
+ // p->events = POLLIN;
+ //}
+
static void add_fd(int fd)
{
! struct epoll_event event;
! int ret;
! event.data.fd = fd; /* return the fd to us later */
! event.events = EPOLLIN || EPOLLOUT;
!
! ret = epoll_ctl (epfd, EPOLL_CTL_ADD, fd, &event);
! if (ret)
! perror ("epoll_ctl");
! }
!
! //static void remove_fd(int fd)
! //{
! // int i;
! //
! // for(i = 0; i < nfds; i++){
! // if(fds[i].fd == fd) break;
! // }
! // if(i == nfds){
! // fprintf(stderr, "remove_fd : Couldn't find descriptor %d\n", fd);
! // }
! // memmove(&fds[i], &fds[i + 1], (maxfds - i - 1) * sizeof(struct pollfd));
! // nfds--;
! //}
static void remove_fd(int fd)
{
! struct epoll_event event;
! int ret;
! ret = epoll_ctl (epfd, EPOLL_CTL_DEL, fd, &event);
! if (ret)
! perror ("epoll_ctl");
}
static void sig_handler(int sig)
***************
*** 503,508 ****
--- 531,541 ----
#endif
printf("\n");
+ epfd = epoll_create (MAX_EVENTS); // need to fix magic number
+ if (epfd < 0)
+ perror ("epoll_create");
+
+
if(isatty(0))
add_fd(0);
add_fd(connect_fd);
***************
*** 518,536 ****
exit(1);
}
! while(1){
char buf[128];
! n = poll(fds, nfds, -1);
! if(n < 0){
if(errno == EINTR) continue;
! perror("poll");
break;
}
! for(i = 0; i < nfds; i++){
! if(fds[i].revents == 0) continue;
! if(fds[i].fd == 0){
! if(fds[i].revents & POLLHUP){
printf("EOF on stdin, cleaning up and exiting\n");
goto out;
}
--- 551,580 ----
exit(1);
}
! struct epoll_event *events;
! int nr_events;
!
! events = malloc (sizeof (struct epoll_event) * MAX_EVENTS);
! if (!events) {
! perror ("malloc");
! return 1;
! }
!
! while(1) {
!
char buf[128];
! nr_events = epoll_wait(epfd, events, MAX_EVENTS, -1);
!
! if(nr_events < 0){
if(errno == EINTR) continue;
! perror("epoll");
break;
}
! for(i = 0; i < nr_events; i++){
! //epoll loop
! if(events[i].data.fd == 0){
! if(events[i].events & EPOLLHUP){
printf("EOF on stdin, cleaning up and exiting\n");
goto out;
}
***************
*** 545,565 ****
goto out;
}
}
! else if(fds[i].fd == connect_fd){
! if(fds[i].revents & POLLHUP){
printf("Error on connection fd\n");
continue;
}
accept_connection(connect_fd);
}
! else if(fds[i].fd == data_fd) handle_sock_data(data_fd, hub);
#ifdef TUNTAP
! else if(fds[i].fd == tap_fd) handle_tap_data(tap_fd, hub);
#endif
else {
! new = handle_port(fds[i].fd);
! if(new) new_port(fds[i].fd, data_fd);
! else close_descriptor(fds[i].fd);
}
}
}
--- 589,609 ----
goto out;
}
}
! else if(events[i].data.fd == connect_fd){
! if(events[i].events & EPOLLHUP){
printf("Error on connection fd\n");
continue;
}
accept_connection(connect_fd);
}
! else if(events[i].data.fd == data_fd) handle_sock_data(data_fd, hub);
#ifdef TUNTAP
! else if(events[i].data.fd == tap_fd) handle_tap_data(tap_fd, hub);
#endif
else {
! new = handle_port(events[i].data.fd);
! if(new) new_port(events[i].data.fd, data_fd);
! else close_descriptor(events[i].data.fd);
}
}
}
-- System Information:
Debian Release: 6.0.1
APT prefers stable-updates
APT policy: (500, 'stable-updates'), (500, 'stable')
Architecture: i386 (i686)
Kernel: Linux 2.6.32-5-686 (SMP w/2 CPU cores)
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Versions of packages uml-utilities depends on:
ii adduser 3.112+nmu2 add and remove users and groups
ii libc6 2.11.2-10 Embedded GNU C Library: Shared lib
ii libfuse2 2.8.4-1.1 Filesystem in USErspace library
ii libncurses5 5.7+20100313-5 shared libraries for terminal hand
ii libreadline5 5.2-7 GNU readline and history libraries
ii lsb-base 3.2-23.2squeeze1 Linux Standard Base 3.2 init scrip
uml-utilities recommends no packages.
Versions of packages uml-utilities suggests:
ii user-mode-linux 2.6.32-1um-4 User-mode Linux (kernel)
-- Configuration Files:
/etc/default/uml-utilities changed [not included]
-- no debconf information
More information about the Pkg-uml-pkgs
mailing list