]> git.proxmox.com Git - mirror_edk2.git/blame - StdLib/LibC/Time/itimer.c
StdLib: Revise the meaning of several feature macros.
[mirror_edk2.git] / StdLib / LibC / Time / itimer.c
CommitLineData
d7ce7006 1/** @file \r
2 setitimer and getitimer functions.\r
3\r
4 Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\r
5 This program and the accompanying materials are licensed and made available under\r
6 the terms and conditions of the BSD License that accompanies this distribution.\r
7 The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php.\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12**/\r
13#include <LibConfig.h>\r
14#include <sys/EfiSysCall.h>\r
15#include <sys/time.h>\r
16#include <time.h>\r
17#include <errno.h>\r
18#include <sys/signal.h>\r
19#include <signal.h>\r
20#include <Library/UefiBootServicesTableLib.h>\r
21#include <Library/BaseMemoryLib.h>\r
22#include <Library/UefiLib.h>\r
23\r
24STATIC EFI_EVENT RealTimer = NULL;\r
25STATIC EFI_EVENT VirtualTimer = NULL;\r
26STATIC EFI_EVENT ProfTimer = NULL;\r
27\r
28STATIC struct itimerval RealTimerInfo = {{0,0},{0,0}};\r
29STATIC struct itimerval VirtualTimerInfo = {{0,0},{0,0}};\r
30STATIC struct itimerval ProfTimerInfo = {{0,0},{0,0}};\r
31\r
32/**\r
33 Function to queue the next iteration of the timer.\r
34\r
35 This will copy the interval part of the struct into the value and (if \r
36 non-zero), then queue the next timer event.\r
37\r
38 @param[in] TimerInfo The timer info structure. \r
39 @param[in] Event The EFI timer event.\r
40**/\r
41VOID\r
42EFIAPI\r
43SetNext (\r
44 IN struct itimerval *TimerInfo,\r
45 IN EFI_EVENT Event\r
46 )\r
47{\r
48 EFI_STATUS Status;\r
49\r
50 CopyMem(&(TimerInfo->it_value), &(TimerInfo->it_interval), sizeof(struct timeval));\r
51\r
52 //\r
53 // If now zero then close and be done.\r
54 //\r
55 if (TimerInfo->it_value.tv_sec+TimerInfo->it_value.tv_usec == 0) {\r
56 if (Event != NULL) {\r
57 gBS->CloseEvent(Event);\r
58 Event = NULL;\r
59 }\r
60 return;\r
61 }\r
62\r
63 //\r
64 // Set up for the next loop.\r
65 //\r
66 Status = gBS->SetTimer (\r
67 Event,\r
68 TimerRelative,\r
69 TimerInfo->it_value.tv_sec*10000000+TimerInfo->it_value.tv_usec*1000);\r
70\r
71 if (EFI_ERROR(Status)) {\r
72 gBS->CloseEvent(Event);\r
73 Event = NULL;\r
74 }\r
75}\r
76\r
77/**\r
78 Notification function for real timer.\r
79\r
80 @param[in] Event The event.\r
81 @param[in] Context Ignored.\r
82**/\r
83VOID\r
84EFIAPI\r
85iTimerRealNotifyFunction (\r
86 IN EFI_EVENT Event,\r
87 IN VOID *Context\r
88 )\r
89{\r
90 raise(SIGALRM);\r
91 SetNext(&RealTimerInfo, RealTimer);\r
92}\r
93\r
94/**\r
95 Notification function for virtual timer.\r
96\r
97 @param[in] Event The event.\r
98 @param[in] Context Ignored.\r
99**/\r
100VOID\r
101EFIAPI\r
102iTimerVirtualNotifyFunction (\r
103 IN EFI_EVENT Event,\r
104 IN VOID *Context\r
105 )\r
106{\r
107 raise(SIGVTALRM);\r
108 SetNext(&VirtualTimerInfo, VirtualTimer);\r
109}\r
110\r
111/**\r
112 Notification function for prof timer.\r
113\r
114 @param[in] Event The event.\r
115 @param[in] Context Ignored.\r
116**/\r
117VOID\r
118EFIAPI\r
119iTimerProfNotifyFunction (\r
120 IN EFI_EVENT Event,\r
121 IN VOID *Context\r
122 )\r
123{\r
124 raise(SIGPROF);\r
125 SetNext(&ProfTimerInfo, ProfTimer);\r
126}\r
127\r
128/**\r
129 The setitimer() function sets the timer specified by which to the value \r
130 specified in the structure pointed to by value, and if ovalue is not a null \r
131 pointer, stores the previous value of the timer in the structure pointed to\r
132 by ovalue. \r
133\r
134 A timer value is defined by the itimerval structure. If it_value is non-zero,\r
135 it indicates the time to the next timer expiration. If it_interval is \r
136 non-zero, it specifies a value to be used in reloading it_value when the \r
137 timer expires. Setting it_value to 0 disables a timer, regardless of the \r
138 value of it_interval. Setting it_interval to 0 disables a timer after its \r
139 next expiration (assuming it_value is non-zero). \r
140\r
141 ITIMER_REAL\r
142 Decrements in real time. A SIGALRM signal is delivered when this timer \r
143 expires. \r
144 \r
145 ITIMER_VIRTUAL\r
146 Decrements in process virtual time. It runs only when the process is \r
147 executing. A SIGVTALRM signal is delivered when it expires. \r
148\r
149 ITIMER_PROF\r
150 Decrements both in process virtual time and when the system is running on \r
151 behalf of the process. It is designed to be used by interpreters in \r
152 statistically profiling the execution of interpreted programs. Each time \r
153 the ITIMER_PROF timer expires, the SIGPROF signal is delivered. \r
154\r
155 @param[in] which Which timer to set. Possible values are described above.\r
156 @param[in] value The new value for this timer.\r
157 @param[out] ovalue The old value for this timer.\r
158\r
159 @retval 0 The operation was successful.\r
160 @retval -1 The operation failed. see errno for more details.\r
161**/\r
162\r
163int setitimer(\r
164 int which, \r
165 const struct itimerval *value,\r
166 struct itimerval *ovalue\r
167 )\r
168{\r
169 EFI_EVENT *EventPointer;\r
170 EFI_EVENT_NOTIFY NotifyFunction;\r
171 EFI_STATUS Status;\r
172\r
173 if (value == NULL) {\r
174 errno = EINVAL;\r
175 return (-1);\r
176 }\r
177\r
178 if (which == ITIMER_REAL) {\r
179 EventPointer = &RealTimer;\r
180 NotifyFunction = iTimerRealNotifyFunction;\r
181 if (ovalue != NULL) {\r
182 CopyMem(ovalue, &RealTimerInfo, sizeof(struct itimerval));\r
183 }\r
184 CopyMem(&RealTimerInfo, value, sizeof(struct itimerval));\r
185 } else if (which == ITIMER_VIRTUAL) {\r
186 EventPointer = &VirtualTimer;\r
187 NotifyFunction = iTimerVirtualNotifyFunction;\r
188 if (ovalue != NULL) {\r
189 CopyMem(ovalue, &VirtualTimerInfo, sizeof(struct itimerval));\r
190 }\r
191 CopyMem(&VirtualTimerInfo, value, sizeof(struct itimerval));\r
192 } else if (which == ITIMER_PROF) {\r
193 EventPointer = &ProfTimer;\r
194 NotifyFunction = iTimerProfNotifyFunction;\r
195 if (ovalue != NULL) {\r
196 CopyMem(ovalue, &ProfTimerInfo, sizeof(struct itimerval));\r
197 }\r
198 CopyMem(&ProfTimerInfo, value, sizeof(struct itimerval));\r
199 } else {\r
200 errno = EINVAL;\r
201 return (-1);\r
202 }\r
203\r
204 if (*EventPointer != NULL) {\r
205 gBS->CloseEvent(*EventPointer);\r
206 *EventPointer = NULL;\r
207 }\r
208\r
209 //\r
210 // This was a 'please cancel me' request.\r
211 //\r
212 if (value->it_value.tv_sec+value->it_value.tv_usec == 0) {\r
213 return 0;\r
214 }\r
215\r
216 Status = gBS->CreateEvent (\r
217 EVT_TIMER|EVT_NOTIFY_SIGNAL,\r
218 EfiGetCurrentTpl(),\r
219 NotifyFunction,\r
220 NULL, // no context\r
221 EventPointer);\r
222\r
223 if (EFI_ERROR(Status)) {\r
224 errno = EINVAL;\r
225 return (-1);\r
226 }\r
227\r
228 Status = gBS->SetTimer (\r
229 *EventPointer,\r
230 TimerRelative,\r
231 value->it_value.tv_sec*10000000+value->it_value.tv_usec*1000);\r
232\r
233 if (EFI_ERROR(Status)) {\r
234 gBS->CloseEvent(*EventPointer);\r
235 *EventPointer = NULL;\r
236 errno = EINVAL;\r
237 return (-1);\r
238 }\r
239\r
240 return 0;\r
241}\r
242\r
243/**\r
244 Function to get the current state of a timer.\r
245\r
246 @param[in] which The identifier of the timer to get. See setitimer for \r
247 details.\r
248 @param[in] value The pointer to populate. must be pre-allocated to size.\r
249\r
250 @return 0 The operation was successful.\r
251 @return -1 The operation failed. \r
252 This means that value or which had an invalid value.\r
253**/\r
254int getitimer(\r
255 int which, \r
256 struct itimerval *value\r
257 )\r
258{\r
259\r
260 if (value == NULL) {\r
261 errno = EINVAL;\r
262 return (-1);\r
263 }\r
264\r
265 if (which == ITIMER_REAL) {\r
266 CopyMem(value, &RealTimerInfo, sizeof(struct itimerval));\r
267 } else if (which == ITIMER_VIRTUAL) {\r
268 CopyMem(value, &VirtualTimerInfo, sizeof(struct itimerval));\r
269 } else if (which == ITIMER_PROF) {\r
270 CopyMem(value, &ProfTimerInfo, sizeof(struct itimerval));\r
271 } else {\r
272 errno = EINVAL;\r
273 return (-1);\r
274 }\r
275\r
276 return 0;\r
277}