18static char SccsId[] =
"%W% %G%";
40#include <sys/syscall.h>
43#include "tab.macros.h"
49 PL_BLOB_UNIQUE | PL_BLOB_NOCOPY,
58#if DEBUG_LOCKS||DEBUG_PE_LOCKS
60bool debug_locks =
true, debug_pe_locks =
true;
61static Int p_debug_locks( USES_REGS1 ) { debug_pe_locks = 1;
return TRUE; }
63static Int p_nodebug_locks( USES_REGS1 ) { debug_locks = 0; debug_pe_locks = 0;
return TRUE; }
76 int new_worker_id = 0;
77 pthread_t
self = pthread_self();
78 while(new_worker_id < MAX_THREADS &&
79 Yap_local[new_worker_id] &&
80 (REMOTE_ThreadHandle(new_worker_id).in_use == TRUE ||
81 REMOTE_ThreadHandle(new_worker_id).zombie == TRUE) ) {
82 if (pthread_equal(
self , REMOTE_ThreadHandle(new_worker_id).pthread_handle) ) {
93 return GLOBAL_NOfThreads;
99 int new_worker_id = 0;
100 LOCK(GLOBAL_ThreadHandlesLock);
101 while(new_worker_id < MAX_THREADS &&
102 Yap_local[new_worker_id] &&
103 (REMOTE_ThreadHandle(new_worker_id).in_use == TRUE ||
104 REMOTE_ThreadHandle(new_worker_id).zombie == TRUE) )
106 if (new_worker_id >= MAX_THREADS) {
108 }
else if (!Yap_local[new_worker_id]) {
109 if (!Yap_InitThread(new_worker_id)) {
110 UNLOCK(GLOBAL_ThreadHandlesLock);
113 MUTEX_LOCK(&(REMOTE_ThreadHandle(new_worker_id).tlock));
114 REMOTE_ThreadHandle(new_worker_id).in_use = TRUE;
115 }
else if (new_worker_id < MAX_THREADS) {
117 MUTEX_LOCK(&(REMOTE_ThreadHandle(new_worker_id).tlock));
118 REMOTE_ThreadHandle(new_worker_id).in_use = TRUE;
122 UNLOCK(GLOBAL_ThreadHandlesLock);
123 return new_worker_id;
128mboxCreate( Term namet, mbox_t *mboxp USES_REGS )
130 pthread_mutex_t *mutexp;
131 pthread_cond_t *condp;
134 memset(mboxp, 0,
sizeof(mbox_t));
135 condp = & mboxp->cond;
136 pthread_cond_init(condp, NULL);
137 mutexp = & mboxp->mutex;
138 pthread_mutex_init(mutexp, NULL);
139 msgsp = & mboxp->msgs;
142 Yap_init_tqueue(msgsp);
150mboxDestroy( mbox_t *mboxp USES_REGS )
152 pthread_mutex_t *mutexp = &mboxp->mutex;
153 pthread_cond_t *condp = &mboxp->cond;
156 if (mboxp->nclients == 0 ) {
157 pthread_cond_destroy(condp);
158 pthread_mutex_destroy(mutexp);
159 Yap_destroy_tqueue(msgsp PASS_REGS);
164 pthread_cond_broadcast(condp);
165 pthread_mutex_unlock(mutexp);
171mboxSend( mbox_t *mboxp, Term t USES_REGS )
173 pthread_mutex_t *mutexp = &mboxp->mutex;
174 pthread_cond_t *condp = &mboxp->cond;
181 Yap_enqueue_tqueue(msgsp, t PASS_REGS);
184 pthread_cond_broadcast(condp);
185 pthread_mutex_unlock(mutexp);
190mboxReceive( mbox_t *mboxp, Term t USES_REGS )
192 pthread_mutex_t *mutexp = &mboxp->mutex;
193 pthread_cond_t *condp = &mboxp->cond;
202 rc = mboxp->nmsgs && Yap_dequeue_tqueue(msgsp, t,
false,
true PASS_REGS);
208 pthread_mutex_unlock(mutexp);
210 }
else if (!mboxp->open) {
213 if (!mboxp->nclients) {
214 pthread_cond_destroy(condp);
215 pthread_mutex_destroy(mutexp);
216 Yap_destroy_tqueue(msgsp PASS_REGS);
219 pthread_cond_broadcast(condp);
220 pthread_mutex_unlock(mutexp);
224 pthread_cond_wait(condp, mutexp);
231mboxPeek( mbox_t *mboxp, Term t USES_REGS )
233 pthread_mutex_t *mutexp = &mboxp->mutex;
235 bool rc = Yap_dequeue_tqueue(msgsp, t,
false,
false PASS_REGS);
236 pthread_mutex_unlock(mutexp);
241store_specs(
int new_worker_id, UInt ssize, UInt tsize, UInt sysize, Term tgoal, Term tdetach, Term texit)
247 if (tsize < MinTrailSpace)
248 tsize = MinTrailSpace;
249 if (ssize < MinStackSpace)
250 ssize = MinStackSpace;
251 REMOTE_ThreadHandle(new_worker_id).ssize = ssize;
252 REMOTE_ThreadHandle(new_worker_id).tsize = tsize;
253 REMOTE_ThreadHandle(new_worker_id).sysize = sysize;
255 if ((
REGSTORE *)pthread_getspecific(Yap_yaamregs_key)) {
256 REMOTE_c_input_stream(new_worker_id) = LOCAL_c_input_stream;
257 REMOTE_c_output_stream(new_worker_id) = LOCAL_c_output_stream;
258 REMOTE_c_error_stream(new_worker_id) = LOCAL_c_error_stream;
261 REMOTE_c_input_stream(new_worker_id) = REMOTE_c_input_stream(0);
262 REMOTE_c_output_stream(new_worker_id) = REMOTE_c_output_stream(0);
263 REMOTE_c_error_stream(new_worker_id) = REMOTE_c_error_stream(0);
265 pm = (ssize + tsize)*K1;
266 if (!(REMOTE_ThreadHandle(new_worker_id).stack_address = malloc(pm))) {
269 REMOTE_ThreadHandle(new_worker_id).tgoal =
270 Yap_StoreTermInDB(Deref(tgoal), 7);
273 REMOTE_ThreadHandle(new_worker_id).cmod =
276 REMOTE_ThreadHandle(new_worker_id).cmod = USER_MODULE;
278 tdetach = Deref(tdetach);
279 if (IsVarTerm(tdetach)){
280 REMOTE_ThreadHandle(new_worker_id).tdetach =
281 MkAtomTerm(AtomFalse);
283 REMOTE_ThreadHandle(new_worker_id).tdetach =
286 tmod = CurrentModule;
287 texit = Yap_StripModule(Deref(texit), &tmod);
288 if (IsAtomTerm(tmod)) {
289 REMOTE_ThreadHandle(new_worker_id).texit_mod = tmod;
291 Yap_Error(TYPE_ERROR_ATOM,tmod,
"module in exit call should be an atom");
293 REMOTE_ThreadHandle(new_worker_id).texit =
294 Yap_StoreTermInDB(texit,7);
295 REMOTE_ThreadHandle(new_worker_id).local_preds =
297 REMOTE_ThreadHandle(new_worker_id).start_of_timesp =
299 REMOTE_ThreadHandle(new_worker_id).last_timep =
301 REMOTE_ScratchPad(new_worker_id).ptr =
304 REMOTE_GlobalArena(new_worker_id) =0;
310kill_thread_engine (
int wid,
int always_die)
312 Prop p0 = AbsPredProp(REMOTE_ThreadHandle(wid).local_preds);
315 REMOTE_ThreadHandle(wid).local_preds = NIL;
316 REMOTE_GlobalVariables(wid) = NULL;
322 Yap_FreeCodeSpace((
char *)ap);
325 gl->global = TermFoundVar;
329 REMOTE_Signals(wid) = 0L;
334 GLOBAL_ThreadsTotalTime += Yap_cputime();
336 if (REMOTE_ScratchPad(wid).ptr)
337 free(REMOTE_ScratchPad(wid).ptr);
340 REMOTE_ThreadHandle(wid).current_yaam_regs = NULL;
341 if (REMOTE_ThreadHandle(wid).start_of_timesp)
342 free(REMOTE_ThreadHandle(wid).start_of_timesp);
343 if (REMOTE_ThreadHandle(wid).last_timep)
344 free(REMOTE_ThreadHandle(wid).last_timep);
345 if (REMOTE_ThreadHandle(wid).texit) {
346 Yap_FreeCodeSpace((ADDR)REMOTE_ThreadHandle(wid).texit);
349 free(REMOTE_ThreadHandle(wid).default_yaam_regs);
350 REMOTE_ThreadHandle(wid).default_yaam_regs = NULL;
351 LOCK(GLOBAL_ThreadHandlesLock);
353 UNLOCK(GLOBAL_ThreadHandlesLock);
354 MUTEX_LOCK(&(REMOTE_ThreadHandle(wid).tlock));
355 if (REMOTE_ThreadHandle(wid).tdetach == MkAtomTerm(AtomTrue) ||
357 REMOTE_ThreadHandle(wid).zombie = FALSE;
358 REMOTE_ThreadHandle(wid).in_use = FALSE;
360 MUTEX_UNLOCK(&(REMOTE_ThreadHandle(wid).tlock));
364thread_die(
int wid,
int always_die)
366 kill_thread_engine(wid, always_die);
370setup_engine(
int myworker_id,
int init_thread)
378 regcache = standard_regs;
380 REMOTE_ThreadHandle(myworker_id).default_yaam_regs = standard_regs;
381 REMOTE_ThreadHandle(myworker_id).current_yaam_regs = standard_regs;
382 Yap_InitExStacks(myworker_id, REMOTE_ThreadHandle(myworker_id).tsize, REMOTE_ThreadHandle(myworker_id).ssize);
383 REMOTE_SourceModule(myworker_id) = CurrentModule = REMOTE_ThreadHandle(myworker_id).cmod;
385 mboxCreate( MkIntTerm(myworker_id), &REMOTE_ThreadHandle(myworker_id).mbox_handle PASS_REGS );
386 Yap_InitTime( myworker_id );
387 Yap_InitYaamRegs( myworker_id,
true] );
389 Yap_ReleasePreAllocCodeSpace(Yap_PreAllocCodeSpace());
391 GLOBAL_NOfThreadsCreated++;
393 MUTEX_UNLOCK(&(REMOTE_ThreadHandle(myworker_id).tlock));
395 new_dependency_frame(REMOTE_top_dep_fr(myworker_id), FALSE, NULL, NULL, B, NULL, FALSE, NULL);
401start_thread(
int myworker_id)
404 pthread_setspecific(Yap_yaamregs_key, (
void *)REMOTE_ThreadHandle(myworker_id).default_yaam_regs);
406 worker_id = myworker_id;
407 LOCAL = REMOTE(myworker_id);
411thread_run(
void *widp)
416 int myworker_id = *((
int *)widp);
417#ifdef OUTPUT_THREADS_TABLING
418 char thread_name[25];
419 char filename[MAX_PATH];
421 sprintf(thread_name,
"/thread_output_%d", myworker_id);
422 strcpy(filename, YAP_BINDIR);
423 strncat(filename, thread_name, 25);
424 REMOTE_thread_output(myworker_id) = fopen(filename,
"w");
426 start_thread(myworker_id);
429 t = tgs[0] = Yap_PopTermFromDB(LOCAL_ThreadHandle.tgoal);
431 if (LOCAL_Error_TYPE == RESOURCE_ERROR_ATTRIBUTED_VARIABLES) {
432 LOCAL_Error_TYPE = YAP_NO_ERROR;
433 if (!Yap_growglobal(NULL)) {
434 Yap_Error(RESOURCE_ERROR_ATTRIBUTED_VARIABLES, TermNil, LOCAL_ErrorMessage);
435 thread_die(worker_id, FALSE);
439 LOCAL_Error_TYPE = YAP_NO_ERROR;
440 if (!Yap_growstack(LOCAL_ThreadHandle.tgoal->NOfCells*CellSize)) {
441 Yap_Error(RESOURCE_ERROR_STACK, TermNil, LOCAL_ErrorMessage);
442 thread_die(worker_id, FALSE);
448 REMOTE_ThreadHandle(myworker_id).tgoal = NULL;
449 tgs[1] = LOCAL_ThreadHandle.tdetach;
450 tgoal = Yap_MkApplTerm(FunctorThreadRun, 2, tgs);
451 Yap_RunTopGoal(tgoal);
456 tab_ent = GLOBAL_root_tab_ent;
458 abolish_table(tab_ent);
459 tab_ent = TabEnt_next(tab_ent);
461 FREE_DEPENDENCY_FRAME(REMOTE_top_dep_fr(worker_id));
462 REMOTE_top_dep_fr(worker_id) = NULL;
463#ifdef USE_PAGES_MALLOC
464 DETACH_PAGES(_pages_void);
466 DETACH_PAGES(_pages_tab_ent);
467#if defined(THREADS_FULL_SHARING) || defined(THREADS_CONSUMER_SHARING)
468 DETACH_PAGES(_pages_sg_ent);
470 DETACH_PAGES(_pages_sg_fr);
471 DETACH_PAGES(_pages_dep_fr);
472 DETACH_PAGES(_pages_sg_node);
473 DETACH_PAGES(_pages_sg_hash);
474 DETACH_PAGES(_pages_ans_node);
475 DETACH_PAGES(_pages_ans_hash);
476#if defined(THREADS_FULL_SHARING)
477 DETACH_PAGES(_pages_ans_ref_node);
479 DETACH_PAGES(_pages_gt_node);
480 DETACH_PAGES(_pages_gt_hash);
481#ifdef OUTPUT_THREADS_TABLING
482 fclose(LOCAL_thread_output);
487 thread_die(worker_id, FALSE);
492p_thread_new_tid( USES_REGS1 )
494 int new_worker = allocate_new_tid();
495 if (new_worker == -1) {
496 Yap_Error(RESOURCE_ERROR_MAX_THREADS, MkIntegerTerm(MAX_THREADS),
"");
499 return Yap_unify(MkIntegerTerm(new_worker), ARG1);
503init_thread_engine(
int new_worker_id, UInt ssize, UInt tsize, UInt sysize, Term tgoal, Term tdetach, Term texit)
505 return store_specs(new_worker_id, ssize, tsize, sysize, tgoal, tdetach, texit);
509p_create_thread( USES_REGS1 )
514 Term x2 = Deref(ARG2);
515 Term x3 = Deref(ARG3);
516 Term x4 = Deref(ARG4);
517 int new_worker_id = IntegerOfTerm(Deref(ARG7)),
521 if (IsBigIntTerm(x2))
523 if (IsBigIntTerm(x3))
525 ssize = IntegerOfTerm(x2);
526 tsize = IntegerOfTerm(x3);
527 sysize = IntegerOfTerm(x4);
529 if (new_worker_id == -1) {
534 if (!init_thread_engine(new_worker_id, ssize, tsize, sysize, ARG1, ARG5, ARG6))
537 REMOTE_ThreadHandle(new_worker_id).id = new_worker_id;
538 REMOTE_ThreadHandle(new_worker_id).ref_count = 1;
539 setup_engine(new_worker_id, FALSE);
540 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) {
541 pthread_setspecific(Yap_yaamregs_key, (
const void *)REMOTE_ThreadHandle(owid).current_yaam_regs);
545 pthread_setspecific(Yap_yaamregs_key, (
const void *)REMOTE_ThreadHandle(owid).current_yaam_regs);
550p_thread_sleep( USES_REGS1 )
552 UInt time = IntegerOfTerm(Deref(ARG1));
554 UInt ntime = IntegerOfTerm(Deref(ARG2));
555 struct timespec req, oreq ;
558 if (nanosleep(&req, &oreq)) {
560 Yap_Error(SYSTEM_ERROR_OPERATING_SYSTEM, ARG1,
"%s in thread_sleep/1", strerror(errno));
562 Yap_Error(SYSTEM_ERROR_OPERATING_SYSTEM, ARG1,
"error %d in thread_sleep/1", errno);
566 return Yap_unify(ARG3,MkIntegerTerm(oreq.tv_sec)) &&
567 Yap_unify(ARG4,MkIntegerTerm(oreq.tv_nsec));
570 if ((rtime = sleep(time)) < 0) {
572 Yap_Error(SYSTEM_ERROR_OPERATING_SYSTEM, ARG1,
"%s in thread_sleep/1", strerror(errno));
574 Yap_Error(SYSTEM_ERROR_OPERATING_SYSTEM, ARG1,
"error %d in thread_sleep/1", errno);
577 return Yap_unify(ARG3,MkIntegerTerm(rtime)) &&
578 Yap_unify(ARG4,MkIntTerm(0L));
580 Yap_Error(SYSTEM_ERROR_OPERATING_SYSTEM, ARG1,
"no support for thread_sleep/1 in this YAP configuration");
585p_thread_self( USES_REGS1 )
587 if (pthread_getspecific(Yap_yaamregs_key) == NULL)
588 return Yap_unify(MkIntegerTerm(-1), ARG1);
589 return Yap_unify(MkIntegerTerm(worker_id), ARG1);
594p_thread_zombie_self( USES_REGS1 )
597 if (pthread_getspecific(Yap_yaamregs_key) == NULL)
598 return Yap_unify(MkIntegerTerm(-1), ARG1);
599 if (Yap_has_signal( YAP_ITI_SIGNAL )) {
603 LOCAL_ThreadHandle.in_use = FALSE;
604 LOCAL_ThreadHandle.zombie = TRUE;
605 MUTEX_UNLOCK(&(LOCAL_ThreadHandle.tlock));
606 return Yap_unify(MkIntegerTerm(worker_id), ARG1);
610p_thread_status_lock( USES_REGS1 )
613 if (pthread_getspecific(Yap_yaamregs_key) == NULL)
615 MUTEX_LOCK(&(LOCAL_ThreadHandle.tlock_status));
616 return Yap_unify(MkIntegerTerm(worker_id), ARG1);
620p_thread_status_unlock( USES_REGS1 )
623 if (pthread_getspecific(Yap_yaamregs_key) == NULL)
625 MUTEX_UNLOCK(&(LOCAL_ThreadHandle.tlock_status));
626 return Yap_unify(MkIntegerTerm(worker_id), ARG1);
633 if (pthread_getspecific(Yap_yaamregs_key) == NULL)
642 int new_id = allocate_new_tid();
656 ops->tsize = DefHeapSpace;
657 ops->ssize = DefStackSpace;
661 if (!pthread_equal(pthread_self() , GLOBAL_master_thread) ) {
663 pthread_setspecific(Yap_yaamregs_key, (
const void *)&Yap_standard_regs);
664 MUTEX_LOCK(&(REMOTE_ThreadHandle(0).tlock));
666 if (!init_thread_engine(new_id, ops->ssize, ops->tsize, ops->sysize, t, t, (ops->egoal)))
669 REMOTE_ThreadHandle(new_id).id = new_id;
670 REMOTE_ThreadHandle(new_id).ref_count = 0;
671 if (!setup_engine(new_id, FALSE))
673 if (!pthread_equal(pthread_self(), GLOBAL_master_thread)) {
674 pthread_setspecific(Yap_yaamregs_key, NULL);
675 MUTEX_UNLOCK(&(REMOTE_ThreadHandle(0).tlock));
681Yap_thread_attach_engine(
int wid)
687 if (REMOTE_ThreadHandle(wid).ref_count ) {
688 REMOTE_ThreadHandle(wid).ref_count++;
689 REMOTE_ThreadHandle(wid).pthread_handle = pthread_self();
690 MUTEX_UNLOCK(&(REMOTE_ThreadHandle(wid).tlock));
693 REMOTE_ThreadHandle(wid).pthread_handle = pthread_self();
694 REMOTE_ThreadHandle(wid).ref_count++;
695 pthread_setspecific(Yap_yaamregs_key, (
const void *)REMOTE_ThreadHandle(wid).current_yaam_regs);
696 MUTEX_UNLOCK(&(REMOTE_ThreadHandle(wid).tlock));
701Yap_thread_detach_engine(
int wid)
703 MUTEX_LOCK(&(REMOTE_ThreadHandle(wid).tlock));
705 REMOTE_ThreadHandle(wid).ref_count--;
706 pthread_setspecific(Yap_yaamregs_key, NULL);
707 MUTEX_UNLOCK(&(REMOTE_ThreadHandle(wid).tlock));
712Yap_thread_destroy_engine(
int wid)
714 MUTEX_LOCK(&(REMOTE_ThreadHandle(wid).tlock));
715 if (REMOTE_ThreadHandle(wid).ref_count == 0) {
716 kill_thread_engine(wid, TRUE);
719 MUTEX_UNLOCK(&(REMOTE_ThreadHandle(wid).tlock));
726p_thread_join( USES_REGS1 )
728 Int tid = IntegerOfTerm(Deref(ARG1));
731 MUTEX_LOCK(&(REMOTE_ThreadHandle(tid).tlock));
732 if (!(REMOTE_ThreadHandle(tid).in_use ||
733 REMOTE_ThreadHandle(tid).zombie)) {
735 MUTEX_UNLOCK(&(REMOTE_ThreadHandle(tid).tlock));
738 if (!REMOTE_ThreadHandle(tid).tdetach == MkAtomTerm(AtomTrue)) {
739 MUTEX_UNLOCK(&(REMOTE_ThreadHandle(tid).tlock));
742 thread = REMOTE_ThreadHandle(tid).pthread_handle;
743 MUTEX_UNLOCK(&(REMOTE_ThreadHandle(tid).tlock));
745 if (pthread_join(thread, NULL) < 0) {
753p_thread_destroy( USES_REGS1 )
755 Int tid = IntegerOfTerm(Deref(ARG1));
757 MUTEX_LOCK(&(REMOTE_ThreadHandle(tid).tlock));
758 REMOTE_ThreadHandle(tid).zombie = FALSE;
759 REMOTE_ThreadHandle(tid).in_use = FALSE;
760 MUTEX_UNLOCK(&(REMOTE_ThreadHandle(tid).tlock));
765p_thread_detach( USES_REGS1 )
767 Int tid = IntegerOfTerm(Deref(ARG1));
768 MUTEX_LOCK(&(REMOTE_ThreadHandle(tid).tlock));
769 if (pthread_detach(REMOTE_ThreadHandle(tid).pthread_handle) < 0) {
771 MUTEX_UNLOCK(&(REMOTE_ThreadHandle(tid).tlock));
774 REMOTE_ThreadHandle(tid).tdetach =
775 MkAtomTerm(AtomTrue);
776 MUTEX_UNLOCK(&(REMOTE_ThreadHandle(tid).tlock));
781p_thread_detached( USES_REGS1 )
783 if (LOCAL_ThreadHandle.tdetach)
784 return Yap_unify(ARG1,LOCAL_ThreadHandle.tdetach);
790p_thread_detached2( USES_REGS1 )
792 Int tid = IntegerOfTerm(Deref(ARG1));
793 if (REMOTE_ThreadHandle(tid).tdetach)
794 return Yap_unify(ARG2,REMOTE_ThreadHandle(tid).tdetach);
800p_thread_exit( USES_REGS1 )
802 thread_die(worker_id, FALSE);
809p_thread_set_concurrency( USES_REGS1 )
811#if HAVE_PTHREAD_GETCONCURRENCY
814 Term tnew = Deref(ARG2);
815 if (IsVarTerm(tnew)) {
817 }
else if (IsIntegerTerm(tnew)) {
818 newc = IntegerOfTerm(tnew);
820 Yap_Error(TYPE_ERROR_INTEGER,tnew,
"thread_set_concurrency/2");
823 cur = MkIntegerTerm(pthread_getconcurrency());
824 if (pthread_setconcurrency(newc) != 0) {
827 return Yap_unify(ARG1, MkIntegerTerm(cur));
834p_thread_yield( USES_REGS1 )
836 if (sched_yield() != 0) {
843p_valid_thread( USES_REGS1 )
845 Int i = IntegerOfTerm(Deref(ARG1));
846 return REMOTE_ThreadHandle(i).in_use || REMOTE_ThreadHandle(i).zombie;
851typedef struct swi_mutex {
857 struct swi_mutex *backbone;
858 struct swi_mutex *prev, *next;
861static SWIMutex *NewMutex(
void) {
863 pthread_mutexattr_t mat;
864#if defined(HAVE_PTHREAD_MUTEXATTR_SETKIND_NP) && !defined(__MINGW32__)
865 extern int pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr,
int kind);
868 LOCK(GLOBAL_MUT_ACCESS);
869 mutp = GLOBAL_FreeMutexes;
871 if ((Int)(mutp->owners) < 0) {
878 mutp = (SWIMutex *)Yap_AllocCodeSpace(
sizeof(SWIMutex));
880 UNLOCK(GLOBAL_MUT_ACCESS);
883 pthread_mutexattr_init(&mat);
885#if defined(HAVE_PTHREAD_MUTEXATTR_SETKIND_NP) && !defined(__MINGW32__)
886 pthread_mutexattr_setkind_np(&mat, PTHREAD_MUTEX_RECURSIVE_NP);
888#ifdef HAVE_PTHREAD_MUTEXATTR_SETTYPE
889 pthread_mutexattr_settype(&mat, PTHREAD_MUTEX_RECURSIVE);
892 pthread_mutex_init(&mutp->m, &mat);
894 mutp->backbone = GLOBAL_mutex_backbone;
895 GLOBAL_mutex_backbone = mutp;
903 UNLOCK(GLOBAL_MUT_ACCESS);
907#define MutexOfTerm(t) MutexOfTerm__(t PASS_REGS)
909static SWIMutex *MutexOfTerm__(Term t USES_REGS){
911 SWIMutex *mut = NULL;
914 Yap_Error(INSTANTIATION_ERROR, t1,
"mutex operation");
916 }
else if (IsApplTerm(t1) && FunctorOfTerm(t1) == FunctorMutex) {
917 mut = AddressOfTerm(ArgOfTerm(1,t1));
918 if ((Int)(mut->owners) < 0 ||
919 IntegerOfTerm(ArgOfTerm(2,t1)) != mut->timestamp) {
920 Yap_Error(EXISTENCE_ERROR_MUTEX, t1,
"mutex access");
923 }
else if (IsAtomTerm(t1)) {
924 mut = Yap_GetMutexFromProp(AtomOfTerm(t1));
927 if ( !Yap_PutAtomMutex( AtomOfTerm(t1), mut ) ) {
936p_new_mutex( USES_REGS1 ){
939 if (IsVarTerm((t1 = Deref(ARG1)))) {
942 if (!(mutp = NewMutex()))
944 ts[0] = MkAddressTerm(mutp);
945 ts[1] = MkIntegerTerm(mutp->timestamp);
946 if (Yap_unify(ARG1, Yap_MkApplTerm(FunctorMutex, 2, ts) ) ) {
949 Yap_Error(UNINSTANTIATION_ERROR, t1,
"mutex_create on an existing mutex");
951 }
else if(IsAtomTerm(t1)) {
952 if (!(mutp = NewMutex()))
954 return Yap_PutAtomMutex( AtomOfTerm(t1), mutp );
955 }
else if (IsApplTerm(t1) && FunctorOfTerm(t1) == FunctorMutex) {
956 Yap_Error(UNINSTANTIATION_ERROR, t1,
"mutex_create on an existing mutex");
967static Int p_destroy_mutex( USES_REGS1 )
969 SWIMutex *mut = MutexOfTerm(Deref(ARG1));
972 if (pthread_mutex_destroy(&mut->m) < 0)
975 mut->alias->Mutex = NULL;
979 LOCK(GLOBAL_MUT_ACCESS);
980 if (GLOBAL_FreeMutexes)
981 mut->prev = GLOBAL_FreeMutexes->prev;
984 mut->next = GLOBAL_FreeMutexes;
985 GLOBAL_FreeMutexes = mut;
986 UNLOCK(GLOBAL_MUT_ACCESS);
991LockMutex( SWIMutex *mut USES_REGS)
996 if (MUTEX_LOCK(&mut->m) < 0)
1000 mut->tid_own = worker_id;
1002 mut->prev = LOCAL_Mutexes->prev;
1005 mut->next = LOCAL_Mutexes;
1006 LOCAL_Mutexes = NULL;
1011UnLockMutex( SWIMutex *mut USES_REGS)
1014 MUTEX_UNLOCK(&mut->m);
1016 if (MUTEX_UNLOCK(&mut->m) < 0)
1021 mut->prev->next = mut->next;
1023 LOCAL_Mutexes = mut->next;
1025 mut->next->prev = NULL;
1028 mut->next->prev = mut->prev;
1054p_lock_mutex( USES_REGS1 )
1056 SWIMutex *mut = MutexOfTerm(Deref(ARG1));
1057 if (!mut || !LockMutex( mut PASS_REGS))
1071p_trylock_mutex( USES_REGS1 )
1073 SWIMutex *mut = MutexOfTerm(Deref(ARG1));
1077 if (MUTEX_TRYLOCK(&mut->m) == EBUSY)
1080 mut->tid_own = worker_id;
1094p_unlock_mutex( USES_REGS1 )
1096 SWIMutex *mut = MutexOfTerm(Deref(ARG1));
1097 if (!mut || !UnLockMutex( mut PASS_REGS))
1119p_with_mutex( USES_REGS1 )
1123 Int creeping = Yap_get_signal(YAP_CREEP_SIGNAL);
1125 Term tm = CurrentModule;
1126 Term tg = Deref(ARG2);
1127 SWIMutex *mut = MutexOfTerm( ARG1 );
1129 if (!mut || !LockMutex(mut PASS_REGS)) {
1133 tg = Yap_StripModule(tg, &tm);
1134 if (IsVarTerm(tg)) {
1135 Yap_Error(INSTANTIATION_ERROR, ARG2,
"with_mutex/2");
1137 }
else if (IsApplTerm(tg)) {
1138 register Functor f = FunctorOfTerm(tg);
1142 f = FunctorOfTerm(tg);
1143 if (IsExtensionFunctor(f)) {
1144 Yap_Error(TYPE_ERROR_CALLABLE, tg,
"with_mutex/2");
1147 arity = ArityOfFunctor(f);
1148 if (arity > MaxTemps) {
1149 Yap_Error(TYPE_ERROR_CALLABLE, tg,
"with_mutex/2");
1152 pe = RepPredProp(PredPropByFunc(f, tm));
1154 for (i= 0; i < arity; i++ )
1156 }
else if (IsAtomTerm(tg)) {
1157 pe = RepPredProp(PredPropByAtom(AtomOfTerm(tg), tm));
1158 }
else if (IsPairTerm(tg)) {
1163 pe = RepPredProp(PredPropByFunc(f, tm));
1168 Yap_Error(TYPE_ERROR_CALLABLE, tg,
"with_mutex/2");
1172 pe->OpcodeOfPred != FAIL_OPCODE &&
1173 Yap_execute_pred(pe, NULL,
true PASS_REGS) ) {
1178 if ( !UnLockMutex(mut PASS_REGS) ) {
1182 Yap_signal( YAP_CREEP_SIGNAL );
1183 }
else if ( excep != 0) {
1184 return Yap_JumpToEnv(excep);
1191p_with_with_mutex( USES_REGS1 )
1193 if (GLOBAL_WithMutex == NULL) {
1194 p_new_mutex( PASS_REGS1 );
1195 GLOBAL_WithMutex = (SWIMutex*)IntegerOfTerm(Deref(ARG1));
1197 ARG1 = MkIntegerTerm((Int)GLOBAL_WithMutex);
1199 return p_lock_mutex( PASS_REGS1 );
1203p_unlock_with_mutex( USES_REGS1 )
1205 ARG1 = MkIntegerTerm((Int)GLOBAL_WithMutex);
1206 return p_unlock_mutex( PASS_REGS1 );
1210p_mutex_info( USES_REGS1 )
1212 SWIMutex *mut = MutexOfTerm(Deref(ARG1));
1216 return Yap_unify(ARG2, MkIntegerTerm(mut->owners)) &&
1217 Yap_unify(ARG3, MkIntegerTerm(mut->tid_own));
1227 p_mbox_create( USES_REGS1 )
1229 Term namet = Deref(ARG1);
1230 mbox_t* mboxp = GLOBAL_named_mboxes;
1232 if (IsVarTerm(namet)) {
1237 ae = Yap_lookupBlob(&mbox,
sizeof(mbox), &PL_Message_Queue, &
new);
1238 namet = MkAtomTerm(RepAtom(ae));
1239 mboxp = (mbox_t *)(ae->rep.blob[0].data);
1240 Yap_unify(ARG1, namet);
1241 LOCK(GLOBAL_mboxq_lock);
1242 }
else if (IsAtomTerm(namet)) {
1243 LOCK(GLOBAL_mboxq_lock);
1244 while( mboxp && mboxp->name != namet)
1245 mboxp = mboxp->next;
1247 UNLOCK(GLOBAL_mboxq_lock);
1250 mboxp = (mbox_t *)Yap_AllocCodeSpace(
sizeof(mbox_t));
1251 if (mboxp == NULL) {
1252 UNLOCK(GLOBAL_mboxq_lock);
1256 mboxp->next = GLOBAL_named_mboxes;
1257 GLOBAL_named_mboxes = mboxp;
1259 bool rc = mboxCreate( namet, mboxp PASS_REGS );
1260 UNLOCK(GLOBAL_mboxq_lock);
1266p_mbox_destroy( USES_REGS1 )
1268 Term namet = Deref(ARG1);
1269 mbox_t* mboxp = GLOBAL_named_mboxes, *prevp;
1271 if (IsVarTerm(namet) )
1273 if (IsIntTerm(namet) ) {
1276 LOCK(GLOBAL_mboxq_lock);
1278 while( mboxp && mboxp->name != namet) {
1280 mboxp = mboxp->next;
1283 UNLOCK(GLOBAL_mboxq_lock);
1286 if (mboxp == GLOBAL_named_mboxes) {
1287 GLOBAL_named_mboxes = mboxp->next;
1289 prevp->next = mboxp->next;
1291 UNLOCK(GLOBAL_mboxq_lock);
1292 mboxDestroy(mboxp PASS_REGS);
1293 Yap_FreeCodeSpace( (
char *)mboxp );
1302 if (IsAtomTerm(t=Deref(t))) {
1303 Atom at = AtomOfTerm(t);
1304 LOCK(GLOBAL_mboxq_lock);
1306 mboxp = (mbox_t *)(RepAtom(at)->rep.blob[0].data);
1308 mboxp = GLOBAL_named_mboxes;
1309 while( mboxp && mboxp->name != t) {
1310 mboxp = mboxp->next;
1316 pthread_mutex_lock(& mboxp->mutex);
1318 UNLOCK(GLOBAL_mboxq_lock);
1319 }
else if (IsIntTerm(t)) {
1320 int wid = IntOfTerm(t);
1322 (REMOTE_ThreadHandle(wid).in_use || REMOTE_ThreadHandle(wid).zombie))
1324 return &REMOTE_ThreadHandle(wid).mbox_handle;
1331 pthread_mutex_lock(& mboxp->mutex);
1341 p_mbox_send( USES_REGS1 )
1343 Term namet = Deref(ARG1);
1344 mbox_t* mboxp = getMbox(namet) ;
1348 return mboxSend(mboxp, Deref(ARG2) PASS_REGS);
1352 p_mbox_size( USES_REGS1 )
1354 Term namet = Deref(ARG1);
1355 mbox_t* mboxp = getMbox(namet) ;
1359 return Yap_unify( ARG2, MkIntTerm(mboxp->nmsgs));
1364 p_mbox_receive( USES_REGS1 )
1366 Term namet = Deref(ARG1);
1367 mbox_t* mboxp = getMbox(namet) ;
1371 return mboxReceive(mboxp, Deref(ARG2) PASS_REGS);
1376 p_mbox_peek( USES_REGS1 )
1378 Term namet = Deref(ARG1);
1379 mbox_t* mboxp = getMbox(namet) ;
1383 return mboxPeek(mboxp, Deref(ARG2) PASS_REGS);
1387p_cond_create( USES_REGS1 )
1389 pthread_cond_t* condp;
1391 condp = (pthread_cond_t *)Yap_AllocCodeSpace(
sizeof(pthread_cond_t));
1392 if (condp == NULL) {
1395 pthread_cond_init(condp, NULL);
1396 return Yap_unify(ARG1, MkIntegerTerm((Int)condp));
1400 p_cond_destroy( USES_REGS1 )
1402 pthread_cond_t *condp = (pthread_cond_t *)IntegerOfTerm(Deref(ARG1));
1404 if (pthread_cond_destroy(condp) < 0)
1406 Yap_FreeCodeSpace((
void *)condp);
1411 p_cond_signal( USES_REGS1 )
1413 pthread_cond_t *condp = (pthread_cond_t *)IntegerOfTerm(Deref(ARG1));
1415 if (pthread_cond_signal(condp) < 0)
1421 p_cond_broadcast( USES_REGS1 )
1423 pthread_cond_t *condp = (pthread_cond_t *)IntegerOfTerm(Deref(ARG1));
1425 if (pthread_cond_broadcast(condp) < 0)
1431 p_cond_wait( USES_REGS1 )
1433 pthread_cond_t *condp = (pthread_cond_t *)IntegerOfTerm(Deref(ARG1));
1434 SWIMutex *mut = (SWIMutex*)IntegerOfTerm(Deref(ARG2));
1435 pthread_cond_wait(condp, &mut->m);
1440p_thread_stacks( USES_REGS1 )
1442 Int tid = IntegerOfTerm(Deref(ARG1));
1445 MUTEX_LOCK(&(REMOTE_ThreadHandle(tid).tlock));
1447 (REMOTE_ThreadHandle(tid).in_use || REMOTE_ThreadHandle(tid).zombie)) {
1448 status &= Yap_unify(ARG2,MkIntegerTerm(REMOTE_ThreadHandle(tid).ssize));
1449 status &= Yap_unify(ARG3,MkIntegerTerm(REMOTE_ThreadHandle(tid).tsize));
1450 status &= Yap_unify(ARG4,MkIntegerTerm(REMOTE_ThreadHandle(tid).sysize));
1451 MUTEX_UNLOCK(&(REMOTE_ThreadHandle(tid).tlock));
1454 MUTEX_UNLOCK(&(REMOTE_ThreadHandle(tid).tlock));
1459p_thread_atexit( USES_REGS1 )
1463 if (LOCAL_ThreadHandle.texit == NULL ||
1464 LOCAL_ThreadHandle.texit->Entry == MkAtomTerm(AtomTrue)) {
1468 t = Yap_PopTermFromDB(LOCAL_ThreadHandle.texit);
1470 if (LOCAL_Error_TYPE == RESOURCE_ERROR_ATTRIBUTED_VARIABLES) {
1471 LOCAL_Error_TYPE = YAP_NO_ERROR;
1472 if (!Yap_growglobal(NULL)) {
1473 Yap_Error(RESOURCE_ERROR_ATTRIBUTED_VARIABLES, TermNil, LOCAL_ErrorMessage);
1474 thread_die(worker_id, FALSE);
1478 LOCAL_Error_TYPE = YAP_NO_ERROR;
1479 if (!Yap_growstack(LOCAL_ThreadHandle.tgoal->NOfCells*CellSize)) {
1480 Yap_Error(RESOURCE_ERROR_STACK, TermNil, LOCAL_ErrorMessage);
1481 thread_die(worker_id, FALSE);
1487 LOCAL_ThreadHandle.texit = NULL;
1488 return Yap_unify(ARG1, t) && Yap_unify(ARG2, LOCAL_ThreadHandle.texit_mod);
1494p_thread_signal( USES_REGS1 )
1496 Int wid = IntegerOfTerm(Deref(ARG1));
1498 MUTEX_LOCK(&(REMOTE_ThreadHandle(wid).tlock));
1499 if (!REMOTE_ThreadHandle(wid).in_use ||
1500 !REMOTE_ThreadHandle(wid).current_yaam_regs) {
1501 MUTEX_UNLOCK(&(REMOTE_ThreadHandle(wid).tlock));
1504 Yap_external_signal( wid, YAP_ITI_SIGNAL );
1505 MUTEX_UNLOCK(&(REMOTE_ThreadHandle(wid).tlock));
1510p_no_threads( USES_REGS1 )
1516p_nof_threads( USES_REGS1 )
1519 LOCK(GLOBAL_ThreadHandlesLock);
1520 for (wid = 0; wid < MAX_THREADS; wid++) {
1521 if (!Yap_local[wid])
break;
1522 if (REMOTE_ThreadHandle(wid).in_use)
1525 UNLOCK(GLOBAL_ThreadHandlesLock);
1526 return Yap_unify(ARG1,MkIntegerTerm(i));
1530p_max_workers( USES_REGS1 )
1532 return Yap_unify(ARG1,MkIntegerTerm(MAX_WORKERS));
1536p_max_threads( USES_REGS1 )
1538 return Yap_unify(ARG1,MkIntegerTerm(MAX_THREADS));
1542p_nof_threads_created( USES_REGS1 )
1544 return Yap_unify(ARG1,MkIntTerm(GLOBAL_NOfThreadsCreated));
1548p_thread_runtime( USES_REGS1 )
1550 return Yap_unify(ARG1,MkIntegerTerm(GLOBAL_ThreadsTotalTime));
1554p_thread_self_lock( USES_REGS1 )
1556 MUTEX_LOCK(&(LOCAL_ThreadHandle.tlock));
1557 return Yap_unify(ARG1,MkIntegerTerm(worker_id));
1561p_thread_unlock( USES_REGS1 )
1563 Int wid = IntegerOfTerm(Deref(ARG1));
1564 MUTEX_UNLOCK(&(REMOTE_ThreadHandle(wid).tlock));
1571#if defined(__APPLE__)
1572 return syscall(SYS_thread_selfid);
1573#elif HAVE_SYS_GETTID || defined(__APPLE__)
1574 return syscall( SYS_GETTID );
1575#elif HAVE_GETTID_SYSCALL
1576 return syscall(__NR_gettid);
1577#elif defined( HAVE_GETTID_MACRO )
1579#elif defined(__WINDOWS__)
1580 return GetCurrentThreadId();
1588Yap_InitFirstWorkerThreadHandle(
void)
1591 LOCAL_ThreadHandle.id = 0;
1592 LOCAL_ThreadHandle.in_use = TRUE;
1593 LOCAL_ThreadHandle.default_yaam_regs =
1595 LOCAL_ThreadHandle.current_yaam_regs =
1597 LOCAL_ThreadHandle.pthread_handle = pthread_self();
1598 pthread_mutex_init(&REMOTE_ThreadHandle(0).tlock, NULL);
1599 pthread_mutex_init(&REMOTE_ThreadHandle(0).tlock_status, NULL);
1600 LOCAL_ThreadHandle.tdetach = MkAtomTerm(AtomFalse);
1601 LOCAL_ThreadHandle.ref_count = 1;
1604void Yap_InitThreadPreds(
void)
1608 Yap_InitCPred(
"$no_threads", 0, p_no_threads, 0);
1609 Yap_InitCPred(
"$max_workers", 1, p_max_workers, 0);
1610 Yap_InitCPred(
"$max_threads", 1, p_max_threads, 0);
1611 Yap_InitCPred(
"$thread_new_tid", 1, p_thread_new_tid, 0);
1612 Yap_InitCPred(
"$create_thread", 7, p_create_thread, 0);
1613 Yap_InitCPred(
"$thread_self", 1, p_thread_self, SafePredFlag);
1614 Yap_InitCPred(
"$thread_status_lock", 1, p_thread_status_lock, SafePredFlag);
1615 Yap_InitCPred(
"$thread_status_unlock", 1, p_thread_status_unlock, SafePredFlag);
1616 Yap_InitCPred(
"$thread_zombie_self", 1, p_thread_zombie_self, SafePredFlag);
1617 Yap_InitCPred(
"$thread_join", 1, p_thread_join, 0);
1618 Yap_InitCPred(
"$thread_destroy", 1, p_thread_destroy, 0);
1619 Yap_InitCPred(
"thread_yield", 0, p_thread_yield, 0);
1627 Yap_InitCPred(
"$detach_thread", 1, p_thread_detach, 0);
1628 Yap_InitCPred(
"$thread_detached", 1, p_thread_detached, 0);
1629 Yap_InitCPred(
"$thread_detached", 2, p_thread_detached2, 0);
1630 Yap_InitCPred(
"$thread_exit", 0, p_thread_exit, 0);
1631 Yap_InitCPred(
"thread_setconcurrency", 2, p_thread_set_concurrency, 0);
1645 Yap_InitCPred(
"$valid_thread", 1, p_valid_thread, 0);
1646 Yap_InitCPred(
"mutex_create", 1, p_new_mutex, SafePredFlag);
1647 Yap_InitCPred(
"mutex_destroy", 1, p_destroy_mutex, SafePredFlag);
1648 Yap_InitCPred(
"mutex_lock", 1, p_lock_mutex, SafePredFlag);
1649 Yap_InitCPred(
"mutex_trylock", 1, p_trylock_mutex, SafePredFlag);
1650 Yap_InitCPred(
"mutex_unlock", 1, p_unlock_mutex, SafePredFlag);
1651 Yap_InitCPred(
"with_mutex", 2, p_with_mutex, MetaPredFlag);
1652 Yap_InitCPred(
"$with_with_mutex", 1, p_with_with_mutex, 0);
1653 Yap_InitCPred(
"$unlock_with_mutex", 1, p_unlock_with_mutex, 0);
1654 Yap_InitCPred(
"$mutex_info", 3, p_mutex_info, SafePredFlag);
1655 Yap_InitCPred(
"$cond_create", 1, p_cond_create, SafePredFlag);
1656 Yap_InitCPred(
"$cond_destroy", 1, p_cond_destroy, SafePredFlag);
1657 Yap_InitCPred(
"$cond_signal", 1, p_cond_signal, SafePredFlag);
1658 Yap_InitCPred(
"$cond_broadcast", 1, p_cond_broadcast, SafePredFlag);
1659 Yap_InitCPred(
"$cond_wait", 2, p_cond_wait, SafePredFlag);
1660 Yap_InitCPred(
"$message_queue_create", 1, p_mbox_create, SafePredFlag);
1661 Yap_InitCPred(
"$message_queue_destroy", 1, p_mbox_destroy, SafePredFlag);
1662 Yap_InitCPred(
"$message_queue_send", 2, p_mbox_send, SafePredFlag);
1663 Yap_InitCPred(
"$message_queue_receive", 2, p_mbox_receive, SafePredFlag);
1664 Yap_InitCPred(
"$message_queue_size", 2, p_mbox_size, SafePredFlag);
1665 Yap_InitCPred(
"$message_queue_peek", 2, p_mbox_peek, SafePredFlag);
1666 Yap_InitCPred(
"$thread_stacks", 4, p_thread_stacks, SafePredFlag);
1667 Yap_InitCPred(
"$signal_thread", 1, p_thread_signal, SafePredFlag);
1668 Yap_InitCPred(
"$nof_threads", 1, p_nof_threads, SafePredFlag);
1669 Yap_InitCPred(
"$nof_threads_created", 1, p_nof_threads_created, SafePredFlag);
1670 Yap_InitCPred(
"$thread_sleep", 4, p_thread_sleep, SafePredFlag);
1671 Yap_InitCPred(
"$thread_runtime", 1, p_thread_runtime, SafePredFlag);
1672 Yap_InitCPred(
"$thread_self_lock", 1, p_thread_self_lock, SafePredFlag);
1673 Yap_InitCPred(
"$thread_run_at_exit", 2, p_thread_atexit, SafePredFlag);
1674 Yap_InitCPred(
"$thread_unlock", 1, p_thread_unlock, SafePredFlag);
1675#if DEBUG_LOCKS||DEBUG_PE_LOCKS
1676 Yap_InitCPred(
"debug_locks", 0, p_debug_locks, SafePredFlag);
1677 Yap_InitCPred(
"nodebug_locks", 0, p_nodebug_locks, SafePredFlag);
1684Yap_NOfThreads(
void) {
1703 return Yap_unify(ARG1,MkIntTerm(1));
1709 return Yap_unify(ARG1,MkIntTerm(1));
1713p_nof_threads_created(
void)
1715 return Yap_unify(ARG1,MkIntTerm(1));
1719p_thread_runtime(
void)
1721 return Yap_unify(ARG1,MkIntTerm(0));
1727 return Yap_unify(ARG1,MkIntTerm(0));
1731p_thread_stacks(
void)
1737p_thread_unlock(
void)
1745 return Yap_unify(ARG1,MkIntTerm(1));
1751 static int mutexes = 1;
1752 return Yap_unify(ARG1, MkIntegerTerm(mutexes++) );
1756 p_with_mutex( USES_REGS1 )
1759 Term t1 = Deref(ARG1), excep;
1761 Int creeping = Yap_get_signal(YAP_CREEP_SIGNAL);
1763 Term tm = CurrentModule;
1764 Term tg = Deref(ARG2);
1766 if (IsVarTerm(t1)) {
1767 p_new_mutex( PASS_REGS1 );
1770 mut = IntOfTerm(t1);
1771 tg = Yap_StripModule(tg, &tm);
1772 if (IsVarTerm(tg)) {
1773 Yap_Error(INSTANTIATION_ERROR, ARG2,
"with_mutex/2");
1775 }
else if (IsApplTerm(tg)) {
1776 register Functor f = FunctorOfTerm(tg);
1780 f = FunctorOfTerm(tg);
1781 if (IsExtensionFunctor(f)) {
1782 Yap_Error(TYPE_ERROR_CALLABLE, tg,
"with_mutex/2");
1785 arity = ArityOfFunctor(f);
1786 if (arity > MaxTemps) {
1787 Yap_Error(TYPE_ERROR_CALLABLE, tg,
"with_mutex/2");
1790 pe = RepPredProp(PredPropByFunc(f, tm));
1792 for (i= 0; i < arity; i++ )
1794 }
else if (IsAtomTerm(tg)) {
1795 pe = RepPredProp(PredPropByAtom(AtomOfTerm(tg), tm));
1796 }
else if (IsPairTerm(tg)) {
1801 pe = RepPredProp(PredPropByFunc(f, tm));
1806 Yap_Error(TYPE_ERROR_CALLABLE, tg,
"with_mutex/2");
1810 pe->OpcodeOfPred != FAIL_OPCODE &&
1811 Yap_execute_pred(pe, NULL,
false PASS_REGS) ) {
1815 ARG1 = MkIntegerTerm(mut);
1818 Yap_signal( YAP_CREEP_SIGNAL );
1819 }
else if ( excep != 0) {
1820 return Yap_JumpToEnv();
1826Yap_InitFirstWorkerThreadHandle(
void)
1830void Yap_InitThreadPreds(
void)
1832 Yap_InitCPred(
"with_mutex", 2, p_with_mutex, MetaPredFlag);
1833 Yap_InitCPred(
"mutex_create", 1, p_new_mutex, SafePredFlag);
1834 Yap_InitCPred(
"$max_workers", 1, p_max_workers, 0);
1835 Yap_InitCPred(
"$thread_self", 1, p_thread_self, SafePredFlag);
1836 Yap_InitCPred(
"$no_threads", 0, p_no_threads, SafePredFlag);
1837 Yap_InitCPred(
"$max_threads", 1, p_max_threads, SafePredFlag);
1838 Yap_InitCPred(
"$nof_threads", 1, p_nof_threads, SafePredFlag);
1839 Yap_InitCPred(
"$nof_threads_created", 1, p_nof_threads_created, SafePredFlag);
1840 Yap_InitCPred(
"$thread_stacks", 4, p_thread_stacks, SafePredFlag);
1841 Yap_InitCPred(
"$thread_runtime", 1, p_thread_runtime, SafePredFlag);
1842 Yap_InitCPred(
"$thread_unlock", 1, p_thread_unlock, SafePredFlag);
1843#if DEBUG_LOCKS||DEBUG_PE_LOCKS
1844 Yap_InitCPred(
"debug_locks", 0, p_debug_locks, SafePredFlag);
1845 Yap_InitCPred(
"nodebug_locks", 0, p_nodebug_locks, SafePredFlag);
yap_error_descriptor_t * Yap_GetException(void)
clone Active Error
@ system_thread_id
report the thread running YAP