do locking on streams

git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@1616 b08c6af1-5177-4d33-ba66-4b1c6b8b522a
This commit is contained in:
vsc 2006-04-28 15:48:33 +00:00
parent 6fb10bfc51
commit 9101c18410
8 changed files with 234 additions and 148 deletions

View File

@ -959,6 +959,7 @@ InitCodes(void)
INIT_LOCK(Yap_heap_regs->dead_mega_clauses_lock);
INIT_LOCK(Yap_heap_regs->dead_static_indices_lock);
INIT_LOCK(Yap_heap_regs->op_list_lock);
INIT_LOCK(Yap_heap_regs->modules_lock);
Yap_heap_regs->heap_top_owner = -1;
{
int i;
@ -968,11 +969,27 @@ InitCodes(void)
Yap_heap_regs->wl[i].scratchpad.msz = SCRATCH_START_SIZE;
Yap_heap_regs->wl[i].dynamic_arrays = NULL;
Yap_heap_regs->wl[i].static_arrays = NULL;
Yap_heap_regs->wl[i].consultlow = (consult_obj *)Yap_AllocCodeSpace(sizeof(consult_obj)*InitialConsultCapacity);
if (Yap_heap_regs->wl[i].consultlow == NULL) {
Yap_Error(OUT_OF_HEAP_ERROR,TermNil,"No Heap Space in InitCodes");
return;
}
Yap_heap_regs->wl[i].consultcapacity = InitialConsultCapacity;
Yap_heap_regs->wl[i].consultbase = Yap_heap_regs->wl[i].consultsp =
Yap_heap_regs->wl[i].consultlow + Yap_heap_regs->wl[i].consultcapacity;
}
}
#else
Yap_heap_regs->wl.dynamic_arrays = NULL;
Yap_heap_regs->wl.static_arrays = NULL;
Yap_heap_regs->wl.consultlow = (consult_obj *)Yap_AllocCodeSpace(sizeof(consult_obj)*InitialConsultCapacity);
if (Yap_heap_regs->wl.consultlow == NULL) {
Yap_Error(OUT_OF_HEAP_ERROR,TermNil,"No Heap Space in InitCodes");
return;
}
Yap_heap_regs->wl.consultcapacity = InitialConsultCapacity;
Yap_heap_regs->wl.consultbase = Yap_heap_regs->wl.consultsp =
Yap_heap_regs->wl.consultlow + Yap_heap_regs->wl.consultcapacity;
#endif /* YAPOR */
Yap_heap_regs->clausecode->arity = 0;
Yap_heap_regs->clausecode->clause = NULL;
@ -981,12 +998,6 @@ InitCodes(void)
Yap_heap_regs->invisiblechain.Entry = NIL;
INIT_RWLOCK(Yap_heap_regs->invisiblechain.AERWLock);
Yap_heap_regs->consultlow = (consult_obj *)Yap_AllocCodeSpace(sizeof(consult_obj)*InitialConsultCapacity);
if (Yap_heap_regs->consultlow == NULL) {
Yap_Error(OUT_OF_HEAP_ERROR,TermNil,"No Heap Space in InitCodes");
return;
}
Yap_heap_regs->consultcapacity = InitialConsultCapacity;
{
Atom at;
PredEntry *pred;
@ -1007,8 +1018,6 @@ InitCodes(void)
Yap_heap_regs->system_pred_goal_expansion_func = FALSE;
Yap_heap_regs->system_pred_goal_expansion_on = FALSE;
Yap_heap_regs->update_mode = UPDATE_MODE_LOGICAL;
Yap_heap_regs->consultbase = Yap_heap_regs->consultsp =
Yap_heap_regs->consultlow + Yap_heap_regs->consultcapacity;
Yap_heap_regs->compiler_compile_mode = 0; /* fast will be for native code */
Yap_heap_regs->compiler_optimizer_on = TRUE;
Yap_heap_regs->maxdepth = 0;

View File

@ -176,6 +176,7 @@ GetFreeStreamD(void)
if (sno == MaxStreams) {
return -1;
}
INIT_LOCK(Stream[sno].streamlock);
return sno;
}
@ -328,6 +329,7 @@ InitStdStream (int sno, SMALLUNSGN flags, YP_File file)
s->linepos = 0;
s->linecount = 1;
s->charcount = 0;
INIT_LOCK(s->streamlock);
unix_upd_stream_info (s);
/* Getting streams to prompt is a mess because we need for cooperation
between readers and writers to the stream :-(
@ -842,11 +844,12 @@ p_is_same_tty (void)
{ /* 'prompt(Atom) */
int sni = CheckStream (ARG1, Input_Stream_f, "put/2");
int sno = CheckStream (ARG2, Output_Stream_f, "put/2");
return (
(Stream[sni].status & Tty_Stream_f) &&
(Stream[sno].status & Tty_Stream_f) &&
is_same_tty(Stream[sno].u.file.file,Stream[sni].u.file.file)
);
int out = (Stream[sni].status & Tty_Stream_f) &&
(Stream[sno].status & Tty_Stream_f) &&
is_same_tty(Stream[sno].u.file.file,Stream[sni].u.file.file);
UNLOCK(Stream[sno].streamlock);
UNLOCK(Stream[sni].streamlock);
return out;
}
static Int
@ -1514,7 +1517,9 @@ Yap_GetStreamFd(int sno)
int
Yap_CheckIOStream(Term stream, char * error)
{
return(CheckStream(stream, Input_Stream_f|Output_Stream_f|Socket_Stream_f, error));
int sno = CheckStream(stream, Input_Stream_f|Output_Stream_f|Socket_Stream_f, error);
UNLOCK(Stream[sno].streamlock);
return(sno);
}
#if USE_SOCKET
@ -1556,7 +1561,9 @@ Yap_InitSocketStream(int fd, socket_info flags, socket_domain domain) {
int
Yap_CheckSocketStream(Term stream, char * error)
{
return(CheckStream(stream, Socket_Stream_f, error));
int sno = CheckStream(stream, Socket_Stream_f, error);
UNLOCK(Stream[sno].streamlock);
return sno;
}
/* given a stream index, get the corresponding domain */
@ -1824,6 +1831,7 @@ static Int p_change_alias_to_stream (void)
== -1)
return(FALSE);
SetAlias(at, sno);
UNLOCK(Stream[sno].streamlock);
return(TRUE);
}
@ -1859,14 +1867,18 @@ p_fetch_stream_alias (void)
return FALSE;
if (IsVarTerm(t2)) {
Atom at = FetchAlias(sno);
UNLOCK(Stream[sno].streamlock);
if (at == AtomFoundVar)
return FALSE;
else
return Yap_unify_constant(t2, MkAtomTerm(at));
} else if (IsAtomTerm(t2)) {
Atom at = AtomOfTerm(t2);
return (Int)FindAliasForStream(sno,at);
Int out = (Int)FindAliasForStream(sno,at);
UNLOCK(Stream[sno].streamlock);
return out;
} else {
UNLOCK(Stream[sno].streamlock);
Yap_Error(TYPE_ERROR_ATOM, t2, "fetch_stream_alias/2");
return FALSE;
}
@ -2373,6 +2385,7 @@ CheckStream (Term arg, int kind, char *msg)
Yap_Error(PERMISSION_ERROR_OUTPUT_STREAM, arg, msg);
return (-1);
}
LOCK(Stream[sno].streamlock);
return (sno);
}
@ -2380,16 +2393,18 @@ static Int
p_check_stream (void)
{ /* '$check_stream'(Stream,Mode) */
Term mode = Deref (ARG2);
return (CheckStream (ARG1,
int sno = CheckStream (ARG1,
AtomOfTerm (mode) == AtomRead ? Input_Stream_f : Output_Stream_f,
"check_stream/2") != -1);
"check_stream/2");
UNLOCK(Stream[sno].streamlock);
return sno != -1;
}
static Int
p_check_if_stream (void)
{ /* '$check_stream'(Stream) */
return (CheckStream (ARG1, Input_Stream_f | Output_Stream_f | Append_Stream_f | Socket_Stream_f, "check_stream/1")
!= -1);
int sno = CheckStream (ARG1, Input_Stream_f | Output_Stream_f | Append_Stream_f | Socket_Stream_f, "check_stream/1");
return sno != -1;
}
static Term
@ -2430,6 +2445,7 @@ init_cur_s (void)
t2 = (Stream[i].status & Input_Stream_f ?
MkAtomTerm (AtomRead) :
MkAtomTerm (AtomWrite));
UNLOCK(Stream[i].streamlock);
if (Yap_unify(ARG1,t1) && Yap_unify(ARG2,t2)) {
cut_succeed();
} else {
@ -2570,6 +2586,7 @@ p_close (void)
if (sno <= StdErrStream)
return (TRUE);
CloseStream(sno);
UNLOCK(Stream[sno].streamlock);
return (TRUE);
}
@ -2589,16 +2606,20 @@ p_peek_mem_write_stream (void)
--i;
tf = MkPairTerm(MkIntTerm(Stream[sno].u.mem_string.buf[i]),tf);
if (H + 1024 >= ASP) {
UNLOCK(Stream[sno].streamlock);
H = HI;
if (!Yap_gc(3, ENV, P)) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(OUT_OF_STACK_ERROR, TermNil, Yap_ErrorMessage);
return(FALSE);
}
i = 0;
tf = ARG2;
LOCK(Stream[sno].streamlock);
goto restart;
}
}
UNLOCK(Stream[sno].streamlock);
return (Yap_unify(ARG3,tf));
}
@ -2607,10 +2628,13 @@ p_past_eof (void)
{ /* at_end_of_stream */
/* the next character is a EOF */
int sno = CheckStream (ARG1, Input_Stream_f, "past_eof/1");
Int out;
if (sno < 0)
return (FALSE);
return(Stream[sno].status & Eof_Stream_f);
out = Stream[sno].status & Eof_Stream_f;
UNLOCK(Stream[sno].streamlock);
return out;
}
static Int
@ -2631,6 +2655,7 @@ p_peek_byte (void)
return(FALSE);
}
if (status & Eof_Stream_f) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(PERMISSION_ERROR_INPUT_PAST_END_OF_STREAM, ARG1, "peek/2");
return(FALSE);
}
@ -2650,6 +2675,7 @@ p_peek_byte (void)
s->stream_getc_for_read = ISOGetc;
else
s->stream_getc_for_read = s->stream_getc;
UNLOCK(s->streamlock);
return(Yap_unify_constant(ARG2,MkIntTerm(ch)));
}
@ -2668,9 +2694,11 @@ p_peek (void)
status = Stream[sno].status;
if (status & (Binary_Stream_f|Eof_Stream_f)) {
if (status & Binary_Stream_f) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(PERMISSION_ERROR_INPUT_BINARY_STREAM, ARG1, "peek/2");
return(FALSE);
} else if (status & (Eof_Error_Stream_f)) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(PERMISSION_ERROR_INPUT_PAST_END_OF_STREAM, ARG1, "peek/2");
return(FALSE);
}
@ -2691,6 +2719,7 @@ p_peek (void)
s->stream_getc_for_read = ISOGetc;
else
s->stream_getc_for_read = s->stream_getc;
UNLOCK(Stream[sno].streamlock);
return(Yap_unify_constant(ARG2,MkIntTerm(ch)));
}
@ -2701,6 +2730,7 @@ p_set_input (void)
if (sno < 0)
return (FALSE);
Yap_c_input_stream = sno;
UNLOCK(Stream[sno].streamlock);
return (TRUE);
}
@ -2711,6 +2741,7 @@ p_set_output (void)
if (sno < 0)
return (FALSE);
Yap_c_output_stream = sno;
UNLOCK(Stream[sno].streamlock);
return (TRUE);
}
@ -2802,6 +2833,7 @@ p_write2 (void)
Yap_c_output_stream = old_output_stream;
return(FALSE);
}
UNLOCK(Stream[Yap_c_output_stream].streamlock);
/* notice: we must have ASP well set when using portray, otherwise
we cannot make recursive Prolog calls */
Yap_StartSlots();
@ -3224,13 +3256,16 @@ static Int
p_read2 (void)
{ /* '$read2'(+Flag,?Term,?Module,?Vars,-Pos,-Err,+Stream) */
int inp_stream;
Int out;
/* needs to change Yap_c_output_stream for write */
inp_stream = CheckStream (ARG7, Input_Stream_f, "read/3");
if (inp_stream == -1) {
return(FALSE);
}
return(do_read(inp_stream, 7));
UNLOCK(Stream[inp_stream].streamlock);
out = do_read(inp_stream, 7);
return out;
}
static Int
@ -3251,6 +3286,7 @@ p_user_file_name (void)
tout = MkAtomTerm(Yap_LookupAtom("charsio"));
else
tout = Stream[sno].u.file.user_name;
UNLOCK(Stream[sno].streamlock);
return (Yap_unify_constant (ARG2, tout));
}
@ -3272,6 +3308,7 @@ p_file_name (void)
tout = MkAtomTerm(Yap_LookupAtom("charsio"));
else
tout = MkAtomTerm(Stream[sno].u.file.name);
UNLOCK(Stream[sno].streamlock);
return Yap_unify_constant (ARG2, tout);
}
@ -3311,6 +3348,7 @@ p_cur_line_no (void)
}
else
tout = MkIntTerm (Stream[sno].linecount);
UNLOCK(Stream[sno].streamlock);
return (Yap_unify_constant (ARG2, tout));
}
@ -3318,8 +3356,7 @@ static Int
p_line_position (void)
{ /* '$line_position'(+Stream,-N) */
Term tout;
int sno =
CheckStream (ARG1, Input_Stream_f | Output_Stream_f | Append_Stream_f, "line_position/2");
int sno = CheckStream (ARG1, Input_Stream_f | Output_Stream_f | Append_Stream_f, "line_position/2");
if (sno < 0)
return (FALSE);
if (Stream[sno].status & Tty_Stream_f)
@ -3337,6 +3374,7 @@ p_line_position (void)
}
else
tout = MkIntTerm (Stream[sno].linepos);
UNLOCK(Stream[sno].streamlock);
return (Yap_unify_constant (ARG2, tout));
}
@ -3344,8 +3382,7 @@ static Int
p_character_count (void)
{ /* '$character_count'(+Stream,-N) */
Term tout;
int sno =
CheckStream (ARG1, Input_Stream_f | Output_Stream_f | Append_Stream_f, "character_count/2");
int sno = CheckStream (ARG1, Input_Stream_f | Output_Stream_f | Append_Stream_f, "character_count/2");
if (sno < 0)
return (FALSE);
if (Stream[sno].status & Tty_Stream_f)
@ -3365,6 +3402,7 @@ p_character_count (void)
tout = MkIntTerm (Stream[sno].charcount);
else
tout = MkIntTerm (YP_ftell (Stream[sno].u.file.file));
UNLOCK(Stream[sno].streamlock);
return (Yap_unify_constant (ARG2, tout));
}
@ -3377,6 +3415,7 @@ p_show_stream_flags(void)
if (sno < 0)
return (FALSE);
tout = MkIntTerm(Stream[sno].status);
UNLOCK(Stream[sno].streamlock);
return (Yap_unify (ARG2, tout));
}
@ -3385,7 +3424,7 @@ p_show_stream_position (void)
{ /* '$show_stream_position'(+Stream,Pos) */
Term sargs[3], tout;
int sno =
CheckStream (ARG1, Input_Stream_f | Output_Stream_f | Append_Stream_f, "stream_position/2");
CheckStream (ARG1, Input_Stream_f | Output_Stream_f | Append_Stream_f, "stream_position/2");
if (sno < 0)
return (FALSE);
if (Stream[sno].status & (Tty_Stream_f|Socket_Stream_f|Pipe_Stream_f|InMemory_Stream_f))
@ -3400,6 +3439,7 @@ p_show_stream_position (void)
}
sargs[1] = MkIntTerm (Stream[sno].linecount);
sargs[2] = MkIntTerm (Stream[sno].linepos);
UNLOCK(Stream[sno].streamlock);
tout = Yap_MkApplTerm (FunctorStreamPos, 3, sargs);
return (Yap_unify (ARG2, tout));
}
@ -3415,43 +3455,53 @@ p_set_stream_position (void)
}
tin = Deref (ARG2);
if (IsVarTerm (tin)) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(INSTANTIATION_ERROR, tin, "set_stream_position/2");
return (FALSE);
} else if (!(IsApplTerm (tin))) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(DOMAIN_ERROR_STREAM_POSITION, tin, "set_stream_position/2");
return (FALSE);
}
if (FunctorOfTerm (tin) == FunctorStreamPos) {
if (IsVarTerm (tp = ArgOfTerm (1, tin))) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(INSTANTIATION_ERROR, tp, "set_stream_position/2");
return (FALSE);
} else if (!IsIntTerm (tp)) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(DOMAIN_ERROR_STREAM_POSITION, tin, "set_stream_position/2");
return (FALSE);
}
if (!(Stream[sno].status & Seekable_Stream_f) ) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(PERMISSION_ERROR_REPOSITION_STREAM, ARG1,"set_stream_position/2");
return(FALSE);
}
char_pos = IntOfTerm (tp);
if (IsVarTerm (tp = ArgOfTerm (2, tin))) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(INSTANTIATION_ERROR, tp, "set_stream_position/2");
return (FALSE);
} else if (!IsIntTerm (tp)) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(DOMAIN_ERROR_STREAM_POSITION, tin, "set_stream_position/2");
return (FALSE);
}
Stream[sno].charcount = char_pos;
Stream[sno].linecount = IntOfTerm (tp);
if (IsVarTerm (tp = ArgOfTerm (3, tin))) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(INSTANTIATION_ERROR, tp, "set_stream_position/2");
return (FALSE);
} else if (!IsIntTerm (tp)) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(DOMAIN_ERROR_STREAM_POSITION, tin, "set_stream_position/2");
return (FALSE);
}
Stream[sno].linepos = IntOfTerm (tp);
if (YP_fseek (Stream[sno].u.file.file, (long) (char_pos), 0) == -1) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(SYSTEM_ERROR, tp,
"fseek failed for set_stream_position/2");
return(FALSE);
@ -3459,17 +3509,21 @@ p_set_stream_position (void)
Stream[sno].stream_getc = PlGetc;
} else if (FunctorOfTerm (tin) == FunctorStreamEOS) {
if (IsVarTerm (tp = ArgOfTerm (1, tin))) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(INSTANTIATION_ERROR, tp, "set_stream_position/2");
return (FALSE);
} else if (tp != MkAtomTerm(Yap_LookupAtom("at"))) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(DOMAIN_ERROR_STREAM_POSITION, tin, "set_stream_position/2");
return (FALSE);
}
if (!(Stream[sno].status & Seekable_Stream_f) ) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(PERMISSION_ERROR_REPOSITION_STREAM, ARG1,"set_stream_position/2");
return(FALSE);
}
if (YP_fseek (Stream[sno].u.file.file, 0L, SEEK_END) == -1) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(SYSTEM_ERROR, tp,
"fseek failed for set_stream_position/2");
return(FALSE);
@ -3480,6 +3534,7 @@ p_set_stream_position (void)
Stream[sno].linecount = 0;
Stream[sno].charcount = 0;
}
UNLOCK(Stream[sno].streamlock);
return (TRUE);
}
@ -3495,14 +3550,17 @@ p_get (void)
status = Stream[sno].status;
if (status & (Binary_Stream_f|Eof_Stream_f)) {
if (status & Binary_Stream_f) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(PERMISSION_ERROR_INPUT_BINARY_STREAM, ARG1, "get/2");
return(FALSE);
} else if (status & Eof_Error_Stream_f) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(PERMISSION_ERROR_INPUT_PAST_END_OF_STREAM, ARG1, "get/2");
return(FALSE);
}
}
while ((ch = Stream[sno].stream_getc(sno)) <= 32 && ch >= 0);
UNLOCK(Stream[sno].streamlock);
return (Yap_unify_constant (ARG2, MkIntTerm (ch)));
}
@ -3518,14 +3576,17 @@ p_get0 (void)
status = Stream[sno].status;
if (status & (Binary_Stream_f|Eof_Stream_f)) {
if (status & Binary_Stream_f) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(PERMISSION_ERROR_INPUT_BINARY_STREAM, ARG1, "get0/2");
return(FALSE);
} else if (status & (Eof_Error_Stream_f)) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(PERMISSION_ERROR_INPUT_PAST_END_OF_STREAM, ARG1, "get0/2");
return(FALSE);
}
}
out = Stream[sno].stream_getc(sno);
UNLOCK(Stream[sno].streamlock);
return (Yap_unify_constant (ARG2, MkIntTerm (out)) );
}
@ -3554,14 +3615,17 @@ p_get0_line_codes (void)
status = Stream[sno].status;
if (status & (Binary_Stream_f|Eof_Stream_f)) {
if (status & Binary_Stream_f) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(PERMISSION_ERROR_INPUT_BINARY_STREAM, ARG1, "get0/2");
return(FALSE);
} else if (status & (Eof_Error_Stream_f)) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(PERMISSION_ERROR_INPUT_PAST_END_OF_STREAM, ARG1, "get0/2");
return(FALSE);
}
}
out = read_line(sno);
UNLOCK(Stream[sno].streamlock);
return(Yap_unify(out,ARG2));
}
@ -3570,20 +3634,25 @@ p_get_byte (void)
{ /* '$get_byte'(Stream,-N) */
int sno = CheckStream (ARG1, Input_Stream_f, "get_byte/2");
Int status;
Term out;
if (sno < 0)
return(FALSE);
status = Stream[sno].status;
if (!(status & Binary_Stream_f) &&
yap_flags[STRICT_ISO_FLAG]) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(PERMISSION_ERROR_INPUT_TEXT_STREAM, ARG1, "get_byte/2");
return(FALSE);
}
if ((status & (Eof_Stream_f|Eof_Error_Stream_f)) == (Eof_Stream_f|Eof_Error_Stream_f)) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(PERMISSION_ERROR_INPUT_PAST_END_OF_STREAM, ARG1, "get_byte/2");
return(FALSE);
}
return (Yap_unify_constant (ARG2, MkIntTerm (Stream[sno].stream_getc(sno))));
out = MkIntTerm (Stream[sno].stream_getc(sno));
UNLOCK(Stream[sno].streamlock);
return (Yap_unify_constant (ARG2, out));
}
static Int
@ -3593,6 +3662,7 @@ p_put (void)
if (sno < 0)
return (FALSE);
if (Stream[sno].status & Binary_Stream_f) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(PERMISSION_ERROR_OUTPUT_BINARY_STREAM, ARG1, "get0/2");
return(FALSE);
}
@ -3601,6 +3671,7 @@ p_put (void)
* if (!(Stream[sno].status & Null_Stream_f))
* yap_fflush(Stream[sno].u.file.file);
*/
UNLOCK(Stream[sno].streamlock);
return (TRUE);
}
@ -3612,6 +3683,7 @@ p_put_byte (void)
return (FALSE);
if (!(Stream[sno].status & Binary_Stream_f) &&
yap_flags[STRICT_ISO_FLAG]) {
UNLOCK(Stream[sno].streamlock);
Yap_Error(PERMISSION_ERROR_OUTPUT_TEXT_STREAM, ARG1, "get0/2");
return(FALSE);
}
@ -3620,6 +3692,7 @@ p_put_byte (void)
* if (!(Stream[sno].status & Null_Stream_f))
* yap_fflush(Stream[sno].u.file.file);
*/
UNLOCK(Stream[sno].streamlock);
return (TRUE);
}
@ -4481,9 +4554,7 @@ static Int
p_format(void)
{ /* 'format'(Control,Args) */
Int res;
//LOCK(BGL);
res = format(Deref(ARG1),Deref(ARG2), Yap_c_output_stream);
//UNLOCK(BGL);
return res;
}
@ -4494,17 +4565,15 @@ p_format2(void)
int old_c_stream = Yap_c_output_stream;
Int out;
//LOCK(BGL);
/* needs to change Yap_c_output_stream for write */
Yap_c_output_stream = CheckStream (ARG1, Output_Stream_f, "format/3");
UNLOCK(Stream[Yap_c_output_stream].streamlock);
if (Yap_c_output_stream == -1) {
Yap_c_output_stream = old_c_stream;
//UNLOCK(BGL);
return(FALSE);
}
out = format(Deref(ARG2),Deref(ARG3),Yap_c_output_stream);
Yap_c_output_stream = old_c_stream;
// UNLOCK(BGL);
return(out);
}
@ -4517,9 +4586,12 @@ p_skip (void)
if (sno < 0)
return (FALSE);
if (n < 0 || n > 127)
if (n < 0 || n > 127) {
UNLOCK(Stream[sno].streamlock);
return (FALSE);
}
while ((ch = Stream[sno].stream_getc(sno)) != n && ch != -1);
UNLOCK(Stream[sno].streamlock);
return (TRUE);
}
@ -4530,7 +4602,8 @@ p_flush (void)
if (sno < 0)
return (FALSE);
yap_fflush (sno);
return (TRUE);
UNLOCK(Stream[sno].streamlock);
return (TRUE);
}
static Int
@ -4538,8 +4611,11 @@ p_flush_all_streams (void)
{ /* $flush_all_streams */
#if BROKEN_FFLUSH_NULL
int i;
for (i = 0; i < MaxStreams; ++i)
for (i = 0; i < MaxStreams; ++i) {
LOCK(Stream[i].streamlock);
yap_fflush (i);
UNLOCK(Stream[i].streamlock);
}
#else
fflush (NULL);
#endif
@ -4589,6 +4665,7 @@ p_stream_select(void)
return(FALSE);
fd = GetStreamFd(sno);
FD_SET(fd, &readfds);
UNLOCK(Stream[sno].streamlock);
if (fd > fdmax)
fdmax = fd;
ti = TailOfTerm(ti);
@ -4664,6 +4741,7 @@ p_stream_select(void)
tout = MkPairTerm(Head,tout);
else
tout = MkPairTerm(TermNil,tout);
UNLOCK(Stream[sno].streamlock);
t1 = TailOfTerm(t1);
}
/* we're done, just pass the info back */
@ -4912,6 +4990,7 @@ Yap_StreamToFileNo(Term t)
int sno =
CheckStream(t, (Input_Stream_f|Output_Stream_f), "StreamToFileNo");
if (Stream[sno].status & Pipe_Stream_f) {
UNLOCK(Stream[sno].streamlock);
#if _MSC_VER || defined(__MINGW32__)
return((int)(Stream[sno].u.pipe.hdl));
#else
@ -4919,11 +4998,14 @@ Yap_StreamToFileNo(Term t)
#endif
#if USE_SOCKET
} else if (Stream[sno].status & Socket_Stream_f) {
UNLOCK(Stream[sno].streamlock);
return(Stream[sno].u.socket.fd);
#endif
} else if (Stream[sno].status & (Null_Stream_f|InMemory_Stream_f)) {
UNLOCK(Stream[sno].streamlock);
return(-1);
} else {
UNLOCK(Stream[sno].streamlock);
return(YP_fileno(Stream[sno].u.file.file));
}
}

