Permalink
Browse files

Add syscall buffering for FIOCLEX/FIONCLEX ioctls.

Rust's run-time library uses one of these for every open. That should be
fixed in Rust, but in the meantime, we may as well make it fast.

Given the Rust program
  use std::fs::File;
  use std::io::prelude::*;
  fn main() {
      for _ in 0..1000000 {
          let mut buffer = [0; 1000];
          File::open("foo.txt").unwrap().read(&mut buffer).unwrap();
      }
  }
this reduces recording overhead from 16x to 1.6x for me.
  • Loading branch information...
rocallahan committed Oct 28, 2015
1 parent 7473103 commit 9bc7077e0a031a200aca7baf785dad17eba9f941
Showing with 45 additions and 0 deletions.
  1. +1 −0 CMakeLists.txt
  2. +28 −0 src/preload/preload.c
  3. +16 −0 src/test/ioctl.c
View
@@ -359,6 +359,7 @@ set(BASIC_TESTS
intr_sleep_no_restart
invalid_fcntl
io
ioctl
legacy_ugid
madvise
map_fixed
View
@@ -64,6 +64,7 @@
#include <sysexits.h>
#include <sys/epoll.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/socket.h>
@@ -1258,6 +1259,32 @@ static long sys_fcntl(const struct syscall_info* call)
}
}
static long sys_safe_nonblocking_ioctl(const struct syscall_info* call)
{
const int syscallno = SYS_ioctl;
int fd = call->args[0];
void* ptr = prep_syscall_for_fd(fd);
long ret;
if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {
return traced_raw_syscall(call);
}
ret = untraced_syscall2(syscallno, fd, call->args[1]);
return commit_raw_syscall(syscallno, ptr, ret);
}
static long sys_ioctl(const struct syscall_info* call)
{
switch (call->args[1]) {
case FIOCLEX:
case FIONCLEX:
return sys_safe_nonblocking_ioctl(call);
default:
return traced_raw_syscall(call);
}
}
static long sys_futex(const struct syscall_info* call) {
enum {
FUTEX_USES_UADDR2 = 1 << 0,
@@ -1925,6 +1952,7 @@ static long syscall_hook_internal(const struct syscall_info* call) {
CASE(getrusage);
CASE(gettid);
CASE(gettimeofday);
CASE(ioctl);
#if defined(SYS__llseek)
CASE(_llseek);
#else
View
@@ -0,0 +1,16 @@
/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */
#include "rrutil.h"
int main(int argc, char* argv[]) {
int pipe_fds[2];
test_assert(0 == pipe(pipe_fds));
test_assert(0 == ioctl(pipe_fds[0], FIOCLEX));
test_assert(FD_CLOEXEC == fcntl(pipe_fds[0], F_GETFD));
test_assert(0 == ioctl(pipe_fds[0], FIONCLEX));
test_assert(0 == fcntl(pipe_fds[0], F_GETFD));
atomic_puts("EXIT-SUCCESS");
return 0;
}

0 comments on commit 9bc7077

Please sign in to comment.