From 04445364fc9123ad40bf5581ffa4c5afac4c57dc Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 21 Sep 2016 15:56:19 -0700 Subject: [PATCH] incbin: if we have to fread(), try to do it only once... If we can't mmap a file and instead have to fread(), if the data is small enough that we can reasonably accomodate it in a memory buffer, then just read it once. It seems rather unlikely that very large files would be used with TIMES anyway. Also note: the previous comment about nasm_file_size[_by_path]() being invoked twice was spurious; it does not actually happen. Signed-off-by: H. Peter Anvin --- asm/assemble.c | 18 +++++++++++++++--- include/nasmlib.h | 2 +- test/incbin.asm | 1 + 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/asm/assemble.c b/asm/assemble.c index 463d7378..b09f7cbb 100644 --- a/asm/assemble.c +++ b/asm/assemble.c @@ -544,6 +544,9 @@ static bool jmp_match(int32_t segment, int64_t offset, int bits, return is_byte; } +/* This is totally just a wild guess what is reasonable... */ +#define INCBIN_MAX_BUF (ZERO_BUF_SIZE * 16) + int64_t assemble(int32_t segment, int64_t start, int bits, iflag_t cp, insn * instruction) { @@ -610,11 +613,13 @@ int64_t assemble(int32_t segment, int64_t start, int bits, iflag_t cp, } else if (instruction->opcode == I_INCBIN) { const char *fname = instruction->eops->stringval; FILE *fp; - static char buf[BUFSIZ]; size_t t = instruction->times; off_t base = 0; off_t len; const void *map = NULL; + char *buf = NULL; + size_t blk = 0; /* Buffered I/O block size */ + size_t m = 0; /* Bytes last read */ fp = nasm_open_read(fname, NF_BINARY|NF_FORMAP); if (!fp) { @@ -651,6 +656,10 @@ int64_t assemble(int32_t segment, int64_t start, int bits, iflag_t cp, /* Try to map file data */ map = nasm_map_file(fp, base, len); + if (!map) { + blk = len < (off_t)INCBIN_MAX_BUF ? (size_t)len : INCBIN_MAX_BUF; + buf = nasm_malloc(blk); + } while (t--) { data.insoffs = 0; @@ -658,6 +667,8 @@ int64_t assemble(int32_t segment, int64_t start, int bits, iflag_t cp, if (map) { out_rawdata(&data, map, len); + } else if ((off_t)m == len) { + out_rawdata(&data, buf, len); } else { off_t l = len; @@ -668,8 +679,7 @@ int64_t assemble(int32_t segment, int64_t start, int bits, iflag_t cp, goto end_incbin; } while (l > 0) { - size_t m = l < (off_t)sizeof(buf) ? (size_t)l : sizeof(buf); - m = fread(buf, 1, m, fp); + m = fread(buf, 1, l < (off_t)blk ? (size_t)l : blk, fp); if (!m || feof(fp)) { /* * This shouldn't happen unless the file @@ -699,6 +709,8 @@ int64_t assemble(int32_t segment, int64_t start, int bits, iflag_t cp, " reading file `%s'", fname); } close_done: + if (buf) + nasm_free(buf); if (map) nasm_unmap_file(map, len); fclose(fp); diff --git a/include/nasmlib.h b/include/nasmlib.h index e24ac1d5..b1c490ca 100644 --- a/include/nasmlib.h +++ b/include/nasmlib.h @@ -455,7 +455,7 @@ FILE *nasm_open_write(const char *filename, enum file_flags flags); /* Probe for existence of a file */ bool nasm_file_exists(const char *filename); -#define ZERO_BUF_SIZE 4096 /* Default value */ +#define ZERO_BUF_SIZE 65536 /* Default value */ #if defined(BUFSIZ) && (BUFSIZ > ZERO_BUF_SIZE) # undef ZERO_BUF_SIZE # define ZERO_BUF_SIZE BUFSIZ diff --git a/test/incbin.asm b/test/incbin.asm index 634302ea..20aa4d9f 100644 --- a/test/incbin.asm +++ b/test/incbin.asm @@ -1,5 +1,6 @@ db '*** ONCE ***', 0Ah incbin "incbin.data",32 + section more start=0x1000000 db '*** TWELVE ***', 0Ah times 12 incbin "incbin.data",32