/[gnuradio]/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.cc
ViewVC logotype

Contents of /gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (show annotations) (download)
Sat Apr 10 18:00:56 2004 UTC (19 years, 11 months ago) by eb
Branch: MAIN
Branch point for: INITIAL_VENDOR
Initial revision

1 /* -*- c++ -*- */
2 /*
3 * Copyright 2003 Free Software Foundation, Inc.
4 *
5 * This file is part of GNU Radio
6 *
7 * GNU Radio is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * GNU Radio is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Radio; see the file COPYING. If not, write to
19 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 #include <gr_vmcircbuf_mmap_tmpfile.h>
27 #include <stdexcept>
28 #include <assert.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #ifdef HAVE_SYS_TYPES_H
32 #include <sys/types.h>
33 #endif
34 #ifdef HAVE_SYS_MMAN_H
35 #include <sys/mman.h>
36 #endif
37 #include <fcntl.h>
38 #include <errno.h>
39 #include <stdio.h>
40 #include <string.h>
41 #include <gr_pagesize.h>
42 #include <gr_tmp_path.h>
43
44
45 gr_vmcircbuf_mmap_tmpfile::gr_vmcircbuf_mmap_tmpfile (int size)
46 : gr_vmcircbuf (size)
47 {
48 #if !defined(HAVE_MMAP)
49 fprintf (stderr, "gr_vmcircbuf_mmap_tmpfile: mmap or mkstemp is not available\n");
50 throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile");
51 #else
52
53 if (size <= 0 || (size % gr_pagesize ()) != 0){
54 fprintf (stderr, "gr_vmcircbuf_mmap_tmpfile: invalid size = %d\n", size);
55 throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile");
56 }
57
58 int seg_fd = -1;
59 char seg_name[1024];
60
61 static int s_seg_counter = 0;
62
63
64 // open a temporary file that we'll map in a bit later
65
66 while (1){
67 snprintf (seg_name, sizeof (seg_name),
68 "%s/gnuradio-%d-%d-XXXXXX", gr_tmp_path (), getpid (), s_seg_counter);
69 s_seg_counter++;
70
71 seg_fd = open (seg_name, O_RDWR | O_CREAT | O_EXCL, 0600);
72 if (seg_fd == -1){
73 if (errno == EEXIST) // File already exists (shouldn't happen). Try again
74 continue;
75
76 char msg[1024];
77 snprintf (msg, sizeof (msg),
78 "gr_vmcircbuf_mmap_tmpfile: open [%s]", seg_name);
79 perror (msg);
80 throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile");
81 }
82 break;
83 }
84
85 if (unlink (seg_name) == -1){
86 perror ("gr_vmcircbuf_mmap_tmpfile: unlink");
87 throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile");
88 }
89
90 // We've got a valid file descriptor to a tmp file.
91 // Now set it's length to 2x what we really want and mmap it in.
92
93 if (ftruncate (seg_fd, (off_t) 2 * size) == -1){
94 close (seg_fd); // cleanup
95 perror ("gr_vmcircbuf_mmap_tmpfile: ftruncate (1)");
96 throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile");
97 }
98
99 void *first_copy = mmap (0, 2 * size,
100 PROT_READ | PROT_WRITE, MAP_SHARED,
101 seg_fd, (off_t) 0);
102
103 if (first_copy == MAP_FAILED){
104 close (seg_fd); // cleanup
105 perror ("gr_vmcircbuf_mmap_tmpfile: mmap (1)");
106 throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile");
107 }
108
109 // unmap the 2nd half
110 if (munmap ((char *) first_copy + size, size) == -1){
111 close (seg_fd); // cleanup
112 perror ("gr_vmcircbuf_mmap_tmpfile: munmap (1)");
113 throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile");
114 }
115
116 // map the first half into the now available hole where the
117 // second half used to be.
118
119 void *second_copy = mmap ((char *) first_copy + size, size,
120 PROT_READ | PROT_WRITE, MAP_SHARED,
121 seg_fd, (off_t) 0);
122
123 if (second_copy == MAP_FAILED){
124 close (seg_fd); // cleanup
125 perror ("gr_vmcircbuf_mmap_tmpfile: mmap (2)");
126 throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile");
127 }
128
129 // cut the tmp file down to size
130 if (ftruncate (seg_fd, (off_t) size) == -1){
131 close (seg_fd); // cleanup
132 perror ("gr_vmcircbuf_mmap_tmpfile: ftruncate (2)");
133 throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile");
134 }
135
136 close (seg_fd); // fd no longer needed. The mapping is retained.
137
138 // Now remember the important stuff
139
140 d_base = (char *) first_copy;
141 d_size = size;
142 #endif
143 }
144
145 gr_vmcircbuf_mmap_tmpfile::~gr_vmcircbuf_mmap_tmpfile ()
146 {
147 #if defined(HAVE_MMAP)
148 if (munmap (d_base, 2 * d_size) == -1){
149 perror ("gr_vmcircbuf_mmap_tmpfile: munmap (2)");
150 }
151 #endif
152 }
153
154 // ----------------------------------------------------------------
155 // The factory interface
156 // ----------------------------------------------------------------
157
158
159 gr_vmcircbuf_factory *gr_vmcircbuf_mmap_tmpfile_factory::s_the_factory = 0;
160
161 gr_vmcircbuf_factory *
162 gr_vmcircbuf_mmap_tmpfile_factory::singleton ()
163 {
164 if (s_the_factory)
165 return s_the_factory;
166
167 s_the_factory = new gr_vmcircbuf_mmap_tmpfile_factory ();
168 return s_the_factory;
169 }
170
171 int
172 gr_vmcircbuf_mmap_tmpfile_factory::granularity ()
173 {
174 return gr_pagesize ();
175 }
176
177 gr_vmcircbuf *
178 gr_vmcircbuf_mmap_tmpfile_factory::make (int size)
179 {
180 try {
181 return new gr_vmcircbuf_mmap_tmpfile (size);
182 }
183 catch (...){
184 return 0;
185 }
186 }

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26