1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*3e14f97fSRoger A. Faulkner * Copyright (c) 1985-2010 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6da2e3ebdSchin * Common Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt *
11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12da2e3ebdSchin * *
13da2e3ebdSchin * Information and Software Systems Research *
14da2e3ebdSchin * AT&T Research *
15da2e3ebdSchin * Florham Park NJ *
16da2e3ebdSchin * *
17da2e3ebdSchin * Glenn Fowler <gsf@research.att.com> *
18da2e3ebdSchin * David Korn <dgk@research.att.com> *
19da2e3ebdSchin * Phong Vo <kpv@research.att.com> *
20da2e3ebdSchin * *
21da2e3ebdSchin ***********************************************************************/
22da2e3ebdSchin #if defined(_UWIN) && defined(_BLD_ast)
23da2e3ebdSchin
_STUB_vmmopen()24da2e3ebdSchin void _STUB_vmmopen(){}
25da2e3ebdSchin
26da2e3ebdSchin #else
27da2e3ebdSchin
28da2e3ebdSchin #include "vmhdr.h"
29da2e3ebdSchin
30da2e3ebdSchin #if _sys_stat
31da2e3ebdSchin #include <sys/stat.h>
32da2e3ebdSchin #endif
33da2e3ebdSchin #include <fcntl.h>
34da2e3ebdSchin
35da2e3ebdSchin #ifdef S_IRUSR
36da2e3ebdSchin #define CREAT_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
37da2e3ebdSchin #else
38da2e3ebdSchin #define CREAT_MODE 0644
39da2e3ebdSchin #endif
40da2e3ebdSchin
41da2e3ebdSchin #if _lib_mmap
42da2e3ebdSchin #include <sys/mman.h>
43da2e3ebdSchin #else
44da2e3ebdSchin #define mmap(a,b,c,d,e,f) MAP_FAILED
45da2e3ebdSchin #define munmap(a,b) MAP_FAILED
46da2e3ebdSchin #endif
47da2e3ebdSchin
48da2e3ebdSchin /* Create a region to allocate based on mmap()
49da2e3ebdSchin **
50da2e3ebdSchin ** Written by Kiem-Phong Vo (kpv@research.att.com)
51da2e3ebdSchin */
52da2e3ebdSchin
53da2e3ebdSchin #ifndef MAP_FAILED
54da2e3ebdSchin #define MAP_FAILED (void*)(-1)
55da2e3ebdSchin #endif
56da2e3ebdSchin
57da2e3ebdSchin #define MM_MAGIC (('V'<<24) | ('M'<<16) | ('A'<<8) | ('P'))
58da2e3ebdSchin #define MM_ROUND (64*1024)
59da2e3ebdSchin #define MM_START ROUND(sizeof(Mmvm_t),ALIGN)
60da2e3ebdSchin
61da2e3ebdSchin typedef struct _user_s
62da2e3ebdSchin { struct _user_s* next; /* link list */
63da2e3ebdSchin int key; /* identifying key */
64da2e3ebdSchin Void_t* data; /* data to be returned */
65da2e3ebdSchin } User_t;
66da2e3ebdSchin
67da2e3ebdSchin typedef struct _mmvm_s
68da2e3ebdSchin {
69da2e3ebdSchin Vmulong_t magic; /* magic bytes */
70da2e3ebdSchin Void_t* base; /* base of the map */
71da2e3ebdSchin size_t size; /* current size */
72da2e3ebdSchin size_t busy; /* amount in use */
73da2e3ebdSchin size_t round; /* amount to round to */
74da2e3ebdSchin User_t* user; /* some user data */
75da2e3ebdSchin } Mmvm_t;
76da2e3ebdSchin
77da2e3ebdSchin typedef struct _mmvmdisc_s
78da2e3ebdSchin {
79da2e3ebdSchin Vmdisc_t disc; /* Vmalloc discipline */
80da2e3ebdSchin int fd; /* file descriptor */
81da2e3ebdSchin Mmvm_t* mm; /* mmap data */
82da2e3ebdSchin } Mmvmdisc_t;
83da2e3ebdSchin
84da2e3ebdSchin #if __STD_C
mmvminit(char * file,Void_t * addr,size_t round,Mmvm_t * mm)85da2e3ebdSchin static int mmvminit(char* file, Void_t* addr, size_t round, Mmvm_t* mm)
86da2e3ebdSchin #else
87da2e3ebdSchin static int mmvminit(file, addr, round, mm)
88da2e3ebdSchin char* file; /* file to map data from */
89da2e3ebdSchin Void_t* addr; /* desired starting address */
90da2e3ebdSchin size_t round; /* amount to round requests */
91da2e3ebdSchin Mmvm_t* mm; /* to return some mapped info */
92da2e3ebdSchin #endif
93da2e3ebdSchin {
94da2e3ebdSchin int fd;
95da2e3ebdSchin off_t size;
96da2e3ebdSchin Void_t *base;
97da2e3ebdSchin Mmvm_t *hdr;
98da2e3ebdSchin
99da2e3ebdSchin base = NIL(Void_t*);
100da2e3ebdSchin if((fd = open(file, O_RDWR, CREAT_MODE)) >= 0)
101da2e3ebdSchin { if((size = lseek(fd, (off_t)0, 2)) < 0)
102da2e3ebdSchin goto done;
103da2e3ebdSchin else if(size == 0)
104da2e3ebdSchin goto new_f;
105da2e3ebdSchin
106da2e3ebdSchin /* read the header */
107da2e3ebdSchin if(lseek(fd, (off_t)0, 0) != (off_t)0)
108da2e3ebdSchin goto done;
109da2e3ebdSchin if(read(fd, mm, sizeof(Mmvm_t)) != sizeof(Mmvm_t))
110da2e3ebdSchin goto done;
111da2e3ebdSchin if(mm->magic != MM_MAGIC || !mm->base ||
112da2e3ebdSchin (off_t)mm->size != size || mm->busy > mm->size )
113da2e3ebdSchin goto done;
114da2e3ebdSchin base = (Void_t*)mmap(mm->base, mm->size, PROT_READ|PROT_WRITE,
115da2e3ebdSchin MAP_FIXED|MAP_SHARED, fd, (off_t)0 );
116da2e3ebdSchin if(base == (Void_t*)MAP_FAILED)
117da2e3ebdSchin base = NIL(Void_t*);
118da2e3ebdSchin }
119da2e3ebdSchin else
120da2e3ebdSchin { if((fd = open(file, O_RDWR|O_CREAT, CREAT_MODE)) < 0)
121da2e3ebdSchin goto done;
122da2e3ebdSchin
123da2e3ebdSchin new_f: /* create an initial set of data */
124da2e3ebdSchin size = round;
125da2e3ebdSchin if(lseek(fd, size-1, 0) != (size-1) || write(fd, "", 1) != 1 )
126da2e3ebdSchin goto done;
127da2e3ebdSchin
128da2e3ebdSchin base = (Void_t*)mmap(addr, (size_t)size, PROT_READ|PROT_WRITE,
129da2e3ebdSchin (addr ? MAP_FIXED : 0)|MAP_SHARED, fd, (off_t)0 );
130da2e3ebdSchin if(base == (Void_t*)MAP_FAILED)
131da2e3ebdSchin base = NIL(Void_t*);
132da2e3ebdSchin if(!base)
133da2e3ebdSchin goto done;
134da2e3ebdSchin
135da2e3ebdSchin /* write magic number */
136da2e3ebdSchin hdr = (Mmvm_t*)base;
137da2e3ebdSchin hdr->magic = MM_MAGIC;
138da2e3ebdSchin hdr->base = base;
139da2e3ebdSchin hdr->size = size;
140da2e3ebdSchin hdr->busy = MM_START;
141da2e3ebdSchin hdr->round = round;
142da2e3ebdSchin hdr->user = NIL(User_t*);
143da2e3ebdSchin memcpy(mm, hdr, sizeof(Mmvm_t));
144da2e3ebdSchin }
145da2e3ebdSchin
146da2e3ebdSchin done:
147da2e3ebdSchin if(!base)
148da2e3ebdSchin { if(fd >= 0)
149da2e3ebdSchin close(fd);
150da2e3ebdSchin fd = -1;
151da2e3ebdSchin }
152da2e3ebdSchin
153da2e3ebdSchin return fd;
154da2e3ebdSchin }
155da2e3ebdSchin
156da2e3ebdSchin
157da2e3ebdSchin #if __STD_C
mmvmmemory(Vmalloc_t * vm,Void_t * caddr,size_t csize,size_t nsize,Vmdisc_t * disc)158da2e3ebdSchin static Void_t* mmvmmemory(Vmalloc_t* vm, Void_t* caddr,
159da2e3ebdSchin size_t csize, size_t nsize, Vmdisc_t* disc)
160da2e3ebdSchin #else
161da2e3ebdSchin static Void_t* mmvmmemory(vm, caddr, csize, nsize, disc)
162da2e3ebdSchin Vmalloc_t* vm;
163da2e3ebdSchin Void_t* caddr;
164da2e3ebdSchin size_t csize;
165da2e3ebdSchin size_t nsize;
166da2e3ebdSchin Vmdisc_t* disc;
167da2e3ebdSchin #endif
168da2e3ebdSchin {
169da2e3ebdSchin Mmvmdisc_t *mmdc = (Mmvmdisc_t*)disc;
170da2e3ebdSchin
171da2e3ebdSchin if(mmdc->fd < 0 || !mmdc->mm)
172da2e3ebdSchin return NIL(Void_t*);
173da2e3ebdSchin
174da2e3ebdSchin #define MMADDR(b) ((Void_t*)(((Vmuchar_t*)b) + MM_START) )
175da2e3ebdSchin if(caddr && caddr != MMADDR(mmdc->mm->base) )
176da2e3ebdSchin return NIL(Void_t*);
177da2e3ebdSchin if(nsize < csize)
178da2e3ebdSchin return NIL(Void_t*);
179da2e3ebdSchin
180da2e3ebdSchin if(nsize > mmdc->mm->size-MM_START)
181da2e3ebdSchin { /* base and size of new map */
182da2e3ebdSchin caddr = mmdc->mm->base;
183da2e3ebdSchin csize = MM_START + nsize +
184da2e3ebdSchin ((nsize % disc->round) < (disc->round/2) ? disc->round/2 : 0);
185da2e3ebdSchin csize = ROUND(csize, disc->round);
186da2e3ebdSchin
187da2e3ebdSchin /* make room for new space */
188da2e3ebdSchin if(lseek(mmdc->fd, (off_t)(csize-1), 0) != (off_t)(csize-1) ||
189da2e3ebdSchin write(mmdc->fd, "", 1) != 1 )
190da2e3ebdSchin return NIL(Void_t*);
191da2e3ebdSchin
192da2e3ebdSchin /* remap the space */
193da2e3ebdSchin (void)munmap(caddr, mmdc->mm->size);
194da2e3ebdSchin caddr = (Void_t*)mmap(caddr, csize, PROT_READ|PROT_WRITE,
195da2e3ebdSchin MAP_FIXED|MAP_SHARED, mmdc->fd, (off_t)0 );
196da2e3ebdSchin if(caddr == (Void_t*)MAP_FAILED)
197da2e3ebdSchin caddr = NIL(Void_t*);
198da2e3ebdSchin if(caddr)
199da2e3ebdSchin mmdc->mm->size = csize;
200da2e3ebdSchin else /* bad problem */
201da2e3ebdSchin { close(mmdc->fd);
202da2e3ebdSchin mmdc->fd = -1;
203da2e3ebdSchin mmdc->mm = NIL(Mmvm_t*);
204da2e3ebdSchin return NIL(Void_t*);
205da2e3ebdSchin }
206da2e3ebdSchin }
207da2e3ebdSchin
208da2e3ebdSchin mmdc->mm->busy = nsize+MM_START;
209da2e3ebdSchin return (Void_t*)(((Vmuchar_t*)mmdc->mm->base) + MM_START);
210da2e3ebdSchin }
211da2e3ebdSchin
212da2e3ebdSchin
213da2e3ebdSchin #if __STD_C
mmvmexcept(Vmalloc_t * vm,int type,Void_t * data,Vmdisc_t * disc)214da2e3ebdSchin static int mmvmexcept(Vmalloc_t* vm, int type, Void_t* data, Vmdisc_t* disc)
215da2e3ebdSchin #else
216da2e3ebdSchin static int mmvmexcept(vm, type, data, disc)
217da2e3ebdSchin Vmalloc_t* vm;
218da2e3ebdSchin int type;
219da2e3ebdSchin Void_t* data;
220da2e3ebdSchin Vmdisc_t* disc;
221da2e3ebdSchin #endif
222da2e3ebdSchin {
223da2e3ebdSchin Mmvmdisc_t *mmdc = (Mmvmdisc_t*)disc;
224da2e3ebdSchin Vmuchar_t *base;
225da2e3ebdSchin
226da2e3ebdSchin if(type == VM_OPEN)
227da2e3ebdSchin { if(mmdc->mm->busy > MM_START)
228da2e3ebdSchin { base = ((Vmuchar_t*)mmdc->mm->base) + MM_START;
229da2e3ebdSchin *((Void_t**)data) = (Void_t*)base;
230da2e3ebdSchin return 1;
231da2e3ebdSchin }
232da2e3ebdSchin else return 0;
233da2e3ebdSchin }
234da2e3ebdSchin else if(type == VM_CLOSE)
235da2e3ebdSchin { (void)munmap(mmdc->mm->base, mmdc->mm->size);
236da2e3ebdSchin (void)close(mmdc->fd);
237da2e3ebdSchin vmfree(Vmheap, mmdc);
238da2e3ebdSchin return 1; /* freeing of mapped data is already done */
239da2e3ebdSchin }
240da2e3ebdSchin else return 0;
241da2e3ebdSchin }
242da2e3ebdSchin
243da2e3ebdSchin
244da2e3ebdSchin #if __STD_C
vmmopen(char * file,Void_t * base,size_t round)245da2e3ebdSchin Vmalloc_t* vmmopen(char* file, Void_t* base, size_t round)
246da2e3ebdSchin #else
247da2e3ebdSchin Vmalloc_t* vmmopen(file, base, round)
248da2e3ebdSchin char* file; /* file mapping data from */
249da2e3ebdSchin Void_t* base; /* desired starting address */
250da2e3ebdSchin size_t round; /* amount to round requests */
251da2e3ebdSchin #endif
252da2e3ebdSchin {
253da2e3ebdSchin Vmalloc_t *vm;
254da2e3ebdSchin Mmvmdisc_t *mmdc;
255da2e3ebdSchin Mmvm_t mm;
256da2e3ebdSchin int fd;
257da2e3ebdSchin
258da2e3ebdSchin if(!file)
259da2e3ebdSchin return NIL(Vmalloc_t*);
260da2e3ebdSchin
261da2e3ebdSchin /* set the amount to round up to on each memory request */
262da2e3ebdSchin GETPAGESIZE(_Vmpagesize);
263da2e3ebdSchin if(round < MM_ROUND)
264da2e3ebdSchin round = MM_ROUND;
265da2e3ebdSchin round = ROUND(round, _Vmpagesize);
266da2e3ebdSchin
267da2e3ebdSchin if((fd = mmvminit(file, base, round, &mm)) < 0)
268da2e3ebdSchin return NIL(Vmalloc_t*);
269da2e3ebdSchin
270da2e3ebdSchin if(!(mmdc = (Mmvmdisc_t*)vmalloc(Vmheap, sizeof(Mmvmdisc_t))) )
271da2e3ebdSchin { close(fd);
272da2e3ebdSchin return NIL(Vmalloc_t*);
273da2e3ebdSchin }
274da2e3ebdSchin
275da2e3ebdSchin mmdc->disc.memoryf = mmvmmemory;
276da2e3ebdSchin mmdc->disc.exceptf = mmvmexcept;
277da2e3ebdSchin mmdc->disc.round = mm.round;
278da2e3ebdSchin mmdc->fd = fd;
279da2e3ebdSchin mmdc->mm = (Mmvm_t*)mm.base;
280da2e3ebdSchin
281da2e3ebdSchin if(!(vm = vmopen(&mmdc->disc, Vmbest, VM_TRUST)) )
282da2e3ebdSchin { mmvmexcept(NIL(Vmalloc_t*), VM_CLOSE, NIL(Void_t*), &mmdc->disc);
283da2e3ebdSchin return NIL(Vmalloc_t*);
284da2e3ebdSchin }
285da2e3ebdSchin
286da2e3ebdSchin return vm;
287da2e3ebdSchin }
288da2e3ebdSchin
289da2e3ebdSchin
290da2e3ebdSchin #if __STD_C
vmmset(Vmalloc_t * vm,int key,Void_t * data,int set)291da2e3ebdSchin Void_t* vmmset(Vmalloc_t* vm, int key, Void_t* data, int set)
292da2e3ebdSchin #else
293da2e3ebdSchin Void_t* vmmset(vm, data, key, set)
294da2e3ebdSchin Vmalloc_t* vm; /* a region based on vmmmopen */
295da2e3ebdSchin int key; /* key of data to be set */
296da2e3ebdSchin Void_t* data; /* data to be set */
297da2e3ebdSchin int set; /* 1 for setting, 0 for getting */
298da2e3ebdSchin #endif
299da2e3ebdSchin {
300da2e3ebdSchin User_t *u;
301da2e3ebdSchin Mmvm_t *mmvm = ((Mmvmdisc_t*)vm->disc)->mm;
302da2e3ebdSchin
303da2e3ebdSchin for(u = mmvm->user; u; u = u->next)
304da2e3ebdSchin if(u->key == key)
305da2e3ebdSchin break;
306da2e3ebdSchin if(!set)
307da2e3ebdSchin return u ? u->data : NIL(Void_t*);
308da2e3ebdSchin else if(u)
309da2e3ebdSchin { Void_t* old = u->data;
310da2e3ebdSchin u->data = data;
311da2e3ebdSchin return old;
312da2e3ebdSchin }
313da2e3ebdSchin else if(!(u = (User_t*)vmalloc(vm, sizeof(User_t))) )
314da2e3ebdSchin return NIL(Void_t*);
315da2e3ebdSchin else
316da2e3ebdSchin { u->data = data;
317da2e3ebdSchin u->key = key;
318da2e3ebdSchin u->next = mmvm->user;
319da2e3ebdSchin mmvm->user = u;
320da2e3ebdSchin return data;
321da2e3ebdSchin }
322da2e3ebdSchin }
323da2e3ebdSchin
324da2e3ebdSchin #endif
325