View previous topic :: View next topic |
Author |
Message |
KennyT
Joined: 02 Aug 2005 Posts: 318
|
Posted: Thu Jan 05, 2023 8:47 am Post subject: GET_GSTORAGE@ doesn't always work? |
|
|
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 |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8019 Location: Salford, UK
|
Posted: Thu Jan 05, 2023 9:05 am Post subject: |
|
|
Kenny
Is it a 32 bit or 64 bit application? |
|
Back to top |
|
|
KennyT
Joined: 02 Aug 2005 Posts: 318
|
Posted: Thu Jan 05, 2023 9:09 am Post subject: |
|
|
32 bit...
K |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8019 Location: Salford, UK
|
Posted: Thu Jan 05, 2023 10:32 am Post subject: |
|
|
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. |
|
Back to top |
|
|
KennyT
Joined: 02 Aug 2005 Posts: 318
|
Posted: Thu Jan 05, 2023 11:03 am Post subject: |
|
|
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 |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8019 Location: Salford, UK
|
Posted: Thu Jan 05, 2023 11:54 am Post subject: |
|
|
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).
Code: | integer addr, get_storage2@
addr = get_storage2@(1000, 0)
print*, addr
|
The second argument is no longer used. |
|
Back to top |
|
|
KennyT
Joined: 02 Aug 2005 Posts: 318
|
Posted: Thu Jan 05, 2023 1:22 pm Post subject: |
|
|
hmmm,
get_storage2@ works twice (the first time it returns 2147...... (i.e. approx max int*4)) and then returns 0's thereafter...
K |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8019 Location: Salford, UK
|
Posted: Thu Jan 05, 2023 1:50 pm Post subject: |
|
|
Kenny
What is the context where you want to get memory? Maybe there is a more direct way. |
|
Back to top |
|
|
KennyT
Joined: 02 Aug 2005 Posts: 318
|
Posted: Thu Jan 05, 2023 3:13 pm Post subject: |
|
|
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... |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8019 Location: Salford, UK
|
Posted: Thu Jan 05, 2023 5:51 pm Post subject: |
|
|
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.
Code: | integer addr(10), get_storage2@
do i =1, 10
addr(i) = get_storage2@(1000000, 0)
write(*, "(Z8)") addr(i)
end do
end
|
|
|
Back to top |
|
|
KennyT
Joined: 02 Aug 2005 Posts: 318
|
Posted: Thu Jan 05, 2023 5:56 pm Post subject: |
|
|
is there an equivalent return_storage2@
K |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8019 Location: Salford, UK
|
Posted: Fri Jan 06, 2023 9:35 am Post subject: |
|
|
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...
Code: | 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 |
|
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8019 Location: Salford, UK
|
Posted: Fri Jan 06, 2023 9:47 am Post subject: |
|
|
Kenny
It is probably safer if you also use your own interface for get_storage...
Code: | 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 |
|
|
Back to top |
|
|
KennyT
Joined: 02 Aug 2005 Posts: 318
|
Posted: Fri Jan 06, 2023 11:02 am Post subject: |
|
|
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:
Code: |
!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:
Code: |
!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
|
|
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8019 Location: Salford, UK
|
Posted: Fri Jan 06, 2023 11:39 am Post subject: |
|
|
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. |
|
Back to top |
|
|
|