1 /* BLURB lgpl
2 
3                            Coda File System
4                               Release 5
5 
6           Copyright (c) 1987-1999 Carnegie Mellon University
7                   Additional copyrights listed below
8 
9 This  code  is  distributed "AS IS" without warranty of any kind under
10 the  terms of the  GNU  Library General Public Licence  Version 2,  as
11 shown in the file LICENSE. The technical and financial contributors to
12 Coda are listed in the file CREDITS.
13 
14                         Additional copyrights
15                            none currently
16 
17 #*/
18 
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22 
23 #include <unistd.h>
24 #include <stdlib.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 
29 #include <rvm/rvm.h>
30 #include <rvm/rvm_segment.h>
31 
32 /* from rvm_private.h */
33 rvm_bool_t rvm_register_page(char *vmaddr, rvm_length_t length);
34 rvm_bool_t rvm_unregister_page(char *vmaddr, rvm_length_t length);
35 
36 #ifdef __CYGWIN32__
37 #include <windows.h>
38 #endif
39 
40 /* Routine to check if regions will overlap in memory. */
41 
overlap(nregions,regionDefs)42 int overlap(nregions, regionDefs)
43      unsigned long      nregions;
44      rvm_region_def_t   regionDefs[];
45 {
46     int i,j;
47     rvm_region_def_t temp;
48 
49     /* sort array */
50     for (i = 0; i < (nregions - 1); i++) {
51 	for (j = i + 1; j < nregions; j++) {
52 	    if (regionDefs[j].vmaddr < regionDefs[i].vmaddr) {
53 		temp.vmaddr = regionDefs[i].vmaddr;
54 		temp.length = regionDefs[i].length;
55 		temp.offset = regionDefs[i].offset;
56 
57 		regionDefs[i].vmaddr = regionDefs[j].vmaddr;
58 		regionDefs[i].length = regionDefs[j].length;
59 		regionDefs[i].offset = regionDefs[j].offset;
60 
61 		regionDefs[j].vmaddr = temp.vmaddr;
62 		regionDefs[j].length = temp.length;
63 		regionDefs[j].offset = temp.offset;
64 	    }
65 	}
66     }
67 
68     for (i = 0; i < (nregions - 1); i++) {
69 	if (regionDefs[i].vmaddr + regionDefs[i].length > regionDefs[i+1].vmaddr)
70 	    return(TRUE);
71     }
72 
73     return FALSE;
74 }
75 
76 
77 /* BSD44 memory allocation; uses mmap as an allocator.  Any mmap-aware
78    system should be able to use this code */
79 
80 #include <sys/types.h>
81 #include <sys/mman.h>
82 #include "coda_mmap_anon.h"
83 #include <errno.h>
84 #define ALLOCATE_VM_DEFINED
85 
86 
87 rvm_return_t
allocate_vm(addr,length)88 allocate_vm(addr, length)
89      char **addr;
90      unsigned long length;
91 {
92     rvm_return_t  ret = RVM_SUCCESS;
93     char *requested_addr = *addr; /* save this so that we can check it
94 				     against the address location
95 				     returned by mmap. this is
96 				     important because if it isn't 0,
97 				     it's a location that we HAVE to
98 				     be able to map to. */
99 
100 #ifdef HAVE_MMAP
101     mmap_anon(*addr, *addr, length, (PROT_READ | PROT_WRITE));
102 #else
103     {
104       HANDLE hMap = CreateFileMapping((HANDLE)0xFFFFFFFF, NULL,
105                                       PAGE_READWRITE, 0, length, NULL);
106       if (hMap == NULL)
107           return(RVM_EINTERNAL);
108       *addr = MapViewOfFileEx(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0, *addr);
109       if (*addr == NULL) {
110 #if 0
111 	  DWORD errnum;
112 	  errnum = GetLastError();
113 	  printf ("allocate_vm: errnum = %d\n", errnum);
114 #endif
115           *addr = (char *)-1;
116       }
117       CloseHandle(hMap);
118     }
119 #endif
120 
121     if (*addr == (char*)-1) {
122 	if (errno == ENOMEM) {
123 	    ret = RVM_ENO_MEMORY;
124 	} else {
125 	    ret = RVM_EINTERNAL;
126 	}
127     }
128 
129     if (requested_addr != 0 && *addr != requested_addr) {
130 	ret = RVM_EINTERNAL;	/* couldn't allocated requested memory. */
131     }
132 
133     /* modified by tilt, Nov 19 1996.
134        When we allocate a page (or range of pages) we register
135        it in an internal table we're keeping around to keep
136        track of pages. (The previous solution was to try to
137        re-allocate the page, and see if it fails, which is
138        not only wrong [since we don't if it's allocated, or
139        actually allocated in the RVM heap!!], but doesn't
140        work with mmap()). */
141     if (rvm_register_page(*addr, length) == rvm_false) {
142 	ret = RVM_EINTERNAL;
143     }
144 
145     return ret;
146 }
147 
148 rvm_return_t
deallocate_vm(addr,length)149 deallocate_vm(addr, length)
150      char *addr;
151      unsigned long length;
152 {
153     rvm_return_t   ret = RVM_SUCCESS;
154 
155 #ifdef HAVE_MMAP
156     if (munmap(addr, length)) {
157 	ret = RVM_EINTERNAL;
158     }
159 #else
160     UnmapViewOfFile(addr);
161 #endif
162 
163     if (rvm_unregister_page(addr, length) == rvm_false) {
164 	ret = RVM_EINTERNAL;
165     }
166 
167     return ret;
168 }
169 
170 
171