Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 24 Jan 2003 03:30:21 +0600
From:      Max Khon <fjoe@iclub.nsu.ru>
To:        Greg Lewis <glewis@eyesbeyond.com>
Cc:        freebsd-java@freebsd.org
Subject:   Re: /usr/local/include/utils.h
Message-ID:  <20030124033021.A38610@iclub.nsu.ru>
In-Reply-To: <20030124044501.B76567@misty.eyesbeyond.com>; from glewis@eyesbeyond.com on Fri, Jan 24, 2003 at 04:45:01AM %2B1030
References:  <20030123194719.B25462@iclub.nsu.ru> <20030124044501.B76567@misty.eyesbeyond.com>

next in thread | previous in thread | raw e-mail | index | archive | help

--rwEMma7ioTxnRzrJ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

hi, there!

On Fri, Jan 24, 2003 at 04:45:01AM +1030, Greg Lewis wrote:

> > Attached patch should fix problem with utils.h (which is taken from
> > /usr/local/include instead of local jdk source)
> 
> Thanks Max!  I'll squeeze this in before patchset 8.

I have another (not thoroughly tested) patch to make
-DWITH_NATIVE_THREADS compile on post-4.7 system

A replacement for j2sdk1.3.1/src/solaris/hpi/native_threads/src/threads_bsd.c
attached. It will not compile on 4.7-RELEASE and earlier, probably
some #ifdef munging should be added but I haven't bumped __FreeBSD_version
after pthreads API modifications. Probably 470101 could be used
to filter out most pre-4.7 installations and it will safely work
for 4.8-RELEASE and later (including 5.0-RELEASE and later).

I haven't looked at PR posted today that fixes something related
to native threads (by the way is it really necessary to use
native threads for hotspot?) -- it's hard to read .uue
and probably will not have enough spare time to fix problems with
native threads my patch may introduce but I will be glad to
hear work/doesn't work reports and do submit this file so it
can be tested and probably integrated to patchset8 by someone else.

/fjoe

--rwEMma7ioTxnRzrJ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="threads_bsd.c"

/*
 *	BSDI $Id: threads_bsd.c,v 1.12 2002/02/07 05:19:54 glewis Exp $
 *
 * from @(#)threads_solaris.c	1.3 98/09/16 * * Copyright 1994-1998 by Sun Microsystems, Inc.,
 * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information
 * of Sun Microsystems, Inc. ("Confidential Information").  You
 * shall not disclose such Confidential Information and shall use
 * it only in accordance with the terms of the license agreement
 * you entered into with Sun.
 */

/*
 * Implementation of HPI that can not be expressed with POSIX threads.
 */

#include "hpi_impl.h"
#include "monitor_md.h"
#include "threads_md.h"
#include "np.h"

#include <pthread.h>
#include <pthread_np.h>

#if defined(__FreeBSD__)

#include <assert.h>

#undef pthread_attr_default
#undef pthread_mutexattr_default
#undef pthread_condattr_default
#include "pthread_private.h"

#endif

#include <string.h>
#include <signal.h>
#include <sys/signal.h>
#include <sys/resource.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/sysctl.h>

/*
 * Forward declarations.
 */

/* Private functions used to implement native threading. --billh */

#ifdef DEBUG_BSD_NATIVE_THREADS
void dumpThreadLogStates(pthread_t);
void dumpThreadStates();
#endif

/*
 * Suspend a thread.  Used to implement java.lang.Thread.suspend(),
 * which is deprecated.
 */
int
np_suspend(sys_thread_t *tid)
{
    return pthread_suspend_np(tid->sys_thread);
}


/*
 * Resume a suspended thread.  Used to implement java.lang.Thread.resume(),
 * which is deprecated.
 */
int
np_continue(sys_thread_t *tid)
{
    return pthread_resume_np(tid->sys_thread);
}

/*
 * If there is any initialization is required by the non-POSIX parts.
 */
