summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2016-09-21 15:56:19 -0700
committerH. Peter Anvin <hpa@linux.intel.com>2016-09-21 15:56:19 -0700
commit04445364fc9123ad40bf5581ffa4c5afac4c57dc (patch)
tree127577894550f7f99518de1e030cbefe4f8fa08b
parentd81a235f33e78ef6b942788b42db073ed51fa801 (diff)
downloadnasm-04445364fc9123ad40bf5581ffa4c5afac4c57dc.tar.gz
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 <hpa@linux.intel.com>
-rw-r--r--asm/assemble.c18
-rw-r--r--include/nasmlib.h2
-rw-r--r--test/incbin.asm1
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