00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifdef linux
00022
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <unistd.h>
00026 #include <errno.h>
00027 #include <string>
00028
00029 #include <string.h>
00030 #include <errno.h>
00031
00032 #ifdef linux
00033
00034 #include <linux/rtc.h>
00035 #include <sys/ioctl.h>
00036 #include <sys/time.h>
00037 #include <sys/select.h>
00038 #include <fcntl.h>
00039 #include <sys/stat.h>
00040 #include <sys/types.h>
00041 #endif
00042
00043 #include <inttypes.h>
00044
00045 #include <rtclock.h>
00046
00047 #include <jutils.h>
00048
00049
00050 typedef void* (kickoff)(void*);
00051
00052
00053 RTClock::RTClock() {
00054 rtcfd = 0;
00055 quit = false;
00056 msec = 0;
00057 _thread = 0x0;
00058 sleeping = false;
00059 }
00060
00061
00062 RTClock::~RTClock() {
00063
00064 if(_thread) {
00065 quit = true;
00066 pthread_join(_thread, NULL);
00067 }
00068
00069
00070 if(rtcfd>0) {
00071 ioctl(rtcfd, RTC_UIE_OFF, 0);
00072
00073 ::close(rtcfd);
00074 }
00075
00076
00077 if(pthread_mutex_destroy(&_mutex) == -1)
00078 error("error destroying POSIX thread mutex");
00079 if(pthread_cond_destroy(&_cond) == -1)
00080 error("error destroying POSIX thread condition");
00081 if(pthread_attr_destroy(&_attr) == -1)
00082 error("error destroying POSIX thread attribute");
00083
00084 }
00085
00086 int RTClock::init() {
00087 int res;
00088
00089
00090 rtcfd = ::open("/dev/rtc",O_RDONLY);
00091 if(rtcfd<0) {
00092 warning("couldn't open real time clock device: %s", strerror(errno));
00093 warning("reverting to POSIX.1 time handling");
00094 return 0;
00095 }
00096
00097 res = ioctl(rtcfd, RTC_UIE_ON, 0);
00098 if(res<0) {
00099 error("couldn't set real time clock device tick: %s", strerror(errno));
00100 return 0;
00101 }
00102
00103
00104 if(pthread_attr_init (&_attr) == -1)
00105 error("error initializing POSIX thread attribute");
00106 if(pthread_mutex_init (&_mutex,NULL) == -1)
00107 error("error initializing POSIX thread mutex");
00108 if(pthread_cond_init (&_cond, NULL) == -1)
00109 error("error initializing POSIX thread condtition");
00110
00111
00112
00113
00114 pthread_attr_setdetachstate(&_attr,PTHREAD_CREATE_JOINABLE);
00115
00116
00117 notice("real time clock succesfully initialized");
00118
00119 return 1;
00120 }
00121
00122 int RTClock::set_freq(unsigned long freq) {
00123 int res;
00124
00125 if(rtcfd<0) {
00126 error("can't set clock frequency: real time clock device is not open");
00127 return -1;
00128 }
00129
00130 res = ioctl(rtcfd,RTC_IRQP_SET,freq);
00131
00132 if(res<0)
00133 error("RTC_IRQP_SET failed: %s", strerror(errno));
00134
00135 else {
00136
00137 res = ioctl(rtcfd,RTC_IRQP_READ,&freq);
00138
00139 if(res<0)
00140 error("RTC_IRQP_READ failed: %s", strerror(errno));
00141
00142 else {
00143
00144 res = ioctl(rtcfd,RTC_PIE_ON,0);
00145 if(res<0)
00146 error("RTC_PIE_ON failed: %s", strerror(errno));
00147 else
00148 act("realtime clock frequency set to %lu",freq);
00149 }
00150 }
00151
00152
00153 quit = false;
00154 msec = 0;
00155
00156 return res;
00157 }
00158
00159 int RTClock::tick() {
00160 int res;
00161
00162
00163 res = read(rtcfd, &rtctime, sizeof(unsigned long));
00164 if(res < 0)
00165 error("problem catching real time clock interrupt: %s", strerror(errno));
00166
00167
00168 msec++;
00169
00170 return res;
00171 }
00172
00173 void RTClock::run() {
00174
00175
00176 while(!quit) {
00177
00178 if(sleeping) wait();
00179
00180 tick();
00181
00182 }
00183
00184 }
00185
00186
00187
00188 int RTClock::start() {
00189 int res;
00190
00191 if(rtcfd<0) {
00192 error("can't start clock: real time clock device is not open");
00193 return -1;
00194 }
00195
00196 if(_thread) {
00197 quit = true;
00198 pthread_join(_thread, NULL);
00199 }
00200
00201
00202 quit = false;
00203 msec = 0;
00204
00205 res = pthread_create(&_thread, &_attr, &kickoff, this);
00206 if(res != 0) {
00207 error("can't create thread: %s",strerror(errno));
00208 return 0;
00209 }
00210 return 1;
00211 }
00212
00213 int RTClock::sleep(uint64_t msec) {
00214 register uint64_t elap_msec;
00215
00216 if(rtcfd<0) {
00217 error("tbt::clock::sleep - real time clock device is not open");
00218 return -1;
00219 }
00220
00221
00222 sleeping = true;
00223
00224
00225 for(elap_msec = msec; elap_msec >0; elap_msec--)
00226 tick();
00227
00228 sleeping = false;
00229 signal();
00230
00231 return 1;
00232 }
00233
00234 #endif