This is the mail archive of the
java@gcc.gnu.org
mailing list for the Java project.
Re: Create binary from GCJ generated assembly
- From: isuru herath <isuru81 at yahoo dot com>
- To: Andrew Haley <aph at redhat dot com>
- Cc: java at gcc dot gnu dot org
- Date: Wed, 28 Oct 2009 11:12:14 -0700 (PDT)
- Subject: Re: Create binary from GCJ generated assembly
Hi Andrew,
Thanks for the reply. My code is attached.
My intention of using this xchg instruction is that the simulator[Simics] I am using recognizes them as an special event and I can start counting the memory reference from that point onwards. I am trying this on Java is because we are going to use benchmark programs written Java. Thats why I am trying to use CNI to insert assembly to the binary.
I dont understand what you mean by "intrinsic counter". I would greatly appreciate if you could explain it bit more if you have time.
Aslo I didn get clearly what you mean by
Personally speaking, I'd just write the routines that need to access the counter in C++.
I am trying to find a way to insert these two assembly instructions to the binary created by gcj so that it will give the same number of memory references as C programs does.
thanks a lot for your help. further help is greatly appreciated.
regards,
isuru
--- On Wed, 10/28/09, Andrew Haley <aph@redhat.com> wrote:
> From: Andrew Haley <aph@redhat.com>
> Subject: Re: Create binary from GCJ generated assembly
> To: "isuru herath" <isuru81@yahoo.com>
> Cc: java@gcc.gnu.org
> Date: Wednesday, October 28, 2009, 8:56 AM
> isuru herath wrote:
>
> > Thanks a lot for the quick reply. I did accordingly.
> But results were not the same. My program is a multi
> threaded shared counter.
> > so in my Java code I have
> > counter++
> >
> > I need to surround this with two xchg instructions.
> like
> >
> > xchg
> > counter++
> > xchg
> >
> > so that I can count number of read and write
> operations between two xchg instructions.
>
> OK.
>
> > with gcc I got both as 1 which is correct.
> > with gcj and JNI I got 47 read operations and 29 write
> operations
> > with gcj and CNI I got 6 read operations and 6 write
> operations
> >
> > the way I am doing with CNI is follows.
> > 1. a java class with native method.(custom.java)
> > 2. c++ implementation of it to insert
> assembly.(custom.cc)
> > 3. compile custom.java (gcj -C custom.java)
> > 4. create the header file (gcjh custom -o custom.h)
> > 5. write multi threaded shared counter program. it has
> calls to native method to insert
> assembly(shared_counter.java)
> > 6. compile all java classes (gcj -C *.java)
> > 7. compile the custom.cc (g++ -c custom.cc -o
> custom.o)
> > 8. create the executable. (gcj do_options.class
> custom.class shared_counter.class custom.o -lstdc++
> --main=shared_counter -o shared_conter)
> >
> > do_options is an interface with final variables. is
> there something that is wrong. or should I need do some
> additional thing. any help/ advice is greatly appreciated.
>
> I'd rather see your code than guess what you did.
>
> But yes, you're right. You'd be calling code to
> invoke the inline asm,
> rather than executing it directly. If you can't
> tolerate that, your
> only recourse is to add an intrinsic counter
> increment. gcj already has
> intrinsics for things like
> sun.misc.Unsafe.compareAndSwapInt(), so this one
> should be easy enough. Personally speaking, I'd just
> write the routines
> that need to access the counter in C++.
>
> Andrew.
>
>
#define _GNU_SOURCE
#include <gcj/cni.h>
#include <pthread.h>
#include <iostream>
#include "custom.h"
#include "java_magic_c.h"
using namespace std;
using namespace java::lang;
void
custom::do_this(jint option)
{
MAGIC(option);
}
jint
custom::bind_this_thread(jlong thread_id)
{
// Mask for achieve the hard coded processor affinity
cpu_set_t mask;
// Initializes all the bits in the mask to zero
CPU_ZERO(&mask);
// Sets only the bits corresponding to the cpu
CPU_SET(thread_id, &mask);
if(sched_setaffinity(0, sizeof(mask), &mask) == -1 )
{
cout << "Thread"<< (int)thread_id << ": WARNING: Could not set CPU Affinity, continuing...\n";
}
return 0;
}
// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*-
#ifndef __custom__
#define __custom__
#pragma interface
#include <java/lang/Object.h>
extern "Java"
{
class custom;
}
class custom : public ::java::lang::Object
{
public:
static void do_this (jint);
static jint bind_this_thread (jlong);
public: // actually package-private
custom ();
public:
static ::java::lang::Class class$;
};
#endif /* __custom__ */
class custom
{
public static native void do_this(int option);
public static native int bind_this_thread(long thread_id);
}interface do_options
{
int TX_ABORT = 0xA;
int TX_BEGIN = 0xB;
int TX_COMMIT = 0xC;
int TX_PRINT = 0xD;
int RW_PRIVATE = 0x1;
int RO_SHARED = 0x2;
int R_SHARED_W_PRIVATE = 0x3;
int RW_SHARED = 0x4;
int HEAP = 0x5;
int THREAD = 0x6;
int START_SIMULATION = 0x8;
int STOP_SIMULATION = 0x9;
}class shared_counter implements Runnable, do_options
{
static int counter = 0;
long thread_id;
shared_counter(long thread_id)
{
this.thread_id = thread_id;
}
long get_thread_id()
{
return thread_id;
}
public void run()
{
custom.bind_this_thread(get_thread_id());
custom.do_this(do_options.TX_BEGIN);
counter++;
custom.do_this(do_options.TX_COMMIT);
}
public static void main(String[]args)
{
Thread sc[] = new Thread[Integer.parseInt(args[0])];
for(int i = 0;i<sc.length;i++)
{
sc[i] = new Thread(new shared_counter(i));
sc[i].start();
}
for(int i = 0;i<sc.length;i++)
{
try
{
sc[i].join();
}
catch(Exception e)
{
System.out.println("Got the error "+e);
}
}
System.out.println("shared counter value is "+counter);
}
}#ifndef JAVA_MAGIC_C_H_
#define JAVA_MAGIC_C_H_
/* use to allow c++ files to import it */
#ifdef __cplusplus
extern "C" {
#endif
#define ABORT_TX 0xA
#define BEGIN_TX 0xB
#define COMMIT_TX 0xC
#define PRINT_TX 0xD
#define MAGIC(n) do { \
asm volatile ("movl %0, %%eax" : : "g" (n) : "eax"); \
asm volatile ("xchg %bx,%bx"); \
} while (0)
#define MAGIC_BREAKPOINT MAGIC(0)
#ifdef __cplusplus
}
#endif
#endif /*JAVA_MAGIC_C_*/