void np_initialize_thread(sys_thread_t *tid)
{
    return;
}


/*
 * Get the stack start address, and max stack size for the current thread.
 */
int
np_stackinfo(void **addr, long *sizep)
{
    pthread_attr_t attr;
    size_t size;

    if ((errno = pthread_attr_init(&attr)))
	return SYS_ERR;
    if ((errno = pthread_attr_get_np(pthread_self(), &attr)))
	goto err;
    if ((errno = pthread_attr_getstackaddr(&attr, addr)))
	goto err;
    if ((errno = pthread_attr_getstacksize(&attr, &size)))
	goto err;
    *sizep = size;
    pthread_attr_destroy(&attr);
    return SYS_OK;

err:
    pthread_attr_destroy(&attr);
    return SYS_ERR;
}

/*
 * We appear to use this code to suspend threads and get snapshots of
 * their state from the profiler.  If that's the case, then it ought
 * to suffice to use pthread_suspend_np() and pthread_resume_np().
 */
void
np_profiler_init(sys_thread_t *tid)
{
/*
	We should probably attach the newly allocated pthread's thread
	structure to the JVM's threading abstraction here, or maybe do
	nothing () ? --billh
*/
}

int
np_profiler_suspend(sys_thread_t *tid)
{
    if (errno = pthread_suspend_np(tid->sys_thread))
	return SYS_ERR;
    return SYS_OK;
}

int
np_profiler_continue(sys_thread_t *tid)
{
    if (errno = pthread_resume_np(tid->sys_thread))
	return SYS_ERR;
    return SYS_OK;
}

/*
 * Instead of picking over saved registers, we sum a chunk of the stack.
 */
bool_t
np_profiler_thread_is_running(sys_thread_t *tid)
{
/*
	This function didn't show up any where in a grep of all the sources,
	nor do any of the other non-posix implementations (Linux, Solaris) have
	a function body more complicated than the single statement "return TRUE;".

	Do this for the FreeBSD implementation too, since this is a silly
	function anyways.  --billh
*/
    return TRUE;
}


int
np_initialize()
{
    return SYS_OK;
}

static void
record_thread_regs()
{
    struct pthread *self = pthread_self();
    sys_thread_t *tid = ThreadQueue;
    int i;

    for (i = 0; i < ActiveThreadCount && tid != NULL; i++, tid = tid->next) {
	struct pthread *thread = tid->sys_thread;

	if (thread == 0) {
	    /*
	     * thread is still in the process of being initalized.
	     * So GC should not care about this thread. Just
	     * set its sp to 0, and this will force GC to ignore it.
	     */
	    tid->sp = 0;
	    continue;
	}

        tid->sp = thread->stack;
/*	Potential race here if the stack isn't setup before GC. --billh */

	/*
	 * The thread that calls this function will alway be the JVM GC thread,
	 * so skip over it in the list of threads.
	 */
	if (thread != self && (thread->flags & PTHREAD_FLAGS_PRIVATE) == 0) {
	    register_t *regbase;

#ifdef DEBUG_BSD_NATIVE_THREADS
	    /*
	     * Got search candidate..
	     */
	    if (thread->state != PS_SUSPENDED)
		dumpThreadLogStates(thread);
#endif

	    regbase = (register_t*) &thread->ctx.jb[0];
	    tid->regs[0] = regbase[6];	/* eax */
	    tid->regs[1] = 0;		/* ecx (missing) */
	    tid->regs[2] = 0;		/* edx (missing) */
	    tid->regs[3] = regbase[1];	/* ebx */
	    tid->regs[4] = regbase[3];	/* ebp */
	    tid->regs[5] = regbase[4];	/* esi */
	    tid->regs[6] = regbase[5];	/* edi */

#ifdef DEBUG_BSD_NATIVE_THREADS
	    dumpThreadStates();
#endif
	}
    }

#ifdef DEBUG_BSD_NATIVE_THREADS
    fprintf(stderr, "\n\n\nCalling GC thread\n\n\n"); fflush(stderr);
#endif
}

