Not able to deallocate static based variable - rpgle

I'm getting strange results when attempting to de-allocate a static based variable. Below is a small test program I've created to demo the issue I'm having. The static based variable is in the proc1 sub-procedure of this test program. Its name is myIx, with based pointer of myIx_p. I put comments in the main body of the program to indicate the issues that I'm having. What am doing wrong here?
D ix s 5i 0
/free
ix = proc1(*off); // ix is 1 after this statement => Expected
ix = proc1(*off); // ix is 2 after this statement => Expected.
ix = proc1(*on); // ix is 0, which is expected. But myIx_p is not being set to null => NOT Expected
ix = proc1(*off); // ix is 3 after this statement => NOT Expected. Expecting 1.
ix = proc1(*on); // try to shutdown again and get CEE0810 error => NOT Expected
*inlr = *on;
*------------------------------------------------------------------------------------------
* proc1 to test based static variable
*------------------------------------------------------------------------------------------
P proc1 B
D pi 5i 0
D piShutDown n const
D myIx s 5i 0 based(myIx_p)
D myIx_p s * static
// caller only wants to shutdown the proc
if (piShutDown and myIx_p <> *null);
dealloc myIx_p;
return 0;
endif;
// allocate myIx if not yet allocated
if (myIx_p = *null);
myIx_p = %alloc(%size(myIx));
endif;
// increase the value by 1 as a test
myIx += 1;
return myIx;
P E
/end-free

The answer is right there in your comments. You do not set myIx_p = *null after you dealloc. Failure to set it to *null means it is still pointing to the same memory location that it was only the operating system no longer sees it as allocated. The behavior you are seeing is entirely expected. The fix is as simple as:
// caller only wants to shutdown the proc
if (piShutDown and myIx_p <> *null);
dealloc myIx_p;
myIx_p = *null;
return 0;
endif;
You can also resolve it as thus according to the IBMi documentation:
// caller only wants to shutdown the proc
if (piShutDown and myIx_p <> *null);
dealloc(n) myIx_p;
return 0;
endif;
If you don't use (n), you must set it to *null yourself like in the first example. See the documentation about dealloc here: https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_74/rzasd/zzdeall.htm

Related

Error while reading same mem positions on different threads

I have a problem while reading a couple of positions in a double array from different threads.
I enqueue the execution with :
nelements = nx*ny;
err = clEnqueueNDRangeKernel(queue,kernelTvl2of,1,NULL,&nelements,NULL,0,NULL,NULL);
kernelTvl2of has (among other) the code
size_t k = get_global_id(0);
(...)
u1_[k] = (float)u1[k];
(...)
barrier(CLK_GLOBAL_MEM_FENCE);
forwardgradient(u1_,u1x,u1y,k,nx,ny);
barrier(CLK_GLOBAL_MEM_FENCE);
and forwardgradient has the code:
void forwardgradient(global double *f, global double *fx, global double *fy, int ker,int nx, int ny){
unsigned int rowsnotlast = ((nx)*(ny-1));
if(ker<rowsnotlast){
fx[ker] = f[ker+1] - f[ker];
fy[ker] = f[ker+nx] - f[ker];
}
if(ker<nx*ny){
fx[ker] = f[ker+1] - f[ker];
if(ker==4607){
fx[0] = f[4607];
fx[1] = f[4608];
fx[2] = f[4608] - f[4607];
fx[3] = f[ker];
fx[4] = f[ker+1];
fx[5] = f[ker+1] - f[ker];
}
}
if(ker==(nx*ny)-1){
fx[ker] = 0;
fy[ker] = 0;
}
if(ker%nx == nx-1){
fx[ker]=0;
}
fx[6] = f[4608];
}
When I get the contents of the first positions of fx, they are:
-6 0 6 -6 0 6 -6
And here's my problem: when I query fx[ker+1] or fx[4608] on thread with id 4607 I get a '0' (positions second and fifth of the output array), but from other threads I get a '-6' last position of the output array)
Anyone has a clue on what I'm doing wrong, or where I could look to?
Thanks a lot,
Anton
Within a kernel, global memory consistency is only achievable within a single work-group. This means that if a work-item writes a value to global memory, a barrier(CLK_GLOBAL_MEM_FENCE) only guarantees that other work-items within the same work-group will be able to read the updated value.
If you need global memory consistency across multiple work-groups, you need to split your kernel into multiple kernels.

