int main(void) { spin(); atomic_puts("done"); return 0; }
static void sighandler(int sig) { atomic_printf("caught signal %d, exiting\n", sig); atomic_puts("EXIT-SUCCESS"); _exit(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; }
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); }
int main(int argc, char* argv[]) { funcall(); atomic_puts("EXIT-SUCCESS"); return 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); }
static void fault_handler(int sig, siginfo_t* si, void* context) { atomic_puts("FAILED: handler should not have been called for blocked signal"); }
static void B(void) { atomic_puts("calling C"); C(); atomic_puts("finished C"); }
void hit_barrier() { atomic_puts("hit barrier"); }
static void C(void) { atomic_puts("in C"); }
int main(void) { atomic_puts("calling A"); A(); atomic_puts("finished A"); return 0; }
static void A(void) { atomic_puts("calling B"); B(); atomic_puts("finished B"); }
static void handle_usr1(int sig) { test_assert(SIGUSR1 == sig); caught_usr1 = 1; atomic_puts("caught usr1"); }
int main(void) { struct passwd* p = getpwnam("root"); atomic_printf("%d\n", p ? p->pw_uid : 0); atomic_puts("EXIT-SUCCESS"); return 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); }
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; }
static void* run_thread(void* p) { atomic_puts("EXIT-SUCCESS"); exit(0); return NULL; }
static void* kill_thread(void* dontcare) { atomic_puts("killing ..."); abort(); atomic_puts("FAILED: abort() didn't work"); return NULL; /* not reached */ }
static void handle_segv(int sig) { test_assert(SIGSEGV == sig); atomic_puts("EXIT-SUCCESS"); exit(0); }
int main(void) { atomic_puts("EXIT-SUCCESS"); return 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; }
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; }
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; }