<commit_before>/*
 * Copyright (c) 1998 The University of Utah. All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file.
 *
 * Contributed by the Flux Research Group at the University of Utah.
 * Authors: <NAME>, <NAME>
 */
/*
 * This file implements jthreads on top of OSKit pthreads.
 */

#include "debug.h"
#include "jthread.h"
#include <sys/wait.h>
#include <sys/time.h>
#include <oskit/dev/dev.h>

/* thread status */
#define THREAD_NEWBORN                	0
#define THREAD_RUNNING                  1
#define THREAD_DYING                    2
#define THREAD_DEAD                     3

/*
 * Variables.
 * These should be kept static to ensure encapsulation.
 */
static int talive; 		/* number of threads alive */
static int tdaemon;		/* number of daemons alive */
static void (*runOnExit)(void);	/* function to run when all non-daemon die */

static struct jthread* liveThreads;	/* list of all live threads */

/* static lock to protect liveThreads etc. */
static pthread_mutex_t threadLock;

static void remove_thread(jthread_t tid);
static void mark_thread_dead(void);
void dumpLiveThreads(int);
static void deathcallback(void *arg);

/*
 * the following variables are set by jthread_init, and show how the
 * threading system is parametrized.
 */
static void *(*allocator)(size_t); 	/* malloc */
static void (*deallocator)(void*);	/* free */
static void (*destructor1)(void*);	/* call when a thread exits */
static void (*onstop)(void);		/* call when a thread is stopped */
static int  max_priority;		/* maximum supported priority */
static int  min_priority;		/* minimum supported priority */

pthread_key_t	cookie_key;	/* key to map pthread -> Hjava_lang_Thread */
pthread_key_t	jthread_key;	/* key to map pthread -> jthread */

/*
 * Function declarations.
 */


/*============================================================================
 *
 * Functions related to interrupt handling
 *
 */

#if !defined(SMP)
/*
 * On the uniprocessor OSKit, stopping all threads as well as acquiring
 * a spinlock means to simply disable interrupts.  Simple enough.
 */
/*
 * disable interrupts
 */
void 
jthread_suspendall(void)
{
	osenv_intr_disable();
}

/*
 * restore interrupts
 */
void
jthread_unsuspendall(void)
{
	osenv_intr_enable();
}

void 
/* ARGSUSED */
jthread_spinon(void *arg)
{
	osenv_intr_disable();
}

void 
/* ARGSUSED */
jthread_spinoff(void *arg)
{
	osenv_intr_enable();
}

#else /* SMP */

/*
 * On the SMP OSKit, spinlocks will be spinlocks and Leigh will invent
 * a way to stop all processors
 */
#error Not yet.
#endif

/*
 * These functions use the OSKit specific "pthread_getstate" extension
 * to obtain the current stack location & stack pointer.
 */
/*
 * determine the interesting stack range for a conservative gc
 */
int
jthread_extract_stack(jthread_t jtid, void **from, unsigned *len)
{
	struct pthread_state ps;

	if (pthread_getstate(jtid->native_thread, &ps))
		panic("jthread_extract_stack: tid(%d)", jtid->native_thread);
	
#if defined(STACK_GROWS_UP)
#error FIXME
#else
#if notyet
	*from = (void *)ps.stackptr;
	*len = ps.stackbase + ps.stacksize - ps.stackptr;
#else
	*from = (void *)ps.stackptr;
	*len = ps.stackbase - ps.stackptr;	/* base is top XXX */

	if (*len < 0 || *len > (256*1024)) {
	    panic("(%d) pthread_getstate(%d) reported obscene numbers: "
		  "base = 0x%x, sp = 0x%x\n", 
		  pthread_self(),
		  jtid->native_thread,
		  ps.stackbase, ps.stackptr);
	    exit(-1);
	}
#endif
#endif
DBG(JTHREAD,
	dprintf("extract_stack(%) base=%p size=%d sp=%p; from=%p len=%d\n", 
		jtid->native_thread,
		ps.stackbase, ps.stacksize, ps.stackptr, *from, *len);
    )
	return (1);
}

/*
 * determine whether an address lies on your current stack frame
 */
