improve multi-threading support from C-interface. Still not quite there.

This commit is contained in:
Vitor Santos Costa 2012-12-11 22:07:10 +00:00
parent ac74c9e3de
commit e41f821d67
11 changed files with 126 additions and 79 deletions

View File

@ -3071,7 +3071,7 @@ YAP_Init(YAP_init_args *yap_init)
}
{ BACKUP_MACHINE_REGS();
Yap_InitYaamRegs();
Yap_InitYaamRegs( 0);
#if HAVE_MPE
Yap_InitMPE ();
@ -3111,7 +3111,7 @@ YAP_Init(YAP_init_args *yap_init)
In the SBA we cannot just happily inherit registers
from the other workers
*/
Yap_InitYaamRegs();
Yap_InitYaamRegs( 0);
#endif /* YAPOR_COPY || YAPOR_SBA */
#ifndef YAPOR_THREADS
Yap_InitPreAllocCodeSpace();
@ -3190,7 +3190,7 @@ YAP_Init(YAP_init_args *yap_init)
/* first, initialise the saved state */
Term t_goal = MkAtomTerm(AtomInitProlog);
YAP_RunGoalOnce(t_goal);
Yap_InitYaamRegs();
Yap_InitYaamRegs( 0 );
/* reset stacks */
return YAP_BOOT_FROM_SAVED_CODE;
} else {
@ -3224,7 +3224,7 @@ YAP_Init(YAP_init_args *yap_init)
goal = Yap_MkApplTerm(fgoal, 1, as);
YAP_RunGoalOnce(goal);
/* reset stacks */
Yap_InitYaamRegs();
Yap_InitYaamRegs( 0 );
}
Yap_PutValue(Yap_FullLookupAtom("$live"), MkAtomTerm (Yap_FullLookupAtom("$true")));
}
@ -3305,13 +3305,13 @@ YAP_Reset(void)
if (Yap_exec_absmi(0) != 0) {
GLOBAL_Initialised = TRUE;
Yap_InitYaamRegs();
Yap_InitYaamRegs( worker_id );
RECOVER_MACHINE_REGS();
return FALSE;
}
}
/* reinitialise the engine */
Yap_InitYaamRegs();
Yap_InitYaamRegs( worker_id );
GLOBAL_Initialised = TRUE;
RECOVER_MACHINE_REGS();

View File

