root/trunk/libffado/tests/systemtests/test-clock_nanosleep.cpp

Revision 1079, 4.0 kB (checked in by ppalmers, 13 years ago)

add nanosleep test

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 #include "debugmodule/debugmodule.h"
25
26 // needed for clock_nanosleep
27 #ifndef _GNU_SOURCE
28     #define _GNU_SOURCE
29 #endif
30
31 #include <time.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include <pthread.h>
36
37 DECLARE_GLOBAL_DEBUG_MODULE;
38
39 #define RUNTIME_USECS 5000000
40
41 #define USE_ABSOLUTE_NANOSLEEP 1
42 #define SLEEP_PERIOD_USECS 200000LL
43 #define NB_THREADS 2
44
45 uint64_t
46 getCurrentTimeAsUsecs()
47 {
48     struct timespec ts;
49     clock_gettime(CLOCK_REALTIME, &ts);
50     return (uint64_t)(ts.tv_sec * 1000000LL + ts.tv_nsec / 1000LL);
51 }
52
53 void
54 SleepUsecRelative(uint64_t usecs)
55 {
56     //usleep(usecs);
57     struct timespec ts;
58     ts.tv_sec = usecs / (1000000LL);
59     ts.tv_nsec = (usecs % (1000000LL)) * 1000LL;
60     clock_nanosleep(CLOCK_REALTIME, 0, &ts, NULL);
61 }
62
63 void
64 SleepUsecAbsolute(uint64_t wake_at_usec)
65 {
66 #if USE_ABSOLUTE_NANOSLEEP
67     struct timespec ts;
68     ts.tv_sec = wake_at_usec / (1000000LL);
69     ts.tv_nsec = (wake_at_usec % (1000000LL)) * 1000LL;
70     debugOutput(DEBUG_LEVEL_VERBOSE,
71                 "clock_nanosleep until %lld sec, %lld nanosec\n",
72                 (int64_t)ts.tv_sec, (int64_t)ts.tv_nsec);
73     int err = clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &ts, NULL);
74     debugOutput(DEBUG_LEVEL_VERBOSE,
75                 "back with err=%d\n",
76                 err);
77 #else
78     uint64_t to_sleep = wake_at_usec - getCurrentTimeAsUsecs();
79     SleepUsecRelative(to_sleep);
80 #endif
81 }
82
83 struct thread_args {
84     bool fRunning;
85     int fCancellation;
86 };
87
88 void* thread_function(void* arg)
89 {
90     struct thread_args* obj = (struct thread_args*)arg;
91     int err;
92
93     if ((err = pthread_setcanceltype(obj->fCancellation, NULL)) != 0) {
94         debugError("pthread_setcanceltype err = %s\n", strerror(err));
95     }
96
97     debugOutput( DEBUG_LEVEL_VERBOSE, "start %p\n", obj);
98     uint64_t now = getCurrentTimeAsUsecs();
99     uint64_t wake_at = now += SLEEP_PERIOD_USECS;
100     // If Init succeed start the thread loop
101     while (obj->fRunning) {
102         debugOutput( DEBUG_LEVEL_VERBOSE, "run %p\n", obj);
103        
104         SleepUsecAbsolute(wake_at);
105         wake_at += SLEEP_PERIOD_USECS;
106        
107         debugOutput( DEBUG_LEVEL_VERBOSE, "cuckoo from %p at %012llu\n", obj, getCurrentTimeAsUsecs());
108        
109         pthread_testcancel();
110     }
111
112     debugOutput( DEBUG_LEVEL_VERBOSE, "exit %p\n", obj);
113     return 0;
114 }
115
116 int
117 main() {
118     setDebugLevel(DEBUG_LEVEL_VERBOSE);
119
120     struct thread_args args[NB_THREADS];
121     pthread_t threads[NB_THREADS];
122
123     int res=0;
124
125     for (int i=0; i<NB_THREADS; i++) {
126         args[i].fRunning = true;
127         args[i].fCancellation = PTHREAD_CANCEL_DEFERRED;
128         if ((res = pthread_create(&threads[i], 0, thread_function, &args[i]))) {
129             debugError("Cannot set create thread %d %s\n", res, strerror(res));
130             return -1;
131         }
132         debugOutput( DEBUG_LEVEL_VERBOSE, "created thread: %p\n", &args[i]);
133     }
134
135
136     SleepUsecRelative(RUNTIME_USECS);
137    
138     for (int i=0; i<NB_THREADS; i++) {
139         debugOutput( DEBUG_LEVEL_VERBOSE, "Stop thread: %p\n", &args[i]);
140         void* status;
141         args[i].fRunning = false; // Request for the thread to stop
142         pthread_join(threads[i], &status);
143         debugOutput( DEBUG_LEVEL_VERBOSE, "Stopped thread: %p\n", &args[i]);
144     }
145
146 }
Note: See TracBrowser for help on using the browser.