- Community Home
- >
- Servers and Operating Systems
- >
- Operating Systems
- >
- Operating System - OpenVMS
- >
- IA64 / PASCAL - LIB$SHOW_VM_ZONE loops CPU bound
Categories
Company
Local Language
Forums
Discussions
Forums
- Data Protection and Retention
- Entry Storage Systems
- Legacy
- Midrange and Enterprise Storage
- Storage Networking
- HPE Nimble Storage
Discussions
Forums
Discussions
Discussions
Discussions
Forums
Discussions
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
- BladeSystem Infrastructure and Application Solutions
- Appliance Servers
- Alpha Servers
- BackOffice Products
- Internet Products
- HPE 9000 and HPE e3000 Servers
- Networking
- Netservers
- Secure OS Software for Linux
- Server Management (Insight Manager 7)
- Windows Server 2003
- Operating System - Tru64 Unix
- ProLiant Deployment and Provisioning
- Linux-Based Community / Regional
- Microsoft System Center Integration
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Community
Resources
Forums
Blogs
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-18-2006 12:16 AM
07-18-2006 12:16 AM
Code example follows:
[INHERIT
( 'SYS$LIBRARY:STARLET',
'SYS$LIBRARY:PASCAL$LIB_ROUTINES',
'SYS$LIBRARY:PASCAL$OTS_ROUTINES',
'SYS$LIBRARY:PASCAL$STR_ROUTINES' ) ]
PROGRAM TEST_TCCOM_VM( OUTPUT );
TYPE
$UQUAD = [QUAD,UNSAFE] RECORD
L0,L1:UNSIGNED; END;
HEADER_$T = [ALIGNED(13),BYTE(512)]
RECORD
RANGE_$Q : $UQUAD;
END;
VAR
GLOB_ZID_$U : [VOLATILE] UNSIGNED VALUE 0;
VAR
GLOB_AUX_HEADER : [VOLATILE] HEADER_$T;
GLOB_GET_PAGE_ADDR_$I : [VOLATILE] INTEGER;
NAME_$V : [VOLATILE] VARYING[255] OF CHAR;
[ASYNCHRONOUS]
FUNCTION VM_GET_PAGE
( NUM_PAGELETS_$I : INTEGER;
VAR ADDR_$I : INTEGER ) : INTEGER;
BEGIN
lib$put_output( '+ Requesting ' + dec(num_pagelets_$i) + ' pages');
!! if NUM_PAGELETS_$I <= 0 then return LIB$_BADBLOSIZ;
ADDR_$I := GLOB_GET_PAGE_ADDR_$I;
GLOB_GET_PAGE_ADDR_$I := GLOB_GET_PAGE_ADDR_$I + NUM_PAGELETS_$I * 512;
lib$put_output( ' Returning ' + hex(addr_$i) + '(h)');
lib$put_output( ' Next addr ' + hex(glob_get_page_addr_$i) + '(h)');
VM_GET_PAGE := SS$_NORMAL;
END;
[ASYNCHRONOUS]
FUNCTION VM_free_PAGE
( NUM_PAGELETS_$I : INTEGER;
ADDR_$I : INTEGER ) : INTEGER;
BEGIN
lib$put_output( '- Releasing ' + dec(num_pagelets_$i) + ' pages at ' + hex(addr_$i) + '(h)');
VM_free_PAGE := SS$_NORMAL;
END;
{------------------------------------------------------------------------------}
{ Globale VM-Zone erzeugen bzw. mappen
{------------------------------------------------------------------------------}
[ ASYNCHRONOUS, UNBOUND ]
FUNCTION TCCOM_CREATE_VM_ZONE
( NUM_PAGES_$I : INTEGER;
BASE_ADDR_$I : INTEGER ): INTEGER;
LABEL EXIT;
VAR
STAT : INTEGER;
RANGE_$Q : $UQUAD;
NUM_PAGELETS_$I : INTEGER;
BEGIN
NAME_$V := 'ULTSK_TCCOM_VM';
NUM_PAGELETS_$I := NUM_PAGES_$I * 16; {(8192 / 512)}
RANGE_$Q.L0 := IADDRESS( GLOB_AUX_HEADER );
RANGE_$Q.L1 := IADDRESS( GLOB_AUX_HEADER ) + 8192 - 1;
lib$put_output( 'Baseaddress ' + hex(base_addr_$i) + '(h)');
lib$put_output( 'Num Pages ' + dec(num_pages_$i));
lib$put_output( 'Pagelets ' + dec(num_pagelets_$i));
lib$put_output( 'Range l0 ' + hex(range_$q.l0) + '(h)');
lib$put_output( 'Range l1 ' + hex(range_$q.l1) + '(h)');
!! lib$put_output( 'Name ' + NAME_$V );
!! STAT := $MGBLSC(
!! INADR := RANGE_$Q,
!! GSDNAM := NAME_$V );
!! IF NOT ODD( STAT ) THEN LIB$SIGNAL( STAT );
!! lib$put_output( 'Name ' + NAME_$V );
RANGE_$Q.L0 := BASE_ADDR_$I;
RANGE_$Q.L1 := BASE_ADDR_$I + NUM_PAGES_$I*8192 - 1;
STAT := $CRMPSC(
INADR := RANGE_$Q,
RETADR := RANGE_$Q,
FLAGS := SEC$M_WRT + SEC$M_PAGFIL + SEC$M_GBL + SEC$M_NO_OVERMAP,
GSDNAM := NAME_$V,
PAGCNT := NUM_PAGELETS_$I );
IF NOT ODD( STAT ) THEN GOTO EXIT;
LIB$PUT_OUTPUT ('### CREATED at '+ HEX(BASE_ADDR_$I) + '(H)');
lib$put_output( 'Range l0 ' + hex(range_$q.l0) + '(h)');
lib$put_output( 'Range l1 ' + hex(range_$q.l1) + '(h)');
GLOB_GET_PAGE_ADDR_$I := BASE_ADDR_$I;
STAT := LIB$CREATE_VM_ZONE
( ZONE_ID := GLOB_ZID_$U,
INITIAL_SIZE := NUM_PAGELETS_$I,
PAGE_LIMIT := NUM_PAGELETS_$I,
GET_PAGE := %IMMED VM_GET_PAGE,
free_PAGE := %IMMED VM_free_PAGE,
ZONE_NAME := 'TCCOM_VM_ZONE' );
IF NOT ODD( STAT ) THEN GOTO EXIT;
EXIT:
TCCOM_CREATE_VM_ZONE := STAT;
END;
VAR
STAT : INTEGER;
ADDR_$I : INTEGER;
BEGIN
STAT := TCCOM_CREATE_VM_ZONE (
NUM_PAGES_$I := 1024,
BASE_ADDR_$I := %x08000000 {%x8000000});
IF NOT ODD(STAT) THEN $exit( stat );
STAT := LIB$SHOW_VM_ZONE( GLOB_ZID_$U, 2 );
IF NOT ODD(STAT) THEN $exit( stat );
END.
-----------
Demo:
(B) SGDEV6::MM:000000 >pascal /nooptimize test_vm
(B) SGDEV6::MM:000000 >link test_vm
(B) SGDEV6::MM:000000 >run test_vm
Baseaddress 08000000(h)
Num Pages 0000001024
Pagelets 0000016384
Range l0 00010000(h)
Range l1 00011FFF(h)
### CREATED at 08000000(H)
Range l0 08000000(h)
Range l1 087FFFFF(h)
+ Requesting 0000000001 pages
Returning 08000000(h)
Next addr 08000200(h)
+ Requesting 0000000000 pages
Returning 08000200(h)
Next addr 08000200(h)
Zone Id = 08000000, Zone name = "TCCOM_VM_ZONE"
Algorithm = LIB$K_VM_FIRST_FIT
Flags = 00000000
----------------------------------------------
Questions:
-) Why does this code loop ? User error or VMS Problem ?
-) Why does LIB$CREATE_VM_ZONE call the get page routine with an value of 0 pages. This value should be invalid.
Remark:
When using the _64 variants of create/show vm_zone everything works as expected.
When using al lower address for the sctioen (i.e. %x0300000) everything works normal.
Thanks for any hints
Martin
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-18-2006 12:26 PM
07-18-2006 12:26 PM
Re: IA64 / PASCAL - LIB$SHOW_VM_ZONE loops CPU bound
So far, this looks like a bug. The call to VM_GET_PAGE requesting (apparently) 0 seems wrong. That call is supposed to be your initial allocation - 16384 pages, but I can't work out why it's appearing as 0 in your routine. Same result when using LIB$GET_VM_PAGE (explicitly), so I don't think it's your code.
I'll look into it further to try and work out why, but if you need a formal response, please log a case with your local customer support centre.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-18-2006 02:50 PM
07-18-2006 02:50 PM
SolutionI think there is a bug somewhere in the LIB$*VM* system. It's got something to do with the request for 0 pages, which has something to do with the LIB$CREATE_VM_ZONE being the first call. You can get around it by adding an allocation and deallocation before creating the zone:
lib$get_vm(512,dummy);
lib$free_vm(512,dummy);
The initial allocation will now be what you ask for.
There is a bug in your program. The section you create is the same size as the initial allocation. That doesn't take into account the header/control structure which is allocated first. Since there is no overflow check in your vm_get_page routine, you're effectively telling the LIB$VM routines that they have an extra pagelet that doesn't exist. However, if I modify the code to allow for the extra space, that doesn't change the symptom. Even more mysterious, if I change your vm_get_page routine to call LIB$GET_VM_PAGE, it works (but only with the get_vm/free_vm hack to fix the initialization bug). I find that very puzzling!
Something that might get around this problem, and arguably a better design - I'm assuming you want to know the location of the heap contents, hence the section? Try this: create the zone, specifying your vm_get_page and vm_free_page routines, but have them call through to the LIB$*_VM_PAGE routines to do the actual allocation. Watch the allocations, you'll see the control structure allocation first (1 pagelet) then the contents. You can catch the contents block address and map a section to it. Kind of inverts what you're doing at the moment.
It makes the contents and control structures independent, and doesn't make your program dependent on having a particular address range free.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-18-2006 04:11 PM
07-18-2006 04:11 PM
Re: IA64 / PASCAL - LIB$SHOW_VM_ZONE loops CPU bound
Bug confirmed. I've been able to reproduce it in MACRO32 with just 2 calls - LIB$CREATE_VM_ZONE and LIB$SHOW_VM_ZONE. To reproduce the bug, you need a non-zero initial size and page limit.
As a workaround, add two lines before your create_vm_zone:
lib$get_vm(100,dummy);
lib$free_vm(100,dummy);
and, modify your vm_get_page routine to check the size being allocated. If it's small (ie: the first allocation used for zone control structures), allocate it with LIB$GET_VM_PAGE. For some reason, this will "correct" the second call, which you can allocate from your existing global section (no longer any need to adjust the size). Obviously this will continue to work after the bug is fixed. It also has the advantage of separating the zone heap from the control structures.
In terms of fixing this, if you want to make certain it happens, you'll have to log a case with your local customer support centre.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-18-2006 06:08 PM
07-18-2006 06:08 PM
Re: IA64 / PASCAL - LIB$SHOW_VM_ZONE loops CPU bound
Thanks for your feedback.
I will try to convince my systemmanagement to log a call. But I think it will take some effort. Normally I must convince them that something is really a problem bevor a case is logged.
It would be a good impovement to let everybody log a case with HP in an official system. Of course nobody without a contract would have a guarantee that something happens. But I think, that bug like this (major impact, easy to reproduce, non totally exotic routine) would be processed by development anyway.
------------------
Referring to your suggestion using othe allocations:
This ruther old code - was written for VAX originally - uses LIB$GET_VM / FREE_VM to allocate memory in a global section. This memory is not always allocated by the same process as it freed by. (Process A allocates some memory and passes this the data to process B using interlocked queues. Process B then deallocates the memory.) I know that the memory must be located at the same virtual address in all processes - and this is a problem. I would design this handling completly different today.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-18-2006 06:37 PM
07-18-2006 06:37 PM
Re: IA64 / PASCAL - LIB$SHOW_VM_ZONE loops CPU bound
I implemented the workaround you suggested and added a call to GET_VM. (Full program is attached)
:
:
VAR
STAT : INTEGER;
ADDR_$I : INTEGER;
BEGIN
STAT := LIB$GET_VM(100, addr_$I);
IF NOT ODD(STAT) THEN $exit( stat );
STAT := TCCOM_CREATE_VM_ZONE (
NUM_PAGES_$I := 1024,
BASE_ADDR_$I := %x08000000 {%x8000000});
IF NOT ODD(STAT) THEN $exit( stat );
STAT := LIB$SHOW_VM_ZONE( GLOB_ZID_$U, 2 );
IF NOT ODD(STAT) THEN $exit( stat );
END.
Now the allocation callbacks are processed as expected:
(B) SGDEV6::MM:000000 >run test_vm
Baseaddress 08000000(h)
Num Pages 0000001024
Pagelets 0000016384
Range l0 00010000(h)
Range l1 00011FFF(h)
### CREATED at 08000000(H)
Range l0 08000000(h)
Range l1 087FFFFF(h)
+ Requesting 0000000001 pages
Returning 08000000(h)
Next addr 08000200(h)
+ Requesting 0000016383 pages
Returning 08000200(h)
Next addr 08800000(h)
Zone Id = 08000000, Zone name = "TCCOM_VM_ZONE"
Algorithm = LIB$K_VM_FIRST_FIT
Flags = 00000000
***BUT*** the main problem, the problem that LIB$SHOW_VM_ZONE is looping is *NOT* solved. Although the incorrect call with 0 bytes is omitted, the looping still occures.
Any more ideas ?
Martin
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-18-2006 08:29 PM
07-18-2006 08:29 PM
Re: IA64 / PASCAL - LIB$SHOW_VM_ZONE loops CPU bound
Purely Personal Opinion
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-18-2006 08:39 PM
07-18-2006 08:39 PM
Re: IA64 / PASCAL - LIB$SHOW_VM_ZONE loops CPU bound
:
:
STAT := TCCOM_CREATE_VM_ZONE (
NUM_PAGES_$I := 1024,
BASE_ADDR_$I := %x08000000 {%x8000000});
IF NOT ODD(STAT) THEN $exit( stat );
STAT := LIB$VERIFY_VM_ZONE( GLOB_ZID_$U );
lib$signal( stat );
STAT := LIB$SHOW_VM_ZONE( GLOB_ZID_$U, 2 );
IF NOT ODD(STAT) THEN $exit( stat );
LIB$VERIFY_VM_ZONE returns SS$_NORMAL.
Output is appended:
SGDEV6::MM:000000 >run test_vm
Baseaddress 08000000(h)
Num Pages 0000001024
Pagelets 0000016384
Range l0 00010000(h)
Range l1 00011FFF(h)
### CREATED at 08000000(H)
Range l0 08000000(h)
Range l1 087FFFFF(h)
+ Requesting 0000000001 pages
Returning 08000000(h)
Next addr 08000200(h)
+ Requesting 0000016383 pages
Returning 08000200(h)
Next addr 08800000(h)
%SYSTEM-S-NORMAL, normal successful completion
Zone Id = 08000000, Zone name = "TCCOM_VM_ZONE"
Algorithm = LIB$K_VM_FIRST_FIT
Flags = 00000000
So I would call it a bug :-)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-19-2006 10:20 AM
07-19-2006 10:20 AM
Re: IA64 / PASCAL - LIB$SHOW_VM_ZONE loops CPU bound
>uses LIB$GET_VM / FREE_VM to allocate
>memory in a global section. This memory
>is not always allocated by the same
>process as it freed by. (Process A
>allocates some memory and passes this
>the data to process B using interlocked
>queues. Process B then deallocates the
>memory.)
YIKES!! How could that ever work? How can you expect the LIB$VM routines to coordinate multiple processes allocating and freeing data from the same pool? Especially when the VM control structures are allocated from the same location.
I'd have said the only plausible way of implementing this would be to roll your own memory management routines which know they can be accessed from multiple processes and perform the appropriate interlocks. Even better wrap the data structure up in a hidden global section and use some kind of relative addressing so you're not dependent on address spaces lining up. All the details of addressing and synchronization can be hidden.
Regarding logging cases... you're company is free to make its own policy, but maybe they should be reminded that support contracts aren't "per event". It's not a resource you have to save up for a special event. Log as many cases as you like - it won't change the cost. You've paid your money, so may as well use it.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-19-2006 10:35 AM
07-19-2006 10:35 AM
Re: IA64 / PASCAL - LIB$SHOW_VM_ZONE loops CPU bound
Yes, it's definitely a bug.
Maybe you missed my suggestion to allocate the FIRST block requested with LIB$GET_VM_PAGE? That corrects your size error, and (for me) makes the program "work". However, now that you say the whole zone should be in the global section, I'm not certain if it will work in your multi process environment (having trouble believing that it ever worked at all anyway!).
A little further investigation, it looks like the looping is dependent on the location of the control structures - which you mentioned before. Maybe you could define two sections? A small one lower in memory for the zone header, and a larger one for everything else?
Note that apart from the length error, the zone appears to "work" correctly, in that you can allocate and deallocate memory, and it passes LIB$VERIFY_VM_ZONE. It's just SHOW_VM_ZONE that loops.
Best I can do is suggest workarounds. In these times where everything is measured and costed, engineers don't have much "spare" time to work on things that can't be shown to have a direct revenue benefit. With accountants in charge, logic doesn't matter. If you want engineering to look at this formally you'll have to log a case.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-19-2006 08:10 PM
07-19-2006 08:10 PM
Re: IA64 / PASCAL - LIB$SHOW_VM_ZONE loops CPU bound
Yes I understand that logging a case is required. I'm very happy that someone could confirm the problem, so that I am sure, that I do not miss some trival thing.
I totally confirm, that this code is bad and it's surprising that it works. I'm not sure whether someone in the late 1980s when this code was written had checked the sources of VMS (at this time we had access to them - on microfiches! Locating a special place was a time of minutes / hours. And t6he big box und the desk ...)
But I can confirm, that the code worked stable on VAX and works on several AXP sytems including multi-cpu systems. (I thing LIB$ uses intterlocked instructions internally). I think you will read it in at least some newspapers if the code fails :-)
Again thanks for the support. I'll close this question.
Martin
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-19-2006 08:13 PM
07-19-2006 08:13 PM