@ -1715,18 +1715,22 @@ p_generate_pred_info( USES_REGS1 ) {
}
void
Yap_InitYaamRegs(void)
Yap_InitYaamRegs( int myworker_id )
{
CACHE_REGS
Term h0var;
#if PUSH_REGS
/* Guarantee that after a longjmp we go back to the original abstract
machine registers */
#ifdef THREADS
int myworker_id = worker_id;
pthread_setspecific(Yap_yaamregs_key, (const void *)REMOTE_ThreadHandle(myworker_id).default_yaam_regs);
REMOTE_ThreadHandle(myworker_id).current_yaam_regs = REMOTE_ThreadHandle(myworker_id).default_yaam_regs;
worker_id = myworker_id; /* ricroc: for what I understand, this shouldn't be necessary */
CACHE_REGS
int wid = worker_id;
if (wid != myworker_id) {
pthread_setspecific(Yap_yaamregs_key, (const void *)REMOTE_ThreadHandle(myworker_id).default_yaam_regs);
REFRESH_CACHE_REGS
REMOTE_ThreadHandle(myworker_id).current_yaam_regs = REMOTE_ThreadHandle(myworker_id).default_yaam_regs;
worker_id = myworker_id;
}
/* may be run by worker_id on behalf on myworker_id */
#else
Yap_regp = &Yap_standard_regs;
#endif
@ -1734,12 +1738,10 @@ Yap_InitYaamRegs(void)
Yap_ResetExceptionTerm ();
Yap_PutValue (AtomBreak, MkIntTerm (0));
TR = (tr_fr_ptr)LOCAL_TrailBase;
if (Yap_AttsSize > (LOCAL_LocalBase-LOCAL_GlobalBase)/8)
Yap_AttsSize = (LOCAL_LocalBase-LOCAL_GlobalBase)/8;
H = H0 = ((CELL *) LOCAL_GlobalBase)+ Yap_AttsSize/sizeof(CELL);
H = H0 = ((CELL *) REMOTE_GlobalBase(wid));
RESET_VARIABLE(H0-1);
LCL0 = ASP = (CELL *) LOCAL_LocalBase;
CurrentTrailTop = (tr_fr_ptr)(LOCAL_TrailTop-MinTrailGap);
LCL0 = ASP = (CELL *) REMOTE_LocalBase(wid);
CurrentTrailTop = (tr_fr_ptr)(REMOTE_TrailTop(wid)-MinTrailGap);
/* notice that an initial choice-point and environment
*must* be created since for the garbage collector to work */
B = NULL;
@ -1754,27 +1756,27 @@ Yap_InitYaamRegs(void)
#ifdef YAPOR_SBA
BSEG =
#endif /* YAPOR_SBA */
BBREG = B_FZ = (choiceptr) LOCAL_LocalBase;
TR = TR_FZ = (tr_fr_ptr) LOCAL_TrailBase;
BBREG = B_FZ = (choiceptr) REMOTE_LocalBase(wid);
TR = TR_FZ = (tr_fr_ptr) REMOTE_TrailBase(wid);
#endif /* FROZEN_STACKS */
LOCK(LOCAL_SignalLock);
LOCK(REMOTE_SignalLock(wid));
CreepFlag = CalculateStackGap();
UNLOCK(LOCAL_SignalLock);
UNLOCK(REMOTE_SignalLock(wid));
EX = NULL;
init_stack(0, NULL, TRUE, NULL PASS_REGS);
/* the first real choice-point will also have AP=FAIL */
/* always have an empty slots for people to use */
CurSlot = 0;
Yap_StartSlots( PASS_REGS1 );
LOCAL_GlobalArena = TermNil;
REMOTE_GlobalArena(wid) = TermNil;
h0var = MkVarTerm();
#if COROUTINING
LOCAL_WokenGoals = Yap_NewTimedVar(TermNil);
LOCAL_AttsMutableList = Yap_NewTimedVar(h0var);
REMOTE_WokenGoals(wid) = Yap_NewTimedVar(TermNil);
REMOTE_AttsMutableList(wid) = Yap_NewTimedVar(h0var);
#endif
LOCAL_GcGeneration = Yap_NewTimedVar(h0var);
LOCAL_GcCurrentPhase = 0L;
LOCAL_GcPhase = Yap_NewTimedVar(MkIntTerm(LOCAL_GcCurrentPhase));
REMOTE_GcGeneration(wid) = Yap_NewTimedVar(h0var);
REMOTE_GcCurrentPhase(wid) = 0L;
REMOTE_GcPhase(wid) = Yap_NewTimedVar(MkIntTerm(REMOTE_GcCurrentPhase(wid)));
#if defined(YAPOR) || defined(THREADS)
PP = NULL;
PREG_ADDR = NULL;
@ -1789,8 +1791,14 @@ Yap_InitYaamRegs(void)
#endif
#ifdef TABLING
/* ensure that LOCAL_top_dep_fr is always valid */
if (LOCAL_top_dep_fr)
DepFr_cons_cp(LOCAL_top_dep_fr) = NORM_CP(B);
if (REMOTE_top_dep_fr(wid))
DepFr_cons_cp(REMOTE_top_dep_fr(wid)) = NORM_CP(B);
#endif
#ifdef THREADS
worker_id = wid;
if (myworker_id != worker_id) {
pthread_setspecific(Yap_yaamregs_key, (const void *)REMOTE_ThreadHandle(worker_id).default_yaam_regs);
}
#endif
}

