2 * Use vmsplice to fill some user memory into a pipe. vmsplice writes
3 * to stdout, so that must be a pipe.
12 #include <sys/types.h>
19 #define ALIGN_MASK (65535) /* 64k-1, should just be PAGE_SIZE - 1 */
20 #define ALIGN(buf) (void *) (((unsigned long) (buf) + ALIGN_MASK) & ~ALIGN_MASK)
22 #define ALIGN_MASK (0)
23 #define ALIGN(buf) (buf)
26 int do_vmsplice(int fd, void *buffer, int len)
28 struct pollfd pfd = { .fd = fd, .events = POLLOUT, };
33 * in a real app you'd be more clever with poll of course,
34 * here we are basically just blocking on output room and
35 * not using the free time for anything interesting.
37 if (poll(&pfd, 1, -1) < 0)
40 written = vmsplice(fd, buffer, min(SPLICE_SIZE, len), 0);
43 return error("vmsplice");
51 int main(int argc, char *argv[])
53 unsigned char *buffer;
58 if (fstat(STDOUT_FILENO, &sb) < 0)
60 if (!S_ISFIFO(sb.st_mode)) {
61 fprintf(stderr, "stdout must be a pipe\n");
65 ret = fcntl(STDOUT_FILENO, F_GETPSZ);
67 return error("F_GETPSZ");
69 page_size = sysconf(_SC_PAGESIZE);
71 return error("_SC_PAGESIZE");
73 fprintf(stderr, "Pipe size: %d pages / %ld bytes\n", ret, ret * page_size);
75 buffer = ALIGN(malloc(2 * SPLICE_SIZE + ALIGN_MASK));
76 for (i = 0; i < 2 * SPLICE_SIZE; i++)
77 buffer[i] = (i & 0xff);
81 * vmsplice the first half of the buffer into the pipe
83 if (do_vmsplice(STDOUT_FILENO, buffer, SPLICE_SIZE))
87 * first half is now in pipe, but we don't quite know when
92 * vmsplice second half
94 if (do_vmsplice(STDOUT_FILENO, buffer + SPLICE_SIZE, SPLICE_SIZE))
98 * We still don't know when we can reuse the second half of
99 * the buffer, but we do now know that all parts of the first
100 * half have been consumed from the pipe - so we can reuse that.