int
jthread_on_current_stack(void *bp)
{
	struct pthread_state ps;
	int rc;

	if (pthread_getstate(pthread_self(), &ps))
		panic("jthread_on_current_stack: pthread_getstate(%d)",
		      pthread_self());
#if notyet
        rc = (uint32)bp >= ps.stackbase && 
	     (uint32)bp < ps.stackbase + ps.stacksize;
#else
	rc = (uint32)bp < ps.stackbase;		/* base is top XXX */
#endif
DBG(JTHREAD,
	dprintf("on current stack(%d) base=%p size=%d bp=%p %s\n",
		pthread_self(),
		ps.stackbase, ps.stacksize, bp, (rc ? "yes" : "no"));
    )
	return rc;
}       

/*
 * See if there is enough room on the stack.
 */
int
jthread_stackcheck(int need)
{
	struct pthread_state ps;
	int room;

	if (pthread_getstate(pthread_self(), &ps))
		panic("jthread_stackcheck: pthread_getstate(%d)",
		      pthread_self());
	
#if defined(STACK_GROWS_UP)
#	error FIXME
#else
	room = ps.stacksize - (ps.stackbase - ps.stackptr);
#endif
	
DBG(JTHREAD,
	dprintf("stackcheck(%d) need=%d base=%p size=%d sp=%p room=%d\n",
		pthread_self(),
		need, ps.stackbase, ps.stacksize, ps.stackptr, room);
    )
	return (room >= need);
}

/*============================================================================
 *
 * Functions dealing with thread contexts and the garbage collection interface
 *
 */

/*
 * free a thread context
 */
void    
jthread_destroy(jthread_t tid)
{
	void *status;
	int oldstate;

	assert(tid);
DBG(JTHREAD, 
	dprintf("destroying tid %d\n", tid->native_thread);	
    )
	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
	pthread_join(tid->native_thread, &status);
	/* XXX ??? XXX */
	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
	deallocator(tid);
}

/*
 * find a native pthread's cookie
 * (Maps pthreads to java.lang.Threads)
 */
