1*b30d1939SAndy Fiddaman /***********************************************************************
2*b30d1939SAndy Fiddaman * *
3*b30d1939SAndy Fiddaman * This software is part of the ast package *
4*b30d1939SAndy Fiddaman * Copyright (c) 1985-2012 AT&T Intellectual Property *
5*b30d1939SAndy Fiddaman * and is licensed under the *
6*b30d1939SAndy Fiddaman * Eclipse Public License, Version 1.0 *
7*b30d1939SAndy Fiddaman * by AT&T Intellectual Property *
8*b30d1939SAndy Fiddaman * *
9*b30d1939SAndy Fiddaman * A copy of the License is available at *
10*b30d1939SAndy Fiddaman * http://www.eclipse.org/org/documents/epl-v10.html *
11*b30d1939SAndy Fiddaman * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12*b30d1939SAndy Fiddaman * *
13*b30d1939SAndy Fiddaman * Information and Software Systems Research *
14*b30d1939SAndy Fiddaman * AT&T Research *
15*b30d1939SAndy Fiddaman * Florham Park NJ *
16*b30d1939SAndy Fiddaman * *
17*b30d1939SAndy Fiddaman * Glenn Fowler <gsf@research.att.com> *
18*b30d1939SAndy Fiddaman * David Korn <dgk@research.att.com> *
19*b30d1939SAndy Fiddaman * Phong Vo <kpv@research.att.com> *
20*b30d1939SAndy Fiddaman * *
21*b30d1939SAndy Fiddaman ***********************************************************************/
22*b30d1939SAndy Fiddaman #if defined(_UWIN) && defined(_BLD_ast)
23*b30d1939SAndy Fiddaman
_STUB_vmmapopen()24*b30d1939SAndy Fiddaman void _STUB_vmmapopen(){}
25*b30d1939SAndy Fiddaman
26*b30d1939SAndy Fiddaman #else
27*b30d1939SAndy Fiddaman
28*b30d1939SAndy Fiddaman #include "vmhdr.h"
29*b30d1939SAndy Fiddaman #include <sys/types.h>
30*b30d1939SAndy Fiddaman #include <string.h>
31*b30d1939SAndy Fiddaman #if _hdr_unistd
32*b30d1939SAndy Fiddaman #include <unistd.h>
33*b30d1939SAndy Fiddaman #endif
34*b30d1939SAndy Fiddaman
35*b30d1939SAndy Fiddaman #undef ALIGN /* some sys/param.h define this */
36*b30d1939SAndy Fiddaman
37*b30d1939SAndy Fiddaman #include <sys/mman.h> /* mmap() headers */
38*b30d1939SAndy Fiddaman #include <sys/file.h>
39*b30d1939SAndy Fiddaman #include <sys/stat.h>
40*b30d1939SAndy Fiddaman #include <fcntl.h>
41*b30d1939SAndy Fiddaman
42*b30d1939SAndy Fiddaman #include <sys/shm.h> /* shm headers */
43*b30d1939SAndy Fiddaman #include <sys/ipc.h>
44*b30d1939SAndy Fiddaman
45*b30d1939SAndy Fiddaman #undef ALIGN
46*b30d1939SAndy Fiddaman #define ALIGN sizeof(struct _align_s)
47*b30d1939SAndy Fiddaman
48*b30d1939SAndy Fiddaman /* Create a region to allocate based on mmap() or shmget().
49*b30d1939SAndy Fiddaman ** Both ways provide for share memory allocation.
50*b30d1939SAndy Fiddaman ** mmap() also allows for allocating persistent data.
51*b30d1939SAndy Fiddaman **
52*b30d1939SAndy Fiddaman ** Written by Kiem-Phong Vo (kpv@research.att.com)
53*b30d1939SAndy Fiddaman */
54*b30d1939SAndy Fiddaman
55*b30d1939SAndy Fiddaman #define MM_INIT 001 /* initialization mode */
56*b30d1939SAndy Fiddaman
57*b30d1939SAndy Fiddaman #define MM_RELEASE 010 /* release share mem */
58*b30d1939SAndy Fiddaman #define MM_CLEANUP 020 /* clean up resources */
59*b30d1939SAndy Fiddaman
60*b30d1939SAndy Fiddaman /* magic word signaling region is being initialized */
61*b30d1939SAndy Fiddaman #define MM_LETMEDOIT ((unsigned int)(('N'<<24) | ('B'<<16) | ('&'<<8) | ('I')) )
62*b30d1939SAndy Fiddaman
63*b30d1939SAndy Fiddaman /* magic word signaling file/segment is ready */
64*b30d1939SAndy Fiddaman #define MM_MAGIC ((unsigned int)(('P'<<24) | ('&'<<16) | ('N'<<8) | ('8')) )
65*b30d1939SAndy Fiddaman
66*b30d1939SAndy Fiddaman /* default mimimum region size */
67*b30d1939SAndy Fiddaman #define MM_MINSIZE (64*_Vmpagesize)
68*b30d1939SAndy Fiddaman
69*b30d1939SAndy Fiddaman /* macros to get the data section and size */
70*b30d1939SAndy Fiddaman #define MMHEAD(file) ROUND(sizeof(Mmvm_t)+strlen(file), ALIGN)
71*b30d1939SAndy Fiddaman #define MMDATA(mmvm) ((Vmuchar_t*)(mmvm)->base + MMHEAD(mmvm->file))
72*b30d1939SAndy Fiddaman #define MMSIZE(mmvm) ((mmvm)->size - MMHEAD(mmvm->file))
73*b30d1939SAndy Fiddaman
74*b30d1939SAndy Fiddaman #ifdef S_IRUSR
75*b30d1939SAndy Fiddaman #define FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
76*b30d1939SAndy Fiddaman #else
77*b30d1939SAndy Fiddaman #define FILE_MODE 0644
78*b30d1939SAndy Fiddaman #endif
79*b30d1939SAndy Fiddaman
80*b30d1939SAndy Fiddaman /* to store key/value pairs for application */
81*b30d1939SAndy Fiddaman typedef struct _mmuser_s Mmuser_t;
82*b30d1939SAndy Fiddaman struct _mmuser_s
83*b30d1939SAndy Fiddaman { Mmuser_t* next; /* link list */
84*b30d1939SAndy Fiddaman int key; /* identifying key */
85*b30d1939SAndy Fiddaman Void_t* val; /* associated value */
86*b30d1939SAndy Fiddaman };
87*b30d1939SAndy Fiddaman
88*b30d1939SAndy Fiddaman typedef struct _mmvm_s
89*b30d1939SAndy Fiddaman { unsigned int magic; /* magic bytes */
90*b30d1939SAndy Fiddaman Void_t* base; /* address to map to */
91*b30d1939SAndy Fiddaman ssize_t size; /* total data size */
92*b30d1939SAndy Fiddaman ssize_t busy; /* amount in use */
93*b30d1939SAndy Fiddaman Mmuser_t* user; /* stored (key,val)'s */
94*b30d1939SAndy Fiddaman int proj; /* project number */
95*b30d1939SAndy Fiddaman char file[1];/* file name */
96*b30d1939SAndy Fiddaman } Mmvm_t;
97*b30d1939SAndy Fiddaman
98*b30d1939SAndy Fiddaman typedef struct _mmdisc_s
99*b30d1939SAndy Fiddaman { Vmdisc_t disc; /* Vmalloc discipline */
100*b30d1939SAndy Fiddaman int flag; /* various modes */
101*b30d1939SAndy Fiddaman Mmvm_t* mmvm; /* shared memory data */
102*b30d1939SAndy Fiddaman ssize_t size; /* desired file size */
103*b30d1939SAndy Fiddaman int shmid; /* ID of the shared mem */
104*b30d1939SAndy Fiddaman int proj; /* shm project ID */
105*b30d1939SAndy Fiddaman char file[1];/* backing store/ftok() */
106*b30d1939SAndy Fiddaman } Mmdisc_t;
107*b30d1939SAndy Fiddaman
108*b30d1939SAndy Fiddaman #if DEBUG
109*b30d1939SAndy Fiddaman #include <stdio.h>
110*b30d1939SAndy Fiddaman #include <string.h>
_vmmdump(Vmalloc_t * vm,int fd)111*b30d1939SAndy Fiddaman int _vmmdump(Vmalloc_t* vm, int fd)
112*b30d1939SAndy Fiddaman {
113*b30d1939SAndy Fiddaman char mesg[1024];
114*b30d1939SAndy Fiddaman Mmdisc_t *mmdc = (Mmdisc_t*)vm->disc;
115*b30d1939SAndy Fiddaman
116*b30d1939SAndy Fiddaman fd = fd < 0 ? 2 : fd;
117*b30d1939SAndy Fiddaman sprintf(mesg, "File: %s\n", mmdc->file ); write(fd, mesg, strlen(mesg));
118*b30d1939SAndy Fiddaman sprintf(mesg, "Project: %10d\n", mmdc->proj); write(fd, mesg, strlen(mesg));
119*b30d1939SAndy Fiddaman sprintf(mesg, "Memory: %#010lx\n", mmdc->mmvm); write(fd, mesg, strlen(mesg));
120*b30d1939SAndy Fiddaman sprintf(mesg, "Size: %10d\n", mmdc->size); write(fd, mesg, strlen(mesg));
121*b30d1939SAndy Fiddaman sprintf(mesg, "Shmid: %10d\n", mmdc->shmid); write(fd, mesg, strlen(mesg));
122*b30d1939SAndy Fiddaman
123*b30d1939SAndy Fiddaman sprintf(mesg, "File header:\n"); write(fd, mesg, strlen(mesg));
124*b30d1939SAndy Fiddaman sprintf(mesg, "Magic: %10d\n", mmdc->mmvm->magic); write(fd, mesg, strlen(mesg));
125*b30d1939SAndy Fiddaman sprintf(mesg, "Base: %#010lx\n", mmdc->mmvm->base); write(fd, mesg, strlen(mesg));
126*b30d1939SAndy Fiddaman sprintf(mesg, "Size: %10d\n", mmdc->mmvm->size); write(fd, mesg, strlen(mesg));
127*b30d1939SAndy Fiddaman sprintf(mesg, "Busy: %10d\n", mmdc->mmvm->busy); write(fd, mesg, strlen(mesg));
128*b30d1939SAndy Fiddaman return 0;
129*b30d1939SAndy Fiddaman }
130*b30d1939SAndy Fiddaman #endif /*DEBUG*/
131*b30d1939SAndy Fiddaman
132*b30d1939SAndy Fiddaman /* fix the mapped address for a region */
mmfix(Mmvm_t * mmvm,Mmdisc_t * mmdc,int fd)133*b30d1939SAndy Fiddaman static Mmvm_t* mmfix(Mmvm_t* mmvm, Mmdisc_t* mmdc, int fd)
134*b30d1939SAndy Fiddaman {
135*b30d1939SAndy Fiddaman Void_t *base = mmvm->base;
136*b30d1939SAndy Fiddaman ssize_t size = mmvm->size;
137*b30d1939SAndy Fiddaman
138*b30d1939SAndy Fiddaman if(base != (Void_t*)mmvm) /* mmvm is not right yet */
139*b30d1939SAndy Fiddaman { /**/ASSERT(!base || (base && (VLONG(base)%_Vmpagesize) == 0) );
140*b30d1939SAndy Fiddaman if(mmdc->proj < 0)
141*b30d1939SAndy Fiddaman { munmap((Void_t*)mmvm, size);
142*b30d1939SAndy Fiddaman mmvm = (Mmvm_t*)mmap(base, size, (PROT_READ|PROT_WRITE),
143*b30d1939SAndy Fiddaman (MAP_FIXED|MAP_SHARED), fd, (off_t)0 );
144*b30d1939SAndy Fiddaman }
145*b30d1939SAndy Fiddaman else
146*b30d1939SAndy Fiddaman { shmdt((Void_t*)mmvm);
147*b30d1939SAndy Fiddaman mmvm = (Mmvm_t*)shmat(mmdc->shmid, base, 0);
148*b30d1939SAndy Fiddaman }
149*b30d1939SAndy Fiddaman if(!mmvm || mmvm == (Mmvm_t*)(-1) )
150*b30d1939SAndy Fiddaman mmvm = NIL(Mmvm_t*);
151*b30d1939SAndy Fiddaman }
152*b30d1939SAndy Fiddaman
153*b30d1939SAndy Fiddaman return mmvm;
154*b30d1939SAndy Fiddaman }
155*b30d1939SAndy Fiddaman
156*b30d1939SAndy Fiddaman /* initialize region data */
mminit(Mmdisc_t * mmdc)157*b30d1939SAndy Fiddaman static int mminit(Mmdisc_t* mmdc)
158*b30d1939SAndy Fiddaman {
159*b30d1939SAndy Fiddaman Void_t *base;
160*b30d1939SAndy Fiddaman int try, k;
161*b30d1939SAndy Fiddaman int fd = -1;
162*b30d1939SAndy Fiddaman key_t key = -1;
163*b30d1939SAndy Fiddaman ssize_t extent, size = 0;
164*b30d1939SAndy Fiddaman Mmvm_t *mmvm = NIL(Mmvm_t*);
165*b30d1939SAndy Fiddaman int rv = -1;
166*b30d1939SAndy Fiddaman
167*b30d1939SAndy Fiddaman if(mmdc->mmvm) /* already done this */
168*b30d1939SAndy Fiddaman return 0;
169*b30d1939SAndy Fiddaman
170*b30d1939SAndy Fiddaman /* fixed size region so make it reasonably large */
171*b30d1939SAndy Fiddaman if((size = mmdc->size) < MM_MINSIZE )
172*b30d1939SAndy Fiddaman size = MM_MINSIZE;
173*b30d1939SAndy Fiddaman size += MMHEAD(mmdc->file) + ALIGN;
174*b30d1939SAndy Fiddaman size = ROUND(size, _Vmpagesize);
175*b30d1939SAndy Fiddaman
176*b30d1939SAndy Fiddaman /* this op can happen simultaneously in different processes */
177*b30d1939SAndy Fiddaman if((fd = open(mmdc->file, O_RDWR|O_CREAT, FILE_MODE)) < 0)
178*b30d1939SAndy Fiddaman return -1;
179*b30d1939SAndy Fiddaman
180*b30d1939SAndy Fiddaman /* get/create the initial segment of data */
181*b30d1939SAndy Fiddaman if(mmdc->proj < 0 ) /* proj < 0 means doing mmap() */
182*b30d1939SAndy Fiddaman { /* Note that the location being written to is always zero! */
183*b30d1939SAndy Fiddaman if((extent = (ssize_t)lseek(fd, (off_t)0, SEEK_END)) < 0)
184*b30d1939SAndy Fiddaman goto done;
185*b30d1939SAndy Fiddaman if(extent < size) /* make the file size large enough */
186*b30d1939SAndy Fiddaman if(lseek(fd, (off_t)size, 0) != (off_t)size || write(fd, "", 1) != 1 )
187*b30d1939SAndy Fiddaman goto done;
188*b30d1939SAndy Fiddaman
189*b30d1939SAndy Fiddaman /* map the file into memory */
190*b30d1939SAndy Fiddaman mmvm = (Mmvm_t*)mmap(NIL(Void_t*), size, (PROT_READ|PROT_WRITE),
191*b30d1939SAndy Fiddaman MAP_SHARED, fd, (off_t)0 );
192*b30d1939SAndy Fiddaman }
193*b30d1939SAndy Fiddaman else
194*b30d1939SAndy Fiddaman { /* make the key and get/create an id for the share mem segment */
195*b30d1939SAndy Fiddaman if((key = ftok(mmdc->file, mmdc->proj)) < 0 )
196*b30d1939SAndy Fiddaman goto done;
197*b30d1939SAndy Fiddaman if((mmdc->shmid = shmget(key, size, IPC_CREAT|FILE_MODE)) < 0 )
198*b30d1939SAndy Fiddaman goto done;
199*b30d1939SAndy Fiddaman
200*b30d1939SAndy Fiddaman /* map the data segment into memory */
201*b30d1939SAndy Fiddaman mmvm = (Mmvm_t*)shmat(mmdc->shmid, NIL(Void_t*), 0);
202*b30d1939SAndy Fiddaman }
203*b30d1939SAndy Fiddaman
204*b30d1939SAndy Fiddaman if(!mmvm || mmvm == (Mmvm_t*)(-1) ) /* initial mapping failed */
205*b30d1939SAndy Fiddaman goto done;
206*b30d1939SAndy Fiddaman
207*b30d1939SAndy Fiddaman /* all processes compete for the chore to initialize data */
208*b30d1939SAndy Fiddaman if(asocasint(&mmvm->magic, 0, MM_LETMEDOIT) == 0 ) /* lucky winner: us! */
209*b30d1939SAndy Fiddaman { if(!(base = vmmaddress(size)) ) /* get a suitable base for the map */
210*b30d1939SAndy Fiddaman base = (Void_t*)mmvm;
211*b30d1939SAndy Fiddaman mmdc->flag |= MM_INIT;
212*b30d1939SAndy Fiddaman mmvm->base = base;
213*b30d1939SAndy Fiddaman mmvm->size = size;
214*b30d1939SAndy Fiddaman mmvm->busy = 0;
215*b30d1939SAndy Fiddaman mmvm->proj = mmdc->proj;
216*b30d1939SAndy Fiddaman strcpy(mmvm->file, mmdc->file);
217*b30d1939SAndy Fiddaman if(mmdc->proj < 0 ) /* flush to file */
218*b30d1939SAndy Fiddaman msync((Void_t*)mmvm, MMHEAD(mmvm->file), MS_SYNC);
219*b30d1939SAndy Fiddaman
220*b30d1939SAndy Fiddaman if(mmvm->base != (Void_t*)mmvm) /* not yet at the right address */
221*b30d1939SAndy Fiddaman if(!(mmvm = mmfix(mmvm, mmdc, fd)) )
222*b30d1939SAndy Fiddaman goto done;
223*b30d1939SAndy Fiddaman rv = 0; /* success, return this value to indicate a new map */
224*b30d1939SAndy Fiddaman }
225*b30d1939SAndy Fiddaman else /* wait for someone else to finish initialization */
226*b30d1939SAndy Fiddaman { /**/ASSERT(!(mmdc->flag&MM_INIT));
227*b30d1939SAndy Fiddaman if(mmvm->magic != MM_LETMEDOIT && mmvm->magic != MM_MAGIC)
228*b30d1939SAndy Fiddaman goto done;
229*b30d1939SAndy Fiddaman
230*b30d1939SAndy Fiddaman for(try = 0, k = 0;; ASOLOOP(k) ) /* waiting */
231*b30d1939SAndy Fiddaman { if(asocasint(&mmvm->magic, MM_MAGIC, MM_MAGIC) == MM_MAGIC )
232*b30d1939SAndy Fiddaman break;
233*b30d1939SAndy Fiddaman else if((try += 1) <= 0 ) /* too many tries */
234*b30d1939SAndy Fiddaman goto done;
235*b30d1939SAndy Fiddaman }
236*b30d1939SAndy Fiddaman
237*b30d1939SAndy Fiddaman /* mapped the wrong memory */
238*b30d1939SAndy Fiddaman if(mmvm->proj != mmdc->proj || strcmp(mmvm->file, mmdc->file) != 0 )
239*b30d1939SAndy Fiddaman goto done;
240*b30d1939SAndy Fiddaman
241*b30d1939SAndy Fiddaman if(mmvm->base != (Void_t*)mmvm) /* not yet at the right address */
242*b30d1939SAndy Fiddaman if(!(mmvm = mmfix(mmvm, mmdc, fd)) )
243*b30d1939SAndy Fiddaman goto done;
244*b30d1939SAndy Fiddaman rv = 1; /* success, return this value to indicate a finished map */
245*b30d1939SAndy Fiddaman }
246*b30d1939SAndy Fiddaman
247*b30d1939SAndy Fiddaman done: (void)close(fd);
248*b30d1939SAndy Fiddaman
249*b30d1939SAndy Fiddaman if(rv >= 0 ) /* successful construction of region */
250*b30d1939SAndy Fiddaman { /**/ASSERT(mmvm && mmvm != (Mmvm_t*)(-1));
251*b30d1939SAndy Fiddaman mmdc->mmvm = mmvm;
252*b30d1939SAndy Fiddaman }
253*b30d1939SAndy Fiddaman else if(mmvm && mmvm != (Mmvm_t*)(-1)) /* error, remove map */
254*b30d1939SAndy Fiddaman { if(mmdc->proj < 0)
255*b30d1939SAndy Fiddaman (void)munmap((Void_t*)mmvm, size);
256*b30d1939SAndy Fiddaman else (void)shmdt((Void_t*)mmvm);
257*b30d1939SAndy Fiddaman }
258*b30d1939SAndy Fiddaman
259*b30d1939SAndy Fiddaman return rv;
260*b30d1939SAndy Fiddaman }
261*b30d1939SAndy Fiddaman
262*b30d1939SAndy Fiddaman #if __STD_C /* end a file mapping */
mmend(Mmdisc_t * mmdc)263*b30d1939SAndy Fiddaman static int mmend(Mmdisc_t* mmdc)
264*b30d1939SAndy Fiddaman #else
265*b30d1939SAndy Fiddaman static int mmend(mmdc)
266*b30d1939SAndy Fiddaman Mmdisc_t* mmdc;
267*b30d1939SAndy Fiddaman #endif
268*b30d1939SAndy Fiddaman {
269*b30d1939SAndy Fiddaman Mmvm_t *mmvm;
270*b30d1939SAndy Fiddaman struct shmid_ds shmds;
271*b30d1939SAndy Fiddaman
272*b30d1939SAndy Fiddaman if(!(mmvm = mmdc->mmvm) )
273*b30d1939SAndy Fiddaman return 0;
274*b30d1939SAndy Fiddaman
275*b30d1939SAndy Fiddaman if(mmdc->proj < 0 )
276*b30d1939SAndy Fiddaman { (void)msync(mmvm->base, mmvm->size, MS_ASYNC);
277*b30d1939SAndy Fiddaman if(mmdc->flag&MM_RELEASE)
278*b30d1939SAndy Fiddaman { if(mmvm->base )
279*b30d1939SAndy Fiddaman (void)munmap(mmvm->base, mmvm->size);
280*b30d1939SAndy Fiddaman }
281*b30d1939SAndy Fiddaman if(mmdc->flag&MM_CLEANUP)
282*b30d1939SAndy Fiddaman (void)unlink(mmdc->file);
283*b30d1939SAndy Fiddaman }
284*b30d1939SAndy Fiddaman else
285*b30d1939SAndy Fiddaman { if(mmdc->flag&MM_RELEASE)
286*b30d1939SAndy Fiddaman { if(mmvm->base )
287*b30d1939SAndy Fiddaman (void)shmdt(mmvm->base);
288*b30d1939SAndy Fiddaman }
289*b30d1939SAndy Fiddaman if(mmdc->flag&MM_CLEANUP)
290*b30d1939SAndy Fiddaman { if(mmdc->shmid >= 0 )
291*b30d1939SAndy Fiddaman (void)shmctl(mmdc->shmid, IPC_RMID, &shmds);
292*b30d1939SAndy Fiddaman }
293*b30d1939SAndy Fiddaman }
294*b30d1939SAndy Fiddaman
295*b30d1939SAndy Fiddaman mmdc->mmvm = NIL(Mmvm_t*);
296*b30d1939SAndy Fiddaman return 0;
297*b30d1939SAndy Fiddaman }
298*b30d1939SAndy Fiddaman
299*b30d1939SAndy Fiddaman #if __STD_C
mmgetmem(Vmalloc_t * vm,Void_t * caddr,size_t csize,size_t nsize,Vmdisc_t * disc)300*b30d1939SAndy Fiddaman static Void_t* mmgetmem(Vmalloc_t* vm, Void_t* caddr,
301*b30d1939SAndy Fiddaman size_t csize, size_t nsize, Vmdisc_t* disc)
302*b30d1939SAndy Fiddaman #else
303*b30d1939SAndy Fiddaman static Void_t* mmgetmem(vm, caddr, csize, nsize, disc)
304*b30d1939SAndy Fiddaman Vmalloc_t* vm;
305*b30d1939SAndy Fiddaman Void_t* caddr;
306*b30d1939SAndy Fiddaman size_t csize;
307*b30d1939SAndy Fiddaman size_t nsize;
308*b30d1939SAndy Fiddaman Vmdisc_t* disc;
309*b30d1939SAndy Fiddaman #endif
310*b30d1939SAndy Fiddaman {
311*b30d1939SAndy Fiddaman Mmvm_t *mmvm;
312*b30d1939SAndy Fiddaman Mmdisc_t *mmdc = (Mmdisc_t*)disc;
313*b30d1939SAndy Fiddaman
314*b30d1939SAndy Fiddaman if(!(mmvm = mmdc->mmvm) ) /* bad data */
315*b30d1939SAndy Fiddaman return NIL(Void_t*);
316*b30d1939SAndy Fiddaman
317*b30d1939SAndy Fiddaman /* this region allows only a single busy block! */
318*b30d1939SAndy Fiddaman if(caddr) /* resizing/freeing an existing block */
319*b30d1939SAndy Fiddaman { if(caddr == MMDATA(mmvm) && nsize <= MMSIZE(mmvm) )
320*b30d1939SAndy Fiddaman { mmvm->busy = nsize;
321*b30d1939SAndy Fiddaman return MMDATA(mmvm);
322*b30d1939SAndy Fiddaman }
323*b30d1939SAndy Fiddaman else return NIL(Void_t*);
324*b30d1939SAndy Fiddaman }
325*b30d1939SAndy Fiddaman else /* requesting a new block */
326*b30d1939SAndy Fiddaman { if(mmvm->busy == 0 )
327*b30d1939SAndy Fiddaman { mmvm->busy = nsize;
328*b30d1939SAndy Fiddaman return MMDATA(mmvm);
329*b30d1939SAndy Fiddaman }
330*b30d1939SAndy Fiddaman else return NIL(Void_t*);
331*b30d1939SAndy Fiddaman }
332*b30d1939SAndy Fiddaman }
333*b30d1939SAndy Fiddaman
334*b30d1939SAndy Fiddaman #if __STD_C
mmexcept(Vmalloc_t * vm,int type,Void_t * data,Vmdisc_t * disc)335*b30d1939SAndy Fiddaman static int mmexcept(Vmalloc_t* vm, int type, Void_t* data, Vmdisc_t* disc)
336*b30d1939SAndy Fiddaman #else
337*b30d1939SAndy Fiddaman static int mmexcept(vm, type, data, disc)
338*b30d1939SAndy Fiddaman Vmalloc_t* vm;
339*b30d1939SAndy Fiddaman int type;
340*b30d1939SAndy Fiddaman Void_t* data;
341*b30d1939SAndy Fiddaman Vmdisc_t* disc;
342*b30d1939SAndy Fiddaman #endif
343*b30d1939SAndy Fiddaman {
344*b30d1939SAndy Fiddaman int rv;
345*b30d1939SAndy Fiddaman Void_t *base;
346*b30d1939SAndy Fiddaman Mmdisc_t *mmdc = (Mmdisc_t*)disc;
347*b30d1939SAndy Fiddaman
348*b30d1939SAndy Fiddaman if(type == VM_OPEN)
349*b30d1939SAndy Fiddaman { if(data) /* VM_OPEN event at start of vmopen() */
350*b30d1939SAndy Fiddaman { if((rv = mminit(mmdc)) < 0 ) /* initialization failed */
351*b30d1939SAndy Fiddaman return -1;
352*b30d1939SAndy Fiddaman else if(rv == 0) /* just started a new map */
353*b30d1939SAndy Fiddaman { /**/ASSERT(mmdc->flag&MM_INIT);
354*b30d1939SAndy Fiddaman /**/ASSERT(mmdc->mmvm->magic == MM_LETMEDOIT);
355*b30d1939SAndy Fiddaman return 0;
356*b30d1939SAndy Fiddaman }
357*b30d1939SAndy Fiddaman else /* an existing map was reconstructed */
358*b30d1939SAndy Fiddaman { /**/ASSERT(!(mmdc->flag&MM_INIT));
359*b30d1939SAndy Fiddaman /**/ASSERT(mmdc->mmvm->magic == MM_MAGIC);
360*b30d1939SAndy Fiddaman *((Void_t**)data) = MMDATA(mmdc->mmvm);
361*b30d1939SAndy Fiddaman return 1;
362*b30d1939SAndy Fiddaman }
363*b30d1939SAndy Fiddaman }
364*b30d1939SAndy Fiddaman else return 0;
365*b30d1939SAndy Fiddaman }
366*b30d1939SAndy Fiddaman else if(type == VM_ENDOPEN) /* at end of vmopen() */
367*b30d1939SAndy Fiddaman { if(mmdc->flag&MM_INIT) /* this is the initializing process! */
368*b30d1939SAndy Fiddaman { /**/ASSERT(mmdc->mmvm->magic == MM_LETMEDOIT);
369*b30d1939SAndy Fiddaman asocasint(&mmdc->mmvm->magic, MM_LETMEDOIT, MM_MAGIC);
370*b30d1939SAndy Fiddaman
371*b30d1939SAndy Fiddaman if(mmdc->proj < 0) /* sync data to file now */
372*b30d1939SAndy Fiddaman msync((Void_t*)mmdc->mmvm, MMHEAD(mmdc->file), MS_SYNC);
373*b30d1939SAndy Fiddaman } /**/ASSERT(mmdc->mmvm->magic == MM_MAGIC);
374*b30d1939SAndy Fiddaman return 0;
375*b30d1939SAndy Fiddaman }
376*b30d1939SAndy Fiddaman else if(type == VM_CLOSE)
377*b30d1939SAndy Fiddaman return 1; /* tell vmclose not to free memory segments */
378*b30d1939SAndy Fiddaman else if(type == VM_ENDCLOSE) /* this is the final closing event */
379*b30d1939SAndy Fiddaman { (void)mmend(mmdc);
380*b30d1939SAndy Fiddaman (void)vmfree(Vmheap, mmdc);
381*b30d1939SAndy Fiddaman return 0; /* all done */
382*b30d1939SAndy Fiddaman }
383*b30d1939SAndy Fiddaman else return 0;
384*b30d1939SAndy Fiddaman }
385*b30d1939SAndy Fiddaman
386*b30d1939SAndy Fiddaman #if __STD_C
vmmopen(char * file,int proj,ssize_t size)387*b30d1939SAndy Fiddaman Vmalloc_t* vmmopen(char* file, int proj, ssize_t size )
388*b30d1939SAndy Fiddaman #else
389*b30d1939SAndy Fiddaman Vmalloc_t* vmmopen(file, proj, size )
390*b30d1939SAndy Fiddaman char* file; /* file for key or data backing */
391*b30d1939SAndy Fiddaman int proj; /* project ID, < 0 doing mmap */
392*b30d1939SAndy Fiddaman ssize_t size; /* desired size for mem segment */
393*b30d1939SAndy Fiddaman #endif
394*b30d1939SAndy Fiddaman {
395*b30d1939SAndy Fiddaman Vmalloc_t *vm;
396*b30d1939SAndy Fiddaman Mmdisc_t *mmdc;
397*b30d1939SAndy Fiddaman
398*b30d1939SAndy Fiddaman GETPAGESIZE(_Vmpagesize);
399*b30d1939SAndy Fiddaman
400*b30d1939SAndy Fiddaman if(!file || !file[0] )
401*b30d1939SAndy Fiddaman return NIL(Vmalloc_t*);
402*b30d1939SAndy Fiddaman
403*b30d1939SAndy Fiddaman /* create discipline structure for getting memory from mmap */
404*b30d1939SAndy Fiddaman if(!(mmdc = vmalloc(Vmheap, sizeof(Mmdisc_t)+strlen(file))) )
405*b30d1939SAndy Fiddaman return NIL(Vmalloc_t*);
406*b30d1939SAndy Fiddaman memset(mmdc, 0, sizeof(Mmdisc_t));
407*b30d1939SAndy Fiddaman mmdc->disc.memoryf = mmgetmem;
408*b30d1939SAndy Fiddaman mmdc->disc.exceptf = mmexcept;
409*b30d1939SAndy Fiddaman mmdc->disc.round = _Vmpagesize; /* round request to this size */
410*b30d1939SAndy Fiddaman mmdc->mmvm = NIL(Mmvm_t*);
411*b30d1939SAndy Fiddaman mmdc->size = size;
412*b30d1939SAndy Fiddaman mmdc->shmid = -1;
413*b30d1939SAndy Fiddaman mmdc->flag = 0;
414*b30d1939SAndy Fiddaman mmdc->proj = proj;
415*b30d1939SAndy Fiddaman strcpy(mmdc->file, file);
416*b30d1939SAndy Fiddaman
417*b30d1939SAndy Fiddaman /* now open the Vmalloc_t handle to return to application */
418*b30d1939SAndy Fiddaman if(!(vm = vmopen(&mmdc->disc, Vmbest, VM_SHARE)) )
419*b30d1939SAndy Fiddaman { (void)mmend(mmdc);
420*b30d1939SAndy Fiddaman (void)vmfree(Vmheap, mmdc);
421*b30d1939SAndy Fiddaman return NIL(Vmalloc_t*);
422*b30d1939SAndy Fiddaman }
423*b30d1939SAndy Fiddaman else
424*b30d1939SAndy Fiddaman { /**/ASSERT(mmdc->mmvm && mmdc->mmvm->magic == MM_MAGIC);
425*b30d1939SAndy Fiddaman return vm;
426*b30d1939SAndy Fiddaman }
427*b30d1939SAndy Fiddaman }
428*b30d1939SAndy Fiddaman
429*b30d1939SAndy Fiddaman /* to store (key,value) data in the map */
430*b30d1939SAndy Fiddaman #if __STD_C
vmmvalue(Vmalloc_t * vm,int key,Void_t * val,int oper)431*b30d1939SAndy Fiddaman Void_t* vmmvalue(Vmalloc_t* vm, int key, Void_t* val, int oper)
432*b30d1939SAndy Fiddaman #else
433*b30d1939SAndy Fiddaman Void_t* vmmvalue(vm, key, val, oper)
434*b30d1939SAndy Fiddaman Vmalloc_t* vm; /* a region based on vmmapopen */
435*b30d1939SAndy Fiddaman int key; /* key of data to be set */
436*b30d1939SAndy Fiddaman Void_t* val; /* data to be set */
437*b30d1939SAndy Fiddaman int oper; /* operation type */
438*b30d1939SAndy Fiddaman #endif
439*b30d1939SAndy Fiddaman {
440*b30d1939SAndy Fiddaman Mmuser_t *u;
441*b30d1939SAndy Fiddaman Mmdisc_t *mmdc = (Mmdisc_t*)vm->disc;
442*b30d1939SAndy Fiddaman Mmvm_t *mmvm = mmdc->mmvm;
443*b30d1939SAndy Fiddaman
444*b30d1939SAndy Fiddaman /* check to see if operation is well-defined */
445*b30d1939SAndy Fiddaman if(oper != VM_MMGET && oper != VM_MMSET && oper != VM_MMADD)
446*b30d1939SAndy Fiddaman return NIL(Void_t*);
447*b30d1939SAndy Fiddaman
448*b30d1939SAndy Fiddaman SETLOCK(vm, 0);
449*b30d1939SAndy Fiddaman
450*b30d1939SAndy Fiddaman /* find the key */
451*b30d1939SAndy Fiddaman for(u = mmvm->user; u; u = u->next)
452*b30d1939SAndy Fiddaman if(u->key == key)
453*b30d1939SAndy Fiddaman break;
454*b30d1939SAndy Fiddaman
455*b30d1939SAndy Fiddaman if(!u && (oper == VM_MMSET || oper == VM_MMADD) )
456*b30d1939SAndy Fiddaman { if((u = KPVALLOC(vm, sizeof(Mmuser_t), vm->meth.allocf)) )
457*b30d1939SAndy Fiddaman { u->val = NIL(Void_t*);
458*b30d1939SAndy Fiddaman u->key = key;
459*b30d1939SAndy Fiddaman u->next = mmvm->user;
460*b30d1939SAndy Fiddaman mmvm->user = u;
461*b30d1939SAndy Fiddaman }
462*b30d1939SAndy Fiddaman }
463*b30d1939SAndy Fiddaman
464*b30d1939SAndy Fiddaman if(u) /* update data and set value to return */
465*b30d1939SAndy Fiddaman { if(oper == VM_MMSET)
466*b30d1939SAndy Fiddaman u->val = val;
467*b30d1939SAndy Fiddaman else if(oper == VM_MMADD)
468*b30d1939SAndy Fiddaman u->val = (Void_t*)((long)(u->val) + (long)(val));
469*b30d1939SAndy Fiddaman val = u->val;
470*b30d1939SAndy Fiddaman }
471*b30d1939SAndy Fiddaman else val = NIL(Void_t*);
472*b30d1939SAndy Fiddaman
473*b30d1939SAndy Fiddaman CLRLOCK(vm, 0);
474*b30d1939SAndy Fiddaman
475*b30d1939SAndy Fiddaman return val;
476*b30d1939SAndy Fiddaman }
477*b30d1939SAndy Fiddaman
vmmrelease(Vmalloc_t * vm,int type)478*b30d1939SAndy Fiddaman void vmmrelease(Vmalloc_t* vm, int type)
479*b30d1939SAndy Fiddaman {
480*b30d1939SAndy Fiddaman Mmdisc_t *mmdc = (Mmdisc_t*)vm->disc;
481*b30d1939SAndy Fiddaman
482*b30d1939SAndy Fiddaman mmdc->flag |= MM_RELEASE;
483*b30d1939SAndy Fiddaman if(type > 0)
484*b30d1939SAndy Fiddaman mmdc->flag |= MM_CLEANUP;
485*b30d1939SAndy Fiddaman }
486*b30d1939SAndy Fiddaman
487*b30d1939SAndy Fiddaman /* suggest an address usable for mapping memory */
vmmaddress(size_t size)488*b30d1939SAndy Fiddaman Void_t* vmmaddress(size_t size)
489*b30d1939SAndy Fiddaman {
490*b30d1939SAndy Fiddaman #if !defined(_map_min) || !defined(_map_max) || !defined(_map_dir)
491*b30d1939SAndy Fiddaman return NIL(Void_t*);
492*b30d1939SAndy Fiddaman #else
493*b30d1939SAndy Fiddaman Void_t *avail;
494*b30d1939SAndy Fiddaman static Vmuchar_t *min = (Vmuchar_t*)_map_min;
495*b30d1939SAndy Fiddaman static Vmuchar_t *max = (Vmuchar_t*)_map_max;
496*b30d1939SAndy Fiddaman
497*b30d1939SAndy Fiddaman GETPAGESIZE(_Vmpagesize);
498*b30d1939SAndy Fiddaman size = ROUND(size, _Vmpagesize);
499*b30d1939SAndy Fiddaman
500*b30d1939SAndy Fiddaman if(_map_dir == 0 || (min+size) > max)
501*b30d1939SAndy Fiddaman avail = NIL(Void_t*);
502*b30d1939SAndy Fiddaman else if(_map_dir > 0)
503*b30d1939SAndy Fiddaman { avail = (Void_t*)min;
504*b30d1939SAndy Fiddaman min += size;
505*b30d1939SAndy Fiddaman }
506*b30d1939SAndy Fiddaman else
507*b30d1939SAndy Fiddaman { max -= size;
508*b30d1939SAndy Fiddaman avail = (Void_t*)max;
509*b30d1939SAndy Fiddaman }
510*b30d1939SAndy Fiddaman
511*b30d1939SAndy Fiddaman return avail;
512*b30d1939SAndy Fiddaman #endif
513*b30d1939SAndy Fiddaman }
514*b30d1939SAndy Fiddaman
515*b30d1939SAndy Fiddaman #endif
516