Skip to content

Commit

Permalink
FIXED: Keep track of base and size of the C-stack
Browse files Browse the repository at this point in the history
This information was stored in the thread-info structure.  However,
if an engine is detached and later attached in a new OS thread this
information is wrong.   We now cache it in the info structure, but
we store it in a pthread key.

This notably fixes thread interaction for JPL.
  • Loading branch information
JanWielemaker committed Jan 9, 2024
1 parent 8ac2fd5 commit 15f8cfd
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 56 deletions.
104 changes: 71 additions & 33 deletions src/os/pl-cstack.c
Original file line number Diff line number Diff line change
Expand Up @@ -1102,7 +1102,33 @@ sigCrashHandler(int sig)
* STACK LOCATION AND SIZE *
*******************************/

#if defined(HAVE_GETRLIMIT) && defined(O_PLMT)
#ifdef O_PLMT
static pthread_once_t c_stack_key_created = PTHREAD_ONCE_INIT;
static pthread_key_t c_stack_key = 0;

static void
c_stack_create_key(void)
{ pthread_key_create(&c_stack_key, free);
}

static c_stack_info *
thread_c_stack_info(c_stack_info *cinfo)
{ pthread_once(&c_stack_key_created, c_stack_create_key);

if ( cinfo )
{ pthread_setspecific(c_stack_key, cinfo);
} else if ( (cinfo=pthread_getspecific(c_stack_key)) )
{ return cinfo;
} else
{ if ( !(cinfo = malloc(sizeof(*cinfo))) )
outOfCore();
memset(cinfo, 0, sizeof(*cinfo));
pthread_setspecific(c_stack_key, cinfo);
}

return cinfo;
}

static size_t
round_pages(size_t n)
{ size_t psize;
Expand All @@ -1116,52 +1142,64 @@ round_pages(size_t n)

return ROUND(n, psize);
}
#endif

size_t
static void
c_stack_base(c_stack_info *cinfo)
{ if ( !cinfo->base && cinfo->size )
{ size_t top = round_pages((size_t)&cinfo);
cinfo->base = (void*)(top - cinfo->size);
}
}

#endif /*O_PLMT*/

