static int setup_engine(int myworker_id, int init_thread) { CACHE_REGS REGSTORE *standard_regs; standard_regs = (REGSTORE *)calloc(1,sizeof(REGSTORE)); if (!standard_regs) return FALSE; regcache = standard_regs; /* create the YAAM descriptor */ REMOTE_ThreadHandle(myworker_id).default_yaam_regs = standard_regs; Yap_InitExStacks(myworker_id, REMOTE_ThreadHandle(myworker_id).tsize, REMOTE_ThreadHandle(myworker_id).ssize); CurrentModule = REMOTE_ThreadHandle(myworker_id).cmod; Yap_InitTime( myworker_id ); Yap_InitYaamRegs( myworker_id ); REFRESH_CACHE_REGS Yap_ReleasePreAllocCodeSpace(Yap_PreAllocCodeSpace()); /* I exist */ GLOBAL_NOfThreadsCreated++; GLOBAL_NOfThreads++; DEBUG_TLOCK_ACCESS(2, myworker_id); pthread_mutex_unlock(&(REMOTE_ThreadHandle(myworker_id).tlock)); #ifdef TABLING 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; }
/* store user time in this variable */ static void InitTime(int wid) { struct timeval tp; gettimeofday(&tp, NULL); (*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; }
static void InitThreadHandle(int wid) { REMOTE_ThreadHandle(wid).in_use = FALSE; REMOTE_ThreadHandle(wid).zombie = FALSE; REMOTE_ThreadHandle(wid).local_preds = NULL; #ifdef LOW_LEVEL_TRACER REMOTE_ThreadHandle(wid).thread_inst_count = 0LL; #endif pthread_mutex_init(&(REMOTE_ThreadHandle(wid).tlock), NULL); pthread_mutex_init(&(REMOTE_ThreadHandle(wid).tlock_status), NULL); REMOTE_ThreadHandle(wid).tdetach = (CELL)0; REMOTE_ThreadHandle(wid).cmod = (CELL)0; { mbox_t *mboxp = &REMOTE_ThreadHandle(wid).mbox_handle; pthread_mutex_t *mutexp; pthread_cond_t *condp; struct idb_queue *msgsp; mboxp->name = MkIntTerm(0); condp = &mboxp->cond; pthread_cond_init(condp, NULL); mutexp = &mboxp->mutex; pthread_mutex_init(mutexp, NULL); msgsp = &mboxp->msgs; mboxp->nmsgs = 0; mboxp->nclients = 0; mboxp->open = true; Yap_init_tqueue(msgsp); } }
int Yap_ThreadID( void ) { int new_worker_id = 0; pthread_t self = pthread_self(); while(new_worker_id < MAX_THREADS && Yap_local[new_worker_id] && (REMOTE_ThreadHandle(new_worker_id).in_use == TRUE || REMOTE_ThreadHandle(new_worker_id).zombie == TRUE) ) { if (pthread_equal(self , REMOTE_ThreadHandle(new_worker_id).pthread_handle) ) { return new_worker_id; } new_worker_id++; } return -1; }
static void start_thread(int myworker_id) { CACHE_REGS pthread_setspecific(Yap_yaamregs_key, (void *)REMOTE_ThreadHandle(myworker_id).default_yaam_regs); REFRESH_CACHE_REGS; worker_id = myworker_id; LOCAL = REMOTE(myworker_id); }
int Yap_InitThread(int new_id) { struct worker_local *new_s; if (new_id) { if (!(new_s = (struct worker_local *)calloc(sizeof(struct worker_local), 1))) return FALSE; Yap_local[new_id] = new_s; if (!((REGSTORE *)pthread_getspecific(Yap_yaamregs_key))) { REGSTORE *rs = (REGSTORE *)calloc(sizeof(REGSTORE), 1); pthread_setspecific(Yap_yaamregs_key, (const void *)rs); REMOTE_ThreadHandle(new_id).default_yaam_regs = rs; REMOTE_ThreadHandle(new_id).current_yaam_regs = rs; rs->worker_id_ = new_id; rs->worker_local_ = REMOTE(new_id); } } InitWorker(new_id); return TRUE; }
static int allocate_new_tid(void) { int new_worker_id = 0; LOCK(GLOBAL_ThreadHandlesLock); while(new_worker_id < MAX_THREADS && Yap_local[new_worker_id] && (REMOTE_ThreadHandle(new_worker_id).in_use == TRUE || REMOTE_ThreadHandle(new_worker_id).zombie == TRUE) ) new_worker_id++; if (new_worker_id >= MAX_THREADS) { new_worker_id = -1; } else if (!Yap_local[new_worker_id]) { if (!Yap_InitThread(new_worker_id)) { UNLOCK(GLOBAL_ThreadHandlesLock); return -1; } MUTEX_LOCK(&(REMOTE_ThreadHandle(new_worker_id).tlock)); REMOTE_ThreadHandle(new_worker_id).in_use = TRUE; } else if (new_worker_id < MAX_THREADS) { // reuse existing thread MUTEX_LOCK(&(REMOTE_ThreadHandle(new_worker_id).tlock)); REMOTE_ThreadHandle(new_worker_id).in_use = TRUE; } else { new_worker_id = -1; } UNLOCK(GLOBAL_ThreadHandlesLock); return new_worker_id; }
static int allocate_new_tid(void) { int new_worker_id = 0; LOCK(GLOBAL_ThreadHandlesLock); while(new_worker_id < MAX_THREADS && Yap_local[new_worker_id] && (REMOTE_ThreadHandle(new_worker_id).in_use == TRUE || REMOTE_ThreadHandle(new_worker_id).zombie == TRUE) ) new_worker_id++; if (new_worker_id >= MAX_THREADS) { new_worker_id = -1; } else if (!Yap_local[new_worker_id]) { if (!Yap_InitThread(new_worker_id)) { return -1; } pthread_mutex_lock(&(REMOTE_ThreadHandle(new_worker_id).tlock)); DEBUG_TLOCK_ACCESS(new_worker_id, 0); REMOTE_ThreadHandle(new_worker_id).in_use = TRUE; } else if (new_worker_id < MAX_THREADS) { pthread_mutex_lock(&(REMOTE_ThreadHandle(new_worker_id).tlock)); DEBUG_TLOCK_ACCESS(new_worker_id, 0); REMOTE_ThreadHandle(new_worker_id).in_use = TRUE; } else { new_worker_id = -1; } UNLOCK(GLOBAL_ThreadHandlesLock); return new_worker_id; }
static void * thread_run(void *widp) { CACHE_REGS Term tgoal, t; Term tgs[2]; int myworker_id = *((int *)widp); #ifdef OUTPUT_THREADS_TABLING char thread_name[25]; char filename[YAP_FILENAME_MAX]; sprintf(thread_name, "/thread_output_%d", myworker_id); strcpy(filename, YAP_BINDIR); strncat(filename, thread_name, 25); REMOTE_thread_output(myworker_id) = fopen(filename, "w"); #endif /* OUTPUT_THREADS_TABLING */ start_thread(myworker_id); REFRESH_CACHE_REGS; do { t = tgs[0] = Yap_PopTermFromDB(LOCAL_ThreadHandle.tgoal); if (t == 0) { if (LOCAL_Error_TYPE == OUT_OF_ATTVARS_ERROR) { LOCAL_Error_TYPE = YAP_NO_ERROR; if (!Yap_growglobal(NULL)) { Yap_Error(OUT_OF_ATTVARS_ERROR, TermNil, LOCAL_ErrorMessage); thread_die(worker_id, FALSE); return NULL; } } else { LOCAL_Error_TYPE = YAP_NO_ERROR; if (!Yap_growstack(LOCAL_ThreadHandle.tgoal->NOfCells*CellSize)) { Yap_Error(OUT_OF_STACK_ERROR, TermNil, LOCAL_ErrorMessage); thread_die(worker_id, FALSE); return NULL; } } } } while (t == 0); REMOTE_ThreadHandle(myworker_id).tgoal = NULL; tgs[1] = LOCAL_ThreadHandle.tdetach; tgoal = Yap_MkApplTerm(FunctorThreadRun, 2, tgs); Yap_RunTopGoal(tgoal); thread_die(worker_id, FALSE); return NULL; }
static Int p_create_thread( USES_REGS1 ) { UInt ssize; UInt tsize; UInt sysize; Term x2 = Deref(ARG2); Term x3 = Deref(ARG3); Term x4 = Deref(ARG4); int new_worker_id = IntegerOfTerm(Deref(ARG7)), owid = worker_id; // fprintf(stderr," %d --> %d\n", worker_id, new_worker_id); if (IsBigIntTerm(x2)) return FALSE; if (IsBigIntTerm(x3)) return FALSE; ssize = IntegerOfTerm(x2); tsize = IntegerOfTerm(x3); sysize = IntegerOfTerm(x4); /* UInt systemsize = IntegerOfTerm(Deref(ARG4)); */ if (new_worker_id == -1) { /* YAP ERROR */ return FALSE; } /* make sure we can proceed */ if (!init_thread_engine(new_worker_id, ssize, tsize, sysize, &ARG1, &ARG5, &ARG6)) return FALSE; //REMOTE_ThreadHandle(new_worker_id).pthread_handle = 0L; REMOTE_ThreadHandle(new_worker_id).id = new_worker_id; REMOTE_ThreadHandle(new_worker_id).ref_count = 1; setup_engine(new_worker_id, FALSE); if ((REMOTE_ThreadHandle(new_worker_id).ret = pthread_create(&REMOTE_ThreadHandle(new_worker_id).pthread_handle, NULL, thread_run, (void *)(&(REMOTE_ThreadHandle(new_worker_id).id)))) == 0) { pthread_setspecific(Yap_yaamregs_key, (const void *)REMOTE_ThreadHandle(owid).current_yaam_regs); /* wait until the client is initialised */ return TRUE; } pthread_setspecific(Yap_yaamregs_key, (const void *)REMOTE_ThreadHandle(owid).current_yaam_regs); return FALSE; }
static int store_specs(int new_worker_id, UInt ssize, UInt tsize, UInt sysize, Term *tpgoal, Term *tpdetach, Term *tpexit) { CACHE_REGS UInt pm; /* memory to be requested */ Term tmod; Term tdetach, tgoal; if (tsize < MinTrailSpace) tsize = MinTrailSpace; if (ssize < MinStackSpace) ssize = MinStackSpace; REMOTE_ThreadHandle(new_worker_id).ssize = ssize; REMOTE_ThreadHandle(new_worker_id).tsize = tsize; REMOTE_ThreadHandle(new_worker_id).sysize = sysize; REMOTE_c_input_stream(new_worker_id) = LOCAL_c_input_stream; REMOTE_c_output_stream(new_worker_id) = LOCAL_c_output_stream; REMOTE_c_error_stream(new_worker_id) = LOCAL_c_error_stream; pm = (ssize + tsize)*1024; if (!(REMOTE_ThreadHandle(new_worker_id).stack_address = malloc(pm))) { return FALSE; } REMOTE_ThreadHandle(new_worker_id).tgoal = Yap_StoreTermInDB(Deref(*tpgoal),7); REMOTE_ThreadHandle(new_worker_id).cmod = CurrentModule; tdetach = Deref(*tpdetach); if (IsVarTerm(tdetach)){ REMOTE_ThreadHandle(new_worker_id).tdetach = MkAtomTerm(AtomFalse); } else { REMOTE_ThreadHandle(new_worker_id).tdetach = tdetach; } tgoal = Yap_StripModule(Deref(*tpexit), &tmod); REMOTE_ThreadHandle(new_worker_id).texit_mod = tmod; REMOTE_ThreadHandle(new_worker_id).texit = Yap_StoreTermInDB(tgoal,7); REMOTE_ThreadHandle(new_worker_id).local_preds = NULL; REMOTE_ThreadHandle(new_worker_id).start_of_timesp = NULL; REMOTE_ThreadHandle(new_worker_id).last_timep = NULL; REMOTE_ScratchPad(new_worker_id).ptr = NULL; return TRUE; }
static void kill_thread_engine (int wid, int always_die) { Prop p0 = AbsPredProp(REMOTE_ThreadHandle(wid).local_preds); GlobalEntry *gl = REMOTE_GlobalVariables(wid); REMOTE_ThreadHandle(wid).local_preds = NIL; REMOTE_GlobalVariables(wid) = NULL; /* kill all thread local preds */ while(p0) { PredEntry *ap = RepPredProp(p0); p0 = ap->NextOfPE; Yap_Abolish(ap); Yap_FreeCodeSpace((char *)ap); } while (gl) { gl->global = TermFoundVar; gl = gl->NextGE; } Yap_KillStacks(wid); REMOTE_ActiveSignals(wid) = 0L; if (REMOTE_ScratchPad(wid).ptr) free(REMOTE_ScratchPad(wid).ptr); REMOTE_ThreadHandle(wid).current_yaam_regs = NULL; if (REMOTE_ThreadHandle(wid).start_of_timesp) free(REMOTE_ThreadHandle(wid).start_of_timesp); if (REMOTE_ThreadHandle(wid).last_timep) free(REMOTE_ThreadHandle(wid).last_timep); if (REMOTE_ThreadHandle(wid).texit) { Yap_FreeCodeSpace((ADDR)REMOTE_ThreadHandle(wid).texit); } /* FreeCodeSpace requires LOCAL requires yaam_regs */ free(REMOTE_ThreadHandle(wid).default_yaam_regs); REMOTE_ThreadHandle(wid).default_yaam_regs = NULL; LOCK(GLOBAL_ThreadHandlesLock); if (REMOTE_ThreadHandle(wid).tdetach == MkAtomTerm(AtomTrue) || always_die) { REMOTE_ThreadHandle(wid).zombie = FALSE; REMOTE_ThreadHandle(wid).in_use = FALSE; DEBUG_TLOCK_ACCESS(1, wid); pthread_mutex_unlock(&(REMOTE_ThreadHandle(wid).tlock)); } UNLOCK(GLOBAL_ThreadHandlesLock); }
/* store user time in this variable */ void Yap_InitTime(int wid) { struct rusage rusage; #if THREADS 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); (*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 = 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; #endif }
/* store user time in this variable */ static void InitTime(void) { struct tms t; times(&t); (*REMOTE_ThreadHandle(wid).last_timep) = StartOfTimes = t.tms_utime; last_time_sys = StartOfTimes_sys = t.tms_stime; }
/* store user time in this variable */ void Yap_InitTime(int wid) { HANDLE hProcess = GetCurrentProcess(); FILETIME CreationTime, ExitTime, KernelTime, UserTime; if (!GetProcessTimes(hProcess, &CreationTime, &ExitTime, &KernelTime, &UserTime)) { /* WIN98 */ clock_t t; t = clock(); Times_last_time = TimesStartOfTimes = t; } else { #if THREADS REMOTE_ThreadHandle(wid).start_of_timesp = (struct _FILETIME *)malloc(sizeof(FILETIME)); REMOTE_ThreadHandle(wid).last_timep = (struct _FILETIME *)malloc(sizeof(FILETIME)); REMOTE_ThreadHandle(wid).start_of_times_sysp = (struct _FILETIME *)malloc(sizeof(FILETIME)); REMOTE_ThreadHandle(wid).last_time_sysp = (struct _FILETIME *)malloc(sizeof(FILETIME)); (*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; #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; #endif } }