Port for mips/ultrix4.2 (was: setjmp/longjmp on mips/ultrix4)

Dirk Grunwald grunwald at pa.dec.com
Thu Oct 22 09:41:00 PDT 1998


I think that your 'sysdepCallMethod' has the same problem mine had for
the Alpha (and that I fixed yesterday).

You need to mark all "callee-saves" registers as being dirty following
the asm() that does the call. Otherwise when you compile with
optimization, the compiler will assume those registers are not
modified by the asm().

Here's the corresponding changes for the Alpha that I made, including
a test-case for the Unix "jthreads" library to verify that it's
working.

What's the official procedure for submitting patches to the
distribution? This version passes most of the test cases, except

./TestScript
	...
BadFloatTest ... error running
  Should have got:
1.2345 9.8765
  But got instead:
0 0
	...
finaltest ... error running
  Should have got:
3.1415926536
  But got instead:
0
finaltest2 ... forNameTest ... passed
	...
GCTest ... error running
  Should have got:
[0]:  Success
[10]:  Success
	...
  But got instead:
java.lang.ArrayStoreException: 
	at java/lang/StringBuffer.append(77)
	at java/lang/StringBuffer.append(48)
	at GCTest.testObjChain(264)
	at GCTest.run(124)
	at java/lang/Thread.run(140)
[0]:  Success

	....
