Skip to content

Commit

Permalink
#2332 Fix thread safety for MMC_TRY THROW and CATCH
Browse files Browse the repository at this point in the history
git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@17215 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
  • Loading branch information
sjoelund committed Sep 12, 2013
1 parent 1209179 commit ad8946e
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 24 deletions.
4 changes: 1 addition & 3 deletions Compiler/Template/CodegenC.tpl
Expand Up @@ -9834,9 +9834,7 @@ int rml_execution_failed(mmc_GC_local_state_type local_GC_state)

int main(int argc, char **argv)
{
init_metamodelica_segv_handler();
mmc_GC_init(mmc_GC_settings_default);
MMC_INIT();
{
mmc_GC_local_state_type local_GC_state = mmc_GC_save_roots_state("top"); /* push the first mark */
void *lst = mmc_mk_nil();
Expand Down
63 changes: 63 additions & 0 deletions Compiler/runtime/System_omc.c
Expand Up @@ -741,6 +741,7 @@ static int System_forkCallJoin(int *statuses, int *ids, int *numWorking, int *wo
}
}

#if 0
extern void* System_forkCall(int numThreads, void *dataLst, void (*fn)(void*))
{
#if defined(__MINGW32__) || defined(_MSC_VER)
Expand Down Expand Up @@ -795,6 +796,68 @@ extern void* System_forkCall(int numThreads, void *dataLst, void (*fn)(void*))
return result;
#endif
}
#else
/* Work in progress: Threading support in OMC */
typedef struct thread_data {
pthread_mutex_t mutex;
void (*fn)(void*);
int fail;
int current;
int len;
void **commands;
int *status;
} thread_data;

static void* System_forkCallThread(void *in)
{
int exitstatus = 1;
int n;
thread_data *data = (thread_data*) in;
while (1) {
pthread_mutex_lock(&data->mutex);
n = data->current++;
pthread_mutex_unlock(&data->mutex);
if (data->fail || data->current > data->len) break;
MMC_TRY()
data->fn(data->commands[n]);
exitstatus = 0;
MMC_CATCH()
data->status[n] = ! exitstatus;
}
return NULL;
}

extern void* System_forkCall(int numThreads, void *dataLst, void (*fn)(void*))
{
int len = listLength(dataLst), i;
void *commands[len];
int status[len], ids[len];
void *result = mmc_mk_nil();
pthread_t th[numThreads];
thread_data data;
pthread_mutex_init(&data.mutex,NULL);
data.fn = fn;
data.current = 0;
data.len = len;
data.commands = commands;
data.status = status;
data.fail = 0;
for (i=0; i<len; i++, dataLst = MMC_CDR(dataLst)) {
commands[i] = MMC_CAR(dataLst);
}
numThreads = min(numThreads,len);
for (i=0; i<numThreads; i++) {
GC_pthread_create(&th[i],NULL,System_forkCallThread,&data);
}
for (i=0; i<numThreads; i++) {
pthread_join(th[i], NULL);
}
for (i=len-1; i>=0; i--) {
result = mmc_mk_cons(mmc_mk_icon(status[i]), result);
}
return result;
}
#endif

#ifdef __cplusplus
}
Expand Down
2 changes: 1 addition & 1 deletion SimulationRuntime/c/meta/meta_modelica.c
Expand Up @@ -36,7 +36,7 @@
#include <stdlib.h>
#include <string.h>

jmp_buf *mmc_jumper;
pthread_key_t mmc_jumper;

/*
void* mmc_mk_rcon(double d)
Expand Down
29 changes: 9 additions & 20 deletions SimulationRuntime/c/meta/meta_modelica.h
Expand Up @@ -629,39 +629,28 @@ struct record_description {
#define mmc_unbox_array(X) (*((base_array_t*)X))

#include <setjmp.h>
#include <pthread.h>

void mmc_catch_dummy_fn();
#if 1
/* Use something like this if needed...
#define MMC_JMP_BUF_SIZE 8192
extern jmp_buf mmc_jumper[MMC_JMP_BUF_SIZE];
extern int jmp_buf_index;
*/
extern jmp_buf *mmc_jumper;
#define MMC_TRY_INTERNAL(X) { jmp_buf new_mmc_jumper, *old_jumper; old_jumper = X; X = &new_mmc_jumper; if (setjmp(new_mmc_jumper) == 0) {

extern pthread_key_t mmc_jumper;
#define MMC_INIT() pthread_key_create(&mmc_jumper,NULL);init_metamodelica_segv_handler();mmc_GC_init(mmc_GC_settings_default);
#define MMC_TRY_INTERNAL(X) { jmp_buf new_mmc_jumper, *old_jumper; old_jumper = (jmp_buf*)pthread_getspecific(X); pthread_setspecific(X,&new_mmc_jumper); if (setjmp(new_mmc_jumper) == 0) {
#define MMC_TRY() MMC_TRY_INTERNAL(mmc_jumper)

#if !defined(_MSC_VER)
#define MMC_CATCH_INTERNAL(X) } X = old_jumper; mmc_GC_unwind_roots_state(mmc_GC_local_state); mmc_catch_dummy_fn();}
#define MMC_CATCH_INTERNAL(X) } pthread_setspecific(X,old_jumper);mmc_catch_dummy_fn();}
#else
#define MMC_CATCH_INTERNAL(X) } X = old_jumper; mmc_GC_unwind_roots_state(mmc_GC_local_state);}
#define MMC_CATCH_INTERNAL(X) } pthread_setspecific(X,old_jumper);}
#endif
#define MMC_CATCH() MMC_CATCH_INTERNAL(mmc_jumper)

#define MMC_THROW() longjmp(*mmc_jumper,1)
#define MMC_THROW() {longjmp(*((jmp_buf*)pthread_getspecific(mmc_jumper)),1);}
#define MMC_ELSE() } else {

#define MMC_TRY_TOP() MMC_TRY()
#define MMC_CATCH_TOP(X) mmc_jumper = old_jumper;} else {mmc_jumper = old_jumper;mmc_GC_unwind_roots_state(mmc_GC_local_state);X;}}

#else
/* Old C++ try/catch/throw implementation */
#define MMC_TRY() try {
#define MMC_CATCH() } catch (...) {}
#define MMC_THROW() throw 1

#define MMC_TRY_TOP() try{
#define MMC_CATCH_TOP(X) } catch (...) {X;}
#define MMC_CATCH_TOP(X) pthread_setspecific(mmc_jumper,old_jumper);} else {pthread_setspecific(mmc_jumper,old_jumper);X;}}

#endif

Expand Down

0 comments on commit ad8946e

Please sign in to comment.