what is the purpose of "(jlong)(ptrdiff_t)(void*)" in heapViewer.c(a JVMTI Demo)? - heap-dump

Below is the demo code():
/* Typedef to hold class details */
typedef struct {
char *signature;
int count;
int space;
} ClassDetails;
....
/* Tag this jclass */
err = (*jvmti)->SetTag(jvmti, classes[i], (jlong)(ptrdiff_t)(void*)(&details[i]));
the prototype of SetTag is
jvmtiError SetTag(jvmtiEnv* env, jobject object, jlong tag).
Can I just use it like this:
err = (*jvmti)->SetTag(jvmti, classes[i], (jlong)(&details[i])); ?

When using a tag that is a pointer, use a cast to ptrdiff_t(Standard C typedef for an integer that holds a pointer difference) to avoid compiler warnings and errors.
Never use int or long, you'll find out that int and long are not always big enough to hold a pointer, truncating your address, where ptrdiff_t will always be big enough to hold all the bits of a pointer.
Detailed info is here JVMPI transition to JVMTI

Related

How to change the default code generated by SWIG for the allocation of memory for a C structure?

I am using a flexible array in the structure. So I want to change the memory allocated for that structure with some of my own code. Basically I want to change the new_structname() and structname_variable_set() functions.
typedef struct vector{
int x;
char y;
int arr[0];
} vector;
here, SWIG generated new_vector() function to allocate memory by calling calloc(1,sizeof(struct vector)) where swig will not handle these type of structure in a special manner. So we need to modify the swig generated new_vector() in order to allocate memory for the flexible array. So is there any way to handle this?
There are a few ways you can do this. What you're looking for though is %extend. That lets us define new constructors and implement them as we see fit. (It even works with a C compiler, they're only constructors from the perspective of the target language).
Using your vector as a starting point we can illustrate this:
%module test
%include <stdint.i>
%inline %{
typedef struct vector{ int x; char y; int arr[0]; }vector;
%}
%extend vector {
vector(const size_t len) {
vector *v = calloc(1, sizeof *v + len);
v->x = len;
return v;
}
}
With this SWIG synthesises a new_vector function in the generated module code as you'd hoped.
I also assumed that you want to record the length inside the struct as one of its members. If that's not the case you can simply delete the assignment I made.

SWIG, not able to create typemap for long*

I have a C function like this one:
int make_call(char* to, int *call_id);
and a very simple interface file:
%include "typemaps.i"
%include "enums.swg"
%include "arrays_java.i"
%header %{
#include <my_header.h>
%}
/* Map "int*" as input & output */
%apply int *INOUT { int * };
This works just fine. In my SWIG file I get:
public static int make_call(String to, int[] call_id) {..}
and I can call it creating an int[] with one element. All good so far.
However as the call_id can be quite large it needs to be a long so I changed this in the C API and I added to the .i file this line:
%apply long *OUTPUT { long * };
I have tried several variants including trying to apply what is said in the java.html doc for SWIG but I always end up with an int[] beeing generated or maybe the swigtype for long that I am not able to use from Java. I am just not able to make it generate a long[] that I am expecting.
I tried just making it a double like this:
%apply double *OUTPUT { double * };
and it works as expected and I get my double[] call_id in the generated interface.
Is there any pitfalls with the long type? It would seem wierd right?
Try one of:
unsigned long
unsigned int
long long

Overloading the CUDA shuffle function makes the original ones invisible

I'm trying to implement my own 64-bit shuffle function in CUDA. However, if I do it like this:
static __inline__ __device__ double __shfl_xor(double var, int laneMask, int width=warpSize)
{
int hi, lo;
asm volatile( "mov.b64 { %0, %1 }, %2;" : "=r"(lo), "=r"(hi) : "d"(var) );
hi = __shfl_xor( hi, laneMask, width );
lo = __shfl_xor( lo, laneMask, width );
return __hiloint2double( hi, lo );
}
All subsequent calls to __shfl_xor will be instantiated from this 64-bit version, no matter what the type of the argument is. For example, if I am doing
int a;
a = __shfl_xor( a, 16 );
It would still use the double version.
A work-around might be using different function names. But since I'm calling this shuffle function from a template function, using different names means that I have to make a different version for 64-bit floating points, which is not quite neat.
So how can I overload the __shfl_xor(double,...) function while on the same time still make sure the __shfl_xor(int,...) can be called appropriately?
All integral types and float can be upcasted to double. When given a choice between in-built function and your specialized double function, the compiler here might be picking yours for all types.
Have you tried creating a function with a different name and using that to create both your specialized double variant and as dummies for the other types?
For example:
static __inline__ __device__ double foo_shfl_xor(double var, int laneMask, int width=warpSize)
{
// Your double shuffle implementation
}
static __inline__ __device__ int foo_shfl_xor(int var, int laneMask, int width=warpSize)
{
// For every non-double data type you use
// Just call the original shuffle function
return __shfl_xor(var, laneMask, width);
}
// Your code that uses shuffle
double d;
int a;
foo_shfl_xor(d, ...); // Calls your custom shuffle
foo_shfl_xor(a, ...); // Calls default shuffle

