summaryrefslogtreecommitdiff
path: root/source/os_specific/service_layers/osunixxf.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/os_specific/service_layers/osunixxf.c')
-rw-r--r--source/os_specific/service_layers/osunixxf.c79
1 files changed, 61 insertions, 18 deletions
diff --git a/source/os_specific/service_layers/osunixxf.c b/source/os_specific/service_layers/osunixxf.c
index 9a92c142f776f..9ae2465366ce1 100644
--- a/source/os_specific/service_layers/osunixxf.c
+++ b/source/os_specific/service_layers/osunixxf.c
@@ -626,7 +626,7 @@ AcpiOsDeleteSemaphore (
*
* PARAMETERS: Handle - Handle returned by AcpiOsCreateSemaphore
* Units - How many units to wait for
- * Timeout - How long to wait
+ * MsecTimeout - How long to wait (milliseconds)
*
* RETURN: Status
*
@@ -638,11 +638,14 @@ ACPI_STATUS
AcpiOsWaitSemaphore (
ACPI_HANDLE Handle,
UINT32 Units,
- UINT16 Timeout)
+ UINT16 MsecTimeout)
{
ACPI_STATUS Status = AE_OK;
sem_t *Sem = (sem_t *) Handle;
- struct timespec T;
+#ifndef ACPI_USE_ALTERNATE_TIMEOUT
+ struct timespec Time;
+ int RetVal;
+#endif
if (!Sem)
@@ -650,7 +653,7 @@ AcpiOsWaitSemaphore (
return (AE_BAD_PARAMETER);
}
- switch (Timeout)
+ switch (MsecTimeout)
{
/*
* No Wait:
@@ -677,37 +680,71 @@ AcpiOsWaitSemaphore (
}
break;
- /* Wait with Timeout */
+ /* Wait with MsecTimeout */
default:
- T.tv_sec = Timeout / 1000;
- T.tv_nsec = (Timeout - (T.tv_sec * 1000)) * 1000000;
-
#ifdef ACPI_USE_ALTERNATE_TIMEOUT
/*
* Alternate timeout mechanism for environments where
* sem_timedwait is not available or does not work properly.
*/
- while (Timeout)
+ while (MsecTimeout)
{
if (sem_trywait (Sem) == 0)
{
/* Got the semaphore */
return (AE_OK);
}
- usleep (1000); /* one millisecond */
- Timeout--;
+
+ if (MsecTimeout >= 10)
+ {
+ MsecTimeout -= 10;
+ usleep (10 * ACPI_USEC_PER_MSEC); /* ten milliseconds */
+ }
+ else
+ {
+ MsecTimeout--;
+ usleep (ACPI_USEC_PER_MSEC); /* one millisecond */
+ }
}
Status = (AE_TIME);
#else
+ /*
+ * The interface to sem_timedwait is an absolute time, so we need to
+ * get the current time, then add in the millisecond Timeout value.
+ */
+ if (clock_gettime (CLOCK_REALTIME, &Time) == -1)
+ {
+ perror ("clock_gettime");
+ return (AE_TIME);
+ }
+
+ Time.tv_sec += (MsecTimeout / ACPI_MSEC_PER_SEC);
+ Time.tv_nsec += ((MsecTimeout % ACPI_MSEC_PER_SEC) * ACPI_NSEC_PER_MSEC);
- if (sem_timedwait (Sem, &T))
+ /* Handle nanosecond overflow (field must be less than one second) */
+
+ if (Time.tv_nsec >= ACPI_NSEC_PER_SEC)
+ {
+ Time.tv_sec += (Time.tv_nsec / ACPI_NSEC_PER_SEC);
+ Time.tv_nsec = (Time.tv_nsec % ACPI_NSEC_PER_SEC);
+ }
+
+ while (((RetVal = sem_timedwait (Sem, &Time)) == -1) && (errno == EINTR))
+ {
+ continue;
+ }
+
+ if (RetVal != 0)
{
+ if (errno != ETIMEDOUT)
+ {
+ perror ("sem_timedwait");
+ }
Status = (AE_TIME);
}
#endif
-
break;
}
@@ -884,12 +921,15 @@ AcpiOsSleep (
UINT64 milliseconds)
{
- sleep (milliseconds / 1000); /* Sleep for whole seconds */
+ /* Sleep for whole seconds */
+
+ sleep (milliseconds / ACPI_MSEC_PER_SEC);
/*
- * Arg to usleep() must be less than 1,000,000 (1 second)
+ * Sleep for remaining microseconds.
+ * Arg to usleep() is in usecs and must be less than 1,000,000 (1 second).
*/
- usleep ((milliseconds % 1000) * 1000); /* Sleep for remaining usecs */
+ usleep ((milliseconds % ACPI_MSEC_PER_SEC) * ACPI_USEC_PER_MSEC);
}
@@ -912,11 +952,14 @@ AcpiOsGetTimer (
struct timeval time;
+ /* This timer has sufficient resolution for user-space application code */
+
gettimeofday (&time, NULL);
- /* Seconds * 10^7 = 100ns(10^-7), Microseconds(10^-6) * 10^1 = 100ns */
+ /* (Seconds * 10^7 = 100ns(10^-7)) + (Microseconds(10^-6) * 10^1 = 100ns) */
- return (((UINT64) time.tv_sec * 10000000) + ((UINT64) time.tv_usec * 10));
+ return (((UINT64) time.tv_sec * ACPI_100NSEC_PER_SEC) +
+ ((UINT64) time.tv_usec * ACPI_100NSEC_PER_USEC));
}