commit d9bc748c4b81d2da20c4be1854427ca7b5ab8a03
parent 27d13ec5bc10a37062c6582c5024653c85ccdcaa
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Fri, 21 Jul 2023 16:16:32 +0200
Merge remote-tracking branch 'origin/feature_posix_make' into feature_posix_make
Diffstat:
5 files changed, 261 insertions(+), 91 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -36,7 +36,7 @@ include_directories(${RSys_INCLUDE_DIR})
# Configure and define targets
################################################################################
set(VERSION_MAJOR 0)
-set(VERSION_MINOR 0)
+set(VERSION_MINOR 1)
set(VERSION_PATCH 0)
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
diff --git a/config.mk b/config.mk
@@ -1,4 +1,4 @@
-VERSION = 0.0.0
+VERSION = 0.1.0
PREFIX = /usr/local
LIB_TYPE = SHARED
diff --git a/src/smsh.c b/src/smsh.c
@@ -21,6 +21,7 @@
#include "smsh_c.h"
#include "smsh_log.h"
+#include <rsys/cstr.h>
#include <rsys/mem_allocator.h>
#include <errno.h>
@@ -38,6 +39,22 @@ check_smsh_create_args(const struct smsh_create_args* args)
return args ? RES_OK : RES_BAD_ARG;
}
+static INLINE res_T
+check_smsh_load_args(const struct smsh_load_args* args)
+{
+ ASSERT(args);
+ if(!args || !args->path) return RES_BAD_ARG;
+ return RES_OK;
+}
+
+static INLINE res_T
+check_smsh_load_stream_args(const struct smsh_load_stream_args* args)
+{
+ ASSERT(args);
+ if(!args || !args->stream || !args->name) return RES_BAD_ARG;
+ return RES_OK;
+}
+
static void
reset_smsh(struct smsh* smsh)
{
@@ -45,20 +62,42 @@ reset_smsh(struct smsh* smsh)
smsh->nnodes = 0;
smsh->ncells = 0;
smsh->pagesize = 0;
- if(smsh->nodes && smsh->nodes != MAP_FAILED)
- munmap(smsh->nodes, smsh->map_len_nodes);
- if(smsh->cells && smsh->cells != MAP_FAILED)
- munmap(smsh->cells, smsh->map_len_cells);
+ if(smsh->nodes) {
+ if(!smsh->map_len_nodes) {
+ MEM_RM(smsh->allocator, smsh->nodes);
+ } else if(smsh->nodes != MAP_FAILED) {
+ munmap(smsh->nodes, smsh->map_len_nodes);
+ }
+ }
+ if(smsh->cells) {
+ if(!smsh->map_len_cells) {
+ MEM_RM(smsh->allocator, smsh->cells);
+ } else if(smsh->nodes != MAP_FAILED) {
+ munmap(smsh->cells, smsh->map_len_cells);
+ }
+ }
smsh->nodes = NULL;
smsh->cells = NULL;
smsh->map_len_nodes = 0;
smsh->map_len_cells = 0;
}
+static INLINE int
+is_stdin(FILE* stream)
+{
+ struct stat stream_buf;
+ struct stat stdin_buf;
+ ASSERT(stream);
+
+ CHK(fstat(fileno(stream), &stream_buf) == 0);
+ CHK(fstat(STDIN_FILENO, &stdin_buf) == 0);
+ return stream_buf.st_dev == stdin_buf.st_dev;
+}
+
static res_T
map_data
(struct smsh* smsh,
- const char* stream_name,
+ const char* name,
const int fd, /* File descriptor */
const size_t filesz, /* Overall filesize */
const char* data_name,
@@ -68,12 +107,12 @@ map_data
{
void* map = NULL;
res_T res = RES_OK;
- ASSERT(smsh && stream_name && filesz && data_name && map_len && out_map);
+ ASSERT(smsh && name && filesz && data_name && map_len && out_map);
ASSERT(IS_ALIGNED((size_t)offset, (size_t)smsh->pagesize));
if((size_t)offset + map_len > filesz) {
log_err(smsh, "%s: the %s to load exceed the file size.\n",
- stream_name, data_name);
+ name, data_name);
res = RES_IO_ERR;
goto error;
}
@@ -81,7 +120,7 @@ map_data
map = mmap(NULL, map_len, PROT_READ, MAP_PRIVATE|MAP_POPULATE, fd, offset);
if(map == MAP_FAILED) {
log_err(smsh, "%s: could not map the %s -- %s.\n",
- stream_name, data_name, strerror(errno));
+ name, data_name, strerror(errno));
res = RES_IO_ERR;
goto error;
}
@@ -94,45 +133,141 @@ error:
goto exit;
}
-static INLINE int
-is_stdin(FILE* stream)
+static res_T
+map_file(struct smsh* smsh, FILE* stream, const char* name)
{
- struct stat stream_buf;
- struct stat stdin_buf;
- ASSERT(stream);
+ off_t pos_offset;
+ off_t ids_offset;
+ size_t filesz;
+ res_T res = RES_OK;
+ ASSERT(smsh && stream && name);
- CHK(fstat(fileno(stream), &stream_buf) == 0);
- CHK(fstat(STDIN_FILENO, &stdin_buf) == 0);
- return stream_buf.st_dev == stdin_buf.st_dev;
+ /* Compute the length in bytes of the data to map */
+ smsh->map_len_nodes = smsh->nnodes * sizeof(double) * smsh->dnode;
+ smsh->map_len_cells = smsh->ncells * sizeof(uint64_t) * smsh->dcell;
+ smsh->map_len_nodes = ALIGN_SIZE(smsh->map_len_nodes, (size_t)smsh->pagesize);
+ smsh->map_len_cells = ALIGN_SIZE(smsh->map_len_cells, (size_t)smsh->pagesize);
+
+ /* Find the offsets of the positions/indices data into the stream */
+ pos_offset = (off_t)ALIGN_SIZE((uint64_t)ftell(stream), smsh->pagesize);
+ ids_offset = (off_t)((size_t)pos_offset + smsh->map_len_nodes);
+
+ /* Retrieve the overall filesize */
+ fseek(stream, 0, SEEK_END);
+ filesz = (size_t)ftell(stream);
+
+ /* Map the nodes */
+ res = map_data(smsh, name, fileno(stream), filesz, "nodes",
+ pos_offset, smsh->map_len_nodes, (void**)&smsh->nodes);
+ if(res != RES_OK) goto error;
+
+ /* Map the cells */
+ res = map_data(smsh, name, fileno(stream), filesz, "cells",
+ ids_offset, smsh->map_len_cells, (void**)&smsh->cells);
+ if(res != RES_OK) goto error;
+
+exit:
+ return res;
+error:
+ goto exit;
}
static res_T
-load_stream(struct smsh* smsh, FILE* stream, const char* stream_name)
+read_padding(FILE* stream, const size_t padding)
{
- off_t pos_offset;
- off_t ids_offset;
- size_t filesz;
+ char chunk[1024];
+ size_t remaining_nbytes = padding;
+
+ while(remaining_nbytes) {
+ const size_t nbytes = MMIN(sizeof(chunk), remaining_nbytes);
+ if(fread(chunk, 1, nbytes, stream) != nbytes) return RES_IO_ERR;
+ remaining_nbytes -= nbytes;
+ }
+ return RES_OK;
+}
+
+static res_T
+load_file(struct smsh* smsh, FILE* stream, const char* name)
+{
+ size_t ncoords;
+ size_t nindices;
+ size_t padding_bytes;
+ size_t sizeof_nodes;
+ size_t sizeof_cells;
+ size_t sizeof_header;
res_T res = RES_OK;
- ASSERT(smsh && stream && stream_name);
+ ASSERT(smsh && stream && name);
+
+ ncoords = smsh->nnodes * smsh->dnode;
+ nindices = smsh->ncells * smsh->dcell;
+ sizeof_nodes = ncoords * sizeof(*smsh->nodes);
+ sizeof_cells = nindices * sizeof(*smsh->cells);
+ sizeof_header =
+ sizeof(smsh->pagesize)
+ + sizeof(smsh->nnodes)
+ + sizeof(smsh->ncells)
+ + sizeof(smsh->dnode)
+ + sizeof(smsh->dcell);
+
+ /* Allocate the memory space where the loaded data will be stored */
+ smsh->nodes = MEM_CALLOC(smsh->allocator, ncoords, sizeof(*smsh->nodes));
+ if(!smsh->nodes) { res = RES_MEM_ERR; goto error; }
+ smsh->cells = MEM_CALLOC(smsh->allocator, nindices, sizeof(*smsh->cells));
+ if(!smsh->cells) { res = RES_MEM_ERR; goto error; }
+
+ padding_bytes = ALIGN_SIZE(sizeof_header, smsh->pagesize) - sizeof_header;
+ if((res = read_padding(stream, padding_bytes)) != RES_OK) goto error;
+
+ /* Load the nodes */
+ if(fread(smsh->nodes, sizeof(*smsh->nodes), ncoords, stream) != ncoords) {
+ res = RES_IO_ERR;
+ goto error;
+ }
+
+ padding_bytes = ALIGN_SIZE(sizeof_nodes, smsh->pagesize) - sizeof_nodes;
+ if((res = read_padding(stream, padding_bytes)) != RES_OK) goto error;
- if(is_stdin(stream)) {
- log_err(smsh, "%s: the data cannot be load from the standard input\n",
- stream_name);
+ /* Load the cells */
+ if(fread(smsh->cells, sizeof(*smsh->cells), nindices, stream) != nindices) {
res = RES_IO_ERR;
goto error;
}
+ padding_bytes = ALIGN_SIZE(sizeof_cells, smsh->pagesize) - sizeof_cells;
+ if((res = read_padding(stream, padding_bytes)) != RES_OK) goto error;
+
+exit:
+ return res;
+error:
+ log_err(smsh, "%s: error while loading data -- %s.\n",
+ name, res_to_cstr(res));
+ goto exit;
+}
+
+static res_T
+load_stream(struct smsh* smsh, const struct smsh_load_stream_args* args)
+{
+ res_T res = RES_OK;
+ ASSERT(smsh && check_smsh_load_stream_args(args) == RES_OK);
+
reset_smsh(smsh);
/* Read file header */
+ if(fread(&smsh->pagesize, sizeof(&smsh->pagesize), 1, args->stream) != 1) {
+ if(ferror(args->stream)) {
+ log_err(smsh, "%s: could not read the pagesize.\n", args->name);
+ }
+ res = RES_IO_ERR;
+ goto error;
+ }
+
#define READ(Var, N, Name) { \
- if(fread((Var), sizeof(*(Var)), (N), stream) != (N)) { \
- log_err(smsh, "%s: could not read the %s.\n", stream_name, (Name)); \
+ if(fread((Var), sizeof(*(Var)), (N), args->stream) != (N)) { \
+ log_err(smsh, "%s: could not read the %s.\n", args->name, (Name)); \
res = RES_IO_ERR; \
goto error; \
} \
} (void)0
- READ(&smsh->pagesize, 1, "page size");
READ(&smsh->nnodes, 1, "number of nodes");
READ(&smsh->ncells, 1, "number of cells");
READ(&smsh->dnode, 1, "node dimension");
@@ -143,34 +278,18 @@ load_stream(struct smsh* smsh, FILE* stream, const char* stream_name)
log_err(smsh,
"%s: invalid page size %li. The page size attribute must be aligned on "
"the page size of the operating system (%lu).\n",
- stream_name, smsh->pagesize, (unsigned long)smsh->pagesize_os);
+ args->name, smsh->pagesize, (unsigned long)smsh->pagesize_os);
res = RES_BAD_ARG;
goto error;
}
- /* Compute the length in bytes of the data to map */
- smsh->map_len_nodes = smsh->nnodes * sizeof(double) * smsh->dnode;
- smsh->map_len_cells = smsh->ncells * sizeof(uint64_t) * smsh->dcell;
- smsh->map_len_nodes = ALIGN_SIZE(smsh->map_len_nodes, (size_t)smsh->pagesize);
- smsh->map_len_cells = ALIGN_SIZE(smsh->map_len_cells, (size_t)smsh->pagesize);
-
- /* Find the offsets of the positions/indices data into the stream */
- pos_offset = (off_t)ALIGN_SIZE((uint64_t)ftell(stream), smsh->pagesize);
- ids_offset = (off_t)((size_t)pos_offset + smsh->map_len_nodes);
-
- /* Retrieve the overall filesize */
- fseek(stream, 0, SEEK_END);
- filesz = (size_t)ftell(stream);
-
- /* Map the nodes */
- res = map_data(smsh, stream_name, fileno(stream), filesz, "nodes",
- pos_offset, smsh->map_len_nodes, (void**)&smsh->nodes);
- if(res != RES_OK) goto error;
-
- /* Map the cells */
- res = map_data(smsh, stream_name, fileno(stream), filesz, "cells",
- ids_offset, smsh->map_len_cells, (void**)&smsh->cells);
- if(res != RES_OK) goto error;
+ if(args->memory_mapping) {
+ res = map_file(smsh, args->stream, args->name);
+ if(res != RES_OK) goto error;
+ } else {
+ res = load_file(smsh, args->stream, args->name);
+ if(res != RES_OK) goto error;
+ }
exit:
return res;
@@ -260,24 +379,27 @@ smsh_ref_put(struct smsh* smsh)
res_T
-smsh_load(struct smsh* smsh, const char* path)
+smsh_load(struct smsh* smsh, const struct smsh_load_args* args)
{
+ struct smsh_load_stream_args stream_args = SMSH_LOAD_STREAM_ARGS_NULL;
FILE* file = NULL;
res_T res = RES_OK;
- if(!smsh || !path) {
- res = RES_BAD_ARG;
- goto error;
- }
+ if(!smsh) { res = RES_BAD_ARG; goto error; }
+ res = check_smsh_load_args(args);
+ if(res != RES_OK) goto error;
- file = fopen(path, "r");
+ file = fopen(args->path, "r");
if(!file) {
- log_err(smsh, "%s: error opening file `%s'.\n", FUNC_NAME, path);
+ log_err(smsh, "%s: error opening file `%s'.\n", FUNC_NAME, args->path);
res = RES_IO_ERR;
goto error;
}
- res = load_stream(smsh, file, path);
+ stream_args.stream = file;
+ stream_args.name = args->path;
+ stream_args.memory_mapping = args->memory_mapping;
+ res = load_stream(smsh, &stream_args);
if(res != RES_OK) goto error;
exit:
@@ -288,13 +410,13 @@ error:
}
res_T
-smsh_load_stream
- (struct smsh* smsh,
- FILE* stream,
- const char* stream_name)
+smsh_load_stream(struct smsh* smsh, const struct smsh_load_stream_args* args)
{
- if(!smsh || !stream) return RES_BAD_ARG;
- return load_stream(smsh, stream, stream_name ? stream_name : "<stream>");
+ res_T res = RES_OK;
+ if(!smsh) return RES_BAD_ARG;
+ res = check_smsh_load_stream_args(args);
+ if(res != RES_OK) return res;
+ return load_stream(smsh, args);
}
res_T
@@ -321,8 +443,8 @@ smsh_desc_compute_hash(const struct smsh_desc* desc, hash256_T hash)
sha256_ctx_update(&ctx, (const char*)(Var), sizeof(*Var)*(Nb));
sha256_ctx_init(&ctx);
- HASH(desc->nodes, desc->nnodes);
- HASH(desc->cells, desc->ncells);
+ HASH(desc->nodes, desc->nnodes*desc->dnode);
+ HASH(desc->cells, desc->ncells*desc->dcell);
HASH(&desc->nnodes, 1);
HASH(&desc->ncells, 1);
HASH(&desc->dnode, 1);
diff --git a/src/smsh.h b/src/smsh.h
@@ -50,9 +50,28 @@ struct smsh_create_args {
static const struct smsh_create_args SMSH_CREATE_ARGS_DEFAULT =
SMSH_CREATE_ARGS_DEFAULT__;
+struct smsh_load_args {
+ const char* path;
+ int memory_mapping; /* Use memory mapping instead of normal loading */
+};
+#define SMSH_LOAD_ARGS_NULL__ {NULL, 0}
+static const struct smsh_load_args SMSH_LOAD_ARGS_NULL =
+ SMSH_LOAD_ARGS_NULL__;
+
+struct smsh_load_stream_args {
+ FILE* stream;
+ const char* name; /* Name of the stream */
+ /* Use memory mapping instead of normal loading. Note that memory mapping
+ * cannot be used on some stream like stdin */
+ int memory_mapping;
+};
+#define SMSH_LOAD_STREAM_ARGS_NULL__ {NULL, "stream", 0}
+static const struct smsh_load_stream_args SMSH_LOAD_STREAM_ARGS_NULL =
+ SMSH_LOAD_STREAM_ARGS_NULL__;
+
struct smsh_desc {
- const double* nodes; /* List of double[3] */
- const uint64_t* cells; /* List of uint64_t[4] */
+ const double* nodes; /* List of double[dnode] */
+ const uint64_t* cells; /* List of uint64_t[dcell] */
size_t nnodes;
size_t ncells;
unsigned dnode; /* Dimension of a node */
@@ -85,13 +104,12 @@ smsh_ref_put
SMSH_API res_T
smsh_load
(struct smsh* smsh,
- const char* path);
+ const struct smsh_load_args* args);
SMSH_API res_T
smsh_load_stream
(struct smsh* smsh,
- FILE* stream,
- const char* stream_name); /* NULL <=> use default stream name */
+ const struct smsh_load_stream_args* args);
SMSH_API res_T
smsh_get_desc
diff --git a/src/test_smsh_load.c b/src/test_smsh_load.c
@@ -19,6 +19,7 @@
#include <rsys/math.h>
#include <rsys/mem_allocator.h>
#include <rsys/rsys.h>
+
#include <stdio.h>
#include <unistd.h>
@@ -70,6 +71,8 @@ test_load_mesh(struct smsh* smsh, const uint32_t dnode, const uint32_t dcell)
hash256_T hash0;
hash256_T hash1;
struct smsh_desc desc = SMSH_DESC_NULL;
+ struct smsh_load_args args = SMSH_LOAD_ARGS_NULL;
+ struct smsh_load_stream_args stream_args = SMSH_LOAD_STREAM_ARGS_NULL;
FILE* fp = NULL;
const char* filename = "test_file.smsh";
const uint64_t pagesize = 16384;
@@ -116,9 +119,17 @@ test_load_mesh(struct smsh* smsh, const uint32_t dnode, const uint32_t dcell)
CHK(fwrite(&byte, sizeof(byte), 1, fp) == 1);
rewind(fp);
- CHK(smsh_load_stream(NULL, fp, filename) == RES_BAD_ARG);
- CHK(smsh_load_stream(smsh, NULL, filename) == RES_BAD_ARG);
- CHK(smsh_load_stream(smsh, fp, NULL) == RES_OK);
+
+ stream_args.stream = fp;
+ stream_args.name = filename;
+ CHK(smsh_load_stream(NULL, &stream_args) == RES_BAD_ARG);
+ stream_args.stream = NULL;
+ CHK(smsh_load_stream(smsh, &stream_args) == RES_BAD_ARG);
+ stream_args.stream = fp;
+ stream_args.name = NULL;
+ CHK(smsh_load_stream(smsh, &stream_args) == RES_BAD_ARG);
+ stream_args.name = filename;
+ CHK(smsh_load_stream(smsh, &stream_args) == RES_OK);
CHK(smsh_get_desc(NULL, &desc) == RES_BAD_ARG);
CHK(smsh_get_desc(smsh, NULL) == RES_BAD_ARG);
CHK(smsh_get_desc(smsh, &desc) == RES_OK);
@@ -129,25 +140,41 @@ test_load_mesh(struct smsh* smsh, const uint32_t dnode, const uint32_t dcell)
CHK(smsh_desc_compute_hash(&desc, hash0) == RES_OK);
rewind(fp);
- CHK(smsh_load_stream(smsh, fp, filename) == RES_OK);
+ stream_args.name = SMSH_LOAD_STREAM_ARGS_NULL.name;
+ stream_args.memory_mapping = 1;
+ CHK(smsh_load_stream(smsh, &stream_args) == RES_OK);
CHK(smsh_get_desc(smsh, &desc) == RES_OK);
check_smsh_desc(&desc, nnodes, ncells, dnode, dcell);
CHK(smsh_desc_compute_hash(&desc, hash1) == RES_OK);
CHK(hash256_eq(hash0, hash1));
+ CHK(fclose(fp) == 0);
- CHK(smsh_load(NULL, filename) == RES_BAD_ARG);
- CHK(smsh_load(smsh, NULL) == RES_BAD_ARG);
- CHK(smsh_load(smsh, "nop") == RES_IO_ERR);
- CHK(smsh_load(smsh, filename) == RES_OK);
+ args.path = filename;
+ CHK(smsh_load(NULL, &args) == RES_BAD_ARG);
+ args.path = NULL;
+ CHK(smsh_load(smsh, &args) == RES_BAD_ARG);
+ args.path = "nop";
+ CHK(smsh_load(smsh, &args) == RES_IO_ERR);
+ args.path = filename;
+ CHK(smsh_load(smsh, &args) == RES_OK);
+ CHK(smsh_get_desc(smsh, &desc) == RES_OK);
check_smsh_desc(&desc, nnodes, ncells, dnode, dcell);
+ CHK(smsh_desc_compute_hash(&desc, hash1) == RES_OK);
+ CHK(hash256_eq(hash0, hash1));
- fclose(fp);
+ args.memory_mapping = 1;
+ CHK(smsh_load(smsh, &args) == RES_OK);
+ CHK(smsh_get_desc(smsh, &desc) == RES_OK);
+ check_smsh_desc(&desc, nnodes, ncells, dnode, dcell);
+ CHK(smsh_desc_compute_hash(&desc, hash1) == RES_OK);
+ CHK(hash256_eq(hash0, hash1));
}
static void
test_load_fail(struct smsh* smsh)
{
+ struct smsh_load_stream_args args = SMSH_LOAD_STREAM_ARGS_NULL;
const char byte = 0;
FILE* fp = NULL;
uint64_t pagesize;
@@ -176,8 +203,9 @@ test_load_fail(struct smsh* smsh)
CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize)-1, SEEK_SET) == 0);
CHK(fwrite(&byte, sizeof(byte), 1, fp) == 1);
rewind(fp);
- CHK(smsh_load_stream(smsh, fp, NULL) == RES_BAD_ARG);
- fclose(fp);
+ args.stream = fp;
+ CHK(smsh_load_stream(smsh, &args) == RES_BAD_ARG);
+ CHK(fclose(fp) == 0);
/* Wrong size */
fp = tmpfile();
@@ -199,16 +227,15 @@ test_load_fail(struct smsh* smsh)
CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize)-2, SEEK_SET) == 0);
CHK(fwrite(&byte, sizeof(byte), 1, fp) == 1);
rewind(fp);
- CHK(smsh_load_stream(smsh, fp, NULL) == RES_IO_ERR);
- fclose(fp);
-
- /* Wrong stream */
- CHK(smsh_load_stream(smsh, stdin, "stdin") == RES_IO_ERR);
+ args.stream = fp;
+ CHK(smsh_load_stream(smsh, &args) == RES_IO_ERR);
+ CHK(fclose(fp) == 0);
}
static void
test_load_files(struct smsh* smsh, int argc, char** argv)
{
+ struct smsh_load_args args = SMSH_LOAD_ARGS_NULL;
hash256_T hash;
int i;
CHK(smsh);
@@ -219,7 +246,10 @@ test_load_files(struct smsh* smsh, int argc, char** argv)
size_t icell;
printf("Load %s\n", argv[i]);
- CHK(smsh_load(smsh, argv[i]) == RES_OK);
+
+ args.path = argv[i];
+ args.memory_mapping = 1;
+ CHK(smsh_load(smsh, &args) == RES_OK);
CHK(smsh_get_desc(smsh, &desc) == RES_OK);
CHK(smsh_desc_compute_hash(&desc, hash) == RES_OK);