CUDA: How to apply __restrict__ on array of pointers to arrays?

This kernel using two __restrict__ int arrays compiles fine:
__global__ void kerFoo( int* __restrict__ arr0, int* __restrict__ arr1, int num )
{
for ( /* Iterate over array */ )
arr1[i] = arr0[i]; // Copy one to other
}
However, the same two int arrays composed into a pointer array fails compilation:
__global__ void kerFoo( int* __restrict__ arr[2], int num )
{
for ( /* Iterate over array */ )
arr[1][i] = arr[0][i]; // Copy one to other
}
The error given by the compiler is:
error: invalid use of `restrict'
I have certain structures that are composed as an array of pointers to arrays. (For example, a struct passed to the kernel that has int* arr[16].) How do I pass them to kernels and be able to apply __restrict__ on them?
The CUDA C manual only refers to the C99 definition of __restrict__, no special CUDA-specific circumstances.
Since the indicated parameter is an array containing two pointers, this use of __restrict__ looks perfectly valid to me, no reason for the compiler to complain IMHO. I would ask the compiler author to verify and possibly/probably correct the issue. I'd be interested in different opinions, though.
One remark to #talonmies:
The whole point of restrict is to tell the compiler that two or more pointer arguments will never overlap in memory.
This is not strictly true. restrict tells the compiler that the pointer in question, for the duration of its lifetime, is the only pointer through which the pointed-to object can be accessed. Be aware that the object pointed to is only assumed to be an array of int. (In truth it's only one int in this case.) Since the compiler cannot know the size of the array, it is up to the programmer to guard the array's boundaries..
Filling in the comment in your code with some arbitrary iteration, we get the following program:
__global__ void kerFoo( int* __restrict__ arr[2], int num )
{
for ( int i = 0; i < 1024; i ++)
arr[1][i] = arr[0][i]; // Copy one to other
}
and this compiles fine with CUDA 10.1 (Godbolt.org).

SWIG and triggering a Python callback from C code

Apologies for not being familiar with formatting on here...I've made
some progress thanks to helpful replies and edited and removed my original
question to be replaced by the current one.
My problem lies with converting a C struct or struct pointer to PyObject. There
is no alternative to this because I am wrapping an existing C library whose
callback requires a C struct pointer.
Following works but with limitations:
%module cain1
%{
typedef struct {
double price;
int volume;
} book_entry_t;
typedef struct {
char symbol[10];
book_entry_t *book;
} trade_t;
typedef void (*CALLBACK)(trade_t trade);
CALLBACK my_callback = 0;
static PyObject *my_pycallback = NULL;
static void bigSnake(trade_t trade)
{
PyObject *result;
PyObject *d1;
result = PyEval_CallObject(my_pycallback,
Py_BuildValue("(y#)",
(char*)&trade,
sizeof(trade_t)
)
);
Py_XDECREF(result);
return /*void*/;
}
void test_cb (PyObject *callMe1) {
trade_t d1;
book_entry_t b1;
b1.price = 123.45;
b1.volume = 99;
Py_XINCREF(callMe1); /* Add a reference to new callback */
my_pycallback = callMe1; /* Remember new callback */
strcpy (d1.symbol,"Gupta Ltd");
d1.book = &b1;
bigSnake(d1);
}
%}
// Expose in python module..
typedef struct {
double price;
int volume;
} book_entry_t;
typedef struct {
char symbol[10];
book_entry_t *book;
} trade_t;
void test_cb(PyObject *callMe1);
and then triggering the callback from Python:
import cain1
import struct
def dave(d1):
N1,N2 = struct.unpack('10sP', d1)
print ('\n %s: %x' % (N1.decode() ,N2))
price,volume = struct.unpack('di',N2)
print (price,volume)
def main():
cain1.test_cb(dave)
main()
but I am unable to recover the book_entry_t strcut contents pointed to by trade_t....
I just feel this is all too convoluted since I have the pointer to structs and there
must be a straightforward way for Python to use that without any fuss.
Py_BuildValue("(N)",details) expects a PyObject* (your "N" says so), and you pass it something very different. Try Py_BuildValue("(i)", details.index) instead, and change it to accomodate any changes in details_t.
You're attempting to build a PyObject from a details_t struct. This isn't valid. Either pass the callback an integer (seems easier since details_t only has the one field) OR create a proper PyObject type. You can't blindly cast one type to another and expect it to work (a PyObject is more than just a pointer).