/* acf4:comp.os.vms / chuck@mitlns.mit.edu / 6:59 pm Nov 29, 1990 */ -Message-Text-Follows- I would like to thank the many people who helped me with my question, I got about 10 very helpful replies. Follows is my summary about what I learned this week. In addition to answers to my questions : Question 1 How do you get demand-zero pages in shareable images. Question 2 How do you make a shareable image with a user defined common block size I've added some related things I learned: 3. Easy instructions for turning your Library file into a shareable image. *These instructions are for FORTRAN libraries, you might have to modify them for other languages.* 4. Using Link /SYMBOL qualifier to create .STB files. If you have a large library that includes a general purpose interactive interface (we do), then this enables you to use the interactive interface program as a kind of 'runtime library' for programs. For us combining the general purpose interface with the user code is a real advantage. 1. Demand-zero compression is not allowed by default for shareable images. To get it add the following to the option file. You have to know the name of the writable psect you want to be demand zero. For Fortran libraries this is probably the name of a COMMON block. For instance if you have COMMON /USER/SPACE(1000000) in the image and you want that common block to be demand zero pages add the following to the linker option file: UNSUPPORTED=1 !Allows demand-zero compression psect_attr=USER,NOSHR !Can't share demand zero pages The UNSUPPORTED word makes people nervous, including me. However no one who replied seem to know of a case personally were this caused problems. Though there were several "rumours" of situations were it is a problem. I've had no trouble with it. 2. How to get a variable size common block. Create a second sharable image that just contains the common block, and perhaps a function to return the size of the common. As long as the common block is declared /NOSHR users can substitue their own version since it does not have to be installed. For instance: INTEGER FUNCTION COM_SIZE parameter (isize=1000000) COMMON/USER/SPACE(isize) COM_SIZE=ISIZE return end In the library declare the common as follows Parameter (min_size=1) COMMON/USER/SPACE(min_size) As long as ISIZE>MIN_SIZE it will work. To change the space of the common just recompile and link COM_SIZE. You don't need to relink the library. You can have several premade versions COM_SIZE_BIG.EXE, COM_SIZE_SMALL.EXE, COM_SIZE.EXE and use the appropiate version by pointing to them with the logical COM_SIZE. Of course the library can't be compiled /CHECK=BOUNDS. To guarentee that the library won't need to be relinked COM_SIZE should have a transfer vector setup as follows: (this basically right out of the linker manual) File XFER.MAR ; Transfer vectors for paw user code ; .title myxfr .psect $$xfrvectors,exe,nowrt .transfer com_size .mask com_size jmp l^com_size+2 .end These are compiled and linked as follows to produce the image, the COLLECT= line in the option file pulls in the COMXFR macro object. $LINK/SHARE PAWC_SIZE,SYS$INPUT:/opt UNSUPPORTED=1 !allows demand zero compression (not neccesary) collect=xxfervector,,xfer !gets transfer vector macro object psect_attr=USER,noshr !make common blocks not shared ^Z 3. How to turn an existing library into a shareable image automatically. Assume you have a library USERLIB that you would like to make shared, here is how to do it without a lot of work. LIBRARY/LIS=SYMBOLS.DAT/NAMES USERLIB (/NAMES is important!!) Every symbol listed must go into a option file on a line like UNIVERSAL=SYMBOLXXX The following fortran program UNIVERSAL will do this for you, I've included it at the end of this message. To use it $LIBRARY/LIS=SYMBOLS.DAT/NAMES USERLIB $DEFINE FOR002 SYMBOLS.DAT $DEFINE FOR003 UNIVERSAL_SYMBOLS.OPT $Run UNIVERSAL Link the library /share. $LINK/SHARE=NL:/MAP=USERLIB.MAP DUMMY.OBJ,UNIVERSAL_SYMBOLS/OPT,- USERLIB/LIB,NECCESARY_LIBRARIES/LIB The DUMMY.OBJ is just a program that does nothing. I needed it because the linker wouldn't let the only module be a library. Alternatively you you could use a /include= statement. The UNIVERSAL_SYMBOLS.OPT creates a reference to every routine in the library so the linker pulls them all out. Every writable PSECT must be declared /NOSHR. (Unless you want to share data between programs). To do this you need a seperate linker option file to declare these psects /NOSHR. The option file has lines that look like this: PSECT_ATTR=USER,NOSHR You can find the writable psects from the map file created above. Or I've included the fortran program NOSHARE at the end of this message which will do it for you. To run it do the following $SEARCH/OUTPUT=WRT_PSECTS.DAT USERLIB.MAP " SHR"," WRT"/MATCH=AND $DEFINE FOR002 WRT_PSECTS.DAT $DEFINE FOR003 NOSHR_PSECTS.OPT $RUN NOSHARE. Finally link the shareable image: $LINK/SHARE DUMMY.OBJ,UNIVERSAL_SYMBOLS/OPT,NOSHR_PSECTS/OPT,- necessary_other_libraries/lib 4. Another useful hack for shareable images. It turns out that this was more appropiate for us than creating a shareable library. When you might use this is when you have a library which also includes a large interactive interface. We have such a situation, but of course people need to able to call the library routines directly, to automate certain processes.Its nice to do this from within the interactive interface because its supports debugging, since you can use all the library utilities to look at what you are doing. So what you do is make the USER code a shareable image, and give the interactive image the ability to call the user code. If the user code can call the subroutines in the interactive interface, then it in effect acts as a runtime library. That is there is only one copy of the library code. It is in the interactive interface program. Everyone runs the same executable to get access to it. The user interface program calls the users program as a subroutine. By using a transfer vectors and putting the user code in a shareable image, the main image doesn't have to be relinked when the user code is changed. The only trick is giving the user program the ability to call the library routines in the main image. Here's how you can give the user access to all the routines in the main image. Create a dummy routine USER_HOOK.FOR. Make it a shareable image. In the large interactive interface program add a call to USER_HOOK. Be sure to link with a transfer vector section. Link the interface routine /SYMBOL to create a .STB file. Users edit USER_HOOK.FOR to create thier programs. When they link include the .STB file to resolve those references to library routines in the main image. Define the process logical USER_HOOK to point to the users version of USER_HOOK.EXE C------------------------------------------------------------- PROGRAM UNIVERSAL C Author Chuck Parsons 11/28/90 C C Searches Library listing input from unit 2 and outputs a option C file on unit 3 declaring the symbols to be universal C CHARACTER*132 LINE CHARACTER*32 SYMBOL LOGICAL SPACE C C Throw away the header C DO I=1,7 READ(2,11)LINE 11 FORMAT(A132) ENDDO C C Read lines until end of file C DO WHILE (.TRUE.) READ(2,11,END=100)LINE C C Ignore Blank and "Module" lines C IF((LINE.NE.' ').AND.(LINE(1:6).NE.'Module'))THEN C C Parse out symbol names seperated by single space C J=1 DO I=1,132 IF('A'.LE.LINE(I:I).LE.'A')THEN LINE(J:J)=LINE(I:I) J=J+1 SPACE=.FALSE. ELSEIF(.NOT.SPACE)THEN LINE(J:J)=' ' J=J+1 SPACE=.TRUE. ENDIF ENDDO C C loop over symbols writing out UNIVERSAL= C do while (line.ne.' ') symbol=line(1:index(line,' ')) line=line(index(line,' ')+1:) if (symbol.ne.' ')write(3,10)symbol 10 format(' UNIVERSAL=',A) enddo endif enddo 100 close(2) close(3) end C------------------------------------------------------------- C------------------------------------------------------------- PROGRAM NOSHARE C Author Chuck Parsons 11/28/90 C C Searches Output of: C $SEARCH/OUTPUT=FOR002.DAT LINKER.MAP " WRT"," SHR"/MATCH=AND C To create OPTION file declaring them to be NOSHR C Input on Unit 2 C Output on Unit 3 C CHARACTER*132 LINE CHARACTER*32 SYMBOL,LAST_SYMBOL C Read lines until end of file LAST_SYMBOL=' ' DO WHILE (.TRUE.) READ(2,11,END=100)LINE 11 FORMAT(A132) SYMBOL=LINE(1:INDEX(LINE,' ')) C C Don't list psects multiple times. IF(LAST_SYMBOL.NE.SYMBOL)WRITE(3,10)SYMBOL(1:INDEX(SYMBOL,' ')) 10 FORMAT(' PSECT_ATTR=',A,',NOSHR') LAST_SYMBOL=SYMBOL ENDDO 100 CLOSE(2) CLOSE(3) end