SWI portability
This commit is contained in:
parent
1bba29c646
commit
7cf4e9442c
@ -937,6 +937,8 @@ COMMON(word) pl_get_prolog_flag(term_t key, term_t value);
|
||||
COMMON(word) pl_prolog_flag5(term_t key, term_t value, word scope, word access, word type, control_t h);
|
||||
COMMON(foreign_t) pl_prolog_flag(term_t name, term_t value, control_t h);
|
||||
|
||||
COMMON(struct tm *) PL_localtime_r(const time_t *t, struct tm *r);
|
||||
|
||||
/* inlines that need ARG_LD */
|
||||
static inline intptr_t
|
||||
skip_list(Word l, Word *tailp ARG_LD) {
|
||||
|
116
os/pl-cstack.c
116
os/pl-cstack.c
@ -89,15 +89,49 @@ get_trace_store(void)
|
||||
}
|
||||
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
next_btrace_id() produces the id for the next backtrace and sets
|
||||
bt->current to the subsequent id. Although bt is thread-local, it may be
|
||||
called from a signal handler or (Windows) exception. We cannot use
|
||||
locking because the mutex functions are not async signal safe. So, we
|
||||
use atomic instructions if possible. Otherwise, we ensure consistency of
|
||||
the datastructures, but we may overwrite an older stack trace.
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
static int
|
||||
next_btrace_id(btrace *bt)
|
||||
{ int current;
|
||||
#ifdef COMPARE_AND_SWAP
|
||||
int next;
|
||||
|
||||
do
|
||||
{ current = bt->current;
|
||||
next = current+1;
|
||||
if ( next == SAVE_TRACES )
|
||||
next = 0;
|
||||
} while ( !COMPARE_AND_SWAP(&bt->current, current, next) );
|
||||
#else
|
||||
current = bt->current++ % SAVE_TRACES;
|
||||
|
||||
if ( bt->current >= SAVE_TRACES )
|
||||
bt->current %= SAVE_TRACES;
|
||||
#endif
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
save_backtrace(const char *why)
|
||||
{ btrace *bt = get_trace_store();
|
||||
|
||||
if ( bt )
|
||||
{ btrace_stack *s = &bt->dumps[bt->current];
|
||||
{ btrace_stack *s;
|
||||
unw_cursor_t cursor; unw_context_t uc;
|
||||
int depth;
|
||||
int current = next_btrace_id(bt);
|
||||
|
||||
s = &bt->dumps[current];
|
||||
unw_getcontext(&uc);
|
||||
unw_init_local(&cursor, &uc);
|
||||
for(depth=0; unw_step(&cursor) > 0 && depth < MAX_DEPTH; depth++)
|
||||
@ -107,9 +141,6 @@ save_backtrace(const char *why)
|
||||
}
|
||||
s->name = why;
|
||||
s->depth = depth;
|
||||
|
||||
if ( ++bt->current == SAVE_TRACES )
|
||||
bt->current = 0;
|
||||
}
|
||||
|
||||
}
|
||||
@ -228,6 +259,33 @@ get_trace_store(void)
|
||||
}
|
||||
|
||||
|
||||
/* Copy of same function above. Relies on a different btrace structure.
|
||||
Ideally, this should be shared :-(
|
||||
*/
|
||||
|
||||
static int
|
||||
next_btrace_id(btrace *bt)
|
||||
{ int current;
|
||||
#ifdef COMPARE_AND_SWAP
|
||||
int next;
|
||||
|
||||
do
|
||||
{ current = bt->current;
|
||||
next = current+1;
|
||||
if ( next == SAVE_TRACES )
|
||||
next = 0;
|
||||
} while ( !COMPARE_AND_SWAP(&bt->current, current, next) );
|
||||
#else
|
||||
current = bt->current++ % SAVE_TRACES;
|
||||
|
||||
if ( bt->current >= SAVE_TRACES )
|
||||
bt->current %= SAVE_TRACES;
|
||||
#endif
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
save_backtrace(const char *why)
|
||||
{ btrace *bt = get_trace_store();
|
||||
@ -235,15 +293,14 @@ save_backtrace(const char *why)
|
||||
if ( bt )
|
||||
{ void *array[100];
|
||||
size_t frames;
|
||||
int current = next_btrace_id(bt);
|
||||
|
||||
frames = backtrace(array, sizeof(array)/sizeof(void *));
|
||||
bt->sizes[bt->current] = frames;
|
||||
if ( bt->symbols[bt->current] )
|
||||
free(bt->symbols[bt->current]);
|
||||
bt->symbols[bt->current] = backtrace_symbols(array, frames);
|
||||
bt->why[bt->current] = why;
|
||||
if ( ++bt->current == SAVE_TRACES )
|
||||
bt->current = 0;
|
||||
bt->sizes[current] = frames;
|
||||
if ( bt->symbols[current] )
|
||||
free(bt->symbols[current]);
|
||||
bt->symbols[current] = backtrace_symbols(array, frames);
|
||||
bt->why[current] = why;
|
||||
}
|
||||
}
|
||||
|
||||
@ -358,6 +415,9 @@ initBackTrace(void)
|
||||
*/
|
||||
#define MAX_MODULE_NAME_LENGTH 64
|
||||
|
||||
#define LOCK() PL_LOCK(L_CSTACK)
|
||||
#define UNLOCK() PL_UNLOCK(L_CSTACK)
|
||||
|
||||
typedef struct
|
||||
{ char name[MAX_FUNCTION_NAME_LENGTH]; /* function called */
|
||||
DWORD64 offset; /* offset in function */
|
||||
@ -397,6 +457,32 @@ get_trace_store(void)
|
||||
return LD->btrace_store;
|
||||
}
|
||||
|
||||
/* Copy of same function above. Relies on a different btrace structure.
|
||||
Ideally, this should be shared :-(
|
||||
*/
|
||||
|
||||
static int
|
||||
next_btrace_id(btrace *bt)
|
||||
{ int current;
|
||||
#ifdef COMPARE_AND_SWAP
|
||||
int next;
|
||||
|
||||
do
|
||||
{ current = bt->current;
|
||||
next = current+1;
|
||||
if ( next == SAVE_TRACES )
|
||||
next = 0;
|
||||
} while ( !COMPARE_AND_SWAP(&bt->current, current, next) );
|
||||
#else
|
||||
current = bt->current++ % SAVE_TRACES;
|
||||
|
||||
if ( bt->current >= SAVE_TRACES )
|
||||
bt->current %= SAVE_TRACES;
|
||||
#endif
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
int backtrace(btrace_stack* trace, PEXCEPTION_POINTERS pExceptionInfo)
|
||||
{ STACKFRAME64 frame;
|
||||
CONTEXT context;
|
||||
@ -406,7 +492,6 @@ int backtrace(btrace_stack* trace, PEXCEPTION_POINTERS pExceptionInfo)
|
||||
char symbolScratch[sizeof(SYMBOL_INFO) + MAX_SYMBOL_LEN];
|
||||
SYMBOL_INFO* symbol = (SYMBOL_INFO*)&symbolScratch;
|
||||
IMAGEHLP_MODULE64 moduleInfo;
|
||||
EXCEPTION_POINTERS *pExp = NULL;
|
||||
DWORD64 offset;
|
||||
DWORD imageType;
|
||||
int skip = 0;
|
||||
@ -529,11 +614,12 @@ void
|
||||
win_save_backtrace(const char *why, PEXCEPTION_POINTERS pExceptionInfo)
|
||||
{ btrace *bt = get_trace_store();
|
||||
if ( bt )
|
||||
{ btrace_stack *s = &bt->dumps[bt->current];
|
||||
{ int current = next_btrace_id(bt);
|
||||
btrace_stack *s = &bt->dumps[current];
|
||||
LOCK();
|
||||
s->depth = backtrace(s, pExceptionInfo);
|
||||
UNLOCK();
|
||||
s->name = why;
|
||||
if ( ++bt->current == SAVE_TRACES )
|
||||
bt->current = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1273,7 +1273,9 @@ cleanupPrologFlags(void)
|
||||
{ Table t = GD->prolog_flag.table;
|
||||
|
||||
GD->prolog_flag.table = NULL;
|
||||
#ifdef O_PLMT
|
||||
t->free_symbol = freeSymbolPrologFlagTable;
|
||||
#endif
|
||||
destroyHTable(t);
|
||||
}
|
||||
}
|
||||
|
@ -173,7 +173,11 @@ rehashHTable(Table ht, Symbol map)
|
||||
{ Symbol *newentries, *oldentries;
|
||||
int newbuckets, oldbuckets;
|
||||
int i;
|
||||
#ifdef O_PLMT
|
||||
int safe_copy = (ht->mutex != NULL);
|
||||
#else
|
||||
int safe_copy = TRUE;
|
||||
#endif
|
||||
|
||||
newbuckets = ht->buckets*2;
|
||||
newentries = allocHTableEntries(newbuckets);
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef TABLE_H_INCLUDED
|
||||
|
162
os/pl-tai.c
162
os/pl-tai.c
@ -1,11 +1,9 @@
|
||||
/* $Id$
|
||||
|
||||
Part of SWI-Prolog
|
||||
/* Part of SWI-Prolog
|
||||
|
||||
Author: Jan Wielemaker
|
||||
E-mail: J.Wielemaker@cs.vu.nl
|
||||
WWW: http://www.swi-prolog.org
|
||||
Copyright (C): 1985-2010, University of Amsterdam
|
||||
Copyright (C): 1985-2012, University of Amsterdam
|
||||
VU University Amsterdam
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
@ -20,17 +18,10 @@
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Solaris has asctime_r() with 3 arguments. Using _POSIX_PTHREAD_SEMANTICS
|
||||
is supposed to give the POSIX standard one.
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#if defined(__sun__) || defined(__sun)
|
||||
#define _POSIX_PTHREAD_SEMANTICS 1
|
||||
#endif
|
||||
#define __MINGW_USE_VC2005_COMPAT /* Get Windows time_t as 64-bit */
|
||||
|
||||
#include <math.h>
|
||||
#include "pl-incl.h"
|
||||
@ -62,37 +53,6 @@ extern long timezone;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef localtime_r
|
||||
struct tm *localtime_r (const time_t *, struct tm *);
|
||||
|
||||
struct tm *
|
||||
localtime_r (const time_t *timer, struct tm *result)
|
||||
{
|
||||
struct tm *local_result;
|
||||
local_result = localtime (timer);
|
||||
|
||||
if (local_result == NULL || result == NULL)
|
||||
return NULL;
|
||||
|
||||
memcpy (result, local_result, sizeof (result));
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef asctime_r
|
||||
#define asctime_r(_Tm, _Buf) ({ char *___tmp_tm = asctime((_Tm)); \
|
||||
if (___tmp_tm) \
|
||||
___tmp_tm = \
|
||||
strcpy((_Buf),___tmp_tm);\
|
||||
___tmp_tm; })
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define TAI_UTC_OFFSET LL(4611686018427387914)
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@ -102,6 +62,8 @@ struct ftm is a `floating' version of the system struct tm.
|
||||
#define HAS_STAMP 0x0001
|
||||
#define HAS_WYDAY 0x0002
|
||||
|
||||
#define NO_UTC_OFFSET 0x7fffffff
|
||||
|
||||
typedef struct ftm
|
||||
{ struct tm tm; /* System time structure */
|
||||
double sec; /* float version of tm.tm_sec */
|
||||
@ -147,7 +109,7 @@ tz_offset(void)
|
||||
{ time_t t = time(NULL);
|
||||
struct tm tm;
|
||||
|
||||
localtime_r(&t, &tm);
|
||||
PL_localtime_r(&t, &tm);
|
||||
|
||||
offset = -tm.tm_gmtoff;
|
||||
if ( tm.tm_isdst > 0 )
|
||||
@ -177,7 +139,7 @@ static atom_t
|
||||
tz_name_as_atom(int dst)
|
||||
{ static atom_t a[2];
|
||||
|
||||
dst = (dst != 0); /* 0 or 1 */
|
||||
dst = (dst > 0); /* 0 or 1 */
|
||||
|
||||
if ( !a[dst] )
|
||||
{ wchar_t wbuf[256];
|
||||
@ -245,10 +207,12 @@ get_tz_arg(int i, term_t t, term_t a, atom_t *tz)
|
||||
atom_t name;
|
||||
|
||||
_PL_get_arg(i, t, a);
|
||||
if ( !PL_get_atom_ex(a, &name) )
|
||||
if ( !PL_is_variable(a) )
|
||||
{ if ( !PL_get_atom_ex(a, &name) )
|
||||
fail;
|
||||
if ( name != ATOM_minus )
|
||||
*tz = name;
|
||||
}
|
||||
|
||||
succeed;
|
||||
}
|
||||
@ -264,6 +228,21 @@ get_int_arg(int i, term_t t, term_t a, int *val)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
get_voff_arg(int i, term_t t, term_t a, int *val)
|
||||
{ GET_LD
|
||||
|
||||
_PL_get_arg(i, t, a);
|
||||
|
||||
if ( PL_is_variable(a) )
|
||||
{ *val = NO_UTC_OFFSET;
|
||||
return TRUE;
|
||||
} else
|
||||
{ return PL_get_integer_ex(a, val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
get_float_arg(int i, term_t t, term_t a, double *val)
|
||||
{ GET_LD
|
||||
@ -275,7 +254,7 @@ get_float_arg(int i, term_t t, term_t a, double *val)
|
||||
|
||||
|
||||
static int
|
||||
get_bool_arg(int i, term_t t, term_t a, int *val)
|
||||
get_dst_arg(int i, term_t t, term_t a, int *val)
|
||||
{ GET_LD
|
||||
atom_t name;
|
||||
|
||||
@ -284,10 +263,16 @@ get_bool_arg(int i, term_t t, term_t a, int *val)
|
||||
{ if ( name == ATOM_true )
|
||||
{ *val = TRUE;
|
||||
return TRUE;
|
||||
} else if ( name == ATOM_false || name == ATOM_minus )
|
||||
} else if ( name == ATOM_false )
|
||||
{ *val = FALSE;
|
||||
return TRUE;
|
||||
} else if ( name == ATOM_minus )
|
||||
{ *val = -1;
|
||||
return TRUE;
|
||||
}
|
||||
} else if ( PL_is_variable(a) )
|
||||
{ *val = -2;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return PL_get_bool_ex(a, val); /* generate an error */
|
||||
@ -297,23 +282,25 @@ get_bool_arg(int i, term_t t, term_t a, int *val)
|
||||
static int
|
||||
get_ftm(term_t t, ftm *ftm)
|
||||
{ GET_LD
|
||||
|
||||
if ( PL_is_functor(t, FUNCTOR_date9) )
|
||||
{ term_t tmp = PL_new_term_ref();
|
||||
term_t tmp = PL_new_term_ref();
|
||||
int date9;
|
||||
|
||||
memset(ftm, 0, sizeof(*ftm));
|
||||
|
||||
if ( get_int_arg (1, t, tmp, &ftm->tm.tm_year) &&
|
||||
if ( (date9=PL_is_functor(t, FUNCTOR_date9)) )
|
||||
{ if ( get_int_arg (1, t, tmp, &ftm->tm.tm_year) &&
|
||||
get_int_arg (2, t, tmp, &ftm->tm.tm_mon) &&
|
||||
get_int_arg (3, t, tmp, &ftm->tm.tm_mday) &&
|
||||
get_int_arg (4, t, tmp, &ftm->tm.tm_hour) &&
|
||||
get_int_arg (5, t, tmp, &ftm->tm.tm_min) &&
|
||||
get_float_arg(6, t, tmp, &ftm->sec) &&
|
||||
get_int_arg (7, t, tmp, &ftm->utcoff) &&
|
||||
get_voff_arg (7, t, tmp, &ftm->utcoff) &&
|
||||
get_tz_arg (8, t, tmp, &ftm->tzname) &&
|
||||
get_bool_arg (9, t, tmp, &ftm->isdst) )
|
||||
get_dst_arg (9, t, tmp, &ftm->isdst) )
|
||||
{ double fp, ip;
|
||||
|
||||
ftm->tm.tm_isdst = (ftm->isdst == -2 ? -1 : ftm->isdst);
|
||||
|
||||
fixup:
|
||||
fp = modf(ftm->sec, &ip);
|
||||
if ( fp < 0.0 )
|
||||
@ -325,20 +312,62 @@ get_ftm(term_t t, ftm *ftm)
|
||||
ftm->tm.tm_year -= 1900; /* 1900 based */
|
||||
ftm->tm.tm_mon--; /* 0-based */
|
||||
|
||||
if ( ftm->utcoff == NO_UTC_OFFSET )
|
||||
{ if ( ftm->tm.tm_isdst < 0 ) /* unknown DST */
|
||||
{ int offset;
|
||||
|
||||
if ( mktime(&ftm->tm) == (time_t)-1 )
|
||||
return PL_representation_error("dst");
|
||||
ftm->flags |= HAS_WYDAY;
|
||||
|
||||
offset = tz_offset();
|
||||
if ( ftm->tm.tm_isdst > 0 )
|
||||
offset -= 3600;
|
||||
ftm->utcoff = offset;
|
||||
|
||||
if ( date9 ) /* variable */
|
||||
{ _PL_get_arg(7, t, tmp);
|
||||
if ( !PL_unify_integer(tmp, ftm->utcoff) )
|
||||
return FALSE;
|
||||
} else
|
||||
{ ftm->utcoff = offset;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ftm->isdst == -2 )
|
||||
{ ftm->isdst = ftm->tm.tm_isdst;
|
||||
_PL_get_arg(9, t, tmp);
|
||||
if ( ftm->isdst < 0 )
|
||||
{ if ( !PL_unify_atom(tmp, ATOM_minus) )
|
||||
return FALSE;
|
||||
} else
|
||||
{ if ( !PL_unify_bool(tmp, ftm->isdst) )
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !ftm->tzname )
|
||||
{ ftm->tzname = tz_name_as_atom(ftm->isdst);
|
||||
_PL_get_arg(8, t, tmp);
|
||||
if ( PL_is_variable(tmp) &&
|
||||
!PL_unify_atom(tmp, ftm->tzname) )
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
succeed;
|
||||
}
|
||||
} else if ( PL_is_functor(t, FUNCTOR_date3) )
|
||||
{ term_t tmp = PL_new_term_ref();
|
||||
|
||||
memset(ftm, 0, sizeof(*ftm));
|
||||
|
||||
if ( get_int_arg (1, t, tmp, &ftm->tm.tm_year) &&
|
||||
{ if ( get_int_arg (1, t, tmp, &ftm->tm.tm_year) &&
|
||||
get_int_arg (2, t, tmp, &ftm->tm.tm_mon) &&
|
||||
get_int_arg (3, t, tmp, &ftm->tm.tm_mday) )
|
||||
{ ftm->tm.tm_isdst = -1;
|
||||
ftm->utcoff = NO_UTC_OFFSET;
|
||||
goto fixup;
|
||||
}
|
||||
}
|
||||
|
||||
fail;
|
||||
return PL_error(NULL, 0, NULL, ERR_TYPE, ATOM_time, t);
|
||||
}
|
||||
|
||||
|
||||
@ -407,7 +436,7 @@ PRED_IMPL("stamp_date_time", 3, stamp_date_time, 0)
|
||||
if ( (int64_t)unixt == ut64 )
|
||||
{ double ip;
|
||||
|
||||
localtime_r(&unixt, &tm);
|
||||
PL_localtime_r(&unixt, &tm);
|
||||
sec = (double)tm.tm_sec + modf(argsec, &ip);
|
||||
ct.date.year = tm.tm_year+1900;
|
||||
ct.date.month = tm.tm_mon+1;
|
||||
@ -654,7 +683,6 @@ format_time(IOSTREAM *fd, const wchar_t *format, ftm *ftm, int posix)
|
||||
case_b:
|
||||
{ char fmt[3];
|
||||
char buf[256];
|
||||
size_t n;
|
||||
|
||||
fmt[0] = '%';
|
||||
fmt[1] = (char)c;
|
||||
@ -662,7 +690,7 @@ format_time(IOSTREAM *fd, const wchar_t *format, ftm *ftm, int posix)
|
||||
|
||||
cal_ftm(ftm, HAS_STAMP|HAS_WYDAY);
|
||||
/* conversion is not thread-safe under locale switch */
|
||||
n = strftime(buf, sizeof(buf), fmt, &ftm->tm);
|
||||
strftime(buf, sizeof(buf), fmt, &ftm->tm);
|
||||
OUTSTRA(buf);
|
||||
break;
|
||||
}
|
||||
@ -856,7 +884,7 @@ format_time(IOSTREAM *fd, const wchar_t *format, ftm *ftm, int posix)
|
||||
{ char buf[26];
|
||||
|
||||
cal_ftm(ftm, HAS_WYDAY);
|
||||
asctime_r(&ftm->tm, buf);
|
||||
PL_asctime_r(&ftm->tm, buf);
|
||||
buf[24] = EOS;
|
||||
OUTSTRA(buf);
|
||||
}
|
||||
@ -920,7 +948,7 @@ pl_format_time(term_t out, term_t format, term_t time, int posix)
|
||||
|
||||
if ( (int64_t)unixt == ut64 )
|
||||
{ tb.utcoff = tz_offset();
|
||||
localtime_r(&unixt, &tb.tm);
|
||||
PL_localtime_r(&unixt, &tb.tm);
|
||||
tb.sec = (double)tb.tm.tm_sec + modf(tb.stamp, &ip);
|
||||
if ( tb.tm.tm_isdst > 0 )
|
||||
{ tb.utcoff -= 3600;
|
||||
@ -942,7 +970,7 @@ pl_format_time(term_t out, term_t format, term_t time, int posix)
|
||||
tb.utcoff = 0;
|
||||
}
|
||||
} else if ( !get_ftm(time, &tb) )
|
||||
{ return PL_error(NULL, 0, NULL, ERR_TYPE, ATOM_time, time);
|
||||
{ return FALSE;
|
||||
}
|
||||
|
||||
if ( !setupOutputRedirect(out, &ctx, FALSE) )
|
||||
|
Reference in New Issue
Block a user