View File

@ -1157,6 +1157,7 @@ InitFirstWorkerThreadHandle(void)
pthread_mutex_init(&REMOTE_ThreadHandle(0).tlock, NULL);
pthread_mutex_init(&REMOTE_ThreadHandle(0).tlock_status, NULL);
LOCAL_ThreadHandle.tdetach = MkAtomTerm(AtomFalse);
LOCAL_ThreadHandle.ref_count = 1;
#endif
}
@ -1314,7 +1315,7 @@ Yap_InitWorkspace(UInt Heap, UInt Stack, UInt Trail, UInt Atts, UInt max_table_s
#endif /* YAPOR || TABLING */
Yap_AttsSize = Atts;
Yap_InitTime();
Yap_InitTime( 0 );
/* InitAbsmi must be done before InitCodes */
/* This must be done before initialising predicates */
for (i = 0; i <= NUMBER_OF_YAP_FLAGS; i++) {

View File

@ -1008,7 +1008,7 @@ ReInitProlog(void)
#if defined(YAPOR) || defined(TABLING)
Yap_init_root_frames();
#endif /* YAPOR || TABLING */
Yap_InitYaamRegs();
Yap_InitYaamRegs( 0 );
YAP_RunGoalOnce(t);
}

View File

@ -1781,7 +1781,7 @@ Restore(char *s, char *lib_dir USES_REGS)
break;
case DO_ONLY_CODE:
UnmarkTrEntries( PASS_REGS1 );
Yap_InitYaamRegs();
Yap_InitYaamRegs( 0 );
break;
}

View File

