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