1 /* |
|
2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: TimerServer |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <time.h> |
|
20 #include <sys/wait.h> |
|
21 #include <sys/types.h> |
|
22 #include <limits.h> |
|
23 #include <signal.h> |
|
24 #include <unistd.h> |
|
25 #include <string.h> |
|
26 #include <errno.h> |
|
27 |
|
28 #include "logger.h" |
|
29 |
|
30 #include "tickerprovider.h" |
|
31 |
|
32 namespace java |
|
33 { |
|
34 namespace captain |
|
35 { |
|
36 |
|
37 TickerProvider::TickerProvider(TickerProviderEventsInterface* aEvents) |
|
38 :TickerProviderInterface(aEvents), mTimerId(0), mNextTickAt(0LL) |
|
39 { |
|
40 JELOG2(EJavaCaptain); |
|
41 int rc = timer_create(CLOCK_REALTIME, NULL, &mTimerId); |
|
42 if (rc != 0) |
|
43 { |
|
44 ELOG2(EJavaCaptain, "tickerProvider timer_create failed(%d) errono=%d", rc, errno); |
|
45 mTimerId = 0; |
|
46 } |
|
47 } |
|
48 |
|
49 TickerProvider::~TickerProvider() |
|
50 { |
|
51 JELOG2(EJavaCaptain); |
|
52 if (mTimerId) |
|
53 { |
|
54 timer_delete(mTimerId); |
|
55 } |
|
56 } |
|
57 |
|
58 void TickerProvider::nextTickAt(const long long& aJavaTime) |
|
59 { |
|
60 JELOG2(EJavaCaptain); |
|
61 |
|
62 long long periodmS = (aJavaTime - getCurrentJavaTime()); |
|
63 LOG1(EJavaCaptain, EInfo, "request %d ms from now", periodmS); |
|
64 |
|
65 // Already or about to expire (within next 100ms) |
|
66 if (periodmS < 100) |
|
67 { |
|
68 cancel(); |
|
69 kill(getpid(), SIGALRM); |
|
70 mNextTickAt = 0LL; |
|
71 } |
|
72 else |
|
73 { |
|
74 long long periodS = periodmS/1000LL; |
|
75 //19 Jan 2038 is maximum timer value(equal with INT_MAX) which can be set to the |
|
76 //to the timer_settime. It is ok to set INT_MAX as value of timer in this situation. |
|
77 //Ultimate solution would be set first INT_MAX to the timer and after expiration of that timer |
|
78 //set rest of the timer value of the orig. timer. |
|
79 int periodnS = 0; |
|
80 if ((long long) INT_MAX < periodS) |
|
81 { |
|
82 periodS = INT_MAX; |
|
83 } |
|
84 else |
|
85 { |
|
86 periodnS = periodmS - (periodS * 1000); |
|
87 periodnS *= 1000L; // ms -> us |
|
88 periodnS *= 1000L; // us -> ns |
|
89 } |
|
90 |
|
91 LOG1(EJavaCaptain, EInfo, "nextTickAt (%ld seconds)", periodS); |
|
92 LOG1(EJavaCaptain, EInfo, "nextTickAt (%d nanoseconds)", periodnS); |
|
93 |
|
94 struct itimerspec value; |
|
95 memset(&value, 0, sizeof(value)); |
|
96 int rc = timer_gettime(mTimerId, &value); |
|
97 |
|
98 if (!rc) |
|
99 { |
|
100 // Start timer if it wasn't already started or was started but set too late |
|
101 if ((!value.it_value.tv_sec && !value.it_value.tv_nsec) || |
|
102 (value.it_value.tv_sec > periodS) || |
|
103 (value.it_value.tv_sec == periodS && value.it_value.tv_nsec > periodnS)) |
|
104 { |
|
105 memset(&value, 0, sizeof(value)); |
|
106 value.it_value.tv_sec = periodS; |
|
107 value.it_value.tv_nsec = periodnS; |
|
108 rc = timer_settime(mTimerId, 0, &value, NULL); |
|
109 if (rc != 0) |
|
110 { |
|
111 ELOG2(EJavaCaptain, "tickerProvider timer_settime failed(%d) errono=%d", rc, errno); |
|
112 } |
|
113 mNextTickAt = aJavaTime; |
|
114 } |
|
115 } |
|
116 else |
|
117 { |
|
118 ELOG2(EJavaCaptain, "tickerProvider timer_gettime failed(%d) errno=%d", rc, errno); |
|
119 } |
|
120 } |
|
121 } |
|
122 |
|
123 long long TickerProvider::getNextTickAt() |
|
124 { |
|
125 JELOG2(EJavaCaptain); |
|
126 |
|
127 struct itimerspec value; |
|
128 memset(&value, 0, sizeof(value)); |
|
129 int rc = timer_gettime(mTimerId, &value); |
|
130 |
|
131 if (!rc) |
|
132 { |
|
133 // Timer was not started |
|
134 if (!value.it_value.tv_sec && !value.it_value.tv_nsec) |
|
135 { |
|
136 mNextTickAt = 0LL; |
|
137 } |
|
138 } |
|
139 else |
|
140 { |
|
141 ELOG2(EJavaCaptain, "tickerProvider timer_gettime failed(%d) errno=%d", rc, errno); |
|
142 } |
|
143 |
|
144 return mNextTickAt; |
|
145 } |
|
146 |
|
147 void TickerProvider::cancel() |
|
148 { |
|
149 JELOG2(EJavaCaptain); |
|
150 |
|
151 struct itimerspec value; |
|
152 memset(&value, 0, sizeof(value)); |
|
153 int rc = timer_gettime(mTimerId, &value); |
|
154 |
|
155 if (!rc) |
|
156 { |
|
157 // Stop timer only if it was started |
|
158 if (value.it_value.tv_sec || value.it_value.tv_nsec) |
|
159 { |
|
160 memset(&value, 0, sizeof(value)); |
|
161 rc = timer_settime(mTimerId, 0, &value, NULL); |
|
162 if (rc != 0) |
|
163 { |
|
164 ELOG2(EJavaCaptain, "tickerProvider timer_settime failed(%d) errono=%d", rc, errno); |
|
165 } |
|
166 } |
|
167 } |
|
168 else |
|
169 { |
|
170 ELOG2(EJavaCaptain, "tickerProvider timer_gettime failed(%d) errno=%d", rc, errno); |
|
171 } |
|
172 } |
|
173 |
|
174 } // namespace captain |
|
175 } // namespace java |
|
176 |
|