[PATCH] acpica: fwts_acpica: optimise semaphore tracking
IvanHu
ivan.hu at canonical.com
Mon Jan 14 10:07:12 UTC 2013
On 01/05/2013 01:12 AM, Colin King wrote:
> From: Colin Ian King <colin.king at canonical.com>
>
> The original semaphore tracking kept a track of semaphores used
> by ACPICA by keeping a hash table. Remove this overhead and just
> have a static table of pre-allocated semaphores. This removes the
> need to allocate and free semaphores for Create/Destroy operation.
>
> Also make the locking around this structure more restrictive to
> ensure no race issues can occur.
>
> Signed-off-by: Colin Ian King <colin.king at canonical.com>
> ---
> src/acpica/fwts_acpica.c | 152 +++++++++++++++++++----------------------------
> 1 file changed, 61 insertions(+), 91 deletions(-)
>
> diff --git a/src/acpica/fwts_acpica.c b/src/acpica/fwts_acpica.c
> index d177401..2c489f1 100644
> --- a/src/acpica/fwts_acpica.c
> +++ b/src/acpica/fwts_acpica.c
> @@ -31,7 +31,7 @@
> #include <signal.h>
> #include <pthread.h>
>
> -static pthread_mutex_t mutex_lock_count;
> +static pthread_mutex_t mutex_lock_sem_table;
> static pthread_mutex_t mutex_thread_info;
>
> #include "fwts.h"
> @@ -52,15 +52,14 @@ static pthread_mutex_t mutex_thread_info;
> #define ACPI_MAX_INIT_TABLES (32)
> #define AEXEC_NUM_REGIONS (8)
>
> -#define MAX_SEMAPHORES (1009)
> -#define HASH_FULL (0xffffffff)
> -
> +#define MAX_SEMAPHORES (1024)
> #define MAX_THREADS (128)
>
> typedef struct {
> - sem_t *sem; /* Semaphore handle */
> + sem_t sem; /* Semaphore handle */
> int count; /* count > 0 if acquired */
> -} sem_hash;
> + bool used; /* Semaphore being used flag */
> +} sem_info;
>
> typedef void * (*PTHREAD_CALLBACK)(void *);
>
> @@ -68,9 +67,9 @@ BOOLEAN AcpiGbl_IgnoreErrors = FALSE;
> UINT8 AcpiGbl_RegionFillValue = 0;
>
> /*
> - * Hash table of semaphore handles
> + * Used to account for semaphores used by AcpiOs*Semaphore()
> */
> -static sem_hash sem_hash_table[MAX_SEMAPHORES];
> +static sem_info sem_table[MAX_SEMAPHORES];
>
> static ACPI_TABLE_DESC Tables[ACPI_MAX_INIT_TABLES];
>
> @@ -129,14 +128,12 @@ void fwts_acpica_sem_count_clear(void)
> {
> int i;
>
> - pthread_mutex_lock(&mutex_lock_count);
> + pthread_mutex_lock(&mutex_lock_sem_table);
>
> - for (i=0;i<MAX_SEMAPHORES;i++) {
> - sem_hash_table[i].sem = NULL;
> - sem_hash_table[i].count = 0;
> - }
> + for (i = 0; i < MAX_SEMAPHORES; i++)
> + sem_table[i].count = 0;
>
> - pthread_mutex_unlock(&mutex_lock_count);
> + pthread_mutex_unlock(&mutex_lock_sem_table);
> }
>
> /*
> @@ -171,13 +168,15 @@ void fwts_acpica_sem_count_get(int *acquired, int *released)
> * All threads (such as Notify() calls now complete, so
> * we can now do the semaphore accounting calculations
> */
> - for (i=0;i<MAX_SEMAPHORES;i++) {
> - if (sem_hash_table[i].sem != NULL) {
> + pthread_mutex_lock(&mutex_lock_sem_table);
> + for (i = 0; i < MAX_SEMAPHORES; i++) {
> + if (sem_table[i].used) {
> (*acquired)++;
> - if (sem_hash_table[i].count == 0)
> + if (sem_table[i].count == 0)
> (*released)++;
> }
> }
> + pthread_mutex_unlock(&mutex_lock_sem_table);
> }
>
> /*
> @@ -190,57 +189,6 @@ void fwts_acpica_simulate_sem_timeout(int timeout)
> fwts_acpica_force_sem_timeout = timeout;
> }
>
> -/*
> - * hash_sem_handle()
> - * generate a simple hash based on semaphore handle
> - */
> -static unsigned int hash_sem_handle(sem_t *sem)
> -{
> - unsigned int i = (unsigned int)((unsigned long)sem % MAX_SEMAPHORES);
> - int j;
> -
> - for (j = 0; j<MAX_SEMAPHORES; j++) {
> - if (sem_hash_table[i].sem == sem)
> - return i;
> - if (sem_hash_table[i].sem == NULL)
> - return i;
> - i = (i+1) % MAX_SEMAPHORES;
> - }
> - return HASH_FULL;
> -}
> -
> -/*
> - * hash_sem_inc_count()
> - * increment semaphore counter
> - */
> -static void hash_sem_inc_count(sem_t *sem)
> -{
> - unsigned int i = hash_sem_handle(sem);
> -
> - if (i != HASH_FULL) {
> - pthread_mutex_lock(&mutex_lock_count);
> - sem_hash_table[i].sem = sem;
> - sem_hash_table[i].count++;
> - pthread_mutex_unlock(&mutex_lock_count);
> - }
> -}
> -
> -/*
> - * hash_sem_dec_count()
> - * decrement semaphore counter
> - */
> -static void hash_sem_dec_count(sem_t *sem)
> -{
> - unsigned int i = hash_sem_handle(sem);
> -
> - if (i != HASH_FULL) {
> - pthread_mutex_lock(&mutex_lock_count);
> - sem_hash_table[i].sem = sem;
> - sem_hash_table[i].count--;
> - pthread_mutex_unlock(&mutex_lock_count);
> - }
> -}
> -
> /* ACPICA Handlers */
>
> /*
> @@ -555,23 +503,36 @@ ACPI_STATUS AcpiOsCreateSemaphore(UINT32 MaxUnits,
> UINT32 InitialUnits,
> ACPI_HANDLE *OutHandle)
> {
> - sem_t *sem;
> + sem_info *sem = NULL;
> + ACPI_STATUS ret = AE_OK;
> + int i;
>
> if (!OutHandle)
> return AE_BAD_PARAMETER;
>
> - sem = AcpiOsAllocate(sizeof(sem_t));
> + pthread_mutex_lock(&mutex_lock_sem_table);
> + for (i = 0; i < MAX_SEMAPHORES; i++) {
> + if (!sem_table[i].used) {
> + sem = &sem_table[i];
> + break;
> + }
> + }
> +
> if (!sem)
> return AE_NO_MEMORY;
>
> - if (sem_init(sem, 0, InitialUnits) == -1) {
> - AcpiOsFree(sem);
> - return AE_BAD_PARAMETER;
> - }
> + sem->used = true;
> + sem->count = 0;
>
> - *OutHandle = (ACPI_HANDLE)sem;
> + if (sem_init(&sem->sem, 0, InitialUnits) == -1) {
> + *OutHandle = NULL;
> + ret = AE_NO_MEMORY;
> + } else {
> + *OutHandle = (ACPI_HANDLE)sem;
> + }
> + pthread_mutex_unlock(&mutex_lock_sem_table);
>
> - return AE_OK;
> + return ret;
> }
>
> /*
> @@ -580,17 +541,20 @@ ACPI_STATUS AcpiOsCreateSemaphore(UINT32 MaxUnits,
> */
> ACPI_STATUS AcpiOsDeleteSemaphore(ACPI_HANDLE Handle)
> {
> - sem_t *sem = (sem_t *)Handle;
> + sem_info *sem = (sem_info *)Handle;
> + ACPI_STATUS ret = AE_OK;
>
> if (!sem)
> return AE_BAD_PARAMETER;
>
> - if (sem_destroy(sem) == -1)
> - return AE_BAD_PARAMETER;
> + pthread_mutex_lock(&mutex_lock_sem_table);
> + if (sem_destroy(&sem->sem) == -1)
> + ret = AE_BAD_PARAMETER;
> + sem->used = false;
>
> - AcpiOsFree(sem);
> + pthread_mutex_unlock(&mutex_lock_sem_table);
>
> - return AE_OK;
> + return ret;
> }
>
>
> @@ -601,7 +565,7 @@ ACPI_STATUS AcpiOsDeleteSemaphore(ACPI_HANDLE Handle)
> */
> ACPI_STATUS AcpiOsWaitSemaphore(ACPI_HANDLE handle, UINT32 Units, UINT16 Timeout)
> {
> - sem_t *sem = (sem_t *)handle;
> + sem_info *sem = (sem_info *)handle;
> struct timespec tm;
>
> if (!handle)
> @@ -612,22 +576,26 @@ ACPI_STATUS AcpiOsWaitSemaphore(ACPI_HANDLE handle, UINT32 Units, UINT16 Timeout
>
> switch (Timeout) {
> case 0:
> - if (sem_trywait(sem) < 0)
> + if (sem_trywait(&sem->sem))
> return AE_TIME;
> break;
> +
> case ACPI_WAIT_FOREVER:
> - if (sem_wait(sem))
> + if (sem_wait(&sem->sem))
> return AE_TIME;
> break;
> default:
> tm.tv_sec = Timeout / 1000;
> tm.tv_nsec = (Timeout - (tm.tv_sec * 1000)) * 1000000;
>
> - if (sem_timedwait(sem, &tm))
> + if (sem_timedwait(&sem->sem, &tm))
> return AE_TIME;
> break;
> }
> - hash_sem_inc_count(sem);
> +
> + pthread_mutex_lock(&mutex_lock_sem_table);
> + sem->count++;
> + pthread_mutex_unlock(&mutex_lock_sem_table);
>
> return AE_OK;
> }
> @@ -639,15 +607,17 @@ ACPI_STATUS AcpiOsWaitSemaphore(ACPI_HANDLE handle, UINT32 Units, UINT16 Timeout
> */
> ACPI_STATUS AcpiOsSignalSemaphore(ACPI_HANDLE handle, UINT32 Units)
> {
> - sem_t *sem = (sem_t *)handle;
> + sem_info *sem = (sem_info *)handle;
>
> if (!handle)
> return AE_BAD_PARAMETER;
>
> - if (sem_post(sem) < 0)
> + if (sem_post(&sem->sem) < 0)
> return AE_LIMIT;
>
> - hash_sem_dec_count(sem);
> + pthread_mutex_lock(&mutex_lock_sem_table);
> + sem->count--;
> + pthread_mutex_unlock(&mutex_lock_sem_table);
>
> return AE_OK;
> }
> @@ -919,7 +889,7 @@ int fwts_acpica_init(fwts_framework *fw)
> if (fwts_acpica_init_called)
> return FWTS_ERROR;
>
> - pthread_mutex_init(&mutex_lock_count, NULL);
> + pthread_mutex_init(&mutex_lock_sem_table, NULL);
> pthread_mutex_init(&mutex_thread_info, NULL);
>
> fwts_acpica_fw = fw;
> @@ -1108,7 +1078,7 @@ int fwts_acpica_deinit(void)
> return FWTS_ERROR;
>
> AcpiTerminate();
> - pthread_mutex_destroy(&mutex_lock_count);
> + pthread_mutex_destroy(&mutex_lock_sem_table);
> pthread_mutex_destroy(&mutex_thread_info);
>
> FWTS_ACPICA_FREE(fwts_acpica_XSDT);
>
Acked-by: Ivan Hu <ivan.hu at canonical.com>
More information about the fwts-devel
mailing list