78 pipes( std::move( kbuff.pipes ) )
94 capacity = kbuff.capacity;
96 pipes = std::move( kbuff.pipes );
105 if( capacity > 0 ) Free();
125 return ( ( uintptr_t ( ptr ) ) % PAGE_SZ ) == 0 ;
135 auto itr = pipes.begin();
136 for( ; itr != pipes.end() ; ++itr )
138 std::array<int, 2> &p = std::get<0>( *itr );
151 inline ssize_t Alloc(
size_t size )
158 std::array<int, 2> pipe_fd;
159 ret = pipe( pipe_fd.data() );
160 if( ret < 0 )
return ret;
162 if( size > MAX_PIPE_SIZE) size = MAX_PIPE_SIZE;
163 ret = fcntl( pipe_fd[0], F_SETPIPE_SZ, size );
164 if( ret < 0 )
return ret;
167 pipes.emplace_back( pipe_fd, 0 );
184 inline ssize_t ReadFromFD(
int fd, uint32_t length, int64_t *offset )
189 inline ssize_t ReadFromFD(
int fd, uint32_t length, loff_t *offset )
191 if( capacity > 0 ) Free();
195 ssize_t ret = Alloc( length );
196 if( ret < 0 )
return ret;
197 if(
size_t( ret ) > length ) ret = length;
198 std::array<int, 2> &pipe_fd = std::get<0>( pipes.back() );
199 size_t &pipedata = std::get<1>( pipes.back() );
200 ret = splice( fd, offset, pipe_fd[1], NULL, ret, SPLICE_F_MOVE | SPLICE_F_MORE );
201 if( ret == 0 )
break;
202 if( ret < 0 )
return -1;
208 pipes_cursor = pipes.begin();
224 inline ssize_t WriteToFD(
int fd, int64_t *offset )
229 inline ssize_t WriteToFD(
int fd, loff_t *offset )
231 if( size == 0 )
return 0;
235 auto itr = pipes_cursor;
236 while( itr != pipes.end() )
238 std::array<int, 2> &pipe_fd = std::get<0>( *itr );
239 size_t &pipedata = std::get<1>( *itr );
241 int ret = splice( pipe_fd[0], NULL, fd, offset, size, SPLICE_F_MOVE | SPLICE_F_MORE );
242 if( ret == 0 )
break;
243 if( ret < 0 )
return -1;
250 if( pipedata > 0 )
continue;
278 inline ssize_t ToUser(
char *&buffer )
283 if( size == 0 )
return 0;
288 int ret = posix_memalign( &void_ptr, PAGE_SZ, size );
294 char *ptr =
reinterpret_cast<char*
>( void_ptr );
296 auto itr = pipes_cursor;
297 while( itr != pipes.end() )
300 size_t len = size > MAX_PIPE_SIZE ? MAX_PIPE_SIZE : size;
304 std::array<int, 2> &pipe_fd = std::get<0>( *itr );
305 size_t &pipedata = std::get<1>( *itr );
306 int ret = vmsplice( pipe_fd[0],
iov, 1, 0 );
324 if( pipedata > 0 )
continue;
332 buffer =
reinterpret_cast<char*
>( void_ptr );
355 inline ssize_t FromUser(
char *&buffer,
size_t length )
366 if( capacity > 0 ) Free();
371 ssize_t ret = Alloc( length );
372 if( ret < 0 )
return ret;
373 std::array<int, 2> &pipe_fd = std::get<0>( pipes.back() );
374 size_t &pipedata = std::get<1>( pipes.back() );
377 iov->iov_len = size_t( ret ) < length ? ret : length;
378 iov->iov_base = buff;
379 ret = vmsplice( pipe_fd[1],
iov, 1, SPLICE_F_GIFT );
381 if( ret < 0 )
return -1;
388 pipes_cursor = pipes.begin();
395 static const size_t PAGE_SZ = 4 * 1024;
396 static const size_t MAX_PIPE_SIZE = 1024 * 1024;
400 std::vector<std::tuple<std::array<int,2>,
size_t>> pipes;
401 std::vector<std::tuple<std::array<int,2>,
size_t>>::iterator pipes_cursor;