Re: Create binary from GCJ generated assembly
isuru herath <[email protected]>
| Newsgroups | gmane.comp.gcc.java.devel |
|---|---|
| Message-ID | <[email protected]> |
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 <[email protected]> wrote: > From: Andrew Haley <[email protected]> > Subject: Re: Create binary from GCJ generated assembly > To: "isuru herath" <[email protected]> > Cc: [email protected] > 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. > >
custom.cc
(text/x-c++src, 670 B)
#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;
}
custom.h
(text/x-chdr, 434 B)
// 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__ */
custom.java
(text/x-java, 124 B)
class custom
{
public static native void do_this(int option);
public static native int bind_this_thread(long thread_id);
}
do_options.java
(text/x-java, 313 B)
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;
}
shared_counter.java
(text/x-java, 802 B)
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);
}
}
java_magic_c.h
(text/x-chdr, 495 B)
#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_*/