diff options
Diffstat (limited to 'erts')
-rw-r--r-- | erts/emulator/drivers/common/efile_drv.c | 33 | ||||
-rw-r--r-- | erts/preloaded/ebin/prim_file.beam | bin | 44612 -> 44880 bytes | |||
-rw-r--r-- | erts/preloaded/src/prim_file.erl | 17 |
3 files changed, 36 insertions, 14 deletions
diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c index dca979c13a..e040864d24 100644 --- a/erts/emulator/drivers/common/efile_drv.c +++ b/erts/emulator/drivers/common/efile_drv.c @@ -167,7 +167,7 @@ dt_private *get_dt_private(int); #ifdef USE_THREADS -#define IF_THRDS if (sys_info.async_threads > 0) +#define THRDS_AVAILABLE (sys_info.async_threads > 0) #ifdef HARDDEBUG /* HARDDEBUG in io.c is expected too */ #define TRACE_DRIVER fprintf(stderr, "Efile: ") #else @@ -177,24 +177,26 @@ dt_private *get_dt_private(int); #define MUTEX_LOCK(m) do { IF_THRDS { TRACE_DRIVER; driver_pdl_lock(m); } } while (0) #define MUTEX_UNLOCK(m) do { IF_THRDS { TRACE_DRIVER; driver_pdl_unlock(m); } } while (0) #else -#define IF_THRDS if (0) +#define THRDS_AVAILABLE (0) #define MUTEX_INIT(m, p) #define MUTEX_LOCK(m) #define MUTEX_UNLOCK(m) #endif +#define IF_THRDS if (THRDS_AVAILABLE) +#define SENDFILE_FLGS_USE_THREADS (1 << 0) /** * On DARWIN sendfile can deadlock with close if called in * different threads. So until Apple fixes so that sendfile * is not buggy we disable usage of the async pool for * DARWIN. The testcase t_sendfile_crashduring reproduces - * this error when using +A 10. + * this error when using +A 10 and enabling SENDFILE_FLGS_USE_THREADS. */ #if defined(__APPLE__) && defined(__MACH__) -#define USE_THRDS_FOR_SENDFILE 0 +#define USE_THRDS_FOR_SENDFILE(DATA) 0 #else -#define USE_THRDS_FOR_SENDFILE (sys_info.async_threads > 0) +#define USE_THRDS_FOR_SENDFILE(DATA) (DATA->flags & SENDFILE_FLGS_USE_THREADS) #endif /* defined(__APPLE__) && defined(__MACH__) */ @@ -300,7 +302,7 @@ static void file_stop_select(ErlDrvEvent event, void* _); enum e_timer {timer_idle, timer_again, timer_write}; #ifdef HAVE_SENDFILE enum e_sendfile {sending, not_sending}; -static void free_sendfile(void *data); +#define SENDFILE_USE_THREADS (1 << 0) #endif /* HAVE_SENDFILE */ struct t_data; @@ -1932,7 +1934,7 @@ static void invoke_sendfile(void *data) d->c.sendfile.written += nbytes; - if (result == 1 || (result == 0 && USE_THRDS_FOR_SENDFILE)) { + if (result == 1 || (result == 0 && USE_THRDS_FOR_SENDFILE(d))) { d->result_ok = 0; } else if (result == 0 && (d->errInfo.posix_errno == EAGAIN || d->errInfo.posix_errno == EINTR)) { @@ -1949,7 +1951,7 @@ static void invoke_sendfile(void *data) static void free_sendfile(void *data) { struct t_data *d = (struct t_data *)data; - if (USE_THRDS_FOR_SENDFILE) { + if (USE_THRDS_FOR_SENDFILE(d)) { SET_NONBLOCKING(d->c.sendfile.out_fd); } else { MUTEX_LOCK(d->c.sendfile.q_mtx); @@ -4122,8 +4124,16 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { goto done; } - if (hd_len != 0 || tl_len != 0 || flags != 0) { - /* We do not allow header, trailers and/or flags right now */ + if (hd_len != 0 || tl_len != 0) { + /* We do not allow header, trailers */ + reply_posix_error(desc, EINVAL); + goto done; + } + + + if (flags & SENDFILE_FLGS_USE_THREADS && !THRDS_AVAILABLE) { + /* We do not allow use_threads flag on a system where + no threads are available. */ reply_posix_error(desc, EINVAL); goto done; } @@ -4133,6 +4143,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->command = command; d->invoke = invoke_sendfile; d->free = free_sendfile; + d->flags = flags; d->level = 2; d->c.sendfile.out_fd = (int) out_fd; @@ -4152,7 +4163,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->c.sendfile.nbytes = nbytes; - if (USE_THRDS_FOR_SENDFILE) { + if (USE_THRDS_FOR_SENDFILE(d)) { SET_BLOCKING(d->c.sendfile.out_fd); } else { /** diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam Binary files differindex d5a1ec766d..e40e33b332 100644 --- a/erts/preloaded/ebin/prim_file.beam +++ b/erts/preloaded/ebin/prim_file.beam diff --git a/erts/preloaded/src/prim_file.erl b/erts/preloaded/src/prim_file.erl index 5999e98340..34679404a2 100644 --- a/erts/preloaded/src/prim_file.erl +++ b/erts/preloaded/src/prim_file.erl @@ -27,7 +27,7 @@ %% Generic file contents operations -export([open/2, close/1, datasync/1, sync/1, advise/4, position/2, truncate/1, write/2, pwrite/2, pwrite/3, read/2, read_line/1, pread/2, pread/3, - copy/3, sendfile/10, allocate/3]). + copy/3, sendfile/8, allocate/3]). %% Specialized file operations -export([open/1, open/3]). @@ -149,6 +149,9 @@ -define(POSIX_FADV_DONTNEED, 4). -define(POSIX_FADV_NOREUSE, 5). +%% Sendfile flags +-define(EFILE_SENDFILE_USE_THREADS, 1). + %%% BIFs @@ -582,13 +585,14 @@ write_file(_, _) -> % {error, enotsup}; sendfile(#file_descriptor{module = ?MODULE, data = {Port, _}}, Dest, Offset, Bytes, _ChunkSize, Headers, Trailers, - _Nodiskio, _MNowait, _Sync) -> + Flags) -> case erlang:port_get_data(Dest) of Data when Data == inet_tcp; Data == inet6_tcp -> ok = inet:lock_socket(Dest,true), {ok, DestFD} = prim_inet:getfd(Dest), + IntFlags = translate_sendfile_flags(Flags), try drv_command(Port, [<<?FILE_SENDFILE, DestFD:32, - 0:8, + IntFlags:8, Offset:64/unsigned, Bytes:64/unsigned, (iolist_size(Headers)):32/unsigned, @@ -601,6 +605,13 @@ sendfile(#file_descriptor{module = ?MODULE, data = {Port, _}}, {error,badarg} end. +translate_sendfile_flags([{use_threads,true}|T]) -> + ?EFILE_SENDFILE_USE_THREADS bor translate_sendfile_flags(T); +translate_sendfile_flags([_|T]) -> + translate_sendfile_flags(T); +translate_sendfile_flags([]) -> + 0. + %%%----------------------------------------------------------------- %%% Functions operating on files without handle to the file. ?DRV. |