Skip to content

Commit

Permalink
MacOS Port
Browse files Browse the repository at this point in the history
  • Loading branch information
Nicolas Laurent committed Nov 23, 2024
1 parent 6b23d8b commit 18bd181
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 63 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ tests/containers/bouncing_ball/bouncing.fmu
tests/containers/bouncing_ball/bouncing_auto.fmu
tests/containers/bouncing_ball/bouncing_unlinked.fmu
container/build-win64
container/build
3 changes: 2 additions & 1 deletion container/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ add_library(container SHARED
fmu.c fmu.h
library.c library.h
logger.c logger.h
profile.c profile.h)
profile.c profile.h
thread.c thread.h)
set_target_properties(container PROPERTIES PREFIX "")
target_include_directories(container PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/../fmi
Expand Down
72 changes: 37 additions & 35 deletions container/container.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include <errno.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Expand Down Expand Up @@ -156,13 +158,13 @@ static int read_conf_io(container_t* container, config_file_t* file) {

#define ALLOC(type, value) \
if (container->nb_local_ ## type) { \
container-> ## type = malloc(container->nb_local_ ## type * sizeof(*container-> ## type)); \
if (!container-> ## type) \
container-> type = malloc(container->nb_local_ ## type * sizeof(*container-> type)); \
if (!container-> type) \
return -2; \
for(fmi2ValueReference i=0; i < container->nb_local_ ## type; i += 1) \
container-> ## type ## [i] = value; \
container-> type [i] = value; \
} else \
container-> ## type = NULL
container-> type = NULL

ALLOC(reals, 0.0);
ALLOC(integers, 0);
Expand Down Expand Up @@ -245,24 +247,24 @@ static int read_conf_fmu_io_ ## causality ## _ ## type (fmu_io_t *fmu_io, config
if (get_line(file)) \
return -1; \
\
fmu_io-> ## type ## . ## causality ## .translations = NULL; \
fmu_io-> type . causality .translations = NULL; \
\
if (sscanf(file->line, "%d", &fmu_io-> ## type ## . ## causality ## .nb) < 1) \
if (sscanf(file->line, "%d", &fmu_io-> type . causality .nb) < 1) \
return -2; \
\
if (fmu_io-> ## type ## . ## causality ## .nb == 0) \
if (fmu_io-> type . causality .nb == 0) \
return 0; \
\
fmu_io-> ## type ## . ## causality ## .translations = malloc(fmu_io-> ## type ## . ## causality ## .nb * sizeof(*fmu_io-> ## type ##. ## causality ## .translations)); \
if (! fmu_io-> ## type ## . ## causality ## .translations) \
fmu_io-> type . causality .translations = malloc(fmu_io-> type . causality .nb * sizeof(*fmu_io-> type . causality .translations)); \
if (! fmu_io-> type . causality .translations) \
return -3; \
\
for(fmi2ValueReference i = 0; i < fmu_io-> ## type ## . ## causality ## .nb; i += 1) { \
for(fmi2ValueReference i = 0; i < fmu_io-> type . causality .nb; i += 1) { \
if (get_line(file)) \
return -4; \
\
if (sscanf(file->line, "%d %d", &fmu_io-> ## type ## . ## causality ## .translations[i].vr, \
&fmu_io-> ## type ## . ## causality ## .translations[i].fmu_vr) < 2) \
if (sscanf(file->line, "%d %d", &fmu_io-> type . causality .translations[i].vr, \
&fmu_io-> type . causality .translations[i].fmu_vr) < 2) \
return -5; \
} \
\
Expand All @@ -275,29 +277,29 @@ static int read_conf_fmu_start_values_ ## type (fmu_io_t *fmu_io, config_file_t*
if (get_line(file)) \
return -1; \
\
fmu_io->start_ ## type ## .vr = NULL; \
fmu_io->start_ ## type ## .values = NULL; \
fmu_io->start_ ## type ## .nb = 0; \
fmu_io->start_ ## type .vr = NULL; \
fmu_io->start_ ## type .values = NULL; \
fmu_io->start_ ## type .nb = 0; \
\
if (sscanf(file->line, "%d", &fmu_io->start_ ## type ## .nb) < 1) \
if (sscanf(file->line, "%d", &fmu_io->start_ ## type .nb) < 1) \
return -2; \
\
if (fmu_io->start_ ## type ## .nb == 0) \
if (fmu_io->start_ ## type .nb == 0) \
return 0; \
\
fmu_io->start_ ## type ## .vr = malloc(fmu_io->start_ ## type ## .nb * sizeof(*fmu_io->start_ ## type ## .vr)); \
if (! fmu_io->start_ ## type ## .vr) \
fmu_io->start_ ## type .vr = malloc(fmu_io->start_ ## type .nb * sizeof(*fmu_io->start_ ## type .vr)); \
if (! fmu_io->start_ ## type .vr) \
return -3; \
fmu_io->start_ ## type ## .values = malloc(fmu_io->start_ ## type ## .nb * sizeof(*fmu_io->start_ ## type ## .values)); \
if (! fmu_io->start_ ## type ## .values) \
fmu_io->start_ ## type .values = malloc(fmu_io->start_ ## type .nb * sizeof(*fmu_io->start_ ## type .values)); \
if (! fmu_io->start_ ## type .values) \
return -3; \
\
for (fmi2ValueReference i = 0; i < fmu_io->start_ ## type ## .nb; i += 1) { \
for (fmi2ValueReference i = 0; i < fmu_io->start_ ## type .nb; i += 1) { \
if (get_line(file)) \
return -4; \
\
if (sscanf(file->line, "%d " format, &fmu_io->start_ ## type ## .vr[i], \
&fmu_io->start_ ## type ## . values[i]) < 2) \
if (sscanf(file->line, "%d " format, &fmu_io->start_ ## type .vr[i], \
&fmu_io->start_ ## type . values[i]) < 2) \
return -5; \
} \
\
Expand Down Expand Up @@ -673,9 +675,9 @@ fmi2Status fmi2EnterInitializationMode(fmi2Component c) {
*/

#define SET_START(fmi_type, type) \
if (container->fmu[i].fmu_io.start_ ## type ## .nb > 0) { \
fmuSet ## fmi_type (&container->fmu[i], container->fmu[i].fmu_io.start_ ## type ## .vr, \
container->fmu[i].fmu_io.start_ ## type ## .nb, container->fmu[i].fmu_io.start_ ## type ## .values); \
if (container->fmu[i].fmu_io.start_ ## type .nb > 0) { \
fmuSet ## fmi_type (&container->fmu[i], container->fmu[i].fmu_io.start_ ## type .vr, \
container->fmu[i].fmu_io.start_ ## type .nb, container->fmu[i].fmu_io.start_ ## type .values); \
}
SET_START(Real, reals);
SET_START(Integer, integers);
Expand Down Expand Up @@ -739,7 +741,7 @@ fmi2Status fmi2Get ## fmi_type (fmi2Component c, const fmi2ValueReference vr[],
const int fmu_id = container->vr_ ## type [vr[i]].fmu_id; \
\
if (fmu_id < 0) { \
value[i] = container-> ## type [vr[i]]; \
value[i] = container-> type [vr[i]]; \
} else { \
const fmi2ValueReference fmu_vr = container->vr_ ## type [vr[i]].fmu_vr; \
const fmu_t *fmu = &container->fmu[fmu_id]; \
Expand Down Expand Up @@ -774,7 +776,7 @@ fmi2Status fmi2Set ## fmi_type (fmi2Component c, const fmi2ValueReference vr[],
for (size_t i = 0; i < nvr; i += 1) { \
const int fmu_id = container->vr_ ##type [vr[i]].fmu_id; \
if (fmu_id < 0) {\
container-> ## type [vr[i]] = value[i]; \
container-> type [vr[i]] = value[i]; \
} else { \
const fmu_t* fmu = &container->fmu[fmu_id]; \
const fmi2ValueReference fmu_vr = container->vr_ ## type [vr[i]].fmu_vr; \
Expand Down Expand Up @@ -868,10 +870,10 @@ static fmi2Status do_step_get_outputs(container_t* container, int fmu_id) {
fmi2Status status = fmi2OK;

#define GETTER(type, fmi_type) \
for (fmi2ValueReference i = 0; i < fmu_io-> ## type ## .out.nb; i += 1) { \
const fmi2ValueReference fmu_vr = fmu_io-> ## type ## .out.translations[i].fmu_vr; \
const fmi2ValueReference local_vr = fmu_io-> ## type ## .out.translations[i].vr; \
status = fmuGet ## fmi_type (fmu, &fmu_vr, 1, &container-> ## type ## [local_vr]); \
for (fmi2ValueReference i = 0; i < fmu_io-> type .out.nb; i += 1) { \
const fmi2ValueReference fmu_vr = fmu_io-> type .out.translations[i].fmu_vr; \
const fmi2ValueReference local_vr = fmu_io-> type .out.translations[i].vr; \
status = fmuGet ## fmi_type (fmu, &fmu_vr, 1, &container-> type [local_vr]); \
if (status != fmi2OK) \
return status; \
}
Expand Down Expand Up @@ -923,12 +925,12 @@ static fmi2Status do_internal_step_parallel_mt(container_t* container, fmi2Real
/* Launch computation for all threads*/
for (int i = 0; i < container->nb_fmu; i += 1) {
container->fmu[i].status = fmi2Error;
SetEvent(container->fmu[i].mutex_container);
thread_mutex_unlock(&container->fmu[i].mutex_container);
}

/* Consolidate results */
for (int i = 0; i < container->nb_fmu; i += 1) {
WaitForSingleObject(container->fmu[i].mutex_fmu, INFINITE);
thread_mutex_lock(&container->fmu[i].mutex_fmu);
if (container->fmu[i].status != fmi2OK)
return container->fmu[i].status;
}
Expand Down
50 changes: 29 additions & 21 deletions container/fmu.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#include <stdarg.h>
#include <string.h>

#include "container.h"
#include "fmu.h"
#include "logger.h"
Expand All @@ -15,10 +18,10 @@ fmi2Status fmu_set_inputs(fmu_t *fmu) {
const fmu_io_t *fmu_io = &fmu->fmu_io;

#define SETTER(type, fmi_type) \
for (fmi2ValueReference i = 0; i < fmu_io-> ## type ## .in.nb; i += 1) { \
const fmi2ValueReference fmu_vr = fmu_io-> ## type ## .in.translations[i].fmu_vr; \
const fmi2ValueReference local_vr = fmu_io-> ## type ## .in.translations[i].vr; \
status = fmuSet ## fmi_type (fmu, &fmu_vr, 1, &container-> ## type ## [local_vr]); \
for (fmi2ValueReference i = 0; i < fmu_io-> type .in.nb; i += 1) { \
const fmi2ValueReference fmu_vr = fmu_io-> type .in.translations[i].fmu_vr; \
const fmi2ValueReference local_vr = fmu_io-> type .in.translations[i].vr; \
status = fmuSet ## fmi_type (fmu, &fmu_vr, 1, &container-> type [local_vr]); \
if (status != fmi2OK) \
return status; \
}
Expand All @@ -38,13 +41,13 @@ static int fmu_do_step_thread(fmu_t* fmu) {
const container_t* container =fmu->container;

while (!fmu->cancel) {
WaitForSingleObject(fmu->mutex_container, INFINITE);
thread_mutex_lock(&fmu->mutex_container);
if (fmu->cancel)
break;

fmu->status = fmu_set_inputs(fmu);
if (fmu->status != fmi2OK) {
SetEvent(fmu->mutex_fmu);
thread_mutex_unlock(&fmu->mutex_fmu);
continue;
}

Expand All @@ -53,10 +56,10 @@ static int fmu_do_step_thread(fmu_t* fmu) {
container->step_size,
container->noSetFMUStatePriorToCurrentPoint);

SetEvent(fmu->mutex_fmu);
thread_mutex_unlock(&fmu->mutex_fmu);
}

SetEvent(fmu->mutex_fmu);
thread_mutex_unlock(&fmu->mutex_fmu);
return 0;
}

Expand Down Expand Up @@ -133,7 +136,7 @@ static void fs_make_path(char* buffer, size_t len, ...) {


/**
* Specific: FMI2.0 and Windows
* Specific: FMI2.0
*/
int fmu_load_from_directory(container_t *container, int i, const char *directory, char *identifier, const char *guid) {
if (! container)
Expand Down Expand Up @@ -168,13 +171,10 @@ int fmu_load_from_directory(container_t *container, int i, const char *directory
else
fmu->profile = NULL;

fmu->mutex_fmu = CreateEventA(NULL, FALSE, FALSE, NULL);
fmu->mutex_container = CreateEventA(NULL, FALSE, FALSE, NULL);
fmu->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)fmu_do_step_thread, fmu, 0, NULL); /* Thread should be create _after_ mutexes */
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
SetThreadPriority(fmu->thread, THREAD_PRIORITY_HIGHEST);
SetThreadPriority(fmu->thread, THREAD_PRIORITY_TIME_CRITICAL); /* Try RT ! */

fmu->mutex_fmu = thread_mutex_new();
fmu->mutex_container = thread_mutex_new();
fmu->thread = thread_new((thread_function_t)fmu_do_step_thread, fmu);

return 0;
}

Expand All @@ -183,14 +183,22 @@ void fmu_unload(fmu_t *fmu) {

/* Stop the thread */
fmu->cancel = 1;
SetEvent(fmu->mutex_container);
WaitForSingleObject(fmu->mutex_fmu, INFINITE);
thread_mutex_unlock(&fmu->mutex_container);
thread_mutex_lock(&fmu->mutex_fmu);
#ifdef WIN32
WaitForSingleObject(fmu->thread, INFINITE);
#else
pthread_join(fmu->thread, NULL);
#endif


/* Free resources linked to threading */
#ifdef WIN32
CloseHandle(fmu->thread);
CloseHandle(fmu->mutex_fmu);
CloseHandle(fmu->mutex_container);
#endif

thread_mutex_free(&fmu->mutex_fmu);
thread_mutex_free(&fmu->mutex_container);

free(fmu->guid);
free(fmu->identifier);
Expand Down Expand Up @@ -286,7 +294,7 @@ fmi2Status fmuInstantiate(fmu_t *fmu,
fmi2Boolean loggingOn) {

fmu->fmi_callback_functions.componentEnvironment = fmu;
fmu->fmi_callback_functions.logger = logger_embedded_fmu;
fmu->fmi_callback_functions.logger = (fmi2CallbackLogger)logger_embedded_fmu;
fmu->fmi_callback_functions.allocateMemory = fmu->container->callback_functions->allocateMemory;
fmu->fmi_callback_functions.freeMemory = fmu->container->callback_functions->freeMemory;
fmu->fmi_callback_functions.stepFinished = NULL;
Expand Down
11 changes: 5 additions & 6 deletions container/fmu.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
#ifndef FMU_H
# define FMU_H

# include <windows.h>

# include "fmi2Functions.h"
# include "container.h"
# include "library.h"
# include "profile.h"
# include "thread.h"


/*----------------------------------------------------------------------------
Expand Down Expand Up @@ -137,7 +136,7 @@ typedef struct {
/*----------------------------------------------------------------------------
F M U _ T
----------------------------------------------------------------------------*/
#define FMU_PATH_MAX_LEN 4096
# define FMU_PATH_MAX_LEN 4096

typedef struct {
char *identifier;
Expand All @@ -150,9 +149,9 @@ typedef struct {
fmi2CallbackFunctions fmi_callback_functions;
fmu_interface_t fmi_functions;

HANDLE thread;
HANDLE mutex_fmu;
HANDLE mutex_container;
thread_t thread;
mutex_t mutex_fmu;
mutex_t mutex_container;

fmu_io_t fmu_io;

Expand Down
1 change: 1 addition & 0 deletions container/logger.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Expand Down
59 changes: 59 additions & 0 deletions container/thread.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include "thread.h"


thread_t thread_new(thread_function_t function, void *data) {
#ifdef WIN32
HANDLE thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)function, data, 0, NULL); /* Thread should be create _after_ mutexes */
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
SetThreadPriority(fmu->thread, THREAD_PRIORITY_HIGHEST);
SetThreadPriority(fmu->thread, THREAD_PRIORITY_TIME_CRITICAL); /* Try RT ! */
#else
pthread_t thread;
pthread_create(&thread, NULL, (void *(*)(void*))function, data);
#endif
return thread;
}


mutex_t thread_mutex_new(void) {
#ifdef WIN32
return CreateEventA(NULL, FALSE, FALSE, NULL);
#else
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
return mutex;
#endif
}


void thread_mutex_free(mutex_t *mutex) {
#ifdef WIN32
CloseHandle(*mutex);
#else
pthread_mutex_destroy(mutex);
#endif

return;
}


void thread_mutex_lock(mutex_t *mutex) {
#ifdef WIN32
WaitForSingleObject(*mutex, INFINITE);
#else
pthread_mutex_lock(mutex);
#endif

return;
}


void thread_mutex_unlock(mutex_t *mutex) {
#ifdef WIN32
SetEvent(*mutex);
#else
pthread_mutex_unlock(mutex);
#endif

return;
}
Loading

0 comments on commit 18bd181

Please sign in to comment.