Subject: tmpfile Virtual Memory Facility (New - #154) Index: usr.lib/libvmf 2.11BSD Description: Excerpted from the documentation: "Since 2.11BSD is not a virtual memory operating system, a user level "virtual memory" system can be of great utility to programs with large address space requirements. This library provides a standard set of routines for managing large virtual memory spaces. It supports creation of multiple concurrent virtual spaces, mapping of virtual pages into real memory, a lock/unlock mechanism, and a capability to clear specified virtual pages. The virtual memory scheme supports any number (subject to open file limitations) of virtual "spaces", each of which is made up of up to 512 segments (pages), each of which is 512 words (16 bit shorts) long. The 512 ints (1024 chars) of a segment can be used for any purpose. At any time during the lifetime of a process that uses the virtual memory facility, some number of segments will be in real memory, but typically most will be "swapped out" to a file. When the calling program knows the real memory address of a segment, the segment may be viewed and accessed as an array of 512 integers or as an array of 1024 characters." Repeat-By: Observation? These are a set of routines i've had for some time, they've proved quite useful, For example an editor written using these routines is able to handle 30k line files quite easily (something 'vi' gives up on a long time ago). Fix: This package will be required for the new 'ld' (link loader) which will handle longer symbol names. I am releasing this now to allow for installation and experimentation time. 'ld' was within about 1kb of not running at all it (more than 56kb of data space) even with the old 8 character limit on symbols - it was obvious something had to be done to allow the new 32 character symbols. These routines are that "something". I have a version of 'ld' working with these routines (but still with the 8 character symbol format) - there is (as you would expect) a speed penalty associated with not having the entire symbol table resident in memory. Using 10 'pages' of memory (10kb instead of 28kb), the speed penalty is between 10 and 14% on kernel linking and less (almost not noticeable) for smaller programs. Save this article to a temporary file (/tmp/foo) and cut where indicated. Then: 1) sh /tmp/foo 2) cd /usr/src/usr.lib/libvmf 3) make 4) make install 5) make clean 6) patch -p0 < /tmp/vmf.patch This will install the library (libvmf.a) in /usr/lib, the man page in chapter 3 (/usr/man/cat3/vmf.0) and the include file (vmf.h) in both /usr/include and /usr/src/include. Also, step 6 will modify the necessary Makefiles so that libvmf.a will be included in any future rebuilding of the system. You may wish to format and print the (more) detailed documentation which is included. This document was written using the 'ms' macros and may be formatted with "nroff -ms vmlib.ms". Note: These routines do _not_ handle the crossing between pages. If the items stored in 'virtual space' span page boundaries it is the program's responsibilty to map the next page. Using data structures which divide evenly into the page size (1024 bytes) makes life easier but is not required. =========================cut here============================ #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # /usr/src/usr.lib/libvmf # /usr/include/vmf.h # /usr/src/include/vmf.h # /tmp/vmf.patch # This archive created: Thu Oct 21 21:27:25 1993 export PATH; PATH=/bin:/usr/bin:$PATH if test ! -d '/usr/src/usr.lib/libvmf' then mkdir '/usr/src/usr.lib/libvmf' fi cd '/usr/src/usr.lib/libvmf' if test -f 'makefile' then echo shar: "will not over-write existing file 'makefile'" else sed 's/^X//' << \SHAR_EOF > 'makefile' XOBJECTS = vmf.o X Xall: genlib genlib_p vmf.0 X XCFLAGS = -O X Xall: genlib genlib_p X Xvmf.0: vmf.3 X nroff -man vmf.3 > vmf.0 X Xinstall: X install -c -m 644 genlib /usr/lib/libvmf.a X ranlib /usr/lib/libvmf.a X install -c -m 644 genlib_p /usr/lib/libvmf_p.a X ranlib /usr/lib/libvmf_p.a X install -c -m 444 vmf.0 /usr/man/cat3/vmf.0 X Xclean: X rm -f ${OBJECTS} profiled/${OBJECTS} genlib genlib_p vmf.0 X X.c.o: X ${CC} -p ${CFLAGS} -c $*.c X -ld -X -r $*.o X mv a.out profiled/$*.o X ${CC} ${CFLAGS} -c $*.c X -ld -X -r $*.o X mv a.out $*.o X Xgenlib genlib_p: ${OBJECTS} X @echo "building profiled genlib" X @cd profiled; ar cru ../genlib_p ${OBJECTS} X @echo "buiding normal genlib" X @ar cru genlib ${OBJECTS} SHAR_EOF chmod 644 'makefile' fi if test -f 'vmf.c' then echo shar: "will not over-write existing file 'vmf.c'" else sed 's/^X//' << \SHAR_EOF > 'vmf.c' X/* Program Name: vmf.c X * Author: S.M. Schultz X * X * ----------- Modification History ------------ X * Version Date Reason For Modification X * 1.0 1JAN80 1. Initial release. X * 2.0 31Mar83 2. Cleanup. X * 2.1 19Oct87 3. Experiment increasing number of segments. X * 2.2 03Dec90 4. Merged error.c into this because it had X * been reduced to two write() statements. X * 3.0 08Sep93 5. Polish it up for use in 'ld.c' (2.11BSD). X * Release into the Public Domain. X * -------------------------------------------------- X*/ X X#include X#include X#include X#include X X/* X * Choose ONE and only one of the following swap policies X */ X/* #define LRU /* Least Recently Used */ X/* #define PERC 3 /* Percolation */ X#define LRS /* Least Recently Swapped */ X X#ifndef DEBUG X#define debugseg(s,m) /* do nothing */ X#else Xstatic void debugseg(); X#endif X X/* X * This is vfm.c, the file of virtual memory management primitives. X * Call vminit first to get the in memory segments set up. X * Then call vmopen for each virtual space to be used. X * Normal transactions against segments are handled via vmmapseg. X * At wrapup time, call vmflush if any modified segments are X * assigned to permanent files. X */ X X#define NOSEGNO (-1) /* can never match a segment number */ X X static struct dlink seghead[1]; X long nswaps, nmapsegs; /* statistics */ X extern int read(), write(), errno; X static int swap(); X static void promote(), vmerror(); X X/* X * vminit --- initialize virtual memory system with 'n' in-memory segments X */ X Xint Xvminit(n) X int n; X { X register struct vseg *s; X static struct vseg *segs; X X segs = (struct vseg *)calloc(n, sizeof (struct vseg)); X if (!segs) X { X errno = ENOMEM; X return(-1); X } X seghead[0].fwd = seghead[0].back = seghead; /* selfpoint */ X X for (s = segs; s < &segs[n] ; s++) X { X s->s_link.fwd = seghead; X s->s_link.back = seghead[0].back; X s->s_link.back->fwd = s->s_link.fwd->back = (struct dlink *)s; X s->s_segno = NOSEGNO; X s->s_vspace = NULL; X s->s_lock_count = 0; /* vmunlocked */ X s->s_flags = 0; /* not DIRTY */ X } X return(0); X } X X/* X * vmmapseg --- convert segment number to real memory address X */ X Xstruct vseg * Xvmmapseg(vspace, segno) X struct vspace *vspace; X u_short segno; X { X register struct vseg *s; X X nmapsegs++; X X if (segno >= vspace->v_maxsegno || segno < 0) X { X#ifdef DEBUG X fprintf(stderr,"vmmapseg vspace0%o segno%d\n", vspace, segno); X#endif X vmerror("vmmapseg: bad segno"); X } X X /* look for segment in memory */ X for (s = (struct vseg *)seghead[0].fwd; X s->s_segno != segno || s->s_vspace != vspace; X s = (struct vseg *)s->s_link.fwd) X { X if (s == (struct vseg *)seghead) X { /* not in memory */ X int status; X X for (s = (struct vseg *)s->s_link.back; s->s_lock_count != 0; X s = (struct vseg *)s->s_link.back) X { X if (s == (struct vseg *)seghead) X vmerror("Too many locked segs!"); X debugseg(s, "back skip"); X } X debugseg(s, "dump on"); X if (s->s_flags & S_DIRTY) X if (swap(s, write) != 0) X { X fprintf(stderr, X "write swap, v=%d fd=%d\n", X s->s_vspace,s->s_vspace->v_fd); X exit(-2); X } X s->s_vspace = vspace; X s->s_segno = segno; X s->s_flags &= ~S_DIRTY; X status = swap(s, read); X if (status == -2) X { X fprintf(stderr, "can't read swap file"); X exit(-2); X } X else if (status == -1) X (void)vmclrseg(s); X#ifdef LRS /* Least Recently Swapped */ X promote(s); X#endif X break; X } X debugseg(s, "forward skip"); X } X#ifdef PERC X { /* percolate just-referenced segment up list */ X register struct dlink *neighbor, *target; X int count; X X s->fwd->back = s->back; /* delete */ X s->back->fwd = s->fwd; X X count = PERC; /* upward mobility */ X for (target = s; target != seghead && count-- > 0; ) X target = target->back; X neighbor = target->fwd; X s->back = target; /* reinsert */ X s->fwd = neighbor; X target->fwd = neighbor->back = s; X } X#endif X#ifdef LRU /* Least Recently Used */ X promote(s); X#endif X debugseg(s, "vmmapseg returns"); X return(s); X } X X/* X * swap --- swap a segment in or out X * (called only from this file) X */ X Xstatic int Xswap(seg, iofunc) /* used only from this file */ X register struct vseg *seg; X int (*iofunc)(); X { X off_t file_address; X register struct vspace *v; X X v = seg->s_vspace; X nswaps++; X file_address = seg->s_segno; X file_address *= (BYTESPERSEG); X file_address += v->v_foffset; X#ifdef SWAPTRACE X printf("fd%d blk%d\tswap %s\n", v->v_fd, file_address, X iofunc == read ? "in" : "out"); X#endif X if (lseek(v->v_fd, file_address, L_SET) == -1L) X return(-2); X X switch ((*iofunc)(v->v_fd, seg->s_cinfo, BYTESPERSEG)) X { X case BYTESPERSEG: X return(0); X case 0: X return(-1); X default: X return(-2); X } X } X Xvoid Xvmclrseg(seg) X register struct vseg *seg; X { X X (void)bzero(seg->s_cinfo, BYTESPERSEG); X vmmodify(seg); X } X X/* X * vmlock --- vmlock a segment into real memory X */ X Xvoid Xvmlock(seg) X register struct vseg *seg; X { X X seg->s_lock_count++; X if (seg->s_lock_count < 0) X vmerror("vmlock: overflow"); X } X X/* X * vmunlock --- unlock a segment X */ X Xvoid Xvmunlock(seg) X register struct vseg *seg; X { X X --seg->s_lock_count; X if (seg->s_lock_count < 0) X vmerror("vmlock: underflow"); X } X X/* X * vmmodify --- declare a segment to have been modified X */ X Xvoid Xvmmodify(seg) Xregister struct vseg *seg; X { X X VMMODIFY(seg); X debugseg(seg, "vmmodify"); X } X X/* X * vmflush --- flush out virtual space buffers X */ X Xvoid Xvmflush() X { X register struct vseg *s; X X for (s = (struct vseg *)seghead[0].fwd; s != (struct vseg *)seghead; X s = (struct vseg *)s->s_link.fwd) X if (s->s_flags & S_DIRTY) X swap(s, write); X } X X/* X * debugseg --- output debugging information about a seg in mem X */ X#ifdef DEBUG Xstatic void Xdebugseg(s, msg) X char *msg; X register struct vseg *s; X { X fprintf(stderr, "seg%o vspace%o segno%d flags%o vmlock%d %s\r\n", X s, s->s_vspace, s->s_segno, s->s_flags, s->s_lock_count, msg); X } X#endif X X/* X * vmopen --- open a virtual space associated with a file X */ X Xint Xvmopen(vs, filename) X register struct vspace *vs; X char *filename; X { X register int fd; X char junk[32]; X X if (!filename) X { X strcpy(junk, "/tmp/vmXXXXXX"); X fd = mkstemp(junk); X unlink(junk); X } X else X fd = open(filename, O_RDWR|O_CREAT, 0664); X X if (fd != -1) X { X vs->v_fd = fd; X vs->v_foffset = 0; X vs->v_maxsegno = MAXSEGNO; X } X return(fd); X } X X/* X * vmclose --- closes a virtual space associated with a file X * invalidates all segments associated with that file X */ X Xvoid Xvmclose(vs) X register struct vspace *vs; X { X register struct vseg *s; X X vmflush(); X /* invalidate all segments associated with that file */ X for (s = (struct vseg *)seghead[0].fwd; s != (struct vseg *)seghead; X s = (struct vseg *)s->s_link.fwd) X { X if (s->s_vspace == vs) X { X s->s_segno = NOSEGNO; X s->s_vspace = NULL; X s->s_lock_count = 0; /* vmunlocked */ X s->s_flags &= ~S_DIRTY; X } X } X close(vs->v_fd); X } X X/* X * promote --- put a segment at the top of the list X */ X Xstatic void Xpromote(s) X register struct vseg *s; X { X X s->s_link.fwd->back = s->s_link.back; /* delete */ X s->s_link.back->fwd = s->s_link.fwd; X X s->s_link.fwd = seghead[0].fwd; /* insert at top of totem pole */ X s->s_link.back = seghead; X seghead[0].fwd = s->s_link.fwd->back = (struct dlink *)s; X } X X/* X * vmerror --- print error message and commit suicide X * Message should always make clear where called from. X * Example: vmerror("In floogle: can't happen!"); X */ X Xstatic void Xvmerror(msg) X char *msg; X { X fprintf(stderr, "%s\n", msg); X abort(); /* terminate process with core dump */ X } SHAR_EOF chmod 644 'vmf.c' fi if test -f 'vmf.3' then echo shar: "will not over-write existing file 'vmf.3'" else sed 's/^X//' << \SHAR_EOF > 'vmf.3' X.\" No copyright (1993) - Steven M. Schultz (sms@wlv.iipo.gtegsc.com) X.\" @(#)vmf.3 3.0 (2.11BSD) 9/24/93 X.\" X.TH VMF 3 "September 24, 1993" X.UC 6 X.SH NAME Xvminit, vmopen, vmclose, vmmapseg, vmmodify, vmlock, vmunlock, vmclrseg, vmflush, \- disk based virtual memory routines X.SH SYNOPSIS X.nf X.PP X.ft B X#include X.PP X.ft B Xstruct vspace { X int v_fd; /* file for swapping */ X off_t v_foffset; /* offset for computing file addresses */ X int v_maxsegno; /* number of segments in this space */ X }; X.PP X.ft B Xstruct vseg { /* structure of a segment in memory */ X struct dlink s_link; /* for linking into lru list */ X int s_segno; /* segment number */ X struct vspace *s_vspace; /* which virtual space */ X int s_lock_count; X int s_flags; X union X { X int _winfo[WORDSPERSEG]; /* the actual segment */ X char _cinfo[BYTESPERSEG]; X } v_un; X }; X#define s_winfo v_un._winfo X#define s_cinfo v_un._cinfo X.PP X.ft B Xint vminit(nseg); X int nseg; X.PP X.ft B Xint vmopen(space, filename); X struct vspace *space; X char *filename; X.PP X.ft B Xstruct vseg *vmmapseg(space, segno); X struct vspace *space; X int segno; X.PP X.ft B Xvoid vmlock(seg); X struct vseg *seg; X.PP X.ft B Xvoid vmunlock(seg); X struct vseg *seg; X.PP X.ft B Xvoid vmclrseg(seg); X struct vseg *seg; X.PP X.ft B Xvoid vmmodify(seg); X.PP X.ft B Xvoid vmflush(); X.PP X.ft B Xvoid vmclose(space); X struct vspace *space; X.fi X.bp X.SH DESCRIPTION XThis library provides a standard set Xof routines for managing large virtual memory spaces. It supports Xcreation of multiple concurrent virtual spaces, mapping of virtual Xpages into real memory, a lock/unlock mechanism, and a capability to Xclear specified virtual pages. X.PP X.IR vminit\ - XThis routine initializes the virtual memory system by setting up the Xpool of in-memory segment buffers. The argument to this function is Xthe number of memory segments to allocate (typically 4 to 8 but can be Xhigher as long as memory can be malloc'd). XIt must be called before any Xother "libvmf" routine is called. X.PP X.IR vmopen\ - XFor each virtual space that a program uses, the program must Xallocate an instance of the space structure ('struct vspace'). XThis routine is used to initialize Xa virtual space structure using the specified address of a Xspace structure and the name of the file that will serve as Xswap file for the space. If the second argument is \fBNULL\fP Xan invisible temporary file is used rather than a named (permanent) Xfile. X.PP X.IR vmclose\ - XThis routine is used to close the UNIX file descriptor associated Xwith the swap file for a virtual space. Any modified in-memory segments Xbelonging to the specified address space are flushed to the paging file. X.PP X.IR vmmapseg\ - XThis routine is the primary interface to the virtual memory mechanism. XIt is executed with a specified virtual space address and a segment Xnumber (between 0 and 511), and returns a pointer to an in-memory Xpage containing the specified segment. X.PP X.IR vmmodify\ - XWhenever a program modifies the data of a segment, it is the program's Xresponsibility to inform the virtual memory system of the modification. XThis function is also available as a macro X(\fBVMMODIFY\fP) for use in-line. X.PP X.IR vmlock\ - XThis routine increments the lock count of the specified segment buffer. XA buffer with a nonzero lock count is X.I locked Xand cannot be swapped out. X.PP X.IR vmunlock\ - XThis routine decrements the lock count of the specified buffer. It is Xa serious error to decrement the count below zero (lock underflow). X.PP X.IR vmclrseg\ - XThis routine clears the user data area (page) of the specified segment buffer. X.IR vmflush\ - XThis routine simply swaps out all segments that are marked as Xmodified. X.SH BUGS XNot as transparent (or as fast) as a larger hardware address space. X.PP XThere is no automatic segment crossing capability, the application must Xcheck if a X.I virtual address Xcrosses page/segment boundaries and perform a X.I vmmapseg Xcall. X.SH SEE ALSO XThere is a nroff document (using the \-ms macros) in the \fIlibvmf\fP source Xdirectory which goes into more details about the \fBvm\fP functions. SHAR_EOF chmod 644 'vmf.3' fi if test -f 'vmlib.ms' then echo shar: "will not over-write existing file 'vmlib.ms'" else sed 's/^X//' << \SHAR_EOF > 'vmlib.ms' X.NH 1 XVMF -- Virtual Memory Facility X.NH 2 XIntroduction X.PP XSince 2.11BSD is not a virtual memory operating system, a user level X"virtual memory" system can be of great utility to programs with Xlarge address space requirements. This library provides a standard set Xof routines for managing large virtual memory spaces. It supports Xcreation of multiple concurrent virtual spaces, mapping of virtual Xpages into real memory, a lock/unlock mechanism, and a capability to Xclear specified virtual pages. X.NH 3 XConcepts X.PP XThe virtual memory scheme supports any number (subject to open file Xlimitations) of virtual X.I spaces, Xeach of which is made up of up to 512 X.I segments X(pages), each of which is 512 words (16 bit shorts) long. XThe 512 ints (1024 chars) of a segment can be used for any purpose. X.PP XEach space may be temporary or permanent, in the sense that it is or Xis not forgotten when the program ends. Between program invocations, Xeach permanent space resides in a named file. The most common (by Xfar) type is temporary using a file which is unlinked immediately Xafter opening the virtual address space. X.PP XAt any time during the lifetime of a process that uses the virtual Xmemory facility, some number of segments will be in real memory, but Xtypically most will be "swapped out" to a file. XWhen the calling program knows Xthe real memory address of a segment, the segment may be viewed Xand accessed as an array of 512 integers or as an array of 1024 Xcharacters. X.NH 3 XData Structures X.PP XTwo structures are associated with the virtual memory scheme: the Xspace structure and the segment buffer structure. X.IP Space\ Structure 4 X.sp XOne instance of the space structure must be allocated by the user for Xeach space to be used. Spaces are identified by the address of their Xspace structures. Included in the structure is the UNIX file descriptor Xof the "swap" file to be used for the space, the offset (in bytes) Xinto the file at which the room allocated for the virtual space begins X(currently this is always zero and is reserved for future use), Xand the number of segments in the space (currently always 512). The Xuser must never be concerned with any element of the space structure. X.IP Segment\ Buffer\ Structure 4 X.sp XThe virtual memory system includes a pool of buffers for holding Xsegments while they reside in real memory. X.sp XThe segment buffer structure (see 'struct seg' definition below) Xincludes: a double link, the segment number (in range [0, 511]), Xthe address of the virtual space structure instance for the virtual Xspace of which the segment is a member, a lock count, a "modified" Xflag, and an array of 512 shorts (1024 bytes) for the segment itself. This Xarray represents the virtual page which is accessed directly by Xthe user. X.NH 2 XDefined Constants and Global Variables X.PP XThe following defined symbolic constants are specified as either Xcalling parameters or returned values of the routines in the "dtlib" Xfacility. X.IP MAXSEGNO 18 XSpecifies the maximum number of segments (pages) in a virtual space. X.IP WORDSPERSEG 18 XSpecifies the number of words in a segment. X.IP BYTESPERSEG 18 XSpecifies the number of bytes in a segment. This is always a power of 2. X.IP LOG2BPS 18 XThe base 2 logarithm of BYTESPERSEG. X.PP XThere are several global variables defined by the "vmlib" facility that an Xapplications programmer may examine. X.IP nswaps 18 XThis is a 32 bit value which gives the number of pages swapped to or from Xthe paging file. X.IP nmapsegs 18 XThis 32 bit value holds the number of calls made to map a segment into Xmemory via \fIvmmapseg\fP. X.PP XThe following Xdefined "C" Language structures are specified as calling parameters Xand/or returned values of the routines in the "vmlib" facility. X.PP X.nf Xstruct vspace { X int v_fd; /* file for swapping */ X off_t v_foffset; /* offset for computing file addresses */ X int v_maxsegno; /* number of segments in this space */ X }; X Xstruct dlink { /* general double link structure */ X struct dlink *fwd; /* forward link */ X struct dlink *back; /* back link */ X }; X Xstruct vseg { /* structure of a segment in memory */ X struct dlink s_link; /* for linking into lru list */ X int s_segno; /* segment number */ X struct vspace *s_vspace; /* which virtual space */ X int s_lock_count; X int s_flags; X union X { X int _winfo[WORDSPERSEG]; /* the actual segment */ X char _cinfo[BYTESPERSEG]; X } v_un; X }; X X#define s_winfo v_un._winfo X#define s_cinfo v_un._cinfo X.fi X.NH 2 XRoutine Synopsis X.PP XBelow are listed the names of each function Xin the "vmlib" facility along with a brief synopsis Xof what each routine does. X.IP vminit 14 XThis routine initializes the virtual memory system by setting up the Xpool of in-memory segment buffers. The argument to this function is Xthe number (typically 4 to 8 but can be higher as long as memory Xcan be malloc'd). XIt must be called before any Xother "vmlib" facility routine is called. X.IP vmopen 14 XFor each virtual space that a program uses, the program must Xallocate an instance of the space structure (see definition Xof 'struct vspace' above). This routine is used to initialize Xa virtual space structure using the specified address of a Xspace structure and the name of the file that will serve as Xswap file for the space. If the second argument is \fBNULL\fP Xan invisible temporary file is used rather than a named (permanent) Xfile. X.IP vmclose 14 XThis routine is used to close the UNIX file descriptor associated Xwith the swap file for a virtual space. Any modified in-memory segments Xbelonging to the specified address space are flushed to the paging file. X.IP vmmapseg 14 XThis routine is the primary interface to the virtual memory mechanism. XIt is executed with a specified virtual space address and a segment Xnumber ( in range [0, 511]), and returns a pointer to an in-memory Xpage containing the specified segment. X.IP vmmodify 14 XWhenever a program modifies the data of a segment, it is the program's Xresponsibility to inform the virtual memory system of the modification. XThis routine flags the specified segment as modified and should be Xexecuted before any future execution of 'vmmapseg' that could overlay Xthe modified buffer. This function is also available as a macro X(\fBVMMODIFY\fP) for use in-line. The macro form is actually preferred Xsince only a single bit is being set in a word. X.IP vmlock 14 XThis routine increments the lock count of the specified segment buffer. XA buffer with a nonzero lock count is X.I locked Xand cannot be overlayed. The utility of this feature to the user is Xthat a locked segment buffer will stay at the same real memory address Xuntil unlocked, hence real memory pointers into or to it can remain Xvalid. Overuse of this feature will result in not being able to page Xany new segments into memory from the paging file. X.IP vmunlock 14 XThis routine decrements the lock count of the specified buffer. It is Xa serious error to decrement the count below zero (lock underflow). X.IP vmclrseg 14 XThis routine clears the user data area (page) of the specified segment buffer. X.IP vmflush 14 XThis routine simply swaps out all segments that are marked as X"modified". It may be called at any time and is always called when X\fIvmclose\fP is called. X.bp X.NH 2 XDetailed Description of Virtual Memory Functions X.NH 3 Xvminit -- Initialize Virtual Memory Interface X.NH 4 X.PP XThe "vminit" routine initializes the virtual memory system by setting up the Xpool of in-memory segment buffers. It must be called before any Xother "vmlib" facility routine is called. X.NH 4 XCALLING SEQUENCE X.PP X.in +8 X.nf Xstatus = vminit(nseg) X Xint nseg; Xint status; X.fi X.in -8 X.IP status XThe return value will be \-1 and \fIerrno\fP will be set to ENOMEM Xif memory for Xthe specified number of segments can not be allocated. X.IP nseg XThis is the number of in-memory segments to allocate. These are shared Xbetween all virtual spaces opened. Each segment is 1kb plus overhead, Xso the number of segments should be chosen with care (if all data could Xbe held in memory we wouldn't need a virtual memory system after all). XTypical number of segments is between 4 and 8 although some applications Xsuch as \fBld\fP(1) use 12 or more. X.NH 3 Xvmopen -- Open a Virtual Space X.NH 4 X.PP XFor each virtual space that a program uses, the program must Xallocate an instance of the space structure (see definition Xof 'struct vspace' above). The "vmopen" routine is used to initialize Xa virtual space structure using the specified address of a Xspace structure and the name of the file that will serve as Xswap file for the space. If the filename is NULL then an invisible Xtemporary file created in /tmp will be used and the address space Xwill be vanish when the program exits or calls \fIvmclose\fP. X.NH 4 XCALLING SEQUENCE X.PP X.in +8 X.nf Xstatus = vmopen(vsptr,filename) X Xstruct vspace *vsptr; Xchar *filename; Xint status; X.fi X.in -8 X.IP status XIndicates success if 0, an error if \-1. An error is caused by failure Xto create (or open for update) the specified file. The global \fBerrno\fP Xwill be set if \-1 is returned by \fIvmopen\fP. X.NH 3 Xvmclose -- Close a Virtual Space X.NH 4 X.PP XClose the UNIX file descriptor associated with the swap Xfile for a virtual space. Modified segments belonging to the specified Xvirtual space are flushed. X.NH 4 XCALLING SEQUENCE X.PP X.in +8 X.nf Xvoid vmclose(vsptr) X Xstruct vspace *vsptr; X.fi X.in -8 X.IP vsptr XThe address of the virtual space structure to be closed. No status is Xreturned. X.NH 3 Xvmmapseg -- Map a Virtual Segment into Real Memory X.NH 4 X.PP XThe "vmmapseg" routine is the primary interface to the virtual memory mechanism. XIt is executed with a specified virtual space address and a segment Xnumber ( in range [0, 511]), and returns the real memory address Xof a buffer guaranteed to contain the segment requested. The address Xreturned is that of the 'struct vseg' not that of the data portion. It Xis up to the program to refer to the 's_cinfo' or 's_winfo' member Xto refer to the byte or word oriented data respectively. X.NH 4 XCALLING SEQUENCE X.PP X.in +8 X.nf Xsegptr = vmmapseg(vsptr,segno) X Xstruct vspace *vsptr; Xint segno; Xstruct vseg *segptr; X.fi X.in -8 X.NH 4 X.IP vsptr XSpecifies the address of a virtual space structure allocated by Xthe calling program. A previous vmopen call using this structure Xmust have been performed before calling \fIvmmapseg\fP. X.IP segno XSpecifies the segment i.e., virtual page, number to be mapped into Xreal physical memory. The value must be in the range [0 to MAXSEGNO-1]. XThere are two macros (defined in \fIvmf.h\fP) which are useful in Xcalculating segment numbers: \fBVSEG\fP and \fBVOFF\fP. X.IP segptr XThe address of a virtual seg structure which contains the virtual Xspace segment associated with segno. The data is referred to with Xthe 's_cinfo' or 's_winfo' structure members: segptr->s_cinfo Xor segptr->s_winfo respectively. X.PP XCurrently this routine aborts the program on an error condition. X.NH 3 Xvmmodify -- Mark a Segment as Modified X.NH 4 X.PP XWhenever the user program modifies any segment, it is the program's Xresponsibility to inform the virtual memory system of the modification. XThe "vmmodify" routine flags the specified segment as modified and should be Xexecuted before any future execution of 'vmmapseg' that could reuse Xthe modified buffer. Note that a locked segment buffer cannot be reused, Xuntil it is unlocked. A macro form of this routine exists, \fBVMMODIFY\fP Xmay be used to mark a segment as modified. X.NH 4 XCALLING SEQUENCE X.PP X.in +8 X.nf Xvoid vmmodify(segptr) X Xstruct vseg *segptr; X.fi X.in -8 X.IP segptr XSpecifies the address of a seg structure associated with a current Xincore virtual memory segment which has been modified. X.NH 3 Xvmlock -- Lock a Virtual Segment into Real Memory X.NH 4 X.PP XIncrement the lock count of the specified segment buffer. XA buffer with a nonzero lock count is X.I locked Xand cannot be reused/swapped-out. The utility of this feature to the user is Xthat a locked segment buffer will stay at the same real memory address Xuntil unlocked, hence real memory pointers into or to it can remain Xvalid. Overuse of \fIvmlock\fP will cause errors in \fIvmmapseg\fP Xwhen no segments are available to satisfy swap in/out requests. X.NH 4 XCALLING SEQUENCE X.PP X.in +8 X.nf Xvoid vmlock(segptr1) X Xstruct vseg *segptr; X.fi X.in -8 X.NH 4 X.IP segptr XSpecifies the address of a seg structure associated with a current Xincore virtual memory segment. No information is returned. X.NH 3 Xvmunlock -- Unlock a Previously Locked Virtual Memory Segment X.NH 4 X.PP XDecrement the lock count of the specified buffer. It is a serious error Xto decrement the count below zero, this typically means that the segment Xwas never locked in the first place. X.NH 4 XCALLING SEQUENCE X.PP X.in +8 X.nf Xvoid vmunlock(segptr) X Xstruct vseg *segptr; X.fi X.in -8 X.NH 4 X.IP segptr1 XSpecifies the address of a seg structure associated with a current Xincore virtual memory segment. No information is returned from this Xroutine. X.NH 3 Xvmclrseg -- Clear a Virtual Memory Segment to Zeros X.NH 4 X.PP XClear the data area of the specified segement buffer. No information is Xreturned by this function. X.NH 4 XCALLING SEQUENCE X.PP X.in +8 X.nf Xvoid vmclrseg(segptr) X Xstruct vseg *segptr X.fi X.in -8 X.NH 4 X.IP segptr XSpecifies the address of a seg structure associated with a current Xincore virtual memory segment. The data portion (segptr->s_cinfo) Xis cleared by a call to \fIbzero\fP(3). X.NH 3 Xvmflush -- Flush Virtual Memory Cache to Swap File X.NH 4 X.PP XSwap out all segments that are marked as X"modified". It may be called just prior to program termination Xif there are any permanent spaces that have been modified but Xnormally a program will simply call \fIvmclose\fP which takes care Xof flushing modified pages as part of its normal duties. X.NH 4 XCALLING SEQUENCE X.PP X.in +8 X.nf Xvoid vmflush() X.fi X.in -8 SHAR_EOF chmod 644 'vmlib.ms' fi if test ! -d 'profiled' then mkdir 'profiled' fi cd 'profiled' chmod 751 . cd .. chmod 755 . cd .. if test -f '/usr/include/vmf.h' then echo shar: "will not over-write existing file '/usr/include/vmf.h'" else sed 's/^X//' << \SHAR_EOF > '/usr/include/vmf.h' X/* Program Name: vmf.h X * Author: S.M. Schultz X * X * ----------- Modification History ------------ X * Version Date Reason For Modification X * 1.0 01Jan80 1. Initial release. X * 2.0 31Mar83 2. Cleanup. X * 3.0 08Sep93 3. Change v_foffset to off_t instead of int. X * 3.1 21Oct93 4. Create union member of structure to X * make 'int' or 'char' access to data easy. X * Define segment+offset and modified macros. X * Place into the public domain. X * -------------------------------------------------- X*/ X X#include X X#define MAXSEGNO 512 /* max number of segments in a space */ X#define BYTESPERSEG 1024 /* must be power of two! */ X#define LOG2BPS 10 /* log2(BYTESPERSEG) */ X#define WORDSPERSEG (BYTESPERSEG/sizeof (int)) X Xstruct vspace { X int v_fd; /* file for swapping */ X off_t v_foffset; /* offset for computing file addresses */ X int v_maxsegno; /* number of segments in this space */ X }; X Xstruct dlink { /* general double link structure */ X struct dlink *fwd; /* forward link */ X struct dlink *back; /* back link */ X }; X Xstruct vseg { /* structure of a segment in memory */ X struct dlink s_link; /* for linking into lru list */ X int s_segno; /* segment number */ X struct vspace *s_vspace; /* which virtual space */ X int s_lock_count; X int s_flags; X union X { X int _winfo[WORDSPERSEG]; /* the actual segment */ X char _cinfo[BYTESPERSEG]; X } v_un; X }; X X#define s_winfo v_un._winfo X#define s_cinfo v_un._cinfo X X/* masks for s_flags */ X#define S_DIRTY 01 /* segment has been modified */ X X long nswaps; /* number of swaps */ X long nmapsegs; /* number of mapseg calls */ X X int vminit(), vmopen(); X struct vseg *vmmapseg(); X void vmlock(), vmunlock(), vmclrseg(), vmmodify(); X void vmflush(), vmclose(); X Xtypedef long VADDR; X#define VMMODIFY(seg) (seg->s_flags |= S_DIRTY) X#define VSEG(va) ((short)(va >> LOG2BPS)) X#define VOFF(va) ((u_short)va % BYTESPERSEG) SHAR_EOF chmod 644 '/usr/include/vmf.h' fi if test -f '/usr/src/include/vmf.h' then echo shar: "will not over-write existing file '/usr/src/include/vmf.h'" else sed 's/^X//' << \SHAR_EOF > '/usr/src/include/vmf.h' X/* Program Name: vmf.h X * Author: S.M. Schultz X * X * ----------- Modification History ------------ X * Version Date Reason For Modification X * 1.0 01Jan80 1. Initial release. X * 2.0 31Mar83 2. Cleanup. X * 3.0 08Sep93 3. Change v_foffset to off_t instead of int. X * 3.1 21Oct93 4. Create union member of structure to X * make 'int' or 'char' access to data easy. X * Define segment+offset and modified macros. X * Place into the public domain. X * -------------------------------------------------- X*/ X X#include X X#define MAXSEGNO 512 /* max number of segments in a space */ X#define BYTESPERSEG 1024 /* must be power of two! */ X#define LOG2BPS 10 /* log2(BYTESPERSEG) */ X#define WORDSPERSEG (BYTESPERSEG/sizeof (int)) X Xstruct vspace { X int v_fd; /* file for swapping */ X off_t v_foffset; /* offset for computing file addresses */ X int v_maxsegno; /* number of segments in this space */ X }; X Xstruct dlink { /* general double link structure */ X struct dlink *fwd; /* forward link */ X struct dlink *back; /* back link */ X }; X Xstruct vseg { /* structure of a segment in memory */ X struct dlink s_link; /* for linking into lru list */ X int s_segno; /* segment number */ X struct vspace *s_vspace; /* which virtual space */ X int s_lock_count; X int s_flags; X union X { X int _winfo[WORDSPERSEG]; /* the actual segment */ X char _cinfo[BYTESPERSEG]; X } v_un; X }; X X#define s_winfo v_un._winfo X#define s_cinfo v_un._cinfo X X/* masks for s_flags */ X#define S_DIRTY 01 /* segment has been modified */ X X long nswaps; /* number of swaps */ X long nmapsegs; /* number of mapseg calls */ X X int vminit(), vmopen(); X struct vseg *vmmapseg(); X void vmlock(), vmunlock(), vmclrseg(), vmmodify(); X void vmflush(), vmclose(); X Xtypedef long VADDR; X#define VMMODIFY(seg) (seg->s_flags |= S_DIRTY) X#define VSEG(va) ((short)(va >> LOG2BPS)) X#define VOFF(va) ((u_short)va % BYTESPERSEG) SHAR_EOF chmod 644 '/usr/src/include/vmf.h' fi if test -f '/tmp/vmf.patch' then echo shar: "will not over-write existing file '/tmp/vmf.patch'" else sed 's/^X//' << \SHAR_EOF > '/tmp/vmf.patch' X*** /usr/src/usr.lib/Makefile.old Mon Jan 18 09:37:45 1993 X--- /usr/src/usr.lib/Makefile Thu Oct 21 20:47:49 1993 X*************** X*** 3,9 **** X # All rights reserved. The Berkeley software License Agreement X # specifies the terms and conditions for redistribution. X # X! # @(#)Makefile 5.10 (Berkeley) 6/7/86 X # X DESTDIR= X CFLAGS= -O X--- 3,9 ---- X # All rights reserved. The Berkeley software License Agreement X # specifies the terms and conditions for redistribution. X # X! # @(#)Makefile 5.11 (2.11BSD GTE) 10/21/93 X # X DESTDIR= X CFLAGS= -O X*************** X*** 14,28 **** X # master tags file (/usr/lib/tags); the Fortran libraries should X # be on this list, but we don't control them.... X # X! TAGSDIR=libcurses libdbm libln libm libmp libpc libtermlib libutil X X # Programs that live in subdirectories, and have makefiles of their own. X # X! # 2.10BSD XXX - Libpc isn't important till someone - if ever - ports X # the 4.3BSD version of ucb/pascal. X # X SUBDIR= learn lib2648 libF77 libI77 libU77 libcurses libdbm libln \ X! libom libmp libplot libtermlib liby lpr me sendmail libutil X X # Shell scripts that need only be installed and are never removed. X # X--- 14,28 ---- X # master tags file (/usr/lib/tags); the Fortran libraries should X # be on this list, but we don't control them.... X # X! TAGSDIR=libcurses libdbm libln libm libmp libpc libtermlib libutil libvmf X X # Programs that live in subdirectories, and have makefiles of their own. X # X! # 2.11BSD XXX - Libpc isn't important till someone - if ever - ports X # the 4.3BSD version of ucb/pascal. X # X SUBDIR= learn lib2648 libF77 libI77 libU77 libcurses libdbm libln \ X! libom libmp libplot libtermlib liby lpr me sendmail libutil libvmf X X # Shell scripts that need only be installed and are never removed. X # SHAR_EOF chmod 640 '/tmp/vmf.patch' fi exit 0 # End of shell archive