Renderscript and garbage collector

Recently I modified my code to store everything in the renderscript (before that I copied the data back and forth wasn't effective), but now the garbage collector is collecting garbage like crazy. (Still the app is preforming better this way.)
I can't figure out what needs to be collected, I use everything I don't create new arrays in the functions, which I call frequently. My only idea is that if I do this:
void __attribute__((kernel)) diffuseVelocityY(float in, uint32_t x, uint32_t y) {
velocityY_prev[x] = velocityY[x] + a*(velocityY_prev[x-1] + velocityY_prev[x+1] + velocityY_prev[x-(width)] + velocityY_prev[x+(width)])/(1+(4*a));
}
it creates a temperaly pointer for it because I'm using data from the same pointer that I want to update(I have no idea if this is the way it works). I tried to change it, so it puts the data in an empty pointer and after it finishes I copy the data to the right place. It seemd that it collected less garbage but there was still garbage collection and the preformance went down aswell.
I uploaded my code here if someone wants to look(the _befores are from before I modified the code).
I have no idea how to stop the garbage collection, I hope someone can help.
One of the methods:
void set_bnd_densiy_prev(int b){
for (int i = 1; i <= gridSizeY; i++) {
density_prev[IX(0, i)] = (b == 1 ? -density_prev[IX(1, i)] : density_prev[IX(1, i)]);
density_prev[IX(gridSizeX + 1, i)] = (b == 1 ? -density_prev[IX(gridSizeX, i)] : density_prev[IX(gridSizeX, i)]);
}
for (int i = 1; i <= gridSizeX; i++) {
density_prev[IX(i, 0)] = (b == 2 ? -density_prev[IX(i, 1)] : density_prev[IX(i, 1)]);
density_prev[IX(i, gridSizeY + 1)] = (b == 2 ? -density_prev[IX(i, gridSizeY)] : density_prev[IX(i, gridSizeY)]);
}
density_prev[IX(0 ,0 )] = 0.5f*(density_prev[IX(1,0 )]+density_prev[IX(0 ,1)]);
density_prev[IX(0 ,gridSizeY+1)] = 0.5f*(density_prev[IX(1,gridSizeY+1)]+density_prev[IX(0 ,gridSizeY )]);
density_prev[IX(gridSizeX+1,0 )] = 0.5f*(density_prev[IX(gridSizeX,0 )]+density_prev[IX(gridSizeX+1,1)]);
density_prev[IX(gridSizeX+1,gridSizeY+1)] = 0.5f*(density_prev[IX(gridSizeX,gridSizeY+1)]+density_prev[IX(gridSizeX+1,gridSizeY )]);
}
Code generated from it:
private final static int mExportFuncIdx_set_bnd_densiy_prev = 3;
public void invoke_set_bnd_densiy_prev(int b) {
FieldPacker set_bnd_densiy_prev_fp = new FieldPacker(4);
set_bnd_densiy_prev_fp.addI32(b);
invoke(mExportFuncIdx_set_bnd_densiy_prev, set_bnd_densiy_prev_fp);
}
The problem was with the function args because renderscript needs to create Fieldpackers to handle them. So if you have the same problem remove the function args then copy paste the function and modify the variables and call the different functions not pretty but it works.
(Thanks thebaron for your help)

Default return value of a function in BASIC

Following is an example program in BASIC. Can someone tell me what this function returns if the marked condition is not true? I have to port the program to C++ and need to understand it. I have no BASIC knowledge - please bear with simple question.
FUNCTION CheckPoss (u)
tot = tot + 1
f = 0
SELECT CASE u
CASE 2
f = f + CheckIntersection(1, 3, 2, 1) 'A
CASE 3
f = f + CheckIntersection(2, 3, 3, 1) 'B
END SELECT
IF f = 0 THEN <============== This condition if true,
CheckPoss = 1 <============== then return value is 1
IF u = 9 THEN
PrintSolution
END IF
END IF
END FUNCTION
This is a good example of bad programming. First some unknown global variable is changed in this function. "tot = tot + 1"! Second line "F" is another unknown global variable is assigned "0". Or is this the only place this variable is used? In that case it is a variant implicitly declared here. Use a dim to declare it. It is legal in basic to do this. Globals should be passed as arguments to the function like this:
function CheckPoss(u as integer, tot as integer) as integer
dim f as integer
f=0
It is all about good practice so the input is clear and output is clear and all variable assignments should be through arguments passed to the function.
The return type is not declared either. Is this visual basic? or is it some older basic? Anyway the return type is a variant in case of visual basic. Older basic would be an integer type.
The output from this function will mostly likely be a zero if the condition is not met! That should also be clear in the code and it is not clear as it is, and I understand why you ask. I am amazed this piece of code comes from a working program.
Good luck with your project!
I don't know exactly that this function do.
On VB.net, the function follow the structure:
Public function CheckPoss(Byval u as integer)
... ' Just commands
return u ' Or other variable
end function
If not exist the 'return' command, the return of function will be 'null' character.
On C, The function will be:
int CheckPoss(int u){
tot++; // Increment tot variable (need be declared)
int f = 0;
switch(u){
case 2:
f += CheckIntersection(1, 3, 2, 1); // A
break;
case 3:
f += CheckIntersection(2, 3, 3, 1); // B
break;
}
if (f == 0){
if (u == 9){
PrintSolution();
}
return 1;
}
}
The return command need be the last command of this function. At case f != 0, the function must return trash (some value or character).
My suggestion is:
int CheckPoss(int u){
tot++; // I think that this must count how times you call this function
int f;
if(u == 2){
f = CheckIntersection(1, 3, 2, 1); // A
}else if(u == 3){
f = CheckIntersection(2, 3, 3, 1); // B
}else{
f = 1; // Case else
}
if (f == 0){
if (u == 9)
PrintSolution();
return 1;
}
}

.NET 4.0: Please help me with this tasks issue

Simple copy pasta here:
static void Main(string[] args)
{
List<Task> Tasks = new List<Task>();
Random r = new Random();
for (int o = 0; o < 5; o++)
Tasks.Add(Task.Factory.StartNew(() => { int i = r.Next(0, 3000); Thread.Sleep(i); Console.WriteLine("{0}: {1}", o, i); }));
Task.WaitAll(Tasks.ToArray());
Console.Read();
}
When you run that, you will get something like this:
5: 98
5: 198
5: 658
5: 1149
5: 1300
What am I not understanding about this? Writing each iteration of o is showing as 5 for all threads when I'd expect to see numbers 0 through 4 in random order.
I tried using an actual method instead of anonymous and it does the same thing. What am I missing?
Edit: I just found the problem with my very first post and edited the question, so sorry if you answered about the improper order problem. However, I am curious as to why o is not writing properly.
() =>
{
int i = r.Next(0, 3000);
Thread.Sleep(i);
Console.WriteLine("{0}: {1}", o, i);
})
Your are closing over your loop variable o with the delegate you use for your task - by the time it is executed your loop has finished and you only get the end value 5 for o. Remember you are creating a closure over the loop variable, not it's current value - the value is only evaluated when the delegate is executed once the task is started.
You have to create a local copy of the loop variable instead, which you can then use safely:
for (int o = 0; o < 5; o++)
{
int localO = o;
Tasks.Add(Task.Factory.StartNew(() => { int i = r.Next(0, 3000); Thread.Sleep(i); Console.WriteLine("{0}: {1}", localO, i); }));
}
There are at least two problems here.
The problem with o having the value of 5 on every iteration is one of those "gotchas" of lexical closures. If you want o to capture its current value, you must create a locally scoped variable inside your loop and use that in your lambda, e.g.:
for (int o = 0; o < 5; ++o)
{
int localO = o;
// now use "localO" in your lambda ...
}
Also, Random is not thread-safe. Using the same instance of Random simultaneously across multiple threads can corrupt its state and give you unexpected results.
I think you are making the assumption that the tasks are executed in the order they are created, and the TPL makes no such guarantees...
As for the 'o' parameter always printing as 5, that is because it is a local variable in the parent scope of the anonymous function, hence when the print is actually executed its value is 5 because the loop has completed (compare to 'i' being scoped within the anonymous function)

A query about lexical scoping

I try to understand lexical-scoping. In lexical-scoping, I have this code, C like syntax:
main{
f1(){
int y = 8;
}
int y = 1; //*
f1();
}
After the execution of f1() line, will the value of y variable in main (I put * next of it) remain 1 or change to 8?
It will remain 1. You have two completely distinct variables. Changes to one do not affect the other.

Resources