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

Revision 1146, 5.5 kB (checked in by ppalmers, 16 years ago)

reset errno when parsing arguments. fixes #107.

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     errno = 0;
115     switch (key) {
116         case 'v':
117             if (arg) {
118                 arguments->verbose = strtoll( arg, &tail, 0 );
119                 if ( errno ) {
120                     fprintf( stderr, "Could not parse 'verbose' argument\n" );
121                     return ARGP_ERR_UNKNOWN;
122                 }
123             } else {
124                 if ( errno ) {
125                     fprintf( stderr, "Could not parse 'verbose' argument\n" );
126                     return ARGP_ERR_UNKNOWN;
127                 }
128             }
129             break;
130        default:
131             return ARGP_ERR_UNKNOWN;
132     }
133     return 0;
134 }
135
136 // Our argp parser.
137 static struct argp argp = { options, parse_opt, args_doc, doc };
138
139
140 static void sighandler (int sig)
141 {
142         run = 0;
143 }
144
145 int main(int argc, char *argv[])
146 {
147
148     Watchdog *w=NULL;
149
150     struct arguments arguments;
151
152     // Default values.
153     arguments.verbose        = DEBUG_LEVEL_VERY_VERBOSE;
154
155     // Parse our arguments; every option seen by `parse_opt' will
156     // be reflected in `arguments'.
157     if ( argp_parse ( &argp, argc, argv, 0, 0, &arguments ) ) {
158         fprintf( stderr, "Could not parse command line\n" );
159         exit(1);
160     }
161
162     setDebugLevel(arguments.verbose);
163
164     run=1;
165
166     signal (SIGINT, sighandler);
167     signal (SIGPIPE, sighandler);
168
169     w=new Watchdog(1000*1000*1, true, 99); // check time is one second
170     w->setVerboseLevel(arguments.verbose);
171
172     HangTask *task1=new HangTask(1000*10, 10); // ten millisecond, 10 hangs
173     PosixThread *thread1 = new Util::PosixThread(task1, true, 10, PTHREAD_CANCEL_DEFERRED);
174     thread1->setVerboseLevel(arguments.verbose);
175
176     HangTask *task2=new HangTask(1000*1000*2, 10); // two seconds, 10 hangs
177     PosixThread *thread2 = new Util::PosixThread(task2, true, 10, PTHREAD_CANCEL_DEFERRED);
178     thread2->setVerboseLevel(arguments.verbose);
179
180     w->registerThread(thread1);
181     w->registerThread(thread2);
182
183     // start the watchdog
184     w->start();
185     Util::SystemTimeSource::SleepUsecRelative(1000*1000*1);
186
187     // start the first thread, should be harmless since it's hang time is too low
188     thread1->Start();
189     Util::SystemTimeSource::SleepUsecRelative(1000*1000*1);
190
191     // start the second thread, should be rescheduled since it hangs too long
192     thread2->Start();
193
194     // wait for a while
195     Util::SystemTimeSource::SleepUsecRelative(1000*1000*5);
196
197
198     thread1->Stop();
199     thread2->Stop();
200
201     w->unregisterThread(thread1);
202     w->unregisterThread(thread2);
203
204     delete thread1;
205     delete thread2;
206     delete task1;
207     delete task2;
208     delete w;
209
210     return EXIT_SUCCESS;
211 }
212
213
Note: See TracBrowser for help on using the browser.