Exemple #1
0
int main(void) {
  spin();
  atomic_puts("done");
  return 0;
}
Exemple #2
0
static void sighandler(int sig) {
  atomic_printf("caught signal %d, exiting\n", sig);
  atomic_puts("EXIT-SUCCESS");
  _exit(0);
}
Exemple #3
0
int main(int argc, char* argv[]) {
  char token = '!';
  struct timeval ts;
  pthread_t reader;
  int sock;

  gettimeofday(&ts, NULL);

  socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfds);
  sock = sockfds[0];

  pthread_mutex_lock(&lock);

  pthread_create(&reader, NULL, reader_thread, NULL);

  /* Make the reader thread wait on its pthread_mutex_lock() */
  atomic_puts("M: sleeping ...");
  usleep(500000);
  atomic_puts("M: unlocking mutex ...");
  pthread_mutex_unlock(&lock);
  atomic_puts("M:   ... done");

  /* Force a wait on read() */
  atomic_puts("M: sleeping again ...");
  usleep(500000);
  atomic_printf("M: writing '%c' to socket ...\n", token);
  check_syscall(1, write(sock, &token, sizeof(token)));
  ++token;
  atomic_puts("M:   ... done");
  /* Force a wait on readv() */
  {
    struct iovec v = { .iov_base = &token, .iov_len = sizeof(token) };

    atomic_puts("M: sleeping again ...");
    usleep(500000);
    atomic_printf("r: writev('%c')'ing socket ...\n", token);
    check_syscall(1, writev(sock, &v, 1));
    ++token;
    atomic_puts("M:   ... done");
  }
  /* Force a wait on recv() */
  atomic_puts("M: sleeping again ...");
  usleep(500000);
  atomic_printf("M: sending '%c' to socket ...\n", token);
  send(sock, &token, sizeof(token), 0);
  ++token;
  atomic_puts("M:   ... done");

  /* Force a wait on recvfrom() */
  atomic_puts("M: sleeping again ...");
  usleep(500000);
  atomic_printf("M: sending '%c' to socket ...\n", token);
  send(sock, &token, sizeof(token), 0);
  ++token;
  atomic_puts("M:   ... done");

  /* Force a wait on recvfrom(&sock) */
  atomic_puts("M: sleeping again ...");
  usleep(500000);
  atomic_printf("M: sending '%c' to socket ...\n", token);
  send(sock, &token, sizeof(token), 0);
  ++token;
  atomic_puts("M:   ... done");
  {
    struct mmsghdr mmsg = { { 0 } };
    struct iovec data = { 0 };
    int magic = msg_magic;

    data.iov_base = &magic;
    data.iov_len = sizeof(magic);
    mmsg.msg_hdr.msg_iov = &data;
    mmsg.msg_hdr.msg_iovlen = 1;

    struct cmsghdr* cmptr = (struct cmsghdr*)malloc(CTRLMSG_LEN); // send a fd
    cmptr->cmsg_level = SOL_SOCKET;
    cmptr->cmsg_type = SCM_RIGHTS;
    cmptr->cmsg_len = CTRLMSG_LEN;
    mmsg.msg_hdr.msg_control = cmptr;
    mmsg.msg_hdr.msg_controllen = CTRLMSG_LEN;
    *(int*)CMSG_DATA(cmptr) = STDERR_FILENO; // send stderr as fd

    /* Force a wait on recvmsg() */
    atomic_puts("M: sleeping again ...");
    usleep(500000);
    atomic_printf("M: sendmsg'ing 0x%x to socket ...\n", msg_magic);
    sendmsg(sock, &mmsg.msg_hdr, 0);
    atomic_puts("M:   ... done");

    /* Force a wait on recvmmsg() */
    atomic_puts("M: sleeping again ...");
    usleep(500000);
    atomic_printf("M: sendmmsg'ing 0x%x to socket ...\n", msg_magic);

    breakpoint();

    sendmmsg(sock, &mmsg, 1, 0);
    atomic_printf("M:   ... sent %u bytes\n", mmsg.msg_len);

    /* Force a wait on recvmmsg() */
    atomic_puts("M: sleeping again ...");
    usleep(500000);
    atomic_printf("M: sendmmsg'ing(by socketcall) 0x%x to socket ...\n",
                  msg_magic);

#if defined(SYS_socketcall)
    struct sendmmsg_arg arg = { 0 };
    arg.sockfd = sock;
    arg.msgvec = &mmsg;
    arg.vlen = 1;
    syscall(SYS_socketcall, SYS_SENDMMSG, (void*)&arg);
#elif defined(SYS_sendmmsg)
    syscall(SYS_sendmmsg, sock, &mmsg, 1, 0);
#else
#error unable to call sendmmsg
#endif

    free(cmptr);
  }
  {
    struct msghdr msg = { 0 };
    struct iovec iovs[2];
    char c1 = token++;
    char c2 = token++;

    iovs[0].iov_base = &c1;
    iovs[0].iov_len = sizeof(c1);
    iovs[1].iov_base = &c2;
    iovs[1].iov_len = sizeof(c2);

    msg.msg_iov = iovs;
    msg.msg_iovlen = sizeof(iovs) / sizeof(iovs[0]);

    /* Force a wait on recvmsg(). */
    atomic_puts("M: sleeping again ...");
    usleep(500000);
    atomic_printf("M: writing { '%c', '%c' } to socket ...\n", c1, c2);
    check_syscall(2, sendmsg(sock, &msg, 0));
    atomic_puts("M:   ... done");
  }
  /* Force a wait on poll() */
  atomic_puts("M: sleeping again ...");
  usleep(500000);
  atomic_printf("M: writing '%c' to socket ...\n", token);
  write(sock, &token, sizeof(token));
  ++token;
  atomic_puts("M:   ... done");

  /* Force a wait on ppoll() */
  atomic_puts("M: sleeping again ...");
  usleep(500000);
  atomic_printf("M: writing '%c' to socket ...\n", token);
  write(sock, &token, sizeof(token));
  ++token;
  atomic_puts("M:   ... done");

  /* Force a wait on select(), raw syscall */
  atomic_puts("M: sleeping again ...");
  usleep(500000);
  atomic_printf("M: writing '%c' to socket ...\n", token);
  write(sock, &token, sizeof(token));
  ++token;
  atomic_puts("M:   ... done");

  /* Force a wait on select(), library call */
  atomic_puts("M: sleeping again ...");
  usleep(500000);
  atomic_printf("M: writing '%c' to socket ...\n", token);
  write(sock, &token, sizeof(token));
  ++token;
  atomic_puts("M:   ... done");

  /* Force a wait on epoll_wait() */
  atomic_puts("M: sleeping again ...");
  usleep(500000);
  atomic_printf("M: writing '%c' to socket ...\n", token);
  write(sock, &token, sizeof(token));
  ++token;
  atomic_puts("M:   ... done");

  /* Force a wait on write() */
  atomic_puts("M: sleeping again ...");
  usleep(500000);
  atomic_printf("M: reading socket ...\n");
  ++token;
  {
    char* buf = (char*)malloc(num_sockbuf_bytes);
    int i;
    for (i = 0; i < 2; ++i) {
      read_all_chunks(sock, buf, num_sockbuf_bytes, token);
      ++token;
    }
    free(buf);
  }
  atomic_puts("M:   ... done");

  /* Force a wait on read() */
  atomic_puts("M: sleeping again ...");
  usleep(500000);
  atomic_printf("M: writing '%c' to socket ...\n", token);
  write(sock, &token, sizeof(token));
  atomic_puts("M:   ... done");

  pthread_join(reader, NULL);

  atomic_puts("EXIT-SUCCESS");
  return 0;
}
Exemple #4
0
int main(void) {
  ssize_t pagesize = sysconf(_SC_PAGESIZE);
  int fd;
  int fd2;
  size_t i;
  int err;
  pid_t parent_pid = getpid();
  pid_t pid;
  int status;

  fd = open(FILENAME, O_CREAT | O_EXCL | O_RDWR, 0600);
  fd2 = open(FILENAME, O_RDWR);
  test_assert(fd >= 0 && fd2 >= 0);

  unlink(FILENAME);

  atomic_printf("parent pid is %d\n", parent_pid);

  /* Write a page's worth of data. */
  for (i = 0; i < pagesize / sizeof(i); ++i) {
    ssize_t nwritten = write(fd, &i, sizeof(i));
    test_assert(nwritten == sizeof(i));
  }

  {
    struct flock64 lock = {
      .l_type = F_WRLCK, .l_whence = SEEK_SET, .l_start = 0, .l_len = pagesize, .l_pid = 0
    };

    atomic_printf("sizeof(flock64) = %zu\n", sizeof(lock));
    err = fcntl(fd, F_OFD_GETLK, &lock);
    if (err == -1 && errno == EINVAL)
    {
      // should we succeed when OFD locks are not supported?
      atomic_puts("EXIT-SUCCESS");
      return 0;
    }

    test_assert(0 == err);

    atomic_printf("before lock: type: %d, pid: %d\n", lock.l_type, lock.l_pid);
    test_assert(F_UNLCK == lock.l_type);

    lock.l_type = F_WRLCK;
    fcntl(fd, F_OFD_SETLK, &lock);
    test_assert(0 == err);

    /* Make sure our lock "took". */
    if (0 == (pid = fork())) {
      lock.l_type = F_RDLCK;
      err = fcntl(fd2, F_OFD_GETLK, &lock);
      test_assert(0 == err);

      atomic_printf("  after GETLK: type: %d, pid: %d\n", lock.l_type,
                    lock.l_pid);
      test_assert(F_WRLCK == lock.l_type && 0 == lock.l_start &&
                  pagesize == lock.l_len && -1 == lock.l_pid);

      lock.l_type = F_RDLCK;
      lock.l_pid = 0;
      err = fcntl(fd2, F_OFD_SETLKW, &lock);
      test_assert(0 == err);

      atomic_printf("  after SETLKW: type: %d, pid: %d\n", lock.l_type,
                    lock.l_pid);
      test_assert(F_RDLCK == lock.l_type && 0 == lock.l_start &&
                  pagesize == lock.l_len && 0 == lock.l_pid);

      atomic_puts("  releasing lock ...");
      lock.l_type = F_UNLCK;
      fcntl(fd2, F_OFD_SETLK, &lock);
      test_assert(0 == err);
      return 0;
    }

    atomic_puts("P: forcing child to block on LK, sleeping ...");
    usleep(500000);
    atomic_puts("P: ... awake, releasing lock");
    lock.l_type = F_UNLCK;
    fcntl(fd, F_OFD_SETLK, &lock);
    test_assert(0 == err);

    waitpid(pid, &status, 0);
    test_assert(WIFEXITED(status) && 0 == WEXITSTATUS(status));
  }

  atomic_puts("EXIT-SUCCESS");
  return 0;
}
static void SEGV_handler(int sig, siginfo_t* si, void* context) {
  atomic_puts(
      "Should not reach SEGV handler, since there's no safe altstack to use");
  exit(1);
}
Exemple #6
0
int main(int argc, char* argv[]) {
  funcall();

  atomic_puts("EXIT-SUCCESS");
  return 0;
}
Exemple #7
0
/* NB: these must *not* be macros so that debugger step-next works as
 * expected per the program source. */
