Browse Source

new command bg_ctrl initializing the .control executing thread

pthreads: using detached threads only
keep controls during 'reset', delete only upon 'quit'
pre-master-46
Holger Vogt 7 years ago
parent
commit
0828a8e706
  1. 6
      src/frontend/misccoms.c
  2. 7
      src/frontend/runcoms2.c
  3. 66
      src/sharedspice.c

6
src/frontend/misccoms.c

@ -32,6 +32,10 @@ extern char history_file[];
extern char history_file[];
#endif
#ifdef SHARED_MODULE
extern void rem_controls(void);
#endif
extern IFsimulator SIMinfo;
extern void spice_destroy_devices(void); /* FIXME need a better place */
static void byemesg(void);
@ -76,6 +80,8 @@ com_quit(wordlist *wl)
cp_remvar("prompt");
}
rem_controls();
/* Destroy CKT when quit. */
if (!ft_nutmeg) {
while(ft_curckt)

7
src/frontend/runcoms2.c

@ -30,7 +30,9 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
extern void line_free_x(struct card *deck, bool recurse);
extern INPmodel *modtab;
extern void com_mc_source(wordlist *wl);
#ifdef SHARED_MODULE
extern void exec_controls(wordlist *newcontrols);
#endif
#define line_free(line, flag) \
do { \
@ -176,6 +178,9 @@ com_rset(wordlist *wl)
return;
}
com_remcirc(NULL);
#ifdef SHARED_MODULE
exec_controls(NULL);
#endif
inp_source_recent();
#else
struct variable *v, *next;

66
src/sharedspice.c

@ -1,4 +1,4 @@
/* Copyright 2013 Holger Vogt
/* Copyright 2013 - 2018 Holger Vogt
*
* Modified BSD license
*/
@ -22,6 +22,25 @@
via a new thread. Delays may occur. */
#define low_latency
/************* About threads in sharedspice.c *************************
If the calling (main) thread loads a circuit, the .control section
commands in the input file are executed immediately by the calling
thread after the ciruit has been parsed and loaded.
Command bg_run from the calling thread then immediately starts the
background thread (id. tid) that issues the 'run' command to
start the simulation in this thread. The main thread returns to the
caller. .control commands typically are executed prematurely before
bg_run has returned.
If the flag 'set controlswait' is given in the .control section,
all commands following are assembled in the wordlist 'shcontrols',
a new thread is started (id: tid2) and suspended immediately. Only
when the background thread tid (and thus the simulation) is ready,
the tid2 thread is released and the .control commands are executed.
Before a repeated 'bg_run' is given, or after a 'reset', the command
'bg_ctrl' has to be sent by the caller to re-start and suspend the
thread tid2, using the still existing shcontrols.
*/
/**********************************************************************/
/* Header files for C functions */
/**********************************************************************/
@ -180,7 +199,8 @@ extern int SIMinit(IFfrontEnd *frontEnd, IFsimulator **simulator);
extern wordlist *cp_varwl(struct variable *var);
extern void create_circbyline(char *line);
void exec_controls(wordlist *controls);
void exec_controls(wordlist *shcontrols);
void rem_controls(void);
/*The current run (to get variable names, etc)*/
static runDesc *cur_run;
@ -249,6 +269,7 @@ static SendInitEvtData* sendinitevt;
static SendEvtData* sendevt;
#endif
static void* euserptr;
static wordlist *shcontrols;
// thread IDs
@ -312,6 +333,8 @@ _cthread_run(void *controls)
{
wordlist *wl;
#ifdef HAVE_LIBPTHREAD
if (!cont_condition)
printf("Prepared to start controls after bg_run has finished\n");
pthread_mutex_lock(&triggerMutex);
while (!cont_condition)
pthread_cond_wait(&cond, &triggerMutex);
@ -320,7 +343,7 @@ _cthread_run(void *controls)
for (wl = controls; wl; wl = wl->wl_next)
cp_evloop(wl->wl_word);
wl_free(controls);
#ifdef HAVE_LIBPTHREAD
cont_condition = FALSE;
#endif
@ -410,27 +433,43 @@ sighandler_sharedspice(int num)
#endif /*THREADS*/
/* create a suspended thread tid2 that is activated when bg_run has finished.
It executes the .control commands. If the arguemnt is NULL, the thread is
stated with the existing controls (e.g. for command 'reset'. */
void
exec_controls(wordlist *controls)
exec_controls(wordlist *newcontrols)
{
if (newcontrols) {
if (shcontrols)
wl_free(shcontrols);
shcontrols = newcontrols;
}
#ifdef THREADS
#ifdef HAVE_LIBPTHREAD
cont_condition = FALSE;
usleep(20000); /* wait a little */
pthread_create(&tid2, NULL, (void * (*)(void *))_cthread_run, (void *)controls);
pthread_create(&tid2, NULL, (void * (*)(void *))_cthread_run, (void *)shcontrols);
pthread_detach(tid2); /* automatically release the memory after thread has finished */
#elif defined _MSC_VER || defined __MINGW32__
tid2 = (HANDLE)_beginthreadex(NULL, 0, (unsigned int(__stdcall *)(void *))_cthread_run,
(void*)controls, CREATE_SUSPENDED, NULL);
(void*)shcontrols, CREATE_SUSPENDED, NULL);
#else
tid2 = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)_cthread_run, (void*)controls,
tid2 = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)_cthread_run, (void*)shcontrols,
0, NULL);
#endif
#else
wordlist *wl;
for (wl = controls; wl; wl = wl->wl_next)
for (wl = shcontrols; wl; wl = wl->wl_next)
cp_evloop(wl->wl_word);
#endif
}
/* free controls after 'quit' */
void rem_controls(void)
{
wl_free(shcontrols);
}
/* run a ngspice command */
static int
@ -446,7 +485,8 @@ runc(char* command)
bool fl_bg = FALSE;
command_id = threadid_self();
/* run task in background if command is preceeded by "bg_" */
if (!cieq("bg_halt", command) && !cieq("bg_pstop", command) && ciprefix("bg_", command)) {
if (!cieq("bg_halt", command) && !cieq("bg_pstop", command)
&& !cieq("bg_ctrl", command) && ciprefix("bg_", command)) {
strncpy(buf, command+3, 1024);
fl_bg = TRUE;
}
@ -503,6 +543,7 @@ runc(char* command)
string = copy(buf); /*as buf gets freed fairly quickly*/
#ifdef HAVE_LIBPTHREAD
pthread_create(&tid, NULL, (void * (*)(void *))_thread_run, (void *)string);
pthread_detach(tid);
#elif defined _MSC_VER || defined __MINGW32__
tid = (HANDLE)_beginthreadex(NULL, 0, (unsigned int (__stdcall *)(void *))_thread_run,
(void*)string, 0, NULL);
@ -515,6 +556,13 @@ runc(char* command)
if (!strcmp(buf, "bg_halt")) {
signal(SIGINT, oldHandler);
return _thread_stop();
/* bg_ctrl prepare running the controls after bg_run */
} else if (!strcmp(buf, "bg_ctrl")) {
if (shcontrols)
exec_controls(wl_copy(shcontrols));
else
fprintf(stderr, "Warning: No .control commands available, bg_ctrl skipped\n");
return 0;
} else
/* cannot do anything if ngspice is running in the bg*/
if (fl_running) {

Loading…
Cancel
Save