Messages in this thread | | | Subject | SMP read() stopping at memory page boundaries | From | Timo Sirainen <> | Date | Wed, 20 Jun 2007 17:52:51 +0300 |
| |
Tested with various 2.6.x i386/x86-64 SMP kernels and CPUs, for example 2.6.21.3/x86-64.
Process 1:
- lock file - write(4096 + 16 bytes) - unlock file
Process 2:
- lock file - read(8192 bytes) - unlock file
Sometimes read() returns only 4096 bytes. I'm locking the file, so I don't think this should ever happen, right?
Attached a test program. Takes from a few seconds to half a minute with my computer to print "page size cut".
/* gcc concurrency2.c -o concurrency -Wall
start two both a reader and a writer:
./concurrency ./concurrency 1 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <assert.h> #include <sys/file.h>
#define MAX_PAGESIZE 8192
int main(int argc, char *argv[]) { char buf[MAX_PAGESIZE*2]; int fd, ret, pagesize;
memset(buf, 0, sizeof(buf));
pagesize = getpagesize(); assert(pagesize <= MAX_PAGESIZE);
buf[pagesize] = 'h'; if (argc == 1) { printf("writing, page size = %d\n", pagesize); for (;;) { fd = open("foo", O_RDWR | O_CREAT | O_TRUNC, 0600); if (fd == -1) { perror("open()"); return 1; }
if (flock(fd, LOCK_EX) < 0) perror("flock()"); write(fd, buf, pagesize+16); if (flock(fd, LOCK_UN) < 0) perror("flock()"); usleep(rand() % 1000); close(fd); } } else { printf("reading, page size = %d\n", pagesize); fd = open("foo", O_RDWR, 0600); if (fd == -1) { perror("open()"); return 1; } for (;;) { usleep(rand() % 1000); if (flock(fd, LOCK_SH) < 0) perror("flock()"); lseek(fd, 0, SEEK_SET); ret = read(fd, buf, sizeof(buf)); if (flock(fd, LOCK_UN) < 0) perror("flock()");
if (ret < pagesize) { if (ret > 0) printf("less than a page: %d\n", ret); } else if (ret == pagesize) { printf("page size cut\n"); } else if (buf[pagesize] != 'h') { printf("broken data\n"); } } } return 0; } [unhandled content-type:application/pgp-signature] | |