/*
 * Suspend all other threads, and record their contexts (register
 * set or stack pointer) into the sys_thread structure, so that a
 * garbage collect can be run.
 */
int
np_single(void)
{
    sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf()));

    pthread_suspend_all_np();
    record_thread_regs();
    return SYS_OK;
}

/*
 * Continue threads suspended earlier.  But clear their context
 * recorded in sys_thread structure first.
 */
void
np_multi(void)
{
    sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf()));
    pthread_resume_all_np();
}

#ifdef DEBUG_BSD_NATIVE_THREADS
/* pthreads hackery begins --billh */

char SignalList [][16]
=
{
	"PS_RUNNING",
	"PS_SIGTHREAD",
	"PS_MUTEX_WAIT",
	"PS_COND_WAIT",
	"PS_FDLR_WAIT",
	"PS_FDLW_WAIT",
	"PS_FDR_WAIT",
	"PS_FDW_WAIT",
	"PS_FILE_WAIT",
	"PS_POLL_WAIT",
	"PS_SELECT_WAIT",
	"PS_SLEEP_WAIT",
	"PS_WAIT_WAIT",
	"PS_SIGSUSPEND",
	"PS_SIGWAIT",
	"PS_SPINBLOCK",
	"PS_JOIN",
	"PS_SUSPENDED",
	"PS_DEAD",
	"PS_DEADLOCK",
	"PS_STATE_MAX",
	"boundless"
};

char *getThreadStateString(enum pthread_state threadState)
{
	if (threadState < SATAN)
		return SignalList[threadState];
	else
		return SignalList[SATAN-1];
}

void dumpThreadStates()
{
	int threadCount = 0;
	struct pthread	*thread;
	struct pthread	*self = pthread_self();

	_thread_kern_sig_defer();
	TAILQ_FOREACH(thread, &_thread_list, tle) {
		if (thread != self) { /* special case this --billh */
			printf("\tthread %d\t%s\n",
				threadCount,
				getThreadStateString(thread->state));

			if (thread->state != PS_SUSPENDED)
				dumpThreadLogStates(thread);
		} else {
			printf("\tgc thread %d\t%s\n",
				threadCount,
				getThreadStateString(thread->state))
		}
		++threadCount;
	}
	_thread_kern_sig_undefer();
	printf("\n");
}

/*
	[A snippet from Dan Eichen's email on the subject]

	You can also look at src/gnu/usr.bin/binutils/gdb/freebsd-uthread.c.
	It knows how to iterate through all the threads and pull out
	(and even set) thread contexts.

	All the threads are stored in a TAILQ called _thread_list.  There
	is one thread that is private to the threads library (uthread_gc.c)
	and is marked with thread->flags & PTHREAD_FLAGS_PRIVATE.  I don't
	think you want to include that thread in whatever you are doing,
	but that's up to you to decide.

	[end]

	1) Write the code to extract the x86's registers from the jmp_buf
		and ucontext_t.

	--billh
*/

void dumpThreadLogStates(pthread_t thread)
{
int i;
	for(i=0; i < STATE_LOG_SIZE; ++i)
	{
		printf("\t\t%s, %s\n",
			getThreadStateString (thread->state_log[i].state),
			getSuspendStateString(thread->suspended)
			);
		printf("\t\tState change fname = %s, lineno = %d, state = %d\n",
			thread->state_log[i].fname,
			thread->state_log[i].lineno,
			thread->state_log[i].state);

		if (thread->state_log[i].state == PS_SUSPENDED)
		{
			printf("\t\t***\n");
			return;
		}
	}
	printf("\t\t***XXX\n");
}
#endif

--rwEMma7ioTxnRzrJ--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-java" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030124033021.A38610>