root/trunk/libffado/tests/test-watchdog.cpp

Revision 1027, 5.5 kB (checked in by ppalmers, 14 years ago)

simplify system time source class. should give a performance increase due to less function calls.

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB.
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 2 of the License, or
12  * (at your option) version 3 of the License.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <argp.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <endian.h>
33
34 #include <signal.h>
35 #include "src/debugmodule/debugmodule.h"
36
37 #include "libutil/PosixThread.h"
38 #include "libutil/Watchdog.h"
39 #include "libutil/SystemTimeSource.h"
40
41 #include <pthread.h>
42
43 using namespace Util;
44
45 DECLARE_GLOBAL_DEBUG_MODULE;
46
47 class HangTask : public Util::RunnableInterface
48 {
49 public:
50     HangTask(unsigned int time_usecs, unsigned int nb_hangs)
51         : m_time( time_usecs )
52         , m_nb_hangs(nb_hangs) {};
53     virtual ~HangTask() {};
54
55     bool Init() {return true;};
56     bool Execute() {
57         debugOutput(DEBUG_LEVEL_VERBOSE, "execute\n");
58         ffado_microsecs_t start = Util::SystemTimeSource::getCurrentTimeAsUsecs();
59         ffado_microsecs_t stop_at = start + m_time;
60         int cnt;
61         int dummyvar = 0;
62         while(Util::SystemTimeSource::getCurrentTimeAsUsecs() < stop_at) {
63             cnt=1000;
64             while(cnt--) { dummyvar++; }
65         }
66
67         // ensure that dummyvar doesn't get optimized away
68         bool always_true = (dummyvar + Util::SystemTimeSource::getCurrentTimeAsUsecs() != 0);
69
70         bool stop = (m_nb_hangs == 0);
71         m_nb_hangs--;
72
73         // we sleep for 100ms after a 'hang'
74         Util::SystemTimeSource::SleepUsecRelative(1000*100);
75
76         // we want the thread to exit after m_nb_hangs 'hangs'
77         return always_true && !stop;
78     };
79     unsigned int m_time;
80     unsigned int m_nb_hangs;
81
82 };
83
84 int run;
85 // Program documentation.
86 static char doc[] = "FFADO -- Watchdog test\n\n";
87
88 // A description of the arguments we accept.
89 static char args_doc[] = "";
90
91
92 struct arguments
93 {
94     short verbose;
95 };
96
97 // The options we understand.
98 static struct argp_option options[] = {
99     {"verbose",     'v',    "n",    0,  "Verbose level" },
100     { 0 }
101 };
102
103 //-------------------------------------------------------------
104
105 // Parse a single option.
106 static error_t
107 parse_opt( int key, char* arg, struct argp_state* state )
108 {
109     // Get the input argument from `argp_parse', which we
110     // know is a pointer to our arguments structure.
111     struct arguments* arguments = ( struct arguments* ) state->input;
112     char* tail;
113
114     switch (key) {
115         case 'v':
116             if (arg) {
117                 arguments->verbose = strtoll( arg, &tail, 0 );
118                 if ( errno ) {
119                     fprintf( stderr, "Could not parse 'verbose' argument\n" );
120                     return ARGP_ERR_UNKNOWN;
121                 }
122             } else {
123                 if ( errno ) {
124                     fprintf( stderr, "Could not parse 'verbose' argument\n" );
125                     return ARGP_ERR_UNKNOWN;
126                 }
127             }
128             break;
129        default:
130             return ARGP_ERR_UNKNOWN;
131     }
132     return 0;
133 }
134
135 // Our argp parser.
136 static struct argp argp = { options, parse_opt, args_doc, doc };
137
138
139 static void sighandler (int sig)
140 {
141         run = 0;
142 }
143
144 int main(int argc, char *argv[])
145 {
146
147     Watchdog *w=NULL;
148
149     struct arguments arguments;
150
151     // Default values.
152     arguments.verbose        = DEBUG_LEVEL_VERY_VERBOSE;
153
154     // Parse our arguments; every option seen by `parse_opt' will
155     // be reflected in `arguments'.
156     if ( argp_parse ( &argp, argc, argv, 0, 0, &arguments ) ) {
157         fprintf( stderr, "Could not parse command line\n" );
158         exit(1);
159     }
160
161     setDebugLevel(arguments.verbose);
162
163     run=1;
164
165     signal (SIGINT, sighandler);
166     signal (SIGPIPE, sighandler);
167
168     w=new Watchdog(1000*1000*1, true, 99); // check time is one second
169     w->setVerboseLevel(arguments.verbose);
170
171     HangTask *task1=new HangTask(1000*10, 10); // ten millisecond, 10 hangs
172     PosixThread *thread1 = new Util::PosixThread(task1, true, 10, PTHREAD_CANCEL_DEFERRED);
173     thread1->setVerboseLevel(arguments.verbose);
174
175     HangTask *task2=new HangTask(1000*1000*2, 10); // two seconds, 10 hangs
176     PosixThread *thread2 = new Util::PosixThread(task2, true, 10, PTHREAD_CANCEL_DEFERRED);
177     thread2->setVerboseLevel(arguments.verbose);
178
179     w->registerThread(thread1);
180     w->registerThread(thread2);
181
182     // start the watchdog
183     w->start();
184     Util::SystemTimeSource::SleepUsecRelative(1000*1000*1);
185
186     // start the first thread, should be harmless since it's hang time is too low
187     thread1->Start();
188     Util::SystemTimeSource::SleepUsecRelative(1000*1000*1);
189
190     // start the second thread, should be rescheduled since it hangs too long
191     thread2->Start();
192
193     // wait for a while
194     Util::SystemTimeSource::SleepUsecRelative(1000*1000*5);
195
196
197     thread1->Stop();
198     thread2->Stop();
199
200     w->unregisterThread(thread1);
201     w->unregisterThread(thread2);
202
203     delete thread1;
204     delete thread2;
205     delete task1;
206     delete task2;
207     delete w;
208
209     return EXIT_SUCCESS;
210 }
211
212
Note: See TracBrowser for help on using the browser.