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); test_assert(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); test_assert(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); test_assert(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(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_barrier_init(&cheater_barrier, NULL, 2); 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); test_assert(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); test_assert(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; /* 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); pthread_barrier_wait(&cheater_barrier); } { 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); test_assert(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() */ 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; }