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