c_stack_info *
CStackSize(DECL_LD)
{
#ifdef O_PLMT
PL_thread_info_t *info = LD->thread.info;
c_stack_info *cinfo;

if ( info->c_stack_size )
return info->c_stack_size;
if ( !(cinfo=info->c_stack) )
cinfo = info->c_stack = thread_c_stack_info(NULL);

if ( info->pl_tid != 1 )
{ DEBUG(1, Sdprintf("Thread-stack: %ld\n", LD->thread.info->c_stack_size));

#ifdef HAVE_PTHREAD_GETATTR_NP
pthread_attr_t attr;
if ( !cinfo->initialised )
{ info->c_stack = thread_c_stack_info(info->c_stack);

if ( pthread_getattr_np(info->tid, &attr) == 0 )
{ pthread_attr_getstack(&attr, &info->c_stack_base, &info->c_stack_size);
pthread_attr_destroy(&attr);
if ( cinfo->size && !cinfo->base )
{ c_stack_base(cinfo);
} else
{ info->c_stack_size = (size_t)-1;
}
#endif

return info->c_stack_size;
}

{ if ( info->pl_tid == 1 )
{
#ifdef HAVE_GETRLIMIT
struct rlimit rlim;
struct rlimit rlim;

if ( getrlimit(RLIMIT_STACK, &rlim) == 0 &&
rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur )
{ size_t top = round_pages((size_t)&info);
if ( getrlimit(RLIMIT_STACK, &rlim) == 0 &&
rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur )
{ cinfo->size = rlim.rlim_cur;
c_stack_base(cinfo);
}
#endif
} else
{
#ifdef HAVE_PTHREAD_GETATTR_NP
pthread_attr_t attr;

DEBUG(1, Sdprintf("Stack: %ld\n", rlim.rlim_cur));
info->c_stack_size = rlim.rlim_cur;
if ( pthread_getattr_np(info->tid, &attr) == 0 )
{ pthread_attr_getstack(&attr, &cinfo->base, &cinfo->size);
pthread_attr_destroy(&attr);
}
#endif
}
}
cinfo->initialised = TRUE;
DEBUG(MSG_CSTACK, Sdprintf("[%d]: C-stack %p[%zd]\n",
info->pl_tid, cinfo->base, cinfo->size));

info->c_stack_base = (void*)(top - info->c_stack_size);
} else
{ info->c_stack_size = (size_t)-1;
}
#endif

return info->c_stack_size;
#else
return (size_t)-1;
return cinfo;
#else /*O_PLMT*/
return NULL;
#endif
}
8 changes: 7 additions & 1 deletion src/os/pl-cstack.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@
#ifndef PL_CSTACK_H_INCLUDED
#define PL_CSTACK_H_INCLUDED

typedef struct c_stack_info
{ int initialised; /* Struct is fully initialized */
void *base; /* Base of the (C-) stack */
size_t size; /* system (C-) stack */
} c_stack_info;

#if USE_LD_MACROS
#define CStackSize(_) LDFUNC(CStackSize, _)
#endif /*USE_LD_MACROS*/
Expand All @@ -48,7 +54,7 @@ COMMON(void) initBackTrace(void);
COMMON(void) sigCrashHandler(int sig);

#define LDFUNC_DECLARATIONS
size_t CStackSize(void);
c_stack_info *CStackSize(void);
#undef LDFUNC_DECLARATIONS

#endif /*PL_CSTACK_H_INCLUDED*/
1 change: 1 addition & 0 deletions src/pl-debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ const debug_topic debug_topics[] =
DEBUG_TOPIC(MSG_PRED_COUNT),

DEBUG_TOPIC(MSG_BACKTRACK),
DEBUG_TOPIC(MSG_CSTACK),

/* GC messages */
DEBUG_TOPIC(MSG_AGC),
Expand Down
1 change: 1 addition & 0 deletions src/pl-debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
#define MSG_PRED_COUNT 83

#define MSG_BACKTRACK 90
#define MSG_CSTACK 91

/* GC messages */
#define MSG_AGC 100
Expand Down
5 changes: 3 additions & 2 deletions src/pl-prims.c
Original file line number Diff line number Diff line change
Expand Up @@ -5806,8 +5806,9 @@ swi_statistics(DECL_LD atom_t key, Number v)
else if (key == ATOM_globalused )
v->value.i = usedStack(global);
else if (key == ATOM_c_stack)
v->value.i = CStackSize();
else if (key == ATOM_atoms) /* atoms */
{ c_stack_info *cinfo = CStackSize();
v->value.i = cinfo ? cinfo->size : 0;
} else if (key == ATOM_atoms) /* atoms */
v->value.i = GD->statistics.atoms;
else if (key == ATOM_atom_space) /* atom_space */
v->value.i = atom_space();
Expand Down
38 changes: 20 additions & 18 deletions src/pl-thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,7 @@ freePrologThread(PL_local_data_t *ld, int after_fork)
destroy_thread_message_queue(&ld->thread.messages);
info->thread_data = NULL; /* avoid a loop */
info->has_tid = FALSE; /* needed? */
info->c_stack = NULL;
if ( !after_fork )
PL_UNLOCK(L_THREAD);

Expand Down Expand Up @@ -2038,6 +2039,7 @@ start_thread(void *closure)

pthread_cleanup_push(free_prolog_thread, info->thread_data);

CStackSize();
PL_LOCK(L_THREAD);
info->status = PL_THREAD_RUNNING;
PL_UNLOCK(L_THREAD);
Expand Down Expand Up @@ -2338,19 +2340,24 @@ pl_thread_create(term_t goal, term_t id, term_t options)
{
#ifdef USE_COPY_STACK_SIZE
struct rlimit rlim;
if ( !stack && getrlimit(RLIMIT_STACK, &rlim) == 0 )
if ( !c_stack && getrlimit(RLIMIT_STACK, &rlim) == 0 )
{ if ( rlim.rlim_cur != RLIM_INFINITY )
stack = rlim.rlim_cur;
c_stack = rlim.rlim_cur;
/* What is an infinite stack!? */
}
#endif
if ( c_stack )
{ stack = round_pages(c_stack);
func = "pthread_attr_setstacksize";
rc = pthread_attr_setstacksize(&attr, c_stack);
info->c_stack_size = c_stack;
} else
{ pthread_attr_getstacksize(&attr, &info->c_stack_size);

if ( rc == 0 )
{ assert(info->c_stack == NULL);
if ( !(info->c_stack = malloc(sizeof(*info->c_stack))) )
outOfCore();
memset(info->c_stack, 0, sizeof(*info->c_stack));
info->c_stack->size = c_stack;
}
}
}
if ( rc == 0 )
Expand Down Expand Up @@ -6588,6 +6595,7 @@ detach_engine(PL_engine_t e)
#endif
#endif
memset(&info->tid, 0, sizeof(info->tid));
info->c_stack = NULL;
}


Expand Down Expand Up @@ -8246,23 +8254,17 @@ markAccessedPredicates(PL_local_data_t *ld)

static size_t
stack_avail(DECL_LD)
{ PL_thread_info_t *info = LD->thread.info;
size_t avail = (size_t)-1;
{ c_stack_info *cinfo = CStackSize();
ssize_t avail = -1;

if ( !info->c_stack_size )
(void)CStackSize();

if ( info->c_stack_base )
{ void *here = &info;

#ifndef __SANITIZE_ADDRESS__
assert(here > info->c_stack_base); /* stack grows down */
#endif
if ( cinfo && cinfo->base )
{ void *here = &cinfo;

avail = (char*)here - (char*)info->c_stack_base;
avail = (char*)here - (char*)cinfo->base;
assert(avail > 0); /* stack grows down */
}

return avail;
return (size_t)avail;
}
#endif

Expand Down
4 changes: 2 additions & 2 deletions src/pl-thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
*/

#include "pl-incl.h"
#include "os/pl-cstack.h"

#ifndef PL_THREAD_H_DEFINED
#define PL_THREAD_H_DEFINED
Expand Down Expand Up @@ -113,8 +114,7 @@ typedef struct _PL_thread_info_t
unsigned c_stack_low : 1; /* TRUE: Signalled low C stack */
unsigned joined_by_creator : 1;
int joining_by; /* TID of joining thread */
void *c_stack_base; /* Base of the (C-) stack */
size_t c_stack_size; /* system (C-) stack */
c_stack_info *c_stack;
size_t stack_limit; /* Stack sizes */
size_t table_space; /* Max size for local tables */
rc_cancel (*cancel)(int id); /* cancel function */
Expand Down

0 comments on commit 15f8cfd

Please sign in to comment.