Imported Upstream version 3.2.2
[debian/gnuradio] / gnuradio-core / src / lib / runtime / gr_vmcircbuf.cc
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 3, 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., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 #include <gr_vmcircbuf.h>
27 #include <assert.h>
28 #include <stdexcept>
29 #include <gr_preferences.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <gr_local_sighandler.h>
33
34 // all the factories we know about
35 #include <gr_vmcircbuf_createfilemapping.h>
36 #include <gr_vmcircbuf_sysv_shm.h>
37 #include <gr_vmcircbuf_mmap_shm_open.h>
38 #include <gr_vmcircbuf_mmap_tmpfile.h>
39
40 static const char *FACTORY_PREF_KEY = "gr_vmcircbuf_default_factory";
41
42 gr_vmcircbuf::~gr_vmcircbuf ()
43 {
44 }
45
46 gr_vmcircbuf_factory::~gr_vmcircbuf_factory ()
47 {
48 }
49
50 // ----------------------------------------------------------------
51
52 static gr_vmcircbuf_factory *s_default_factory = 0;
53
54 gr_vmcircbuf_factory *
55 gr_vmcircbuf_sysconfig::get_default_factory ()
56 {
57   if (s_default_factory)
58     return s_default_factory;
59
60   bool verbose = false;
61
62   std::vector<gr_vmcircbuf_factory *> all = all_factories ();
63
64   const char *name = gr_preferences::get (FACTORY_PREF_KEY);
65
66   if (name){
67     for (unsigned int i = 0; i < all.size (); i++){
68       if (strcmp (name, all[i]->name ()) == 0){
69         s_default_factory = all[i];
70         if (verbose)
71           fprintf (stderr, "gr_vmcircbuf_sysconfig: using %s\n",
72                    s_default_factory->name ());
73         return s_default_factory;
74       }
75     }
76   }
77
78   // either we don't have a default, or the default named is not in our
79   // list of factories.  Find the first factory that works.
80
81   if (verbose)
82     fprintf (stderr, "gr_vmcircbuf_sysconfig: finding a working factory...\n");
83
84   for (unsigned int i = 0; i < all.size (); i++){
85     if (test_factory (all[i], verbose)){
86       set_default_factory (all[i]);
87       return s_default_factory;
88     }
89   }
90
91   // We're screwed!
92
93   fprintf (stderr, "gr_vmcircbuf_sysconfig: unable to find a working factory!\n");
94   throw std::runtime_error ("gr_vmcircbuf_sysconfig");
95 }
96
97 std::vector<gr_vmcircbuf_factory *>
98 gr_vmcircbuf_sysconfig::all_factories ()
99 {
100   std::vector<gr_vmcircbuf_factory *> result;
101
102   result.push_back (gr_vmcircbuf_createfilemapping_factory::singleton ());
103   result.push_back (gr_vmcircbuf_sysv_shm_factory::singleton ());
104   result.push_back (gr_vmcircbuf_mmap_shm_open_factory::singleton ());
105   result.push_back (gr_vmcircbuf_mmap_tmpfile_factory::singleton ());
106
107   return result;
108 }
109
110 void
111 gr_vmcircbuf_sysconfig::set_default_factory (gr_vmcircbuf_factory *f)
112 {
113   gr_preferences::set (FACTORY_PREF_KEY, f->name ());
114   s_default_factory = f;
115 }
116
117
118 // ------------------------------------------------------------------------
119 //                  test code for vmcircbuf factories
120 // ------------------------------------------------------------------------
121
122 static void
123 init_buffer (gr_vmcircbuf *c, int counter, int size)
124 {
125   unsigned int *p = (unsigned int *) c->pointer_to_first_copy ();
126   for (unsigned int i = 0; i < size / sizeof (int); i++)
127     p[i] = counter + i;
128 }
129
130 static bool
131 check_mapping (gr_vmcircbuf *c, int counter, int size, char *msg, bool verbose)
132 {
133   bool ok = true;
134   
135   if (verbose)
136     fprintf (stderr, "... %s", msg);
137
138   unsigned int *p1 = (unsigned int *) c->pointer_to_first_copy ();
139   unsigned int *p2 = (unsigned int *) c->pointer_to_second_copy ();
140
141   // fprintf (stderr, "p1 = %p, p2 = %p\n", p1, p2);
142
143   for (unsigned int i = 0; i < size / sizeof (int); i++){
144     if (p1[i] != counter + i){
145       ok = false;
146       if (verbose)
147         fprintf (stderr, "  p1[%d] == %u, expected %u\n", i, p1[i], counter + i);
148       break;
149     }
150     if (p2[i] != counter + i){
151       if (verbose)
152         fprintf (stderr, "  p2[%d] == %u, expected %u\n", i, p2[i], counter + i);
153       ok = false;
154       break;
155     }
156   }
157
158   if (ok && verbose){
159     fprintf (stderr, "  OK\n");
160   }
161   return ok;
162 }
163
164 static char *
165 memsize (int size)
166 {
167   static char buf[100];
168   if (size >= (1 << 20)){
169     snprintf (buf, sizeof (buf), "%dMB", size / (1 << 20));
170   }
171   else if (size >= (1 << 10)){
172     snprintf (buf, sizeof (buf), "%dKB", size / (1 << 10));
173   }
174   else {
175     snprintf (buf, sizeof (buf), "%d", size);
176   }
177   return buf;
178 }
179
180 static bool
181 test_a_bunch (gr_vmcircbuf_factory *factory, int n, int size, int *start_ptr, bool verbose)
182 {
183   bool          ok = true;
184   int           counter[n];
185   gr_vmcircbuf *c[n];
186   int           cum_size = 0;
187
188   for (int i = 0; i < n; i++){
189     counter[i] = *start_ptr;
190     *start_ptr += size;
191     if ((c[i] = factory->make (size)) == 0){
192       if (verbose)
193         fprintf (stderr,
194                  "Failed to allocate gr_vmcircbuf number %d of size %d (cum = %s)\n",
195                  i + 1, size, memsize (cum_size));
196       return false;
197     }
198     init_buffer (c[i], counter[i], size);
199     cum_size += size;
200   }
201
202   for (int i = 0; i < n; i++){
203     char msg[100];
204     snprintf (msg, sizeof (msg), "test_a_bunch_%dx%s[%d]", n, memsize (size), i);
205     ok &= check_mapping (c[i], counter[i], size, msg, verbose);
206   }
207
208   for (int i = 0; i < n; i++){
209     delete c[i];
210     c[i] = 0;
211   }
212
213   return ok;
214 }
215
216 static bool
217 standard_tests (gr_vmcircbuf_factory *f, int verbose)
218 {
219   if (verbose >= 1)
220     fprintf (stderr, "Testing %s...\n", f->name ());
221
222   bool  v = verbose >= 2;
223   int   granularity = f->granularity ();
224   int   start = 0;
225   bool  ok = true;
226
227   ok &= test_a_bunch (f,   1,   1 * granularity, &start,  v);   //   1 x   4KB =   4KB
228
229   if (ok){
230     ok &= test_a_bunch (f,  64,   4 * granularity, &start, v);  //  64 x  16KB =   1MB
231     ok &= test_a_bunch (f,   4,   4 * (1L << 20),  &start, v);  //   4 x   4MB =  16MB
232 //  ok &= test_a_bunch (f, 256, 256 * (1L << 10),  &start, v);  // 256 x 256KB =  64MB
233   }
234
235   if (verbose >= 1)
236     fprintf (stderr, "....... %s: %s", f->name (), ok ? "OK\n" : "Doesn't work\n");
237
238   return ok;
239 }
240
241 bool
242 gr_vmcircbuf_sysconfig::test_factory (gr_vmcircbuf_factory *f, int verbose)
243 {
244   // Install local signal handlers for SIGSEGV and SIGBUS.
245   // If something goes wrong, these signals may be invoked.
246   
247 #ifdef SIGSEGV
248   gr_local_sighandler sigsegv (SIGSEGV, gr_local_sighandler::throw_signal);
249 #endif
250 #ifdef SIGBUS
251   gr_local_sighandler sigbus (SIGBUS, gr_local_sighandler::throw_signal);
252 #endif
253 #ifdef SIGSYS
254   gr_local_sighandler sigsys (SIGSYS, gr_local_sighandler::throw_signal);
255 #endif
256
257   try {
258     return standard_tests (f, verbose);
259   }
260   catch (gr_signal &sig){
261     if (verbose){
262       fprintf (stderr, "....... %s: %s", f->name (), "Doesn't work\n");
263       fprintf (stderr,
264                "gr_vmcircbuf_factory::test_factory (%s): caught %s\n",
265                f->name (), sig.name().c_str());
266       return false;
267     }
268   }
269   catch (...){
270     if (verbose){
271       fprintf (stderr, "....... %s: %s", f->name (), "Doesn't work\n");
272       fprintf (stderr,
273                "gr_vmcircbuf_factory::test_factory (%s): some kind of uncaught exception\n",
274                f->name ());
275     }
276     return false;
277   }
278   return false;                 // never gets here.  shut compiler up.
279 }
280
281 bool
282 gr_vmcircbuf_sysconfig::test_all_factories (int verbose)
283 {
284   bool ok = false;
285   
286   std::vector<gr_vmcircbuf_factory *> all = all_factories ();
287
288   for (unsigned int i = 0; i < all.size (); i++)
289     ok |= test_factory (all[i], verbose);
290
291   return ok;
292 }