View File

@ -54,12 +54,15 @@ LookupModule(Term a)
/* prolog module */
if (a == 0)
return 0;
LOCK(ModulesLock);
for (i = 0; i < NoOfModules; ++i) {
if (ModuleName[i] == a) {
UNLOCK(ModulesLock);
return i;
}
}
ModuleName[i = NoOfModules++] = a;
UNLOCK(ModulesLock);
if (NoOfModules == MaxModules) {
Yap_Error(SYSTEM_ERROR,a,"number of modules overflowed");
}
@ -133,9 +136,12 @@ cont_current_module(void)
Int imod = IntOfTerm(EXTRA_CBACK_ARG(1,1));
Term t = ModuleName[imod];
LOCK(ModulesLock);
if (imod == NoOfModules) {
UNLOCK(ModulesLock);
cut_fail();
}
UNLOCK(ModulesLock);
EXTRA_CBACK_ARG(1,1) = MkIntTerm(imod+1);
return(Yap_unify(ARG1,t));
}

View File

@ -697,6 +697,7 @@ Yap_tokenizer(int inp_stream)
ScannerExtraBlocks = NULL;
l = NULL;
p = NULL; /* Just to make lint happy */
LOCK(Stream[inp_stream].streamlock);
ch = Nxtch(inp_stream);
do {
int och, quote, isvar;
@ -713,6 +714,7 @@ Yap_tokenizer(int inp_stream)
if (p)
p->Tok = Ord(kind = eot_tok);
/* serious error now */
UNLOCK(Stream[inp_stream].streamlock);
return l;
}
if (!l)
@ -757,6 +759,7 @@ Yap_tokenizer(int inp_stream)
if (p)
p->Tok = Ord(kind = eot_tok);
/* serious error now */
UNLOCK(Stream[inp_stream].streamlock);
return l;
}
*charp++ = ch;
@ -771,6 +774,7 @@ Yap_tokenizer(int inp_stream)
if (p)
t->Tok = Ord(kind = eot_tok);
/* serious error now */
UNLOCK(Stream[inp_stream].streamlock);
return l;
}
t->TokInfo = Unsigned(ae);
@ -792,6 +796,7 @@ Yap_tokenizer(int inp_stream)
cherr = 0;
if (!(ptr = AllocScannerMemory(4096))) {
UNLOCK(Stream[inp_stream].streamlock);
Yap_ErrorMessage = "Trail Overflow";
Yap_Error_TYPE = OUT_OF_TRAIL_ERROR;
if (p)
@ -800,6 +805,7 @@ Yap_tokenizer(int inp_stream)
return l;
}
if (ASP-H < 1024) {
UNLOCK(Stream[inp_stream].streamlock);
Yap_ErrorMessage = "Stack Overflow";
Yap_Error_TYPE = OUT_OF_STACK_ERROR;
if (p)
@ -808,6 +814,7 @@ Yap_tokenizer(int inp_stream)
return l;
}
if ((t->TokInfo = get_num(&cha,&cherr,inp_stream,Nxtch,QuotedNxtch,ptr,4096)) == 0L) {
UNLOCK(Stream[inp_stream].streamlock);
if (p)
p->Tok = Ord(kind = eot_tok);
/* serious error now */
@ -821,6 +828,7 @@ Yap_tokenizer(int inp_stream)
t->TokPos = GetCurInpPos(inp_stream);
e = (TokEntry *) AllocScannerMemory(sizeof(TokEntry));
if (e == NULL) {
UNLOCK(Stream[inp_stream].streamlock);
Yap_ErrorMessage = "Trail Overflow";
Yap_Error_TYPE = OUT_OF_TRAIL_ERROR;
if (p)
@ -850,6 +858,7 @@ Yap_tokenizer(int inp_stream)
t->TokPos = GetCurInpPos(inp_stream);
e2 = (TokEntry *) AllocScannerMemory(sizeof(TokEntry));
if (e2 == NULL) {
UNLOCK(Stream[inp_stream].streamlock);
Yap_ErrorMessage = "Trail Overflow";
Yap_Error_TYPE = OUT_OF_TRAIL_ERROR;
if (p)
@ -881,6 +890,7 @@ Yap_tokenizer(int inp_stream)
t->TokPos = GetCurInpPos(inp_stream);
e2 = (TokEntry *) AllocScannerMemory(sizeof(TokEntry));
if (e2 == NULL) {
UNLOCK(Stream[inp_stream].streamlock);
Yap_ErrorMessage = "Trail Overflow";
Yap_Error_TYPE = OUT_OF_TRAIL_ERROR;
t->Tok = Ord(kind = eot_tok);
@ -943,6 +953,7 @@ Yap_tokenizer(int inp_stream)
}
++len;
if (charp > (char *)AuxSp - 1024) {
UNLOCK(Stream[inp_stream].streamlock);
/* Not enough space to read in the string. */
Yap_Error_TYPE = OUT_OF_AUXSPACE_ERROR;
Yap_ErrorMessage = "not enough space to read in string or quoted atom";
@ -956,6 +967,7 @@ Yap_tokenizer(int inp_stream)
if (quote == '"') {
mp = AllocScannerMemory(len + 1);
if (mp == NULL) {
UNLOCK(Stream[inp_stream].streamlock);
Yap_ErrorMessage = "not enough heap space to read in string or quoted atom";
Yap_ReleasePreAllocCodeSpace((CODEADDR)TokImage);
t->Tok = Ord(kind = eot_tok);
@ -1062,6 +1074,7 @@ Yap_tokenizer(int inp_stream)
/* insert an error token to inform the system of what happened */
TokEntry *e = (TokEntry *) AllocScannerMemory(sizeof(TokEntry));
if (e == NULL) {
UNLOCK(Stream[inp_stream].streamlock);
Yap_ErrorMessage = "Trail Overflow";
Yap_Error_TYPE = OUT_OF_TRAIL_ERROR;
p->Tok = Ord(kind = eot_tok);
@ -1077,6 +1090,7 @@ Yap_tokenizer(int inp_stream)
p = e;
}
} while (kind != eot_tok);
UNLOCK(Stream[inp_stream].streamlock);
return (l);
}

163
H/Heap.h
View File

@ -10,7 +10,7 @@
* File: Heap.h *
* mods: *
* comments: Heap Init Structure *
* version: $Id: Heap.h,v 1.96 2006-04-28 13:23:23 vsc Exp $ *
* version: $Id: Heap.h,v 1.97 2006-04-28 15:48:32 vsc Exp $ *
*************************************************************************/
/* information that can be stored in Code Space */
@ -19,6 +19,14 @@
#ifndef HEAP_H
#define HEAP_H 1
#if defined(YAPOR) || defined(THREADS)
#define WL wl[worker_id]
#define RINFO rinfo[worker_id]
#else
#define WL wl
#define RINFO rinfo
#endif
#ifndef INT_KEYS_DEFAULT_SIZE
#define INT_KEYS_DEFAULT_SIZE 256
#endif
@ -85,6 +93,10 @@ typedef struct worker_local_struct {
#ifdef USE_GMP
mpz_t big_tmp;
#endif
union CONSULT_OBJ *consultsp;
union CONSULT_OBJ *consultbase;
union CONSULT_OBJ *consultlow;
UInt consultcapacity;
UInt active_signals;
UInt i_pred_arity;
yamop *prof_end;
@ -244,10 +256,6 @@ typedef struct various_codes {
struct yami *clause;
Functor func;
} clausecode[1];
union CONSULT_OBJ *consultsp;
union CONSULT_OBJ *consultbase;
union CONSULT_OBJ *consultlow;
UInt consultcapacity;
#if HAVE_LIBREADLINE
char *readline_buf, *readline_pos;
#endif
@ -306,6 +314,7 @@ typedef struct various_codes {
#ifdef LOW_LEVEL_TRACER
lockvar low_level_trace_lock;
#endif
lockvar modules_lock;
#endif
unsigned int size_of_overflow;
Term module_name[MaxModules];
@ -766,48 +775,8 @@ struct various_codes *Yap_heap_regs;
#define WakeUpCode Yap_heap_regs->wake_up_code
#endif
#if defined(YAPOR) || defined(THREADS)
/* The old stack pointers */
#define OldASP rinfo[worker_id].old_ASP
#define OldLCL0 rinfo[worker_id].old_LCL0
#define OldTR rinfo[worker_id].old_TR
#define OldGlobalBase rinfo[worker_id].old_GlobalBase
#define OldH rinfo[worker_id].old_H
#define OldH0 rinfo[worker_id].old_H0
#define OldTrailBase rinfo[worker_id].old_TrailBase
#define OldTrailTop rinfo[worker_id].old_TrailTop
#define OldHeapBase rinfo[worker_id].old_HeapBase
#define OldHeapTop rinfo[worker_id].old_HeapTop
#define ClDiff rinfo[worker_id].cl_diff
#define GDiff rinfo[worker_id].g_diff
#define HDiff rinfo[worker_id].h_diff
#define LDiff rinfo[worker_id].l_diff
#define TrDiff rinfo[worker_id].tr_diff
#define XDiff rinfo[worker_id].x_diff
#define DelayDiff rinfo[worker_id].delay_diff
#define FormatInfo Yap_heap_regs->wl[worker_id].f_info
#define ScannerStack Yap_heap_regs->wl[worker_id].scanner_stack
#define ScannerExtraBlocks Yap_heap_regs->wl[worker_id].scanner_extra_blocks
#define SignalLock Yap_heap_regs->wl[worker_id].signal_lock
#define WPP Yap_heap_regs->wl[worker_id].wpp
#define UncaughtThrow Yap_heap_regs->wl[worker_id].uncaught_throw
#define DoingUndefp Yap_heap_regs->wl[worker_id].doing_undefp
#define Yap_BigTmp Yap_heap_regs->wl[worker_id].big_tmp
#define ActiveSignals Yap_heap_regs->wl[worker_id].active_signals
#define IPredArity Yap_heap_regs->wl[worker_id].i_pred_arity
#define ProfEnd Yap_heap_regs->wl[worker_id].prof_end
#define StartLine Yap_heap_regs->wl[worker_id].start_line
#define ScratchPad Yap_heap_regs->wl[worker_id].scratchpad
#ifdef COROUTINING
#define WokenGoals Yap_heap_regs->wl[worker_id].woken_goals
#define AttsMutableList Yap_heap_regs->wl[worker_id].atts_mutable_list
#endif
/* support for generations with backtracking */
#define GcCalls Yap_heap_regs->wl[worker_id].gc_calls
#define GcGeneration Yap_heap_regs->wl[worker_id].gc_generation
#define GcPhase Yap_heap_regs->wl[worker_id].gc_phase
#define GcCurrentPhase Yap_heap_regs->wl[worker_id].gc_current_phase
#define TotGcTime Yap_heap_regs->wl[worker_id].tot_gc_time
#define TotGcRecovered Yap_heap_regs->wl[worker_id].tot_gc_recovered
#define total_marked Yap_heap_regs->wl[worker_id].tot_marked
#define total_oldies Yap_heap_regs->wl[worker_id].tot_oldies
#if DEBUG
@ -835,54 +804,57 @@ struct various_codes *Yap_heap_regs;
#define db_root Yap_heap_regs->wl[worker_id].DB_root
#define db_nil Yap_heap_regs->wl[worker_id].DB_nil
#define cont_top Yap_heap_regs->wl[worker_id].conttop
#define Yap_gc_restore Yap_heap_regs->wl[worker_id].gc_restore
#define TrustLUCode Yap_heap_regs->wl[worker_id].trust_lu_code
#define DynamicArrays Yap_heap_regs->wl[worker_id].dynamic_arrays
#define StaticArrays Yap_heap_regs->wl[worker_id].static_arrays
#else
#define OldASP rinfo.old_ASP
#define OldLCL0 rinfo.old_LCL0
#define OldTR rinfo.old_TR
#define OldGlobalBase rinfo.old_GlobalBase
#define OldH rinfo.old_H
#define OldH0 rinfo.old_H0
#define OldTrailBase rinfo.old_TrailBase
#define OldTrailTop rinfo.old_TrailTop
#define OldHeapBase rinfo.old_HeapBase
#define OldHeapTop rinfo.old_HeapTop
#define ClDiff rinfo.cl_diff
#define GDiff rinfo.g_diff
#define HDiff rinfo.h_diff
#define LDiff rinfo.l_diff
#define TrDiff rinfo.tr_diff
#define XDiff rinfo.x_diff
#define DelayDiff rinfo.delay_diff
#define FormatInfo Yap_heap_regs->wl.f_info
#define ScannerStack Yap_heap_regs->wl.scanner_stack
#define ScannerExtraBlocks Yap_heap_regs->wl.scanner_extra_blocks
#define Yap_BigTmp Yap_heap_regs->wl.big_tmp
#define ActiveSignals Yap_heap_regs->wl.active_signals
#define IPredArity Yap_heap_regs->wl.i_pred_arity
#define ProfEnd Yap_heap_regs->wl.prof_end
#define UncaughtThrow Yap_heap_regs->wl.uncaught_throw
#define DoingUndefp Yap_heap_regs->wl.doing_undefp
#define StartLine Yap_heap_regs->wl.start_line
#define ScratchPad Yap_heap_regs->wl.scratchpad
#endif
#define OldASP RINFO.old_ASP
#define OldLCL0 RINFO.old_LCL0
#define OldTR RINFO.old_TR
#define OldGlobalBase RINFO.old_GlobalBase
#define OldH RINFO.old_H
#define OldH0 RINFO.old_H0
#define OldTrailBase RINFO.old_TrailBase
#define OldTrailTop RINFO.old_TrailTop
#define OldHeapBase RINFO.old_HeapBase
#define OldHeapTop RINFO.old_HeapTop
#define ClDiff RINFO.cl_diff
#define GDiff RINFO.g_diff
#define HDiff RINFO.h_diff
#define LDiff RINFO.l_diff
#define TrDiff RINFO.tr_diff
#define XDiff RINFO.x_diff
#define DelayDiff RINFO.delay_diff
/* current consult stack */
#define ConsultSp Yap_heap_regs->WL.consultsp
/* top of consult stack */
#define ConsultBase Yap_heap_regs->WL.consultbase
/* low-water mark for consult */
#define ConsultLow Yap_heap_regs->WL.consultlow
/* current maximum number of cells in consult stack */
#define ConsultCapacity Yap_heap_regs->WL.consultcapacity
#define FormatInfo Yap_heap_regs->WL.f_info
#define ScannerStack Yap_heap_regs->WL.scanner_stack
#define ScannerExtraBlocks Yap_heap_regs->WL.scanner_extra_blocks
#define Yap_BigTmp Yap_heap_regs->WL.big_tmp
#define ActiveSignals Yap_heap_regs->WL.active_signals
#define IPredArity Yap_heap_regs->WL.i_pred_arity
#define ProfEnd Yap_heap_regs->WL.prof_end
#define UncaughtThrow Yap_heap_regs->WL.uncaught_throw
#define DoingUndefp Yap_heap_regs->WL.doing_undefp
#define StartLine Yap_heap_regs->WL.start_line
#define ScratchPad Yap_heap_regs->WL.scratchpad
#ifdef COROUTINING
#define WokenGoals Yap_heap_regs->wl.woken_goals
#define AttsMutableList Yap_heap_regs->wl.atts_mutable_list
#endif
#define GcGeneration Yap_heap_regs->wl.gc_generation
#define GcPhase Yap_heap_regs->wl.gc_phase
#define GcCurrentPhase Yap_heap_regs->wl.gc_current_phase
#define GcCalls Yap_heap_regs->wl.gc_calls
#define TotGcTime Yap_heap_regs->wl.tot_gc_time
#define TotGcRecovered Yap_heap_regs->wl.tot_gc_recovered
#define Yap_gc_restore Yap_heap_regs->wl.gc_restore
#define TrustLUCode Yap_heap_regs->wl.trust_lu_code
#define DynamicArrays Yap_heap_regs->wl.dynamic_arrays
#define StaticArrays Yap_heap_regs->wl.static_arrays
#define WokenGoals Yap_heap_regs->WL.woken_goals
#define AttsMutableList Yap_heap_regs->WL.atts_mutable_list
#endif
#define GcGeneration Yap_heap_regs->WL.gc_generation
#define GcPhase Yap_heap_regs->WL.gc_phase
#define GcCurrentPhase Yap_heap_regs->WL.gc_current_phase
#define GcCalls Yap_heap_regs->WL.gc_calls
#define TotGcTime Yap_heap_regs->WL.tot_gc_time
#define TotGcRecovered Yap_heap_regs->WL.tot_gc_recovered
#define Yap_gc_restore Yap_heap_regs->WL.gc_restore
#define TrustLUCode Yap_heap_regs->WL.trust_lu_code
#define DynamicArrays Yap_heap_regs->WL.dynamic_arrays
#define StaticArrays Yap_heap_regs->WL.static_arrays
#define profiling Yap_heap_regs->compiler_profiling
#define call_counting Yap_heap_regs->compiler_call_counting
#define compile_arrays Yap_heap_regs->compiler_compile_arrays
@ -912,6 +884,7 @@ struct various_codes *Yap_heap_regs;
#define DeadStaticClausesLock Yap_heap_regs->dead_static_clauses_lock
#define DeadMegaClausesLock Yap_heap_regs->dead_mega_clauses_lock
#define DeadStaticIndicesLock Yap_heap_regs->dead_static_indices_lock
#define ModulesLock Yap_heap_regs->modules_lock
#endif
#define CreepCode Yap_heap_regs->creep_code
#define UndefCode Yap_heap_regs->undef_code
@ -933,14 +906,6 @@ struct various_codes *Yap_heap_regs;
/* initially allow for files with up to 1024 predicates. This number
is extended whenever needed */
#define InitialConsultCapacity 1024
/* current consult stack */
#define ConsultSp (Yap_heap_regs->consultsp )
/* top of consult stack */
#define ConsultBase (Yap_heap_regs->consultbase )
/* low-water mark for consult */
#define ConsultLow (Yap_heap_regs->consultlow )
/* current maximum number of cells in consult stack */
#define ConsultCapacity (Yap_heap_regs->consultcapacity )
#if HAVE_LIBREADLINE
#define ReadlineBuf Yap_heap_regs->readline_buf
#define ReadlinePos Yap_heap_regs->readline_pos

View File

@ -65,14 +65,17 @@ typedef struct stream_desc
} socket;
#endif
} u;
Int charcount, linecount, linepos;
Int status;
Int och;
#if defined(YAPOR) || defined(THREADS)
lockvar streamlock; /* protect stream access */
#endif
int (* stream_putc)(int, int); /* function the stream uses for writing */
int (* stream_getc)(int); /* function the stream uses for reading */
/* function the stream uses for parser. It may be different if the ISO
character conversion is on */
int (* stream_getc_for_read)(int);
Int charcount, linecount, linepos;
Int status;
Int och;
}
StreamDesc;

View File

@ -11,8 +11,12 @@
* File: rheap.h *
* comments: walk through heap code *
* *
* Last rev: $Date: 2006-04-28 13:23:23 $,$Author: vsc $ *
* Last rev: $Date: 2006-04-28 15:48:33 $,$Author: vsc $ *
* $Log: not supported by cvs2svn $
* Revision 1.65 2006/04/28 13:23:23 vsc
* fix number of overflow bugs affecting threaded version
* make current_op faster.
*
* Revision 1.64 2006/03/22 20:07:28 vsc
* take better care of zombies
*
@ -404,24 +408,26 @@ restore_codes(void)
(Functor)AtomAdjust((Atom)(Yap_heap_regs->clausecode->func));
}
}
#if !defined(THREADS)
/* restore consult stack. It consists of heap pointers, so it
is easy to fix.
*/
Yap_heap_regs->consultlow =
ConsultObjAdjust(Yap_heap_regs->consultlow);
Yap_heap_regs->consultbase =
ConsultObjAdjust(Yap_heap_regs->consultbase);
Yap_heap_regs->consultsp =
ConsultObjAdjust(Yap_heap_regs->consultsp);
Yap_heap_regs->wl.consultlow =
ConsultObjAdjust(Yap_heap_regs->wl.consultlow);
Yap_heap_regs->wl.consultbase =
ConsultObjAdjust(Yap_heap_regs->wl.consultbase);
Yap_heap_regs->wl.consultsp =
ConsultObjAdjust(Yap_heap_regs->wl.consultsp);
{
/* we assume all pointers have the same size */
register consult_obj *pt = Yap_heap_regs->consultsp;
register consult_obj *pt = Yap_heap_regs->wl.consultsp;
while (pt <
Yap_heap_regs->consultlow+Yap_heap_regs->consultcapacity) {
Yap_heap_regs->wl.consultlow+Yap_heap_regs->wl.consultcapacity) {
pt->p = PropAdjust(pt->p);
pt ++;
}
}
#endif
#if USE_THREADED_CODE
Yap_heap_regs->op_rtable = (opentry *)
CodeAddrAdjust((CODEADDR)(Yap_heap_regs->op_rtable));

View File

@ -16,6 +16,7 @@
<h2>Yap-5.1.2:</h2>
<ul>
<li> NEW: lock streams while using them (concurrent writing is still allowed).</li>
<li> FIXED: make current_op only walk over atoms.</li>
<li> FIXED: memory corruption when copying consult stack (obs Paulo Moura).</li>
<li> FIXED: get rid of some silly locks.</li>
@ -25,7 +26,7 @@
<li> FIXED: system/1 and shell/1 should check return code (obs Nicos
Angelopoulos).</li>
<li> FIXED: thread_peek_message should use aliases (obs Paulo Moura).</li>
<li> FIXED: garbage collector should no rewrite cp_tr fields until
<li> FIXED: garbage collector should not rewrite cp_tr fields until
after marking (obs Paulo Moura).</li>
<li> FIXED: garbage collector was allowing garbage trail entries for
multi-assignment variables. Namely, old var value might point to new space