@@ -231,7 +231,7 @@ class FdHandleData {
231231 }
232232
233233 int16_t fd;
234- std::mutex mutex;
234+ std::recursive_mutex mutex;
235235
236236 int numReferences () const {
237237 return refs;
@@ -471,6 +471,53 @@ ssize_t FdHandle::read(void* value, size_t size) const {
471471 return getHandleData (fd).read (value, size);
472472}
473473
474+ ssize_t FdHandle::pread (void * value, size_t size, off_t offset) const {
475+ FdHandleData& handle = getHandleData (fd);
476+
477+ // Drain any queued positional writes so the read sees the latest data,
478+ // then release the handle mutex before issuing the syscall. Multiple
479+ // readers can then execute concurrently inside the kernel.
480+ {
481+ std::lock_guard<std::recursive_mutex> _ (handle.mutex );
482+ handle.flushWrites ();
483+ }
484+
485+ char * buffer = (char *)value;
486+ size_t totalRead = 0 ;
487+ while (totalRead < size) {
488+ ssize_t res = ::pread (handle.fd , &buffer[totalRead], size - totalRead, offset + (off_t )totalRead);
489+ if (res < 0 ) {
490+ if (totalRead > 0 ) return (ssize_t )totalRead;
491+ return res;
492+ } else if (res == 0 )
493+ break ;
494+ totalRead += (size_t )res;
495+ }
496+ return (ssize_t )totalRead;
497+ }
498+
499+ ssize_t FdHandle::pwrite (const void * value, size_t size, off_t offset) const {
500+ FdHandleData& handle = getHandleData (fd);
501+
502+ {
503+ std::lock_guard<std::recursive_mutex> _ (handle.mutex );
504+ handle.flushWrites ();
505+ }
506+
507+ const char * buffer = (const char *)value;
508+ size_t totalWritten = 0 ;
509+ while (totalWritten < size) {
510+ ssize_t res = ::pwrite (handle.fd , &buffer[totalWritten], size - totalWritten, offset + (off_t )totalWritten);
511+ if (res < 0 ) {
512+ if (totalWritten > 0 ) return (ssize_t )totalWritten;
513+ return res;
514+ } else if (res == 0 )
515+ break ;
516+ totalWritten += (size_t )res;
517+ }
518+ return (ssize_t )totalWritten;
519+ }
520+
474521bool FdHandle::waitForRead () const {
475522 return getHandleData (fd).waitForRead ();
476523}
@@ -547,8 +594,8 @@ void FdHandle::close() {
547594 }
548595}
549596
550- std::lock_guard<std::mutex > FdHandle::getLock () const {
551- return std::lock_guard<std::mutex >(getHandleData (fd).mutex );
597+ std::lock_guard<std::recursive_mutex > FdHandle::getLock () const {
598+ return std::lock_guard<std::recursive_mutex >(getHandleData (fd).mutex );
552599}
553600
554601void FdHandle::markToClose () const {
@@ -561,7 +608,7 @@ MmapHandle FdHandle::getMmapHandle(off_t offset, size_t size, int prot, int flag
561608 // Make sure the file is big enough, then
562609 // restore the previous cursor position
563610 {
564- std::lock_guard<std::mutex > _ (handle.mutex );
611+ std::lock_guard<std::recursive_mutex > _ (handle.mutex );
565612
566613 // Get current file offset to restore later
567614 off_t previousOffset = lseek (fd, 0 , SEEK_CUR);
0 commit comments