@ -90,7 +90,7 @@ static char SccsId[] = "%W% %G%";
#endif
STATIC_PROTO (void InitTime, (void));
STATIC_PROTO (void InitTime, (int));
STATIC_PROTO (void InitWTime, (void));
STATIC_PROTO (Int p_sh, ( USES_REGS1 ));
STATIC_PROTO (Int p_shell, ( USES_REGS1 ));
@ -335,32 +335,60 @@ bla bla
#define StartOfTimes (*(LOCAL_ThreadHandle.start_of_timesp))
#define last_time (*(LOCAL_ThreadHandle.last_timep))
#define StartOfTimes_sys (*(LOCAL_ThreadHandle.start_of_times_sysp))
#define last_time_sys (*(LOCAL_ThreadHandle.last_time_sysp))
#else
/* since the point YAP was started */
static struct timeval StartOfTimes;
/* since last call to runtime */
static struct timeval last_time;
#endif
/* same for system time */
static struct timeval last_time_sys;
static struct timeval StartOfTimes_sys;
#endif
/* store user time in this variable */
static void
InitTime (void)
InitTime (int wid)
{
CACHE_REGS
struct rusage rusage;
#if THREADS
LOCAL_ThreadHandle.start_of_timesp = (struct timeval *)malloc(sizeof(struct timeval));
LOCAL_ThreadHandle.last_timep = (struct timeval *)malloc(sizeof(struct timeval));
#endif
REMOTE_ThreadHandle(wid).start_of_timesp = (struct timeval *)malloc(sizeof(struct timeval));
REMOTE_ThreadHandle(wid).last_timep = (struct timeval *)malloc(sizeof(struct timeval));
REMOTE_ThreadHandle(wid).start_of_times_sysp = (struct timeval *)malloc(sizeof(struct timeval));
REMOTE_ThreadHandle(wid).last_time_sysp = (struct timeval *)malloc(sizeof(struct timeval));
getrusage(RUSAGE_SELF, &rusage);
last_time.tv_sec = StartOfTimes.tv_sec = rusage.ru_utime.tv_sec;
last_time.tv_usec = StartOfTimes.tv_usec = rusage.ru_utime.tv_usec;
last_time_sys.tv_sec = StartOfTimes_sys.tv_sec = rusage.ru_stime.tv_sec;
last_time_sys.tv_usec = StartOfTimes_sys.tv_usec = rusage.ru_stime.tv_usec;
(*REMOTE_ThreadHandle(wid).last_timep).tv_sec =
(*REMOTE_ThreadHandle(wid).start_of_timesp).tv_sec =
rusage.ru_utime.tv_sec;
(*REMOTE_ThreadHandle(wid).last_timep).tv_usec =
(*REMOTE_ThreadHandle(wid).start_of_timesp).tv_usec =
rusage.ru_utime.tv_usec;
(*REMOTE_ThreadHandle(wid).last_time_sysp).tv_sec =
(*REMOTE_ThreadHandle(wid).start_of_times_sysp).tv_sec =
rusage.ru_stime.tv_sec;
(*REMOTE_ThreadHandle(wid).last_time_sysp).tv_usec =
(*REMOTE_ThreadHandle(wid).start_of_times_sysp).tv_usec =
rusage.ru_stime.tv_usec;
#else
getrusage(RUSAGE_SELF, &rusage);
last_time.tv_sec =
start_of_times.tv_sec =
rusage.ru_utime.tv_sec;
last_time.tv_usec =
start_of_times.tv_usec =
rusage.ru_utime.tv_usec;
last_time_sys.tv_sec =
start_of_times_sys.tv_sec =
rusage.ru_stime.tv_sec;
last_time_sys.tv_usec =
start_of_times_sys.tv_usec =
rusage.ru_stime.tv_usec;
#endif
}
@ -391,6 +419,7 @@ void Yap_cputime_interval(Int *now,Int *interval)
void Yap_systime_interval(Int *now,Int *interval)
{
CACHE_REGS
struct rusage rusage;
getrusage(RUSAGE_SELF, &rusage);
@ -437,7 +466,7 @@ static clock_t TimesStartOfTimes, Times_last_time;
/* store user time in this variable */
static void
InitTime (void)
InitTime (int)
{
HANDLE hProcess = GetCurrentProcess();
FILETIME CreationTime, ExitTime, KernelTime, UserTime;
@ -447,14 +476,22 @@ InitTime (void)
t = clock ();
Times_last_time = TimesStartOfTimes = t;
} else {
last_time.dwLowDateTime = UserTime.dwLowDateTime;
last_time.dwHighDateTime = UserTime.dwHighDateTime;
StartOfTimes.dwLowDateTime = UserTime.dwLowDateTime;
StartOfTimes.dwHighDateTime = UserTime.dwHighDateTime;
last_time_sys.dwLowDateTime = KernelTime.dwLowDateTime;
last_time_sys.dwHighDateTime = KernelTime.dwHighDateTime;
StartOfTimes_sys.dwLowDateTime = KernelTime.dwLowDateTime;
StartOfTimes_sys.dwHighDateTime = KernelTime.dwHighDateTime;
(*REMOTE_ThreadHandle(wid).last_timep).dwLowDateTime =
UserTime.dwLowDateTime;
(*REMOTE_ThreadHandle(wid).last_timep).dwHighDateTime =
UserTime.dwHighDateTime;
(*REMOTE_ThreadHandle(wid).start_of_timesp).dwLowDateTime =
UserTime.dwLowDateTime;
(*REMOTE_ThreadHandle(wid).start_of_timesp).dwHighDateTime =
UserTime.dwHighDateTime;
(*REMOTE_ThreadHandle(wid).last_time_sysp).dwLowDateTime =
KernelTime.dwLowDateTime;
(*REMOTE_ThreadHandle(wid).last_time_sysp).dwHighDateTime =
KernelTime.dwHighDateTime;
(*REMOTE_ThreadHandle(wid).start_of_times_sysp).dwLowDateTime =
KernelTime.dwLowDateTime;
(*REMOTE_ThreadHandle(wid).start_of_times_sysp).dwHighDateTime =
KernelTime.dwHighDateTime;
}
}
@ -604,7 +641,7 @@ InitTime (void)
{
struct tms t;
times (&t);
last_time = StartOfTimes = t.tms_utime;
(*REMOTE_ThreadHandle(wid).last_timep) = StartOfTimes = t.tms_utime;
last_time_sys = StartOfTimes_sys = t.tms_stime;
}
@ -648,13 +685,13 @@ static struct timeval last_time;
/* store user time in this variable */
static void
InitTime (void)
InitTime (int wid)
{
struct timeval tp;
gettimeofday(&tp,NULL);
last_time.tv_sec = StartOfTimes.tv_sec = tp.tv_sec;
last_time.tv_usec = StartOfTimes.tv_usec = tp.tv_usec;
(*REMOTE_ThreadHandle(wid).last_timep).tv_sec = (*REMOTE_ThreadHandle.start_of_timesp(wid)).tv_sec = tp.tv_sec;
(*REMOTE_ThreadHandle(wid).last_timep).tv_usec = (*REMOTE_ThreadHandle.start_of_timesp(wid)).tv_usec = tp.tv_usec;
}
@ -2730,9 +2767,9 @@ Yap_InitSysbits (void)
}
void
Yap_InitTime(void)
Yap_InitTime( int wid )
{
InitTime();
InitTime( wid );
}
void

