ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/RdataShareMap.cpp
Revision: 2.4
Committed: Thu Mar 20 17:59:10 2025 UTC (6 weeks ago) by greg
Branch: MAIN
CVS Tags: HEAD
Changes since 2.3: +2 -2 lines
Log Message:
fix: Variable was being used in error message before being set

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.4 static const char RCSid[] = "$Id: RdataShareMap.cpp,v 2.3 2024/10/31 23:55:04 greg Exp $";
3 greg 2.1 #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 greg 2.2 int oflags, mmprot;
40 greg 2.1 switch (flags & (RDSread|RDSwrite)) {
41     case RDSread|RDSwrite:
42 greg 2.2 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 greg 2.1 break;
49     case RDSread:
50 greg 2.2 mmprot = PROT_READ;
51     oflags = O_RDONLY;
52 greg 2.1 break;
53     }
54     int fd = -1;
55     if (name) { // opening a shared file
56 greg 2.2 if (flags & RDSexcl) oflags |= O_EXCL;
57 greg 2.1 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 greg 2.4 sprintf(errmsg, "cannot stat '%s'", name);
72 greg 2.1 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 greg 2.3 if (siz) mmorg = (void *)mmap(NULL, siz, mmprot,
84 greg 2.1 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 (new_siz > 0) {
111     if (new_siz == osiz)
112     return osiz;
113     if (!(mode & RDSwrite)) {
114     error(CONSISTENCY, "cannot resize read-only map");
115     return 0;
116     }
117     }
118     if (bufCount > 0) {
119     error(INTERNAL, "cannot resize while memory is checked out");
120     return 0;
121     }
122     if (!chName) {
123     if (!new_siz) // XXX should issue warning?
124     return osiz;
125     if (new_siz > osiz) {
126     error(INTERNAL, "cannot grow anonymous map");
127     return 0;
128     }
129     return osiz = new_siz; // just pretend we shrank
130     }
131     if (!new_siz) { // sync to current file length?
132     struct stat sbuf;
133     if (stat(chName, &sbuf) < 0) {
134     sprintf(errmsg, "cannot stat '%s'", chName);
135     error(SYSTEM, errmsg);
136     return 0;
137     }
138     if (sbuf.st_size <= osiz)
139     return osiz = sbuf.st_size;
140    
141     new_siz = sbuf.st_size;
142     }
143     if (new_siz > osiz) { // need to extend & remap
144     int fd = open(chName, mode&RDSread ? O_RDWR : O_WRONLY);
145     if (fd < 0) {
146     sprintf(errmsg, "cannot reopen '%s'", chName);
147     error(SYSTEM, errmsg);
148     return 0;
149     }
150     if (ftruncate(fd, new_siz) < 0) {
151     sprintf(errmsg, "cannot grow '%s'", chName);
152     error(SYSTEM, errmsg);
153     close(fd);
154     return 0;
155     }
156 greg 2.3 if (mmorg) munmap(mmorg, osiz);
157 greg 2.1 mmorg = mmap(NULL, new_siz,
158     mode&RDSread ? PROT_READ|PROT_WRITE : PROT_WRITE,
159     MAP_SHARED|MAP_FILE, fd, 0);
160     close(fd);
161     if (mmorg == MAP_FAILED) {
162     sprintf(errmsg, "mmap() failed on '%s'", chName);
163     error(SYSTEM, errmsg);
164     mmorg = NULL;
165     return osiz = 0;
166     }
167     } else if (truncate(chName, new_siz) < 0) {
168     sprintf(errmsg, "cannot truncate '%s'", chName);
169     return 0;
170     }
171     return osiz = new_siz;
172     }
173    
174     // Get data buffer
175     void *
176     RdataShareMap::GetMemory(size_t offs, size_t len, int fl)
177     {
178     if (chName && fl & RDSextend) { // resize/extend?
179     if (offs + len > osiz ? !Resize(offs + len) : !Resize())
180     return NULL;
181     }
182     if (offs + len > osiz) {
183     if (chName)
184     sprintf(errmsg, "requested block of %lu bytes outside map '%s'",
185     (unsigned long)len, chName);
186     else
187     sprintf(errmsg, "requested block of %lu bytes outside %lu byte map",
188     (unsigned long)len, (unsigned long)osiz);
189     error(CONSISTENCY, errmsg);
190     return NULL;
191     }
192     ++bufCount;
193     return (char *)mmorg + offs;
194     }
195    
196     // Return data buffer
197     bool
198     RdataShareMap::ReleaseMemory(void *dp, int fl)
199     {
200     if ((dp < mmorg) | ((char *)dp >= (char *)mmorg + osiz)) {
201     if (chName)
202     sprintf(errmsg, "returned block outside map '%s'", chName);
203     else
204     sprintf(errmsg, "returned block outside %lu byte map",
205     (unsigned long)osiz);
206     error(CONSISTENCY, errmsg);
207     return false;
208     }
209     bufCount -= (bufCount > 0);
210     return true;
211     }