This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/BEAM/eam_am.c

3774 lines
101 KiB
C
Raw Permalink Normal View History

/*************************************************************************
* *
* BEAM -> Basic Extended Andorra Model *
* BEAM extends the YAP Prolog system to support the EAM *
* Copyright: Ricardo Lopes and NCC - University of Porto, Portugal *
* *
**************************************************************************
* comments: eam abstract machine emulator *
* *
* IMPORTANT: ON i386 ISAPPL SHOUD ALWAYS BE AFTER ISVAR *
*************************************************************************/
#ifdef BEAM
#include "Yap.h"
#include "Yatom.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define Debug 0
#define Debug_GC 1
#define Debug_Dump_State 0 /* 0 =off || 1==only on Scheduling || 2== only on GC || 4=on every abs inst NOTE: DEBUG has to be enable to use 4*/
#define Debug_MEMORY 0
#define Memory_Stat 0
#define Clear_MEMORY 0 /* 0- do not clear || 1-> clear on request || 2-> clear on release || 3 -> both*/
#define Fast_go 1 /* normaly 1 ; use 0 to run some extra tests only to control some possible bugs (slower) */
#define USE_SPLIT 1
#define MEM_FOR_BOXES 32 /* In Mb */
#define MEM_FOR_HEAP 32 /* In Mb */
#define MEM_FOR_VARS 32 /* In Mb */
#define MEM_BOXES MEM_FOR_BOXES*1024*1024
#define MEM_H MEM_FOR_HEAP*1024*1024
#define MEM_VARS MEM_FOR_VARS*1024*1024
#define INDEX_SIZE 100000 /* size of vector for saving memory requests */
#define GARBAGE_COLLECTOR 2 /* 0= NO GC || 1 = Heap only || 2 = Heap + Box */
#define HYBRID_BOXMEM 1 /* 0 - Off || 1 - On */
#define START_ON_NEXT 1 /* PLEASE DON'T CHANGE , specially if you use skip_while_var */
#define USE_LEFTMOST 1 /* SHOULD ALWAYS BE 1 for now... */
#define MICRO_TIME 1 /* 0 == eamtime uses CPU time 1 == eamtime uses total time */
#define MAX_MEMORYSTAT 5000
#define READ 0
#define WRITE 1
#include "eam.h"
#include "eamamasm.h"
int EAM=0; /* Is EAM enabled ? */
Cell *beam_ALTERNATIVES; /* NEEDED FOR ABSMI */
PredEntry *bpEntry;
struct EAM_Global EAMGlobal;
struct EAM_Global *eamGlobal=&EAMGlobal;
#if !Debug
#define INLINE inline
#define DIRECT_JUMP 1
#else
#define INLINE
#define DIRECT_JUMP 0
void break_top(void); void break_top(void) { };
void break_debug(int);
void break_debug(int conta) {
#if Debug_Dump_State & 4
dump_eam_state();
#endif
if (Debug!=-1 && conta>Debug*100) {printf("exit por contador>debug\n"); exit(1); }
};
#endif
#define push_mode_and_sreg() { *--beam_sp = (Cell) beam_Mode; *--beam_sp = (Cell) beam_S; }
#define pop_mode_and_sreg() { beam_S = (Cell *) *beam_sp++; beam_Mode = (short) *beam_sp++; }
#define isvar(a) IsVarTerm((Cell) a)
#define isappl(a) IsApplTerm((Cell) a)
#define ispair(a) IsPairTerm((Cell) a)
#define isatom(a) IsAtomOrIntTerm((Cell) a)
#define reppair(a) RepPair((Cell) a)
#define repappl(a) RepAppl((Cell) a)
#define abspair(a) AbsPair((Term *) a)
#define absappl(a) AbsAppl((Term *) a)
int is_perm_var(Cell *a); inline int is_perm_var(Cell *a) { if (a>=(Cell *) beam_END_BOX && a<(Cell *) (beam_END_BOX+MEM_VARS)) return(1); else return (0); }
//int is_perm_var(Cell *a); inline int is_perm_var(Cell *a) { if (a<(Cell *) beam_END_BOX) return(0); else return (1); }
//int is_perm_var(Cell *a); inline int is_perm_var(Cell *a) { if ( a<(Cell *) beam_START_ADDR_HEAP || a>=(Cell *) beam_END_BOX) return(1); else return (0); }
Cell deref(Cell a);
int Unify(Cell *a, Cell *b);
void UnifyCells(Cell *a, Cell *b);
void trail(struct AND_BOX *andbox,struct PERM_VAR *a);
void limpa_trail(struct AND_BOX *andbox);
void get_arguments(int nr, Cell *a);
Cell *save_arguments(int nr);
void remove_memory_arguments(Cell *a);
void initialize_memory_areas(void);
Cell *request_memory(int size);
void free_memory(Cell *mem,int size);
void limpa_trail_orbox(struct OR_BOX *orbox);
struct SUSPENSIONS *addto_suspensions_list(struct AND_BOX *a,int reason);
void delfrom_suspensions_list(struct SUSPENSIONS *b);
void totop_suspensions_list(struct SUSPENSIONS *b);
int verify_externals(struct AND_BOX *and_box);
void remove_from_perm_var_suspensions(struct PERM_VAR *v,struct AND_BOX *andbox);
void change_perm_var_suspensions(struct PERM_VAR *v,struct AND_BOX *andbox,struct AND_BOX *new);
void do_forking_andbox(struct AND_BOX *a);
void remove_all_externals(struct AND_BOX *andbox);
void remove_all_externals_suspensions(struct AND_BOX *andbox);
void del_andbox_and_sons(struct AND_BOX *andbox);
void del_orbox_and_sons(struct OR_BOX *orbox);
void waking_boxes_suspended_on_var(struct PERM_VAR *v);
struct PERM_VAR *request_permVar(struct AND_BOX *a);
void free_permVar(struct PERM_VAR *v);
Cell *request_memory_locals(int nr);
Cell *request_memory_locals_noinit(int nr);
void free_memory_locals(Cell *l);
void add_to_list_perms(struct PERM_VAR *var,struct AND_BOX *a);
void remove_list_perms(struct AND_BOX *a);
void move_perm_vars(struct AND_BOX *b, struct AND_BOX *a);
void move_perm_variables(struct AND_BOX *a);
void inc_level(struct AND_BOX *andbox,int dif);
void abort_eam(char *s);
void exit_eam(char *s);
int HEAP_MEM_FULL(void);
void change_from_to(struct PERM_VAR *o,struct PERM_VAR *d);
unsigned int index_of_hash_table_atom(Cell c, int nr);
unsigned int index_of_hash_table_appl(Cell c, int nr);
int deve_limpar_var(struct EXTERNAL_VAR *e);
struct status_and *remove_call_from_andbox(struct status_and *ncall, struct AND_BOX *a);
int is_leftmost(struct AND_BOX *a, struct status_and *n);
int exists_var_in(Cell *c);
void garbage_collector(void);
void conta_memoria_livre(int size);
int showTime(void);
struct AND_BOX *choose_leftmost(void);
extern Cell BEAM_is(void);
extern void do_eam_indexing(struct Predicates *);
2015-06-17 23:54:54 +01:00
extern void Yap_plwrite(Term, struct stream_desc *, int, int);
#if Debug_Dump_State
void dump_eam_state(void);
#endif
/************************************************************************\
* Debug + Status routines *
\************************************************************************/
void conta_memoria_livre(int size){
int i,nr,ult=0;
long total=0;
Cell *c;
for(i=0;i<INDEX_SIZE;i++) {
nr=0;
c=beam_IndexFree[i];
while(c!=NULL) {
ult=i;
nr++;
c=(Cell *) *c;
}
total=total+nr*i;
}
printf("Ultimo Pedido (bytes) =%d <20> Ultimo bloco livre=%d\n",size,(int) ult*CELL_SIZE);
printf("Memoria TOTAL (bytes) =%ld \n",((unsigned long) beam_END_BOX)-((unsigned long) beam_START_ADDR_BOXES));
printf("Memoria livre no IndexFree=%ld \n",total*CELL_SIZE);
printf("Memoria Total livre =%ld \n",total*CELL_SIZE+((unsigned long) beam_END_BOX)-((unsigned long)beam_NextFree));
printf("Memoria Total na HEAP=%ld livre=%ld \n",(unsigned long) MEM_H,(unsigned long) beam_H-(unsigned long) beam_START_ADDR_HEAP);
}
void abort_eam(char *s)
{
printf("%s\n",s);
exit(1);
}
void exit_eam(char *s)
{
printf("%s\n",s);
if (beam_nr_call_forking) printf("%d forks executed\n",beam_nr_call_forking);
if (beam_nr_gc_heap)
printf("GC was called %d times on Heap Mem\n",beam_nr_gc_heap);
if (beam_nr_gc_boxed)
printf("GC was called %d times on Boxed Mem\n",beam_nr_gc_boxed);
if (beam_nr_gc_boxed && beam_nr_gc_heap)
printf("GC was called %d times \n",beam_nr_gc_boxed+beam_nr_gc_heap);
#if Memory_Stat
{unsigned long req, used;
req=beam_TOTAL_MEM+beam_TOTAL_PERMS;
used=(beam_TOTAL_MEM+beam_TOTAL_PERMS)-(beam_MEM_REUSED+beam_PERMS_REUSED);
printf("-------------------------------------------------------------------\n");
printf("Total Mem: Requested %ld (%.2fKb) (%.2fMb) \n", req, req/1024.0, req/1048576.0);
printf(" Used %ld (%.2fKb) (%.2fMb) / Reused (%3.2f%c)\n", used,used/1024.0, used/1048576.0, (float) (req-used)/req*100,'%');
printf("-------------------------------------------------------------------\n");
used=(beam_TOTAL_MEM-beam_TOTAL_TEMPS)-(beam_MEM_REUSED-beam_TEMPS_REUSED);
printf("Boxed Mem: Requested %ld (%.2fKb) (%.2fMb) \n", beam_TOTAL_MEM-beam_TOTAL_TEMPS, (beam_TOTAL_MEM-beam_TOTAL_TEMPS)/1024.0, (beam_TOTAL_MEM-beam_TOTAL_TEMPS)/1048576.0);
printf(" Used %ld (%.2fKb) (%.2fMb) / Reused (%3.2f%c)\n", used, used/1024.0, used/1048576.0, (float) (beam_MEM_REUSED-beam_TEMPS_REUSED)/(beam_TOTAL_MEM-beam_TOTAL_TEMPS)*100,'%');
used=beam_TOTAL_TEMPS-beam_TEMPS_REUSED;
printf("Temps Mem: Requested %ld (%.2fKb) (%.2fMB)\n", beam_TOTAL_TEMPS, beam_TOTAL_TEMPS/1024.0, beam_TOTAL_TEMPS/1048576.0);
printf(" Used %ld (%.2fKb) (%.2fMb) / Reused (%3.2f%c)\n", used, used/1024.0,used/1048576.0,(float) beam_TEMPS_REUSED/(beam_TOTAL_TEMPS)*100,'%');
used=beam_TOTAL_PERMS-beam_PERMS_REUSED;
printf("Perms Mem: Requested %ld (%.2fKb) (%.2fMB)\n", beam_TOTAL_PERMS, beam_TOTAL_PERMS/1024.0, beam_TOTAL_PERMS/1048576.0);
printf(" Used %ld (%.2fKb) (%.2fMb) / Reused (%3.2f%c)\n", used, used/1024.0,used/1048576.0,(float) beam_PERMS_REUSED/(beam_TOTAL_PERMS)*100,'%');
}
printf("-------------------------------------------------------------------\n");
if (beam_nr_gc_boxed+beam_nr_gc_heap>0) {
int i;
beam_Memory_STAT[0][0]=0; beam_Memory_STAT[0][1]=0; beam_Memory_STAT[0][2]=0; beam_Memory_STAT[0][3]=0; beam_Memory_STAT[0][4]=0;
for(i=1;i<=beam_nr_gc_boxed+beam_nr_gc_heap;i++) {
beam_Memory_STAT[0][0]+=beam_Memory_STAT[i][0];
beam_Memory_STAT[0][1]+=beam_Memory_STAT[i][1];
beam_Memory_STAT[0][2]+=beam_Memory_STAT[i][2];
beam_Memory_STAT[0][3]+=beam_Memory_STAT[i][3];
beam_Memory_STAT[0][4]+=beam_Memory_STAT[i][4];
printf("GC %4d Time=%ld H=%ld to %ld (%3.2f) Box=%ld to %ld (%3.2f)\n",
i, beam_Memory_STAT[i][0], beam_Memory_STAT[i][1], beam_Memory_STAT[i][3],
((float) beam_Memory_STAT[i][3]/beam_Memory_STAT[i][1])*100 , beam_Memory_STAT[i][2], beam_Memory_STAT[i][4],
((float) beam_Memory_STAT[i][4]/beam_Memory_STAT[i][2])*100);
}
i--;
printf("\nRESUME GC: Time=%ld H=%ld to %ld (%3.2f) Box=%ld to %ld (%3.2f)\n",
beam_Memory_STAT[0][0]/i, beam_Memory_STAT[0][1]/i, beam_Memory_STAT[0][3]/i,
100.0-((float) beam_Memory_STAT[0][3]/beam_Memory_STAT[0][1])*100 , beam_Memory_STAT[0][2]/i, beam_Memory_STAT[0][4]/i,
100.0-((float) beam_Memory_STAT[0][4]/beam_Memory_STAT[0][2])*100);
} else {
printf("Heap Mem Requested %ld (%.2fKb) (%.2fMB) \n", ((unsigned long) beam_H-beam_START_ADDR_HEAP), ((unsigned long) beam_H-beam_START_ADDR_HEAP)/1024.0, ((unsigned long) beam_H-beam_START_ADDR_HEAP)/1048576.0);
printf("-------------------------------------------------------------------\n");
}
#endif
exit(0);
}
/************************************************************************\
* Memory Management routines *
\************************************************************************/
void initialize_memory_areas()
{
static int first_time=1;
if (first_time) {
first_time=0;
beam_IndexFree=(Cell **) malloc(INDEX_SIZE*POINTER_SIZE);
if ((void *) beam_IndexFree==(void *)NULL) abort_eam("Memory Initialization Error IndexFree\n");
beam_START_ADDR_HEAP=(unsigned long) malloc(MEM_H+MEM_BOXES+MEM_VARS);
if ((void *)beam_START_ADDR_HEAP==(void *)NULL) abort_eam("Memory Initialization Error Heap+Boxes\n");
beam_START_ADDR_BOXES=beam_START_ADDR_HEAP+MEM_H;
beam_END_H=beam_START_ADDR_HEAP+MEM_H;
beam_END_BOX=beam_START_ADDR_BOXES+MEM_BOXES;
}
beam_sp=(Cell *) beam_END_H; beam_sp-=2;
beam_NextVar=(struct PERM_VAR *) beam_END_BOX;
beam_H=(Cell *) beam_START_ADDR_HEAP;
#if GARBAGE_COLLECTOR!=2
beam_NextFree=(Cell *) beam_END_BOX;
#else
beam_NextFree=(Cell *) beam_START_ADDR_BOXES;
#endif
beam_MemGoing=1;
memset(beam_IndexFree,0,INDEX_SIZE*POINTER_SIZE);
{ int i,max;
max=MEM_VARS/PERM_VAR_SIZE;
for(i=0;i<max-1;i++) {
beam_NextVar[i].next=&beam_NextVar[i+1];
}
beam_NextVar[max-1].next=NULL;
}
beam_varlocals=NULL;
beam_USE_SAME_ANDBOX=NULL;
beam_nr_alternative=NULL;
beam_nr_call=NULL;
beam_nr_gc_heap=0;
beam_nr_gc_boxed=0;
beam_Mode=READ;
beam_VAR_TRAIL_NR=0;
beam_nr_call_forking=0;
beam_Mem_FULL=0;
#if Memory_Stat
beam_TOTAL_MEM=0; beam_MEM_REUSED=0; beam_TOTAL_TEMPS=0; beam_TEMPS_REUSED=0; beam_TOTAL_PERMS=0; beam_PERMS_REUSED=0;
memset(beam_Memory_STAT,0,MAX_MEMORYSTAT*5*sizeof(unsigned long));
#endif
}
INLINE int HEAP_MEM_FULL(void)
{
if (beam_MemGoing==1) {
if ((unsigned long)beam_H>(unsigned long)(beam_START_ADDR_HEAP+MEM_H/2)) {
beam_Mem_FULL|=2;
}
} else {
if ((unsigned long) beam_H>(unsigned long)(beam_START_ADDR_HEAP+MEM_H)) {
beam_Mem_FULL|=2;
}
}
return(beam_Mem_FULL);
}
INLINE Cell *request_memory(int size) /* size in bytes */
{
register Cell *mem;
register int size_cells;
if (size==0) return NULL;
size_cells=size/CELL_SIZE;
#if !Fast_go
if (size_cells> INDEX_SIZE)
abort_eam("Foi pedido um block de memoria grande demais !!! \n");
#endif
#if Debug & Debug_MEMORY
printf("Requesting memory size %d\n",size_cells);
#endif
#if HYBRID_BOXMEM
mem=beam_IndexFree[(unsigned) size_cells];
#if Memory_Stat
beam_TOTAL_MEM+=size;
if (mem!=NULL) beam_MEM_REUSED+=size;
#endif
if (mem==NULL) {
#else /* GC Only */
#if Memory_Stat
beam_TOTAL_MEM+=size;
#endif
if (1) {
#endif
#if GARBAGE_COLLECTOR!=2
beam_NextFree-=size_cells;
mem=beam_NextFree;
if (beam_NextFree< (Cell *) beam_START_ADDR_BOXES) abort_eam("No more BOX_MEM \n");
#else
if (beam_MemGoing==1) {
mem=beam_NextFree;
beam_NextFree+=size_cells;
if (beam_NextFree> (Cell *) ( beam_START_ADDR_BOXES+MEM_BOXES/2)) beam_Mem_FULL |= 1;
} else {
beam_NextFree-=size_cells;
mem=beam_NextFree;
if (beam_NextFree< (Cell *) ( beam_START_ADDR_BOXES+MEM_BOXES/2)) beam_Mem_FULL |=1;
}
#endif
} else {
beam_IndexFree[(unsigned) size_cells]=(Cell *) *mem;
}
#if Clear_MEMORY & 1
memset(mem,0,size); /* NOT REALLY NECESSARY, use only to detect possible errors*/
#endif
return(mem);
}
#if HYBRID_BOXMEM==0
void free_memory(Cell *mem,int size) {
#if Clear_MEMORY & 2
memset(mem,0,size);
#endif
};
#else
INLINE void free_memory(Cell *mem,int size) /* size in bytes */
{
register int size_cells;
if (size==0 || mem==NULL) return;
size_cells=size/CELL_SIZE;
#if Clear_MEMORY & 2
memset(mem,0,size); /* NOT REALLY NECESSARY, use only to detect possible errors*/
#endif
#if Debug & Debug_MEMORY
printf("Freeing memory size %d\n",size_cells);
#endif
*mem=(Cell) beam_IndexFree[size_cells];
beam_IndexFree[size_cells]=mem;
}
#endif
INLINE void get_arguments(int nr, Cell *a)
{
register int i;
for(i=1;i<=nr;i++) beam_X[i]=a[i];
}
INLINE Cell *save_arguments(int nr) /* nr arguments */
{
if (!nr) return(NULL);
{
register int i;
register Cell *a;
a=(Cell *)request_memory((nr+1)*CELL_SIZE);
a[0]=nr+1;
for(i=1;i<=nr;i++) a[i]=beam_X[i];
return(a);
}
}
INLINE void remove_memory_arguments(Cell *a)
{
if (a==NULL) return;
#if !Fast_go
if (a[0]<1 || a[0]>1000)
printf("%d Numero Invalido de Argumentos............\n",a[0]);
#endif
free_memory(a,a[0]*CELL_SIZE);
}
struct PERM_VAR *request_permVar(struct AND_BOX *a) {
struct PERM_VAR *pv;
#if Memory_Stat
static struct PERM_VAR *old=NULL;
beam_TOTAL_PERMS+=PERM_VAR_SIZE;
if (old<=beam_NextVar) old=beam_NextVar;
else beam_PERMS_REUSED+=PERM_VAR_SIZE;
#endif
#if Debug && Debug_MEMORY
printf("Requesting a permVar...\n");
#endif
#if !Fast_go
if (beam_NextVar->next==NULL) { printf("Fim da memoria para variaveis\n"); exit (-1); }
#endif
pv=beam_NextVar;
beam_NextVar=beam_NextVar->next;
pv->value=(Cell) &(pv->value);
pv->home=a;
pv->suspensions=NULL;
pv->yapvar=NULL;
pv->next=a->perms;
a->perms=pv;
return (pv);
}
void free_permVar(struct PERM_VAR *v) {
#if Clear_MEMORY
v->value=(Cell) NULL;
v->home=(struct AND_BOX *) NULL;
v->suspensions=(struct SUSPENSIONS_VAR *) NULL;
#endif
#if Debug & Debug_MEMORY
printf("Freeing a permVar...\n");
#endif
v->next=beam_NextVar;
beam_NextVar=v;
return;
}
INLINE Cell *request_memory_locals(int nr)
{
Cell *l;
int i;
#if Memory_Stat
Cell *old;
old=beam_NextFree;
beam_TOTAL_TEMPS+=CELL_SIZE*(nr+1);
#endif
#if Debug_MEMORY
printf("Requesting Memory for %d+1 locals...\n",nr);
#endif
l=(Cell *)request_memory(CELL_SIZE*(nr+1));
l[0]=nr;
l++;
for(i=0;i<nr;i++) {
l[i]=(Cell) &l[i];
}
#if Memory_Stat
if (old==beam_NextFree) beam_TEMPS_REUSED+=CELL_SIZE*(nr+1);
#endif
return(l);
}
INLINE Cell *request_memory_locals_noinit(int nr)
{
Cell *l;
#if Memory_Stat
Cell *old;
old=beam_NextFree;
beam_TOTAL_TEMPS+=CELL_SIZE*(nr+1);
#endif
#if Debug_MEMORY
printf("Requesting Memory for %d+1 locals (not initialized)...\n",nr);
#endif
l=(Cell *)request_memory(CELL_SIZE*(nr+1));
l[0]=nr;
l++;
#if Memory_Stat
if (old==beam_NextFree) beam_TEMPS_REUSED+=CELL_SIZE*(nr+1);
#endif
return(l);
}
INLINE void free_memory_locals(Cell *l)
{
if (l==NULL || l[-1]==0) return;
#if Debug_MEMORY
printf("Freeing Memory for %ld+1 locals...\n",l[-1]);
#endif
free_memory((Cell *) &l[-1], CELL_SIZE*(l[-1]+1));
l[-1]=0; /* <20> necess<73>rio para evitar apagar este vector novamente
porque varias calls podem estar a referenciar o mesmo vector locals */
}
/************************************************************************\
* Manipulating And-Or-Boxes structures *
\************************************************************************/
void del_andbox_and_sons(struct AND_BOX *andbox )
{
register struct status_and *ncall;
if (andbox==NULL) return;
remove_all_externals(andbox);
delfrom_suspensions_list(andbox->suspended);
ncall=andbox->calls;
while(ncall!=NULL) {
del_orbox_and_sons(ncall->call);
{
struct status_and *ncall_old;
ncall_old=ncall;
ncall=ncall->next;
free_memory_locals(ncall_old->locals);
free_memory((Cell *) ncall_old,STATUS_AND_SIZE);
}
}
remove_list_perms(andbox);
free_memory((Cell *) andbox,ANDBOX_SIZE);
}
void del_orbox_and_sons(struct OR_BOX *orbox)
{
struct status_or *so;
Cell *a=NULL;
if (orbox==NULL) return;
so=orbox->alternatives;
while (so!=NULL) {
struct status_or *old;
del_andbox_and_sons(so->alternative);
a=so->args;
old=so;
so=so->next;
free_memory((Cell *) old,STATUS_OR_SIZE);
}
remove_memory_arguments(a); /* remove args */
free_memory((Cell *) orbox,ORBOX_SIZE);
}
INLINE struct status_and *remove_call_from_andbox(struct status_and *ncall, struct AND_BOX *a)
{
register int nr;
struct status_and *r;
nr=a->nr_all_calls;
nr--;
a->nr_all_calls=nr;
if (nr==0) {
a->calls=NULL;
} else {
if (ncall->previous!=NULL) {
ncall->previous->next=ncall->next;
} else a->calls=ncall->next;
if (ncall->next!=NULL) {
ncall->next->previous=ncall->previous;
}
}
r=ncall->next;
{ /* vou ver se as locals ainda estao a ser usadas por outra ncall */
int aSerUsada=0;
struct status_and *l;
l=ncall->previous;
while (l!=NULL) {
if (l->locals==ncall->locals) { aSerUsada=1; break; }
l=l->previous;
}
l=r;
while (aSerUsada==0 && l!=NULL) {
if (l->locals==ncall->locals) { aSerUsada=1; break; }
l=l->next;
}
// aSerUsada=1; /* CUIDADO ao apagar as var locals da call */
if (aSerUsada==0) free_memory_locals(ncall->locals);
}
free_memory((Cell *) ncall,STATUS_AND_SIZE);
return(r);
}
INLINE void totop_suspensions_list(struct SUSPENSIONS *b)
{
if (beam_su==b) return; /* is already on top of list */
if (beam_su->prev==b) { beam_su=b; return; } /* It was the last one */
b->prev->next=b->next;
b->next->prev=b->prev;
b->next=beam_su;
b->prev=beam_su->prev;
beam_su->prev=b;
b->prev->next=b;
beam_su=b;
}
void waking_boxes_suspended_on_var(struct PERM_VAR *v)
{
struct SUSPENSIONS_VAR *s;
s=v->suspensions;
while(s!=NULL) {
register struct AND_BOX *a;
#if Debug
printf("Waking and_box assigment changed on a var that forced and_box to suspend \n");
#endif
a=s->and_box;
totop_suspensions_list(a->suspended);
a->nr_alternative->state|=WAKE;
s=s->next;
}
}
/* THE FALLOWING ROTINES ARE TO BE APPLYED TO THE SUSPENSION LIST
(DO NOT USE IT TO THE SUSPENSIONS ON THE LOCAL_VAR) */
INLINE struct SUSPENSIONS *addto_suspensions_list(struct AND_BOX *a,int r)
{
struct SUSPENSIONS *s;
if (a->suspended) return(a->suspended); /* already suspended */
s=(struct SUSPENSIONS *) request_memory(SUSPENSIONS_SIZE);
s->and_box=a;
s->reason=r;
if (beam_su==NULL) {
s->next=s;
s->prev=s;
beam_su=s;
} else {
s->next=beam_su;
s->prev=beam_su->prev;
beam_su->prev=s;
if (beam_su->next==beam_su) { /* so existem 2 elementos na lista */
beam_su->next=s;
} else {
s->prev->next=s;
}
}
return(s);
}
void delfrom_suspensions_list(struct SUSPENSIONS *b)
{
if (b==NULL) return;
#if !Fast_go
if ( b->and_box->suspended==NULL)
abort_eam("Nunca deveria acontecer no delfrom_suspensions_list ?????\n");
#endif
remove_all_externals_suspensions(b->and_box);
b->and_box->suspended=NULL;
if (b==beam_su) beam_su=b->next;
if (b==beam_su) { /* so existe um */
beam_su=NULL;
} else {
b->prev->next=b->next;
b->next->prev=b->prev;
}
free_memory((Cell *) b,SUSPENSIONS_SIZE);
}
INLINE void change_perm_var_suspensions(struct PERM_VAR *v,struct AND_BOX *andbox,struct AND_BOX *new)
{
struct SUSPENSIONS_VAR *s;
s=v->suspensions;
while(s!=NULL)
{
if (s->and_box==andbox) {
s->and_box=new;
return;
}
s=s->next;
}
}
/* MANIPULATE PERM VARS SUSPENSIONS */
INLINE void remove_from_perm_var_suspensions(struct PERM_VAR *v,struct AND_BOX *andbox)
{
struct SUSPENSIONS_VAR *s,*prev=NULL;
if (v==NULL) {
#if !Fast_go
abort_eam("Nunca deveria acontecer no remove_from_perm_var_suspensions ?????\n");
#endif
return;
}
s=v->suspensions;
while(s!=NULL)
{
struct SUSPENSIONS_VAR *next;
next=s->next;
if (s->and_box==andbox) {
if (prev==NULL) {
v->suspensions=s->next;
} else prev->next=s->next;
free_memory((Cell *) s,SUSPENSIONS_VAR_SIZE);
} else { /* acordar as boxes restantes porque houve uma alteracao */
s->and_box->nr_alternative->state |=WAKE;
prev=s;
}
s=next;
}
}
void remove_all_externals_suspensions(struct AND_BOX *andbox)
{
struct EXTERNAL_VAR *e;
e=andbox->externals;
while(e) {
remove_from_perm_var_suspensions(e->var,andbox);
e=e->next;
}
}
void remove_all_externals(struct AND_BOX *andbox)
{
struct EXTERNAL_VAR *e;
e=andbox->externals;
while(e) {
struct EXTERNAL_VAR *next;
next=e->next;
remove_from_perm_var_suspensions(e->var,andbox);
free_memory((Cell *)e,EXTERNAL_VAR_SIZE);
e=next;
}
}
void remove_list_perms(struct AND_BOX *a)
{
struct PERM_VAR *l,*oldl;
l=a->perms;
a->perms=NULL;
while(l) {
oldl=l;
l=oldl->next;
free_permVar(oldl);
}
}
INLINE void move_perm_vars(struct AND_BOX *b, struct AND_BOX *a) /* (from b to a) */
{
struct PERM_VAR *l,*old;
l=b->perms;
if (l==NULL) return;
do {
old=l;
l->home=a;
if (l->suspensions) change_perm_var_suspensions(l,b,a);
l=l->next;
} while(l!=NULL);
old->next=a->perms;
a->perms=b->perms;
return;
}
void add_to_list_perms(struct PERM_VAR *var,struct AND_BOX *a)
{
var->next=a->perms;
a->perms=var;
return;
}
/* change all suspended external references of perm var o to perm var d */
void change_from_to(struct PERM_VAR *o,struct PERM_VAR *d) {
struct SUSPENSIONS_VAR *s,*last;
#if Debug
printf("Change Vars from one andbox to another\n");
#endif