#define _FILE_OFFSET_BITS 64 #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #define ERR(args...) fprintf(stderr, args); #define READSIZE 4096 #define FILENAME "./bigfile" int nthreads = 64; extern int errno; int fds[1024]; pthread_mutex_t locks[1024]; uint64_t filesize; sem_t sem; void * thread(void *arg) { char buf[READSIZE]; off_t offset; int index, fd, ret; fd = 0; do { for(index = 0; index < nthreads; index++) { if(pthread_mutex_trylock(&locks[index]) == 0) { // Found a free file descriptor fd = fds[index]; break; } } } while(fd == 0); offset = (((uint64_t)random() << 32) | random()) % (filesize - READSIZE); assert(offset < filesize - READSIZE); if(lseek(fd, offset, SEEK_SET) == -1) { ERR("thread(): lseek(): %s\n", strerror(errno)); goto done; } if((ret = read(fd, buf, READSIZE)) != READSIZE) { if(ret == -1) { ERR("thread(): read(): %s\n", strerror(errno)); } else if(ret == 0) { ERR("thread(): read(): EOF\n"); } else { ERR("thread(): read(): Only read %d of %d bytes\n", ret, READSIZE); } } done: pthread_mutex_unlock(&locks[index]); sem_post(&sem); } int main(int argc, char **argv) { pthread_attr_t attr; pthread_t child; struct stat fstat; int i; if(argc == 2) { nthreads = atoi(argv[1]); assert(nthreads < 1024); } if(pthread_attr_init(&attr) != 0) { ERR("main(): pthread_attr_init(): failed\n"); exit(1); } if(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0) { ERR("main(): pthread_attr_setdetachstate(): failed\n"); exit(1); } if(stat(FILENAME, &fstat) == -1) { ERR("main(): stat(): %s\n", strerror(errno)); exit(1); } filesize = fstat.st_size; for(i = 0; i < nthreads; i++) { if((fds[i] = open(FILENAME, O_RDONLY | O_LARGEFILE)) == -1) { ERR("main(): open(): %s\n", strerror(errno)); exit(1); } if(pthread_mutex_init(&locks[i], NULL) != 0) { ERR("main(): pthread_mutex_init(): %s\n", strerror(errno)); exit(1); } } if(sem_init(&sem, 0, nthreads) == -1) { ERR("main(): sem_init(): %s\n", strerror(errno)); exit(1); } while(1) { if(sem_wait(&sem) == 0) { if(pthread_create(&child, &attr, thread, NULL) != 0) { ERR("main(): pthread_create(): failed\n"); exit(1); } } } }