root/branches/libffado-2.0/tests/systemtests/test-sysload.cpp

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

reset errno when parsing arguments. fixes #107.

Line 
1 /*
2  * Parts 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 /*
25  * based on howdyget.c (unknown source, maybe Maas Digital LLC)
26  */
27
28 #include <stdio.h>
29 #include <errno.h>
30 #include <unistd.h>
31 #include <signal.h>
32
33 #include <argp.h>
34
35 #include <inttypes.h>
36
37 #include "debugmodule/debugmodule.h"
38 #include "realtimetools.h"
39
40 uint32_t count = 0;
41
42 DECLARE_GLOBAL_DEBUG_MODULE;
43
44 #define MAX_EXTRA_ARGS 2
45 // Program documentation.
46 // Program documentation.
47 static char doc[] = "FFADO -- simple RT system loader\n\n";
48
49 // A description of the arguments we accept.
50 static char args_doc[] = "";
51
52 struct arguments
53 {
54     long int verbose;
55     long int rtprio;
56     long int period;
57     long int countdown;
58     long int cpu_pct;
59     char* args[MAX_EXTRA_ARGS];
60 };
61
62 // The options we understand.
63 static struct argp_option options[] = {
64     {"verbose",  'v', "level",    0,  "Verbose level" },
65     {"rtprio",  'P', "prio",  0,  "real time priority of the iterator process/thread (0 = no RT)" },
66     {"period",  'p', "usecs",  0,  "period duration (in usecs)" },
67     {"countdown",  'u', "count",  0,  "number of times to run the load loop" },
68     {"cpu_pct",  'c', "count",  0,  "target CPU use (in percent)" },
69     { 0 }
70 };
71
72 // Parse a single option.
73 #define PARSE_ARG_LONG(XXletterXX, XXvarXX, XXdescXX) \
74     case XXletterXX: \
75         if (arg) { \
76             XXvarXX = strtol( arg, &tail, 0 ); \
77             if ( errno ) { \
78                 fprintf( stderr,  "Could not parse '%s' argument\n", XXdescXX ); \
79                 return ARGP_ERR_UNKNOWN; \
80             } \
81         } \
82         break;
83
84 static error_t
85 parse_opt( int key, char* arg, struct argp_state* state )
86 {
87     // Get the input argument from `argp_parse', which we
88     // know is a pointer to our arguments structure.
89     struct arguments* arguments = ( struct arguments* ) state->input;
90     char* tail;
91
92     errno = 0;
93     switch (key) {
94     PARSE_ARG_LONG('v', arguments->verbose, "verbose");
95     PARSE_ARG_LONG('P', arguments->rtprio, "rtprio");
96     PARSE_ARG_LONG('p', arguments->period, "period");
97     PARSE_ARG_LONG('u', arguments->countdown, "countdown");
98     PARSE_ARG_LONG('c', arguments->cpu_pct, "cpu_pct");
99
100     case ARGP_KEY_ARG:
101         break;
102     case ARGP_KEY_END:
103         break;
104     default:
105         return ARGP_ERR_UNKNOWN;
106     }
107     return 0;
108 }
109
110 // Our argp parser.
111 static struct argp argp = { options, parse_opt, args_doc, doc };
112
113 // the global arguments struct
114 struct arguments arguments;
115
116 // signal handler
117 int run;
118 static void sighandler (int sig)
119 {
120     run = 0;
121 }
122
123 // the load function
124 float global;
125 void load_function() {
126     int cnt = 10;
127     while(cnt--) {
128         int global_int = (int)global;
129         global = global / 7.0;
130         global_int++;
131         global += (float)global_int;
132     }
133 }
134
135 int main(int argc, char **argv)
136 {
137     // register signal handler
138     run = 1;
139     signal (SIGINT, sighandler);
140     signal (SIGPIPE, sighandler);
141
142     // Default values.
143     arguments.verbose = DEBUG_LEVEL_VERBOSE;
144     arguments.rtprio = 0;
145     arguments.countdown = 1000;
146     arguments.period = 1000;
147     arguments.cpu_pct = 50;
148
149     // Parse our arguments; every option seen by `parse_opt' will
150     // be reflected in `arguments'.
151     if ( argp_parse ( &argp, argc, argv, 0, 0, &arguments ) ) {
152         debugError("Could not parse command line\n" );
153         return -1;
154     }
155
156     debugOutput(DEBUG_LEVEL_INFO, "Simple RT system loader\n");
157     debugOutput(DEBUG_LEVEL_INFO, " Arguments:\n");
158     debugOutput(DEBUG_LEVEL_INFO, "  RT priority : %d\n", arguments.rtprio);
159     debugOutput(DEBUG_LEVEL_INFO, "  Countdown   : %d\n", arguments.countdown);
160     debugOutput(DEBUG_LEVEL_INFO, "  Period      : %d usec\n", arguments.period);
161     debugOutput(DEBUG_LEVEL_INFO, "  CPU load    : %d%%\n", arguments.cpu_pct);
162
163     debugOutput(DEBUG_LEVEL_INFO, "Setting RT priority (%d)...\n", arguments.rtprio);
164     set_realtime_priority(arguments.rtprio);
165
166     debugOutput(DEBUG_LEVEL_INFO, "Starting iterate loop...\n");
167     flushDebugOutput();
168    
169     int countdown = arguments.countdown;
170     uint64_t sleep_time = rt_gettime_usecs();
171     while(countdown-- && run)
172     {
173         // figure out when to stop calling the load function
174         uint64_t run_until = sleep_time + arguments.period * arguments.cpu_pct / 100;
175        
176 //         uint64_t tic = rt_gettime_usecs();
177         while(rt_gettime_usecs() < run_until) load_function();
178         uint64_t toc = rt_gettime_usecs();
179
180         // now wait for the period to end
181         sleep_time += arguments.period;
182         rt_sleep_absolute_usecs(sleep_time);
183        
184         // check if we are late
185         toc = rt_gettime_usecs();
186         int64_t usecs_late = toc - sleep_time;
187         if(usecs_late > 1000) {
188             debugWarning("late wakeup: %lld usecs\n", usecs_late);
189         }
190
191         // try and detect lockup ()
192         if(usecs_late > 100000) {
193             debugWarning("very late wakeup: %lld usecs\n", usecs_late);
194             // force exit, since this is a loop out of control
195             run=0;
196         }
197     }
198
199     if(run) {
200         debugOutput(DEBUG_LEVEL_INFO, "Clean exit...\n");
201     } else {
202         debugOutput(DEBUG_LEVEL_INFO, "Forced exit...\n");
203     }
204     return 0;
205 }
Note: See TracBrowser for help on using the browser.