ThreadLocalTest ... error compiling
ThreadLocalTest.java:4: Class ThreadLocal not found in type declaration.
  private static ThreadLocal tl = new ThreadLocal() {
                                ^
ThreadLocalTest.java:4: Class ThreadLocal not found in type declaration.
  private static ThreadLocal tl = new ThreadLocal() {

Th floating point cases worry me. This was using a recent (2 day old?)
snapshot.


#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.2).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 1998-10-22 09:31 PDT by <grunwald at rushmore.pa.dec.com>.
# Source directory was `/tmp_mnt/n/wrl-nfs1/wrl_user/grunwald/Src/Kaffe/Kaffe'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode       name
# ------ ---------- ------------------------------------------
#   5719 -rw-rwsr-- config/alpha/common.h
#    584 -rw-rw-r-- config/alpha/threads.h
#   1607 -rw-rw-r-- kaffe/kaffevm/systems/unix-jthreads/test-jthread.c
#
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
  if test "$gettext_dir" = FAILED && test -f $dir/gettext \
     && ($dir/gettext --version >/dev/null 2>&1)
  then
    set `$dir/gettext --version 2>&1`
    if test "$3" = GNU
    then
      gettext_dir=$dir
    fi
  fi
  if test "$locale_dir" = FAILED && test -f $dir/shar \
     && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
  then
    locale_dir=`$dir/shar --print-text-domain-dir`
  fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
  echo=echo
else
  TEXTDOMAINDIR=$locale_dir
  export TEXTDOMAINDIR
  TEXTDOMAIN=sharutils
  export TEXTDOMAIN
  echo="$gettext_dir/gettext -s"
fi
touch -am 1231235999 $$.touch >/dev/null 2>&1
if test ! -f 1231235999 && test -f $$.touch; then
  shar_touch=touch
else
  shar_touch=:
  echo
  $echo 'WARNING: not restoring timestamps.  Consider getting and'
  $echo "installing GNU \`touch', distributed in GNU File Utilities..."
  echo
fi
rm -f 1231235999 $$.touch
#
if mkdir _sh24565; then
  $echo 'x -' 'creating lock directory'
else
  $echo 'failed to create lock directory'
  exit 1
fi
# ============= config/alpha/common.h ==============
if test ! -d 'config'; then
  $echo 'x -' 'creating directory' 'config'
  mkdir 'config'
fi
if test ! -d 'config/alpha'; then
  $echo 'x -' 'creating directory' 'config/alpha'
  mkdir 'config/alpha'
fi
if test -f 'config/alpha/common.h' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'config/alpha/common.h' '(file already exists)'
else
  $echo 'x -' extracting 'config/alpha/common.h' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'config/alpha/common.h' &&
/*
X * alpha/common.h
X * Common Alpha configuration information.
X *
X * Copyright (c) 1996, 1997
X *	Transvirtual Technologies, Inc.  All rights reserved.
X *
X * See the file "license.terms" for information on usage and redistribution 
X * of this file. 
X *
X * 15 July, 1998:
X *      Modified by Rick Greer (rick at sandpiper.com) for use with Alpha Linux
X */
X
#ifndef __alpha_common_h
#define __alpha_common_h
X
/*
X * Make a call to a native or Java (JIT) method.
X *  This assembly code should build a standard C call using the passed
X *  call information.  By its nature this is highly processor specific.
X *  This function is mandatory for the JIT, but can be avoided for
X *  the interpreter if you don't define NO_KAFFE_STUBS.  However, the
X *  Kaffe stubs will be deprecated at some time in the future and
X *  this function will be needed for JNI support when it comes.
X */
#define	NO_KAFFE_STUBS
X
#define getJavaArg(CALL, n)						      \
(   /*									      \
X     *  Sign-extend short arguments:					      \
X     *									      \
X     *  This macro sign extends short (i.e, 32-bit or less) arguments to a    \
X     *  64-bit "long" that can be inserted directly into a 64-bit register.   \
X     */									      \
X									      \
X    ((CALL)->callsize[n] == 2) ? (CALL)->args[n].j : (long)((CALL)->args[n].i)\
)
X
#define	sysdepCallMethod(__call__)						      \
{   /*									      \
X     *  Call a Java Method:						      \
X     *									      \
X     *  This macro generates an in-line call to the Java method described by  \
X     *  the given method info structure ("CALL" argument) and stores the      \
X     *  return value in the info struct as well.			      \
X     */									      \
X									      \
X    asm ("" ::: "$9", "$10", "$11", "$12"); \
X    asm ("" ::: "$16", "$17", "$18", "$19", "$20", "$21", "$9", "$27", "$26"); \
X    {                                                                         \
X    int x, rags = 0;		    					      \
X	/* The parameter registers ... 					    */\
X        register long r16 asm("$16");					      \
X        register long r17 asm("$17");					      \
X        register long r18 asm("$18");					      \
X        register long r19 asm("$19");					      \
X        register long r20 asm("$20");					      \
X        register long r21 asm("$21");					      \
X    register unsigned long *osp asm("$9"); \
X    register unsigned long *ogp asm("$10"); \
X    /* any temporary register would do.. */  \
X    register unsigned long *nsp asm("$11"); \
X    register callMethodInfo *CALL asm("$12"); \
X    asm ("mov	$30,%0" : "=r" (osp)); \
X    asm ("mov	$29,%0" : "=r" (ogp)); \
X    nsp = osp;						      \
X    CALL = __call__;						      \
X									      \
X    for (x = 0; x < (CALL)->nrargs; x++)				      \
X    {   /*								      \
X         *  The alpha has 64-bit registers, so we don't really need the ex-   \
X         *  tra "callsize = 0" entries in the arg list.  This loop removes    \
X         *  them by sliding any subsequent entries to the left.		      \
X         */								      \
X									      \
X        if ((CALL)->callsize[x] > 0)					      \
X        {								      \
X            if (x > rags) (CALL)->args[rags] = (CALL)->args[x];		      \
X            rags += 1;							      \
X        }								      \
X    }									      \
X									      \
X    {                                                                         \
X									      \
X    switch (rags)							      \
X    {                                                                         \
X        default:							      \
X	  {									\
X        /*		                                                              \
X         * We're doing to hack the frame buffer the difficult way..               \
X         */                                                                       \
X        int margs = rags - 6;        \
X        nsp = osp - margs;  \
X	/* Copy arguments to the stack we allocated */			      \
X	  for (x = 0; x < margs; x++) {						\
X	    nsp[x] = getJavaArg(CALL, x+6);					\
X	  }									\
X        }								      \
X									      \
X        /* The first 6 arguments are loaded into the parameter registers.   */\
X        case 6: r21 = getJavaArg(CALL, 5);				      \
X        case 5: r20 = getJavaArg(CALL, 4);				      \
X        case 4: r19 = getJavaArg(CALL, 3);				      \
X        case 3: r18 = getJavaArg(CALL, 2);				      \
X        case 2: r17 = getJavaArg(CALL, 1);				      \
X        case 1: r16 = getJavaArg(CALL, 0);				      \
X        case 0:  /* nothing */ \
X    }									      \
X    asm ("\
X	 mov %3,$27\n\
X	 mov %0,$30\n\
X         jsr $26,($27),0 \n\
X	 mov %1, $30\n\
X	 mov %2, $29\n\
X	 "  :: "r" (nsp), "r" (osp), "r" (ogp), "r" ((CALL) -> function), \
X	/* include all the argument registers least they get DCE'd away */   \
X	"r" (r16), "r" (r17), "r" (r18), "r" (r19), "r" (r20), "r" (r21) \
X	/* and mention that we kill these.. */   \
X	: \
X		 "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", \
X		 "$22", "$23", "$24", "$25", "$27", "$26", \
X		 "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9",  \
X		 "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", "$f16", "$f17", "$f18", "$f19",  \
X		 "$f20", "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", \
X		 "$f30", \
X		 "memory"); \
X    }									      \
X    asm ("stq $0,%0" : "=m" ((CALL)->ret->j));				      \
X									      \
X    /* Store floating point return value over (default) integer value ...   */\
X    {									      \
X      char rt = (CALL) -> rettype;									      \
X      if (rt == 'D') asm volatile ("stt $f0,%0" : "=m" ((CALL)->ret->d));    \
X      if (rt == 'F') asm volatile ("sts $f0,%0" : "=m" ((CALL)->ret->f));    \
X    }									      \
X    }									      \
}
#endif
SHAR_EOF
  $shar_touch -am 1021221598 'config/alpha/common.h' &&
  chmod 0664 'config/alpha/common.h' ||
  $echo 'restore of' 'config/alpha/common.h' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'config/alpha/common.h:' 'MD5 check failed'
bd183d21ae34b1a01b8c3a804d9ee850  config/alpha/common.h
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'config/alpha/common.h'`"
    test 5719 -eq "$shar_count" ||
    $echo 'config/alpha/common.h:' 'original size' '5719,' 'current size' "$shar_count!"
  fi
fi
# ============= config/alpha/threads.h ==============
if test -f 'config/alpha/threads.h' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'config/alpha/threads.h' '(file already exists)'
else
  $echo 'x -' extracting 'config/alpha/threads.h' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'config/alpha/threads.h' &&
/*
X * alpha/threads.h
X * Alpha threading information.
X *
X * Copyright (c) 1996, 1997
X *	Transvirtual Technologies, Inc.  All rights reserved.
X *
X * See the file "license.terms" for information on usage and redistribution 
X * of this file. 
X */
X
#ifndef __alpha_threads_h
#define __alpha_threads_h
X
/**/
/* Thread handling */
/**/
#define	USE_INTERNAL_THREADS
X
#define	THREADSTACKSIZE		(32 * 1024)
X
/*
X * Stack offset.
X * This is the offset into the setjmp buffer where the stack pointer is
X * stored.  This may be different with different OSes.
X */
X
#define	SP_OFFSET		(4+30)
X
#endif
SHAR_EOF
  $shar_touch -am 1014174398 'config/alpha/threads.h' &&
  chmod 0664 'config/alpha/threads.h' ||
  $echo 'restore of' 'config/alpha/threads.h' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'config/alpha/threads.h:' 'MD5 check failed'
6152f8726f71e2d8d372a0d6ff66820b  config/alpha/threads.h
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'config/alpha/threads.h'`"
    test 584 -eq "$shar_count" ||
    $echo 'config/alpha/threads.h:' 'original size' '584,' 'current size' "$shar_count!"
  fi
fi
# ============= kaffe/kaffevm/systems/unix-jthreads/test-jthread.c ==============
if test ! -d 'kaffe'; then
  $echo 'x -' 'creating directory' 'kaffe'
  mkdir 'kaffe'
fi
if test ! -d 'kaffe/kaffevm'; then
  $echo 'x -' 'creating directory' 'kaffe/kaffevm'
  mkdir 'kaffe/kaffevm'
fi
if test ! -d 'kaffe/kaffevm/systems'; then
  $echo 'x -' 'creating directory' 'kaffe/kaffevm/systems'
  mkdir 'kaffe/kaffevm/systems'
fi
if test ! -d 'kaffe/kaffevm/systems/unix-jthreads'; then
  $echo 'x -' 'creating directory' 'kaffe/kaffevm/systems/unix-jthreads'
  mkdir 'kaffe/kaffevm/systems/unix-jthreads'
fi
if test -f 'kaffe/kaffevm/systems/unix-jthreads/test-jthread.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'kaffe/kaffevm/systems/unix-jthreads/test-jthread.c' '(file already exists)'
else
  $echo 'x -' extracting 'kaffe/kaffevm/systems/unix-jthreads/test-jthread.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'kaffe/kaffevm/systems/unix-jthreads/test-jthread.c' &&
#include <stdio.h>
#include "jthread.h"
X
/*
X * A stand-alone test of the jthread library.
X * This creates 10 threads that print a message and yield.
X * As each thread dies, it decrements the count of
X * living threads. The main thread exits when that
X * count is zero.
X *
X * Tests locks, condition variables and thread management.
X */
X
static int threads_to_create = 10;
static int living_threads = 10;
static jmutex lock;
static jcondvar cv;
X
void threadexits(void)
{
X  fprintf(stderr,"threadexits\n");
}
X
void threadstops(void)
{
X  fprintf(stderr,"threadstops\n");
}
X
void
threadA(void *cookie)
{
X  int i;
X
X  for(i = 0; i < 2; i++) {
X    fprintf(stderr, "Thread %ld\n", (long) cookie);
X    jthread_yield();
X  }
X  
X  fprintf(stderr,"Thread %ld exits\n", (long) cookie);
X  jmutex_lock(&lock);
X  living_threads--;
X  jmutex_unlock(&lock);
X  fprintf(stderr,"Now do signal\n");
X  jcondvar_signal(&cv, &lock);
}
X
main()
{
X  int i;
X
X  jthread_init(1, 10, 1, 1, 1024*32, malloc, free, threadexits, threadstops);
X  for (living_threads = 0; living_threads < threads_to_create; living_threads++) {
X    fprintf(stderr,"Creating thread %d\n", living_threads);
X    jthread_create( 1, threadA, 1, (void *) living_threads, 128 * 1024);
X  }
X  fprintf(stderr,"Initialize lock\n");
X  jmutex_initialise(&lock);
X  jcondvar_initialise(&cv);
X
X  do {
X    jmutex_lock(&lock);
X    fprintf(stderr,"Living threads = %d\n", living_threads);
X    if ( living_threads > 0 ) {
X      jcondvar_wait(&cv, &lock, 10000);
X    } else {
X      break;
X    }
X    jmutex_unlock(&lock);
X  } while(1);
X  fprintf(stderr,"Done waiting for threads\n");
}
SHAR_EOF
  $shar_touch -am 1015100498 'kaffe/kaffevm/systems/unix-jthreads/test-jthread.c' &&
  chmod 0664 'kaffe/kaffevm/systems/unix-jthreads/test-jthread.c' ||
  $echo 'restore of' 'kaffe/kaffevm/systems/unix-jthreads/test-jthread.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'kaffe/kaffevm/systems/unix-jthreads/test-jthread.c:' 'MD5 check failed'
855e7a1566b7346fa0dd587c578853e6  kaffe/kaffevm/systems/unix-jthreads/test-jthread.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'kaffe/kaffevm/systems/unix-jthreads/test-jthread.c'`"
    test 1607 -eq "$shar_count" ||
    $echo 'kaffe/kaffevm/systems/unix-jthreads/test-jthread.c:' 'original size' '1607,' 'current size' "$shar_count!"
  fi
fi
rm -fr _sh24565
exit 0



More information about the kaffe mailing list