root/trunk/libffado/src/libutil/SystemTimeSource.cpp

Revision 2174, 4.1 kB (checked in by jwoithe, 12 years ago)

SystemTimeSource?: defines from config.h are referenced within this module but config.h was not included either implicitly or explicitly.

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  * Copytight (C) 2012 by Jonathan Woithe
4  *
5  * This file is part of FFADO
6  * FFADO = Free Firewire (pro-)audio drivers for linux
7  *
8  * FFADO is based upon FreeBoB.
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 2 of the License, or
13  * (at your option) version 3 of the License.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24 #include "config.h"
25
26 #include "SystemTimeSource.h"
27 #include "Time.h"
28
29 // needed for clock_nanosleep
30 #ifndef _GNU_SOURCE
31     #define _GNU_SOURCE
32 #endif
33
34 #include <time.h>
35 #include <stdlib.h>
36
37 DECLARE_GLOBAL_DEBUG_MODULE;
38
39 namespace Util {
40
41 static clockid_t clock_id = CLOCK_REALTIME;
42
43 bool
44 SystemTimeSource::setSource(clockid_t id)
45 {
46     struct timespec tp;
47     // Determine at runtime whether the kernel has support for the
48     // requested clock source.
49     if (clock_gettime(id, &tp) == 0) {
50         clock_id = id;
51         return true;
52     }
53     return false;
54 }
55
56 clockid_t
57 SystemTimeSource::getSource(void)
58 {
59     return clock_id;
60 }
61
62 int
63 SystemTimeSource::clockGettime(struct timespec *tp)
64 {
65     return clock_gettime(clock_id, tp);
66 }
67
68 void
69 SystemTimeSource::SleepUsecRelative(ffado_microsecs_t usecs)
70 {
71     //usleep(usecs);
72     struct timespec ts;
73     ts.tv_sec = usecs / (1000000LL);
74     ts.tv_nsec = (usecs % (1000000LL)) * 1000LL;
75
76     // clock_nanosleep() is not implemented for CLOCK_MONOTONIC_RAW.
77     // If the clock source is CLOCK_MONOTONIC_RAW, use CLOCK_MONOTONIC
78     // as an approximation for the purposes of sleep timing.
79     clockid_t clk = (clock_id==CLOCK_MONOTONIC_RAW)?CLOCK_MONOTONIC:clock_id;
80
81     clock_nanosleep(clk, 0, &ts, NULL);
82 }
83
84 void
85 SystemTimeSource::SleepUsecAbsolute(ffado_microsecs_t wake_at_usec)
86 {
87 // If the system time is based on CLOCK_MONOTONIC_RAW we can't use
88 // TIMER_ABSTIME because wake_at_usec will be in terms of
89 // CLOCK_MONOTONIC_RAW while clock_nanosleep() can at best use only
90 // CLOCK_MONOTONIC.  There is, AFAIK, no guarantee that the two are even
91 // remotely related.  For now, resolve this problem by unconditionally
92 // disabling the use of TIMER_ABSTIME here, regardless of the setting of
93 // USE_ABSOLUTE_NANOSLEEP.  Jonathan Woithe, 25 June 2012.
94 #if USE_ABSOLUTE_NANOSLEEP && 0
95     // CLOCK_MONOTONIC_RAW isn't supported by clock_nanosleep()
96     clockid_t clk = (clock_id==CLOCK_MONOTONIC_RAW)?CLOCK_MONOTONIC:clock_id;
97     struct timespec ts;
98     ts.tv_sec = wake_at_usec / (1000000LL);
99     ts.tv_nsec = (wake_at_usec % (1000000LL)) * 1000LL;
100     debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
101                        "clock_nanosleep until %"PRId64" sec, %"PRId64" nanosec\n",
102                        (int64_t)ts.tv_sec, (int64_t)ts.tv_nsec);
103     int err = clock_nanosleep(clk, TIMER_ABSTIME, &ts, NULL);
104     if(err) {
105         // maybe signal occurred, but we're going to ignore that
106     }
107     debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
108                 "back with err=%d\n",
109                 err);
110 #else
111     // only sleep if needed
112     ffado_microsecs_t now = getCurrentTime();
113     if(wake_at_usec >= now) {
114         ffado_microsecs_t to_sleep = wake_at_usec - now;
115         SleepUsecRelative(to_sleep);
116     }
117 #endif
118 }
119
120 ffado_microsecs_t
121 SystemTimeSource::SleepUsecRandom(ffado_microsecs_t max_usec)
122 {
123     long int rnd = random();
124     long long int tmp = (rnd*max_usec);
125     tmp /= RAND_MAX;
126     ffado_microsecs_t usec = tmp;
127     SleepUsecRelative(usec);
128     return usec;
129 }
130
131 ffado_microsecs_t
132 SystemTimeSource::getCurrentTime()
133 {
134     return getCurrentTimeAsUsecs();
135 }
136
137 ffado_microsecs_t
138 SystemTimeSource::getCurrentTimeAsUsecs()
139 {
140     struct timespec ts;
141     clock_gettime(clock_id, &ts);
142     return (ffado_microsecs_t)(ts.tv_sec * 1000000LL + ts.tv_nsec / 1000LL);
143 }
144
145 } // end of namespace Util
Note: See TracBrowser for help on using the browser.