Silverfrost Forums

Welcome to our forums

GET_GSTORAGE@ doesn't always work?

5 Jan 2023 7:47 #29736

hi,

I’m getting a return address of -1 from a call to:

  CALL GET_GSTORAGE@ (IA, NB)

NB= ~80k (amongst other values) and has been successfully called multiple times previously - only ~1GB has been 'committed' by the application so there should be plenty of RAM available (it normally only “chokes” at ~ 2GB) and the system memory usage is less than 80%.

Is there some other condition that can cause this value to be returned?

K

5 Jan 2023 8:05 #29739

Kenny

Is it a 32 bit or 64 bit application?

5 Jan 2023 8:09 #29740

32 bit...

K

5 Jan 2023 9:32 #29741

The essence of GET_GSTORAGE@ is a call to VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE).

In this context size (NB) is a signed 32 bit integer so values up to 2GB should work. The only way for this routine to fail is when VirtualAlloc fails.

Memory is committed from the virtual address space, not the global heap.

Looking at the Microsoft documentation for VirtualAlloc, there is no indication that MEM_RESERVE is also required in this context i.e. where the base address in not specified (is NULL).

It is just possible that a change in the operating system has meant that MEM_RESERVE is now required but this seems unlikely.

5 Jan 2023 10:03 #29742

ok, tks.

i've reduced the number of calls to GET_GSTORAGE@ by setting the limit on its usage higher. previously, any request for memory > 16 bytes used GSTORAGE, ⇐16 used GET_STORAGE.

I've changed that decision to 256bytes and it seems better.

is there a recommended buffer size to decide which routine to call?

K

5 Jan 2023 10:54 #29743

The documentation does not say anything about when to switch from GET_STORAGE@ to GET_GSTORAGE@.

Both of these routines get memory from the virtual address space.

If you prefer to get memory from the global heap (and don't want to use ALLOCATE) then you could use GET_STORAGE2@ (for a 32 bit application).

 integer addr, get_storage2@
 addr = get_storage2@(1000, 0)
 print*, addr

The second argument is no longer used.

5 Jan 2023 12:22 #29747

hmmm,

get_storage2@ works twice (the first time it returns 2147...... (i.e. approx max int*4)) and then returns 0's thereafter...

K

5 Jan 2023 12:50 #29750

Kenny

What is the context where you want to get memory? Maybe there is a more direct way.

5 Jan 2023 2:13 #29752

we make frequent use of memory addresses for storage of various data items, using two routines: vmget and vmfree. a typical situation is our dialogue handling code where we grab a number of addresses, pass them to generic field processing routines, then relaese the memory when the dialogue closes. this is legacy code and there is a LOT of it! at the moment vmget calls GET_*STORAGE@ and vmfree calls RETURN_*STORAGE@.

the only alternative i can think of is to do something like this, using a character buffer:

vmget calls ALLOCATE(ch(nb)) and passes back IAD = LOC(ch) vmfree calls DEALLOCATE(ccore1(IAD))

which i will try now unless you can recommend something better...

K

edit: no, it doesn't work unless i keep a record in memory of all the allocated addresses and their size which is impractical, i think...

5 Jan 2023 4:51 #29757

Using ALLOCATE and DEALLOCATE in this way seems like a useful work-around but we need a direct approach to allocating memory from the global heap such as that provided by get_storage2@ which works OK for me.

 integer addr(10), get_storage2@
 do i =1, 10
 addr(i)  = get_storage2@(1000000, 0)
 write(*, '(Z8)') addr(i)
 end do
 end
5 Jan 2023 4:56 #29758

is there an equivalent return_storage2@

K

6 Jan 2023 8:35 #29762

Kenny

There is an equivalent and it is called return_storage1@ but, having tested it, I find that it is not working. However, you can provide your own interface...

 integer addr(10), get_storage2@
 c_external return_storage2 '__release_memory'(VAL3)
 do i =1, 10
   addr(i)  = get_storage2@(1000000, 0)
   write(*, '(Z8)') addr(i)
 end do
 do i =1,10
   call return_storage2(addr(i))
 end do
 end
6 Jan 2023 8:47 #29763

Kenny

It is probably safer if you also use your own interface for get_storage...

 c_external get_storage2    '__get_memory'(VAL3,VAL3):INTEGER*4
 c_external return_storage2 '__release_memory'(VAL3)
 integer addr(10)
 do i =1, 10
   addr(i)  = get_storage2(1000000, 0)
   write(*, '(Z8)') addr(i)
 end do
 do i =1,10
   call return_storage2(addr(i))
 end do
 end
6 Jan 2023 10:02 #29764

hmm,

it seems to only work partially, seems OK when all in same obj file.

but it looks like when the call to get_storage2 is in a DLL, it grabs about 60Mb memory (according to resmon) even if i've only requested 4 bytes! so my test prog soon runs out of gas.

K

MAIN:

!ftn95$free
       integer addr(10), get_storage2@
       character*4	:: ch
        c_external return_storage2@ '__release_memory'(VAL3)
      do i=1,10
      call a_vmget(4, addr(i), ir)
!      addr(i)=get_storage2@(4, 0)
      write(*, *) addr(i)
      end do
       read(*,*)ch
      do i=1,10
      call a_vmfree(addr(i))
 !     call return_storage2@(addr(i))
      write(*, *) addr(i)
      end do
       read(*,*)ch
      end 

DLL:

!ftn95$free
SUBROUTINE A_VMGet (nb, IA, IRET)
  INTEGER(KIND=7)       IA, get_storage2@
      ia    =  get_storage2@(nb,0)
      return
END SUBROUTINE




!**	Free virtual memory										*****  A_VMFree	*****
SUBROUTINE A_VMFree (IA)
 c_external return_storage2@ '__release_memory'(VAL3)
  INTEGER(KIND=7)       IA 
    call return_storage2@(ia)
END SUBROUTINE
6 Jan 2023 10:39 #29765

Kenny

Try using your own interface for both routines, as in my last post.

The KIND=7 should be OK but remember that this is only for 32 bit applications.

6 Jan 2023 10:45 #29766

hi, i've tried that and it seems to work in a 'noddy' but not in my main application (but i'm still testing).

a question, does the number of bytes in the call to get memory have to be a multiple of 4/8/16?

K

6 Jan 2023 11:04 #29767

No. The call is to GlobalAlloc and the memory allocation is guaranteed to be aligned on an 8-byte boundary.

6 Jan 2023 1:00 #29768

It is worth remembering that VirtualAlloc allocates (or uses memory) at page size granularity. So an alloc of a few bytes takes a full 4K page

6 Jan 2023 3:40 #29770

Seems to work well!

the memory 'jumps' are much smaller than before.

the proof of the pudding is in the hands of our most rigorous user.

all being well, he shd be quite happy...

tks.

K

9 Jan 2023 10:08 #29782

hi,

just following up...

you mentioned that this was only a 32-bit solution. what is the recommended equivalent 64-bit version?

K

Please login to reply.