void* 
jthread_getcookie(void* ntid)
{
	struct jthread* tid;

        for (tid = liveThreads; tid != NULL; tid = tid->nextlive) {
		if ((void*)tid->native_thread == ntid) {
			return (tid->jlThread);<commit_msg>fixed call to pthread_setcancelstate around pthread_join<commit_after>/*
 * Copyright (c) 1998 The University of Utah. All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file.
 *
 * Contributed by the Flux Research Group at the University of Utah.
 * Authors: <NAME>, <NAME>
 */
/*
 * This file implements jthreads on top of OSKit pthreads.
 */

#include "debug.h"
#include "jthread.h"
#include <sys/wait.h>
#include <sys/time.h>
#include <oskit/dev/dev.h>

/* thread status */
#define THREAD_NEWBORN                	0
#define THREAD_RUNNING                  1
#define THREAD_DYING                    2
#define THREAD_DEAD                     3

/*
 * Variables.
 * These should be kept static to ensure encapsulation.
 */
static int talive; 		/* number of threads alive */
static int tdaemon;		/* number of daemons alive */
static void (*runOnExit)(void);	/* function to run when all non-daemon die */

static struct jthread* liveThreads;	/* list of all live threads */

/* static lock to protect liveThreads etc. */
static pthread_mutex_t threadLock;

static void remove_thread(jthread_t tid);
static void mark_thread_dead(void);
void dumpLiveThreads(int);
static void deathcallback(void *arg);

/*
 * the following variables are set by jthread_init, and show how the
 * threading system is parametrized.
 */
static void *(*allocator)(size_t); 	/* malloc */
static void (*deallocator)(void*);	/* free */
static void (*destructor1)(void*);	/* call when a thread exits */
static void (*onstop)(void);		/* call when a thread is stopped */
static int  max_priority;		/* maximum supported priority */
static int  min_priority;		/* minimum supported priority */

pthread_key_t	cookie_key;	/* key to map pthread -> Hjava_lang_Thread */
pthread_key_t	jthread_key;	/* key to map pthread -> jthread */

/*
 * Function declarations.
 */


/*============================================================================
 *
 * Functions related to interrupt handling
 *
 */

#if !defined(SMP)
/*
 * On the uniprocessor OSKit, stopping all threads as well as acquiring
 * a spinlock means to simply disable interrupts.  Simple enough.
 */
/*
 * disable interrupts
 */
void 
jthread_suspendall(void)
{
	osenv_intr_disable();
}

/*
 * restore interrupts
 */
void
jthread_unsuspendall(void)
{
	osenv_intr_enable();
}

void 
/* ARGSUSED */
jthread_spinon(void *arg)
{
	osenv_intr_disable();
}

void 
/* ARGSUSED */
jthread_spinoff(void *arg)
{
	osenv_intr_enable();
}

#else /* SMP */

/*
 * On the SMP OSKit, spinlocks will be spinlocks and Leigh will invent
 * a way to stop all processors
 */
#error Not yet.
#endif

/*
 * These functions use the OSKit specific "pthread_getstate" extension
 * to obtain the current stack location & stack pointer.
 */
/*
 * determine the interesting stack range for a conservative gc
 */
int
jthread_extract_stack(jthread_t jtid, void **from, unsigned *len)
{
	struct pthread_state ps;

	if (pthread_getstate(jtid->native_thread, &ps))
		panic("jthread_extract_stack: tid(%d)", jtid->native_thread);
	
#if defined(STACK_GROWS_UP)
#error FIXME
#else
#if notyet
	*from = (void *)ps.stackptr;
	*len = ps.stackbase + ps.stacksize - ps.stackptr;
#else
	*from = (void *)ps.stackptr;
	*len = ps.stackbase - ps.stackptr;	/* base is top XXX */

	if (*len < 0 || *len > (256*1024)) {
	    panic("(%d) pthread_getstate(%d) reported obscene numbers: "
		  "base = 0x%x, sp = 0x%x\n", 
		  pthread_self(),
		  jtid->native_thread,
		  ps.stackbase, ps.stackptr);
	    exit(-1);
	}
#endif
#endif
DBG(JTHREAD,
	dprintf("extract_stack(%) base=%p size=%d sp=%p; from=%p len=%d\n", 
		jtid->native_thread,
		ps.stackbase, ps.stacksize, ps.stackptr, *from, *len);
    )
	return (1);
}

/*
 * determine whether an address lies on your current stack frame
 */
int
jthread_on_current_stack(void *bp)
{
	struct pthread_state ps;
	int rc;

	if (pthread_getstate(pthread_self(), &ps))
		panic("jthread_on_current_stack: pthread_getstate(%d)",
		      pthread_self());
#if notyet
        rc = (uint32)bp >= ps.stackbase && 
	     (uint32)bp < ps.stackbase + ps.stacksize;
#else
	rc = (uint32)bp < ps.stackbase;		/* base is top XXX */
#endif
DBG(JTHREAD,
	dprintf("on current stack(%d) base=%p size=%d bp=%p %s\n",
		pthread_self(),
		ps.stackbase, ps.stacksize, bp, (rc ? "yes" : "no"));
    )
	return rc;
}       

/*
 * See if there is enough room on the stack.
 */
int
jthread_stackcheck(int need)
{
	struct pthread_state ps;
	int room;

	if (pthread_getstate(pthread_self(), &ps))
		panic("jthread_stackcheck: pthread_getstate(%d)",
		      pthread_self());
	
#if defined(STACK_GROWS_UP)
#	error FIXME
#else
	room = ps.stacksize - (ps.stackbase - ps.stackptr);
#endif
	
DBG(JTHREAD,
	dprintf("stackcheck(%d) need=%d base=%p size=%d sp=%p room=%d\n",
		pthread_self(),
		need, ps.stackbase, ps.stacksize, ps.stackptr, room);
    )
	return (room >= need);
}

/*============================================================================
 *
 * Functions dealing with thread contexts and the garbage collection interface
 *
 */

/*
 * free a thread context
 */
void    
jthread_destroy(jthread_t tid)
{
	void *status;
	int oldstate;

	assert(tid);
DBG(JTHREAD, 
	dprintf("destroying tid %d\n", tid->native_thread);	
    )
	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
	pthread_join(tid->native_thread, &status);
	pthread_setcancelstate(oldstate, 0);
	deallocator(tid);
}

/*
 * find a native pthread's cookie
 * (Maps pthreads to java.lang.Threads)
 */
void* 
jthread_getcookie(void* ntid)
{
	struct jthread* tid;

        for (tid = liveThreads; tid != NULL; tid = tid->nextlive) {
		if ((void*)tid->native_thread == ntid) {
			return (tid->jlThread);
{'fraction_non_alphanumeric': 0.15613252906722616, 'fraction_numerical': 0.004808112597255005, 'mean_word_length': 3.831081081081081, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1452713', 'n_tokens_mistral': 4057, 'n_tokens_neox': 3873, 'n_words': 1094}