void A() {
	atomic_puts("entered A");
	pthread_barrier_wait(&bar);
	pthread_barrier_wait(&bar);
}
Exemple #8
0
static void fault_handler(int sig, siginfo_t* si, void* context) {
  atomic_puts("FAILED: handler should not have been called for blocked signal");
}
Exemple #9
0
static void B(void) {
  atomic_puts("calling C");
  C();
  atomic_puts("finished C");
}
Exemple #10
0
void hit_barrier() {
	atomic_puts("hit barrier");
}
Exemple #11
0
static void C(void) { atomic_puts("in C"); }
Exemple #12
0
int main(void) {
  atomic_puts("calling A");
  A();
  atomic_puts("finished A");
  return 0;
}
Exemple #13
0
static void A(void) {
  atomic_puts("calling B");
  B();
  atomic_puts("finished B");
}
Exemple #14
0
static void handle_usr1(int sig) {
  test_assert(SIGUSR1 == sig);
  caught_usr1 = 1;
  atomic_puts("caught usr1");
}
Exemple #15
0
int main(void) {
  struct passwd* p = getpwnam("root");
  atomic_printf("%d\n", p ? p->pw_uid : 0);
  atomic_puts("EXIT-SUCCESS");
  return 0;
}
Exemple #16
0
void catcher(int sig) {
	atomic_printf("Signal caught, Counter is %ld\n", counter);
	atomic_puts("EXIT-SUCCESS");
	_exit(0);
}
static void SEGV_handler(int sig, siginfo_t* si, void* context) {
  atomic_printf("depth = %d\n", depth);
  atomic_puts("EXIT-SUCCESS");
  exit(0);
}
Exemple #18
0
int main(void) {
  size_t page_size = sysconf(_SC_PAGESIZE);
  unsigned char* p =
      (unsigned char*)mmap(NULL, page_size * 2, PROT_READ | PROT_WRITE,
                           MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
  struct iovec in_iov[2];
  struct iovec out_iov[2];
  int ret;

  test_assert(p != MAP_FAILED);
  test_assert(0 == munmap(p + page_size, page_size));

  in_iov[0].iov_base = p;
  in_iov[0].iov_len = 2;
  in_iov[1].iov_base = p + 3;
  in_iov[1].iov_len = 3;
  out_iov[0].iov_base = p + page_size - 6;
  out_iov[0].iov_len = 3;
  out_iov[1].iov_base = p + page_size - 1;
  out_iov[1].iov_len = 2;

  clear(p);
  test_assert(4 == process_vm_readv(getpid(), out_iov, 2, in_iov, 2, 0));
  test_assert(out_iov[1].iov_len == 2);
  test_assert(p[page_size - 7] == ((page_size - 7) & 0xff));
  test_assert(p[page_size - 6] == 0);
  test_assert(p[page_size - 5] == 1);
  test_assert(p[page_size - 4] == 3);
  test_assert(p[page_size - 3] == ((page_size - 3) & 0xff));
  test_assert(p[page_size - 2] == ((page_size - 2) & 0xff));
  test_assert(p[page_size - 1] == 4);
  clear(p);
  ret = process_vm_writev(getpid(), in_iov, 2, out_iov, 2, 0);
  if (3 == ret) {
    test_assert(out_iov[1].iov_len == 2);
    test_assert(p[page_size - 7] == ((page_size - 7) & 0xff));
    test_assert(p[page_size - 6] == 0);
    test_assert(p[page_size - 5] == 1);
    test_assert(p[page_size - 4] == 3);
    test_assert(p[page_size - 3] == ((page_size - 3) & 0xff));
    test_assert(p[page_size - 2] == ((page_size - 2) & 0xff));
    test_assert(p[page_size - 1] == ((page_size - 1) & 0xff));
  } else {
    test_assert(4 == ret);
    test_assert(out_iov[1].iov_len == 2);
    test_assert(p[page_size - 7] == ((page_size - 7) & 0xff));
    test_assert(p[page_size - 6] == 0);
    test_assert(p[page_size - 5] == 1);
    test_assert(p[page_size - 4] == 3);
    test_assert(p[page_size - 3] == ((page_size - 3) & 0xff));
    test_assert(p[page_size - 2] == ((page_size - 2) & 0xff));
    test_assert(p[page_size - 1] == 4);
  }

  out_iov[1].iov_base = p + page_size - 2;
  out_iov[1].iov_len = 3;

  clear(p);
  test_assert(5 == process_vm_readv(getpid(), out_iov, 2, in_iov, 2, 0));
  test_assert(p[page_size - 7] == ((page_size - 7) & 0xff));
  test_assert(p[page_size - 6] == 0);
  test_assert(p[page_size - 5] == 1);
  test_assert(p[page_size - 4] == 3);
  test_assert(p[page_size - 3] == ((page_size - 3) & 0xff));
  test_assert(p[page_size - 2] == 4);
  test_assert(p[page_size - 1] == 5);
  clear(p);
  ret = process_vm_writev(getpid(), in_iov, 2, out_iov, 2, 0);
  if (3 == ret) {
    test_assert(p[page_size - 7] == ((page_size - 7) & 0xff));
    test_assert(p[page_size - 6] == 0);
    test_assert(p[page_size - 5] == 1);
    test_assert(p[page_size - 4] == 3);
    test_assert(p[page_size - 3] == ((page_size - 3) & 0xff));
    test_assert(p[page_size - 2] == ((page_size - 2) & 0xff));
    test_assert(p[page_size - 1] == ((page_size - 1) & 0xff));
  } else {
    test_assert(5 == ret);
    test_assert(p[page_size - 7] == ((page_size - 7) & 0xff));
    test_assert(p[page_size - 6] == 0);
    test_assert(p[page_size - 5] == 1);
    test_assert(p[page_size - 4] == 3);
    test_assert(p[page_size - 3] == ((page_size - 3) & 0xff));
    test_assert(p[page_size - 2] == 4);
    test_assert(p[page_size - 1] == 5);
  }

  in_iov[0].iov_base = p + page_size - 1;
  in_iov[0].iov_len = 2;
  out_iov[0].iov_base = p;
  out_iov[0].iov_len = 3;

  clear(p);
  ret = process_vm_readv(getpid(), out_iov, 1, in_iov, 1, 0);
  if (ret == -1 && errno == EFAULT) {
    test_assert(p[0] == 0);
    test_assert(p[1] == 1);
  } else {
    test_assert(1 == ret);
    test_assert(p[0] == ((page_size - 1) & 0xff));
    test_assert(p[1] == 1);
  }
  clear(p);
  test_assert(1 == process_vm_writev(getpid(), in_iov, 1, out_iov, 1, 0));
  test_assert(p[0] == ((page_size - 1) & 0xff));
  /* Linux kernel bug: should be 1, but sometimes is zero ---
     extra data written. https://bugzilla.kernel.org/show_bug.cgi?id=113541 */
  if (p[1] == 0) {
    atomic_puts("Kernel bug detected!");
  }
  test_assert(p[1] == 1 || p[1] == 0);

  in_iov[0].iov_base = p + page_size - 4;
  in_iov[0].iov_len = 2;
  in_iov[1].iov_base = p + page_size - 2;
  in_iov[1].iov_len = 3;
  out_iov[0].iov_base = p;
  out_iov[0].iov_len = 1;
  out_iov[1].iov_base = p + 2;
  out_iov[1].iov_len = 4;

  clear(p);
  ret = process_vm_readv(getpid(), out_iov, 2, in_iov, 2, 0);
  if (2 == ret) {
    test_assert(p[0] == ((page_size - 4) & 0xff));
    test_assert(p[1] == 1);
    test_assert(p[2] == ((page_size - 3) & 0xff));
    test_assert(p[3] == 3);
    test_assert(p[4] == 4);
    test_assert(p[5] == 5);
  } else {
    test_assert(4 == ret);
    test_assert(p[0] == ((page_size - 4) & 0xff));
    test_assert(p[1] == 1);
    test_assert(p[2] == ((page_size - 3) & 0xff));
    test_assert(p[3] == ((page_size - 2) & 0xff));
    test_assert(p[4] == ((page_size - 1) & 0xff));
    test_assert(p[5] == 5);
  }
  clear(p);
  test_assert(4 == process_vm_writev(getpid(), in_iov, 2, out_iov, 2, 0));
  test_assert(p[0] == ((page_size - 4) & 0xff));
  test_assert(p[1] == 1);
  test_assert(p[2] == ((page_size - 3) & 0xff));
  test_assert(p[3] == ((page_size - 2) & 0xff));
  test_assert(p[4] == ((page_size - 1) & 0xff));
  if (p[5] == 0) {
    atomic_puts("Kernel bug detected!");
  }
  test_assert(p[5] == 5 || p[5] == 0);

  atomic_puts("EXIT-SUCCESS");
  return 0;
}
Exemple #19
0
static void* run_thread(void* p) {
  atomic_puts("EXIT-SUCCESS");
  exit(0);
  return NULL;
}
Exemple #20
0
static void* kill_thread(void* dontcare) {
	atomic_puts("killing ...");
	abort();
	atomic_puts("FAILED: abort() didn't work");
	return NULL;		/* not reached */
}
Exemple #21
0
static void handle_segv(int sig) {
  test_assert(SIGSEGV == sig);
  atomic_puts("EXIT-SUCCESS");
  exit(0);
}
Exemple #22
0
int main(void) {
  atomic_puts("EXIT-SUCCESS");
  return 0;
}
Exemple #23
0
int main(void) {
  unsigned int eax, ecx, edx;
  unsigned int required_cpuid_flags = AVX_FEATURE_FLAG | OSXSAVE_FEATURE_FLAG;

  cpuid(CPUID_GETFEATURES, 0, &eax, &ecx, &edx);
  AVX_enabled = (ecx & required_cpuid_flags) == required_cpuid_flags;

  if (!AVX_enabled) {
    atomic_puts("AVX YMM registers disabled, not tested");
  }

  __asm__ __volatile__(
/* Push the constants in stack order so they look as
 * we expect in gdb. */
#if __i386__
      "fldl st7\n\t"
      "fldl st6\n\t"
      "fldl st5\n\t"
      "fldl st4\n\t"
      "fldl st3\n\t"
      "fldl st2\n\t"
      "fldl st1\n\t"
      "fldl st0\n\t"
      "movss xmm0, %xmm0\n\t"
      "movss xmm1, %xmm1\n\t"
      "movss xmm2, %xmm2\n\t"
      "movss xmm3, %xmm3\n\t"
      "movss xmm4, %xmm4\n\t"
      "movss xmm5, %xmm5\n\t"
      "movss xmm6, %xmm6\n\t"
      "movss xmm7, %xmm7\n\t"
#elif __x86_64__
      "fldl st7(%rip)\n\t"
      "fldl st6(%rip)\n\t"
      "fldl st5(%rip)\n\t"
      "fldl st4(%rip)\n\t"
      "fldl st3(%rip)\n\t"
      "fldl st2(%rip)\n\t"
      "fldl st1(%rip)\n\t"
      "fldl st0(%rip)\n\t"
      "movss xmm0(%rip), %xmm0\n\t"
      "movss xmm1(%rip), %xmm1\n\t"
      "movss xmm2(%rip), %xmm2\n\t"
      "movss xmm3(%rip), %xmm3\n\t"
      "movss xmm4(%rip), %xmm4\n\t"
      "movss xmm5(%rip), %xmm5\n\t"
      "movss xmm6(%rip), %xmm6\n\t"
      "movss xmm7(%rip), %xmm7\n\t"
      "movss xmm8(%rip), %xmm8\n\t"
      "movss xmm9(%rip), %xmm9\n\t"
      "movss xmm10(%rip), %xmm10\n\t"
      "movss xmm11(%rip), %xmm11\n\t"
      "movss xmm12(%rip), %xmm12\n\t"
      "movss xmm13(%rip), %xmm13\n\t"
      "movss xmm14(%rip), %xmm14\n\t"
      "movss xmm15(%rip), %xmm15\n\t"
#else
#error unexpected architecture
#endif
      );

  if (AVX_enabled) {
    __asm__ __volatile__(
#if defined(__i386__) || defined(__x86_64__)
        "vinsertf128 $1,%xmm1,%ymm0,%ymm0\n\t"
        "vinsertf128 $1,%xmm2,%ymm1,%ymm1\n\t"
        "vinsertf128 $1,%xmm3,%ymm2,%ymm2\n\t"
        "vinsertf128 $1,%xmm4,%ymm3,%ymm3\n\t"
        "vinsertf128 $1,%xmm5,%ymm4,%ymm4\n\t"
        "vinsertf128 $1,%xmm6,%ymm5,%ymm5\n\t"
        "vinsertf128 $1,%xmm7,%ymm6,%ymm6\n\t"
        "vinsertf128 $1,%xmm0,%ymm7,%ymm7\n\t"
#endif
#ifdef __x86_64__
        "vinsertf128 $1,%xmm9,%ymm8,%ymm8\n\t"
        "vinsertf128 $1,%xmm10,%ymm9,%ymm9\n\t"
        "vinsertf128 $1,%xmm11,%ymm10,%ymm10\n\t"
        "vinsertf128 $1,%xmm12,%ymm11,%ymm11\n\t"
        "vinsertf128 $1,%xmm13,%ymm12,%ymm12\n\t"
        "vinsertf128 $1,%xmm14,%ymm13,%ymm13\n\t"
        "vinsertf128 $1,%xmm15,%ymm14,%ymm14\n\t"
        "vinsertf128 $1,%xmm8,%ymm15,%ymm15\n\t"
#endif
        );
  }

  breakpoint();

  atomic_puts("EXIT-SUCCESS");
  return 0;
}
Exemple #24
0
static void* reader_thread(void* dontcare) {
  char token = '!';
  int sock = sockfds[1];
  struct timeval ts;
  char c = '\0';
  int i;

  gettimeofday(&ts, NULL);

  atomic_puts("r: acquiring mutex ...");
  pthread_mutex_lock(&lock);
  atomic_puts("r:   ... releasing mutex");
  pthread_mutex_unlock(&lock);

  for (i = 0; i < 2; ++i) {
    atomic_puts("r: reading socket ...");
    gettimeofday(&ts, NULL);
    check_syscall(1, read(sock, &c, sizeof(c)));
    atomic_printf("r:   ... read '%c'\n", c);
    test_assert(c == token);
    ++token;
  }
  /* TODO: readv() support */

  atomic_puts("r: recv'ing socket ...");
  gettimeofday(&ts, NULL);
  check_syscall(1, recv(sock, &c, sizeof(c), 0));
  atomic_printf("r:   ... recv'd '%c'\n", c);
  test_assert(c == token);
  ++token;

  atomic_puts("r: recvfrom'ing socket ...");
  check_syscall(1, recvfrom(sock, &c, sizeof(c), 0, NULL, NULL));
  atomic_printf("r:   ... recvfrom'd '%c'\n", c);
  test_assert(c == token);
  ++token;
  {
    struct sockaddr_un addr;
    socklen_t addrlen = sizeof(addr);

    atomic_puts("r: recvfrom(&sock)'ing socket ...");
    check_syscall(1, recvfrom(sock, &c, sizeof(c), 0, &addr, &addrlen));
    atomic_printf("r:   ... recvfrom'd '%c' from sock len:%d\n", c, addrlen);
    test_assert(c == token);
    /* socketpair() AF_LOCAL sockets don't identify
     * themselves. */
    test_assert(addrlen == 0);
    ++token;
  }
  {
    struct mmsghdr mmsg = { { 0 } };
    struct iovec data = { 0 };
    int magic = ~msg_magic;
    int err, ret;

    data.iov_base = &magic;
    data.iov_len = sizeof(magic);
    mmsg.msg_hdr.msg_iov = &data;
    mmsg.msg_hdr.msg_iovlen = 1;

    struct cmsghdr* cmptr = (struct cmsghdr*)malloc(CTRLMSG_LEN);
    mmsg.msg_hdr.msg_control = cmptr;
    mmsg.msg_hdr.msg_controllen = CTRLMSG_LEN;

    atomic_puts("r: recvmsg with DONTWAIT ...");
    ret = recvmsg(sock, &mmsg.msg_hdr, MSG_DONTWAIT);
    err = errno;
    atomic_printf("r:  ... returned %d (%s/%d)\n", ret, strerror(err), err);
    check_syscall(-1, ret);
    test_assert(EWOULDBLOCK == err);

    atomic_puts("r: recmsg'ing socket ...");

    test_assert(0 < recvmsg(sock, &mmsg.msg_hdr, 0));
    atomic_printf("r:   ... recvmsg'd 0x%x\n", magic);
    test_assert(msg_magic == magic);

    int fd = *(int*)CMSG_DATA(cmptr);
    struct stat fs_new, fs_old;
    fstat(fd, &fs_new);
    fstat(STDERR_FILENO, &fs_old);
    // check if control msg was send successfully
    test_assert(
        fs_old.st_dev == fs_new.st_dev && fs_old.st_ino == fs_new.st_ino &&
        fs_old.st_uid == fs_new.st_uid && fs_old.st_gid == fs_new.st_gid &&
        fs_old.st_rdev == fs_new.st_rdev && fs_old.st_size == fs_new.st_size);

    magic = ~msg_magic;
    atomic_puts("r: recmmsg'ing socket ...");

    breakpoint();
    check_syscall(1, recvmmsg(sock, &mmsg, 1, 0, NULL));
    atomic_printf("r:   ... recvmmsg'd 0x%x (%u bytes)\n", magic, mmsg.msg_len);
    test_assert(msg_magic == magic);

    magic = ~msg_magic;
#if defined(SYS_socketcall)
    struct recvmmsg_arg arg = { 0 };
    arg.sockfd = sock;
    arg.msgvec = &mmsg;
    arg.vlen = 1;
    check_syscall(1, syscall(SYS_socketcall, SYS_RECVMMSG, (void*)&arg));
#elif defined(SYS_recvmmsg)
    check_syscall(1, syscall(SYS_recvmmsg, sock, &mmsg, 1, 0, NULL));
#else
#error unable to call recvmmsg
#endif
    atomic_printf("r:   ... recvmmsg'd(by socketcall) 0x%x (%u bytes)\n", magic,
                  mmsg.msg_len);
    test_assert(msg_magic == magic);

    free(cmptr);
  }
  {
    struct msghdr msg = { 0 };
    struct iovec iovs[2];
    char c1 = '\0', c2 = '\0';

    iovs[0].iov_base = &c1;
    iovs[0].iov_len = sizeof(c1);
    iovs[1].iov_base = &c2;
    iovs[1].iov_len = sizeof(c2);

    msg.msg_iov = iovs;
    msg.msg_iovlen = sizeof(iovs) / sizeof(iovs[0]);

    atomic_puts("r: recmsg'ing socket with two iovs ...");
    check_syscall(2, recvmsg(sock, &msg, 0));
    atomic_printf("r:   ... recvmsg'd '%c' and '%c'\n", c1, c2);

    test_assert(c1 == token);
    token++;
    test_assert(c2 == token);
    token++;
  }
  {
    struct pollfd pfd;

    atomic_puts("r: polling socket ...");
    pfd.fd = sock;
    pfd.events = POLLIN;
    gettimeofday(&ts, NULL);
    poll(&pfd, 1, -1);
    atomic_puts("r:   ... done, doing nonblocking read ...");
    check_syscall(1, read(sock, &c, sizeof(c)));
    atomic_printf("r:   ... read '%c'\n", c);
    test_assert(c == token);
    ++token;
  }
  {
    struct pollfd pfd;

    atomic_puts("r: polling socket ...");
    pfd.fd = sock;
    pfd.events = POLLIN;
    gettimeofday(&ts, NULL);
    ppoll(&pfd, 1, NULL, NULL);
    atomic_puts("r:   ... done, doing nonblocking read ...");
    check_syscall(1, read(sock, &c, sizeof(c)));
    atomic_printf("r:   ... read '%c'\n", c);
    test_assert(c == token);
    ++token;
  }
  {
    fd_set fds;
    const struct timeval infinity = { 1 << 30, 0 };
    struct timeval tv = infinity;
    int ret;

    atomic_puts("r: select()ing socket ...");
    FD_ZERO(&fds);
    FD_SET(sock, &fds);
#if defined(__i386__)
    struct select_arg arg = { 0 };
    arg.n_fds = sock + 1;
    arg.read = &fds;
    arg.write = NULL;
    arg.except = NULL;
    arg.timeout = &tv;
    ret = syscall(SYS_select, &arg);
#else
    ret = syscall(SYS_select, sock + 1, &fds, NULL, NULL, &tv);
#endif
    atomic_printf("r:   ... returned %d; tv { %ld, %ld }\n", ret, tv.tv_sec,
                  tv.tv_usec);
    check_syscall(1, ret);
    test_assert(FD_ISSET(sock, &fds));
    test_assert(0 < tv.tv_sec && tv.tv_sec < infinity.tv_sec);

    atomic_puts("r:   ... done, doing nonblocking read ...");
    check_syscall(1, read(sock, &c, sizeof(c)));
    atomic_printf("r:   ... read '%c'\n", c);
    test_assert(c == token);
    ++token;
  }
  {
    fd_set fds;
    const struct timeval infinity = { 1 << 30, 0 };
    struct timeval tv = infinity;
    int ret;

    atomic_puts("r: select()ing socket ...");
    FD_ZERO(&fds);
    FD_SET(sock, &fds);
    ret = select(sock + 1, &fds, NULL, NULL, &tv);
    atomic_printf("r:   ... returned %d; tv { %ld, %ld }\n", ret, tv.tv_sec,
                  tv.tv_usec);
    check_syscall(1, ret);
    test_assert(FD_ISSET(sock, &fds));
    test_assert(0 < tv.tv_sec && tv.tv_sec < infinity.tv_sec);

    atomic_puts("r:   ... done, doing nonblocking read ...");
    check_syscall(1, read(sock, &c, sizeof(c)));
    atomic_printf("r:   ... read '%c'\n", c);
    test_assert(c == token);
    ++token;
  }
  {
    int epfd;
    struct epoll_event ev;

    atomic_puts("r: epolling socket ...");
    test_assert(0 <= (epfd = epoll_create(1 /*num events*/)));
    ev.events = EPOLLIN;
    ev.data.fd = sock;
    gettimeofday(&ts, NULL);
    check_syscall(0, epoll_ctl(epfd, EPOLL_CTL_ADD, ev.data.fd, &ev));
    check_syscall(1, epoll_wait(epfd, &ev, 1, -1));
    atomic_puts("r:   ... done, doing nonblocking read ...");
    test_assert(sock == ev.data.fd);
    check_syscall(1, epoll_wait(epfd, &ev, 1, -1));
    check_syscall(1, read(sock, &c, sizeof(c)));
    atomic_printf("r:   ... read '%c'\n", c);
    test_assert(c == token);
    ++token;

    close(epfd);
  }
  {
    char* buf = (char*)malloc(num_sockbuf_bytes);
    ssize_t nwritten = 0;
    struct iovec iov;

    ++token;
    memset(buf, token, num_sockbuf_bytes);

    atomic_printf("r: writing outbuf of size %zd ...\n", num_sockbuf_bytes);
    while (nwritten < num_sockbuf_bytes) {
      ssize_t this_write = write(sock, buf, num_sockbuf_bytes - nwritten);
      atomic_printf("r:   wrote %zd bytes this time\n", this_write);
      nwritten += this_write;
    }

    ++token;
    memset(buf, token, num_sockbuf_bytes);
    iov.iov_base = buf;
    iov.iov_len = num_sockbuf_bytes;
    atomic_printf("r: writev()ing outbuf of size %zd ...\n", num_sockbuf_bytes);
    while (iov.iov_len > 0) {
      ssize_t this_write = writev(sock, &iov, 1);
      atomic_printf("r:   wrote %zd bytes this time\n", this_write);
      iov.iov_len -= this_write;
    }

    free(buf);
  }

  atomic_puts("r: reading socket with masked signals ...");
  {
    sigset_t old_mask, mask;
    sigfillset(&mask);
    check_syscall(0, pthread_sigmask(SIG_BLOCK, &mask, &old_mask));

    check_syscall(1, read(sock, &c, sizeof(c)));

    check_syscall(0, pthread_sigmask(SIG_SETMASK, &old_mask, NULL));
  }
  ++token;
  atomic_printf("r:   ... read '%c'\n", c);
  test_assert(c == token);

  /* Make the main thread wait on our join() */
  atomic_puts("r: sleeping ...");
  usleep(500000);

  return NULL;
}
Exemple #25
0
int main(void) {
  size_t num_bytes = sysconf(_SC_PAGESIZE);
  int fd = open("temp", O_CREAT | O_EXCL | O_RDWR);
  int* rpage;

  unlink("temp");

  test_assert(fd >= 0);

  int magic = 0x5a5a5a5a;
  size_t i;
  for (i = 0; i < 3 * num_bytes / sizeof(magic); ++i) {
    pwrite64(fd, &magic, sizeof(magic), i * sizeof(magic));
  }

  rpage = mmap(NULL, num_bytes, PROT_READ, MAP_SHARED, fd, 0);
  atomic_printf("rpage:%p\n", rpage);
  test_assert(rpage != MAP_FAILED);

  magic = 0xa5a5a5a5;
  for (i = 0; i < num_bytes / sizeof(magic); ++i) {
    pwrite64(fd, &magic, sizeof(magic), i * sizeof(magic));
  }

  check_mapping(rpage, 0xa5a5a5a5, num_bytes / sizeof(*rpage));

  magic = 0x5a5a5a5a;
  for (i = 0; i < num_bytes / sizeof(magic); ++i) {
    pwrite64(fd, &magic, sizeof(magic), i * sizeof(magic));
  }

  check_mapping(rpage, 0x5a5a5a5a, num_bytes / sizeof(*rpage));

  magic = 0xa5a5a5a5;
  for (i = 0; i < num_bytes / sizeof(magic); ++i) {
    pwrite64(fd, &magic, sizeof(magic), num_bytes + i * sizeof(magic));
  }

  check_mapping(rpage, 0x5a5a5a5a, num_bytes / sizeof(*rpage));

  magic = 0xdeadbeef;
  pwrite64(fd, &magic, sizeof(magic), num_bytes / 2);

  test_assert(rpage[num_bytes / (sizeof(magic) * 2)] == magic);
  test_assert(rpage[0] != magic);

  pwrite64(fd, &magic, sizeof(magic), num_bytes - 2);
  test_assert(rpage[num_bytes / sizeof(magic) - 1] == (int)0xbeef5a5a);

  rpage = mremap(rpage, num_bytes, 5 * num_bytes, MREMAP_MAYMOVE);
  for (i = 3 * num_bytes / sizeof(magic); i < 5 * num_bytes / sizeof(magic);
       ++i) {
    pwrite64(fd, &magic, sizeof(magic), i * sizeof(magic));
  }
  check_mapping(&rpage[(3 * num_bytes) / sizeof(magic)], 0xdeadbeef,
                2 * num_bytes / sizeof(*rpage));

  munmap(rpage, 5 * num_bytes);

  // The case when all pages have been unmapped is special in the
  // implementation - make sure it gets sufficient coverage
  write(fd, &magic, sizeof(magic));
  write(fd, &magic, sizeof(magic));

  rpage = mmap(NULL, num_bytes, PROT_READ, MAP_SHARED, fd, 0);
  atomic_printf("rpage:%p\n", rpage);
  test_assert(rpage != MAP_FAILED);

  // This tests both that the monitor gets activated again if the page is
  // remapped and that `write` works on a monitored page.
  lseek(fd, 0, SEEK_SET);
  magic = 0xb6b6b6b6;
  for (i = 0; i < num_bytes / sizeof(magic); ++i) {
    write(fd, &magic, sizeof(magic));
  }
  check_mapping(rpage, magic, num_bytes / sizeof(*rpage));

  atomic_puts("EXIT-SUCCESS");

  return 0;
}