ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/RdataShareMap.cpp
Revision: 2.2
Committed: Wed Oct 30 01:38:21 2024 UTC (6 months ago) by greg
Branch: MAIN
Changes since 2.1: +11 -12 lines
Log Message:
fix(rxcontrib): Fixes in file loading & process management

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: RdataShareMap.cpp,v 2.1 2024/10/29 00:36:54 greg Exp $";
3 #endif
4 /*
5 * RdataShareMap.cpp
6 *
7 * Shared data using memory-mapped file
8 *
9 * Created by Greg Ward on 10/14/2024
10 */
11
12 #include "rtio.h"
13 #include "rterror.h"
14 #include "RdataShare.h"
15 #include <unistd.h>
16 #include <sys/stat.h>
17 #include <sys/mman.h>
18
19 // Create memory-mapped file object
20 RdataShareMap::RdataShareMap(const char *name, int flags, size_t siz)
21 {
22 mmorg = NULL;
23 bufCount = 0;
24
25 if (!(flags & (RDSread|RDSwrite))) {
26 error(CONSISTENCY, "RdataShareMap() flags must include RDSread or RDSwrite");
27 return;
28 }
29 if (name && !*name) name = NULL;
30 if (!name && !siz | ((flags & (RDSextend|RDSread|RDSwrite)) !=
31 (RDSextend|RDSread|RDSwrite))) {
32 error(CONSISTENCY, "anonymous memory map must be read/write");
33 return;
34 }
35 if ((flags & (RDSextend|RDSwrite)) == RDSextend) {
36 error(CONSISTENCY, "bad RDSextend in RdataShareMap()");
37 return;
38 }
39 int oflags, mmprot;
40 switch (flags & (RDSread|RDSwrite)) {
41 case RDSread|RDSwrite:
42 mmprot = PROT_READ|PROT_WRITE;
43 oflags = O_RDWR|O_CREAT;
44 break;
45 case RDSwrite:
46 mmprot = PROT_WRITE;
47 oflags = O_RDWR|O_CREAT; // XXX system limitation
48 break;
49 case RDSread:
50 mmprot = PROT_READ;
51 oflags = O_RDONLY;
52 break;
53 }
54 int fd = -1;
55 if (name) { // opening a shared file
56 if (flags & RDSexcl) oflags |= O_EXCL;
57 else if (flags & RDSextend && !siz) oflags |= O_TRUNC;
58 fd = open(name, oflags, 0666);
59 if (fd < 0) {
60 sprintf(errmsg, "cannot open '%s'", name);
61 error(SYSTEM, errmsg);
62 return;
63 }
64 if (!(flags & RDSextend)) {
65 struct stat sbuf;
66 if (flags & RDSexcl)
67 siz = 0;
68 else if (fstat(fd, &sbuf) >= 0)
69 siz = sbuf.st_size;
70 else {
71 sprintf(errmsg, "cannot stat '%s'", chName);
72 error(SYSTEM, errmsg);
73 close(fd);
74 return;
75 }
76 } else if (siz && ftruncate(fd, siz) < 0) {
77 sprintf(errmsg, "cannot resize '%s'", name);
78 error(SYSTEM, errmsg);
79 close(fd);
80 return;
81 }
82 }
83 mmorg = (void *)mmap(NULL, siz, mmprot,
84 MAP_SHARED|(name ? MAP_FILE : MAP_ANON), fd, 0);
85 close(fd);
86 if (mmorg == MAP_FAILED) {
87 if (name)
88 sprintf(errmsg, "cannot map '%s' to memory", name);
89 else
90 sprintf(errmsg, "cannot map anonymous map of %ld KBytes",
91 long(siz/1024));
92 error(SYSTEM, errmsg);
93 mmorg = NULL;
94 return;
95 }
96 osiz = siz;
97 if (name) chName = savqstr(name);
98 mode = flags;
99 }
100
101 RdataShareMap::~RdataShareMap()
102 {
103 if (mmorg) munmap(mmorg, osiz);
104 }
105
106 // Attempt to extend or shrink object (adjust if 0)
107 size_t
108 RdataShareMap::Resize(size_t new_siz)
109 {
110 if (!mmorg)
111 return 0;
112 if (new_siz > 0) {
113 if (new_siz == osiz)
114 return osiz;
115 if (!(mode & RDSwrite)) {
116 error(CONSISTENCY, "cannot resize read-only map");
117 return 0;
118 }
119 }
120 if (bufCount > 0) {
121 error(INTERNAL, "cannot resize while memory is checked out");
122 return 0;
123 }
124 if (!chName) {
125 if (!new_siz) // XXX should issue warning?
126 return osiz;
127 if (new_siz > osiz) {
128 error(INTERNAL, "cannot grow anonymous map");
129 return 0;
130 }
131 return osiz = new_siz; // just pretend we shrank
132 }
133 if (!new_siz) { // sync to current file length?
134 struct stat sbuf;
135 if (stat(chName, &sbuf) < 0) {
136 sprintf(errmsg, "cannot stat '%s'", chName);
137 error(SYSTEM, errmsg);
138 return 0;
139 }
140 if (sbuf.st_size <= osiz)
141 return osiz = sbuf.st_size;
142
143 new_siz = sbuf.st_size;
144 }
145 if (new_siz > osiz) { // need to extend & remap
146 int fd = open(chName, mode&RDSread ? O_RDWR : O_WRONLY);
147 if (fd < 0) {
148 sprintf(errmsg, "cannot reopen '%s'", chName);
149 error(SYSTEM, errmsg);
150 return 0;
151 }
152 if (ftruncate(fd, new_siz) < 0) {
153 sprintf(errmsg, "cannot grow '%s'", chName);
154 error(SYSTEM, errmsg);
155 close(fd);
156 return 0;
157 }
158 munmap(mmorg, osiz);
159 mmorg = mmap(NULL, new_siz,
160 mode&RDSread ? PROT_READ|PROT_WRITE : PROT_WRITE,
161 MAP_SHARED|MAP_FILE, fd, 0);
162 close(fd);
163 if (mmorg == MAP_FAILED) {
164 sprintf(errmsg, "mmap() failed on '%s'", chName);
165 error(SYSTEM, errmsg);
166 mmorg = NULL;
167 return osiz = 0;
168 }
169 } else if (truncate(chName, new_siz) < 0) {
170 sprintf(errmsg, "cannot truncate '%s'", chName);
171 return 0;
172 }
173 return osiz = new_siz;
174 }
175
176 // Get data buffer
177 void *
178 RdataShareMap::GetMemory(size_t offs, size_t len, int fl)
179 {
180 if (chName && fl & RDSextend) { // resize/extend?
181 if (offs + len > osiz ? !Resize(offs + len) : !Resize())
182 return NULL;
183 }
184 if (offs + len > osiz) {
185 if (chName)
186 sprintf(errmsg, "requested block of %lu bytes outside map '%s'",
187 (unsigned long)len, chName);
188 else
189 sprintf(errmsg, "requested block of %lu bytes outside %lu byte map",
190 (unsigned long)len, (unsigned long)osiz);
191 error(CONSISTENCY, errmsg);
192 return NULL;
193 }
194 ++bufCount;
195 return (char *)mmorg + offs;
196 }
197
198 // Return data buffer
199 bool
200 RdataShareMap::ReleaseMemory(void *dp, int fl)
201 {
202 if ((dp < mmorg) | ((char *)dp >= (char *)mmorg + osiz)) {
203 if (chName)
204 sprintf(errmsg, "returned block outside map '%s'", chName);
205 else
206 sprintf(errmsg, "returned block outside %lu byte map",
207 (unsigned long)osiz);
208 error(CONSISTENCY, errmsg);
209 return false;
210 }
211 bufCount -= (bufCount > 0);
212 return true;
213 }