View File

@ -237,8 +237,8 @@ setup_engine(int myworker_id, int init_thread)
LOCAL = REMOTE(worker_id);
Yap_InitExStacks(REMOTE_ThreadHandle(myworker_id).tsize, REMOTE_ThreadHandle(myworker_id).ssize);
CurrentModule = REMOTE_ThreadHandle(myworker_id).cmod;
Yap_InitTime();
Yap_InitYaamRegs();
Yap_InitTime( myworker_id );
Yap_InitYaamRegs( myworker_id );
Yap_ReleasePreAllocCodeSpace(Yap_PreAllocCodeSpace());
/* I exist */
GLOBAL_NOfThreadsCreated++;
@ -246,7 +246,7 @@ setup_engine(int myworker_id, int init_thread)
DEBUG_TLOCK_ACCESS(2, myworker_id);
pthread_mutex_unlock(&(REMOTE_ThreadHandle(myworker_id).tlock));
#ifdef TABLING
new_dependency_frame(LOCAL_top_dep_fr, FALSE, NULL, NULL, B, NULL, FALSE, NULL); /* same as in Yap_init_root_frames() */
new_dependency_frame(REMOTE_top_dep_fr(myworker_id), FALSE, NULL, NULL, B, NULL, FALSE, NULL); /* same as in Yap_init_root_frames() */
#endif /* TABLING */
return TRUE;
}
@ -456,8 +456,9 @@ Yap_thread_create_engine(thread_attr *ops)
Term t = TermNil;
/*
ok, this creates a problem, because we are initializing an engine from some "empty" thread.
We need first to foool the thread into believing it is the main thread
ok, this creates a problem, because we are initializing an engine from
some "empty" thread.
We need first to fool the thread into believing it is the main thread
*/
if (new_id == -1) {
/* YAP ERROR */

View File

@ -83,6 +83,7 @@ INLINE_ONLY inline EXTERN void restore_B(void);
INLINE_ONLY inline EXTERN void save_B(void);
#define CACHE_REGS
#define REFRESH_CACHE_REGS
#define INIT_REGS
#define PASS_REGS1
#define PASS_REGS
@ -182,12 +183,14 @@ extern Term Yap_XREGS[MaxTemps]; /* 29 */
extern pthread_key_t Yap_yaamregs_key;
#undef CACHE_REGS
#undef REFRESH_CACHE_REGS
#undef INIT_REGS
#undef PASS_REGS
#undef PASS_REGS1
#undef USES_REGS
#undef USES_REGS1
#define CACHE_REGS REGSTORE *regcache = ((REGSTORE *)pthread_getspecific(Yap_yaamregs_key));
#define REFRESH_CACHE_REGS regcache = ((REGSTORE *)pthread_getspecific(Yap_yaamregs_key));
#define INIT_REGS , ((REGSTORE *)pthread_getspecific(Yap_yaamregs_key))
#define PASS_REGS1 regcache
#define PASS_REGS , regcache

View File

@ -749,6 +749,8 @@ typedef struct thandle {
#if HAVE_GETRUSAGE||defined(_WIN32)
struct timeval *start_of_timesp;
struct timeval *last_timep;
struct timeval *start_of_times_sysp;
struct timeval *last_time_sysp;
#endif
} yap_thandle;
#endif /* THREADS */

View File

@ -248,7 +248,7 @@ void STD_PROTO(Yap_KillStacks,(int));
#else
void STD_PROTO(Yap_KillStacks,(int));
#endif
void STD_PROTO(Yap_InitYaamRegs,(void));
void STD_PROTO(Yap_InitYaamRegs,(int));
void STD_PROTO(Yap_ReInitWallTime, (void));
int STD_PROTO(Yap_OpDec,(int,char *,Atom,Term));
void STD_PROTO(Yap_CloseScratchPad,(void));
@ -360,7 +360,7 @@ void STD_PROTO(Yap_systime_interval,(Int *,Int *));
void STD_PROTO(Yap_walltime_interval,(Int *,Int *));
void STD_PROTO(Yap_InitSysbits,(void));
void STD_PROTO(Yap_InitSysPreds,(void));
void STD_PROTO(Yap_InitTime,(void));
void STD_PROTO(Yap_InitTime,(int));
int STD_PROTO(Yap_TrueFileName, (char *, char *, int));
double STD_PROTO(Yap_random, (void));
#ifdef _WIN32

View File

@ -2545,6 +2545,7 @@ X_API PL_engine_t
PL_create_engine(const PL_thread_attr_t *attr)
{
#if THREADS
int eng;
if (attr) {
YAP_thread_attr yapt;
@ -2552,13 +2553,15 @@ PL_create_engine(const PL_thread_attr_t *attr)
yapt.tsize = attr->global_size;
yapt.alias = (YAP_Term)attr->alias;
yapt.cancel = attr->cancel;
return Yap_local+YAP_ThreadCreateEngine(&yapt);
eng = YAP_ThreadCreateEngine(&yapt);
} else {
return Yap_local+YAP_ThreadCreateEngine(NULL);
eng = YAP_ThreadCreateEngine(NULL);
}
#else
return NULL;
if (eng >= 0)
return Yap_local[eng];
#endif
return NULL;
}
@ -2578,7 +2581,6 @@ PL_set_engine(PL_engine_t engine, PL_engine_t *old)
CACHE_REGS
#if THREADS
int cwid = PL_thread_self(), nwid;
if (cwid >= 0) {
if (old) *old = (PL_engine_t)(Yap_local[cwid]);
}
@ -2599,7 +2601,7 @@ PL_set_engine(PL_engine_t engine, PL_engine_t *old)
}
return PL_ENGINE_SET;
} else {
nwid = ((struct worker_local *)engine)->ThreadHandle_.current_yaam_regs->worker_id_;
nwid = ((struct worker_local *)engine)->ThreadHandle_.id;
}
pthread_mutex_lock(&(REMOTE_ThreadHandle(nwid).tlock));
@ -2610,13 +2612,6 @@ PL_set_engine(PL_engine_t engine, PL_engine_t *old)
}
return PL_ENGINE_SET;
}
if (cwid >= 0) {
if (!YAP_ThreadDetachEngine(cwid)) {
*old = NULL;
pthread_mutex_unlock(&(REMOTE_ThreadHandle(nwid).tlock));
return PL_ENGINE_INVAL;
}
}
if (!YAP_ThreadAttachEngine(nwid)) {
return PL_ENGINE_INVAL;
}