From patchwork Thu Jul 19 08:44:18 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Colin Ian King X-Patchwork-Id: 171908 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from chlorine.canonical.com (chlorine.canonical.com [91.189.94.204]) by ozlabs.org (Postfix) with ESMTP id 6EC022C0120 for ; Thu, 19 Jul 2012 18:44:25 +1000 (EST) Received: from localhost ([127.0.0.1] helo=chlorine.canonical.com) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1SrmLQ-00028a-A9 for incoming@patchwork.ozlabs.org; Thu, 19 Jul 2012 08:44:24 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1SrmLN-00028Q-Vn for fwts-devel@lists.ubuntu.com; Thu, 19 Jul 2012 08:44:22 +0000 Received: from [12.232.236.2] (helo=localhost) by youngberry.canonical.com with esmtpsa (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1SrmLN-00059c-BL for fwts-devel@lists.ubuntu.com; Thu, 19 Jul 2012 08:44:21 +0000 From: Colin King To: fwts-devel@lists.ubuntu.com Subject: [PATCH] lib: acpica: fix semaphore counting by waiting for threads to complete Date: Thu, 19 Jul 2012 01:44:18 -0700 Message-Id: <1342687458-11966-1-git-send-email-colin.king@canonical.com> X-Mailer: git-send-email 1.7.10.4 X-BeenThere: fwts-devel@lists.ubuntu.com X-Mailman-Version: 2.1.13 Precedence: list List-Id: Firmware Test Suite Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: fwts-devel-bounces@lists.ubuntu.com Errors-To: fwts-devel-bounces@lists.ubuntu.com From: Colin Ian King When executing Notify() handlers ACPICA creates separate threads which we need to wait to complete before we do any semaphore usage accounting. This is because these threads can themselves use internal or AML semaphores which will be in an unknown state if we do the start doing semaphore usage accounted before we wait for them to terminate. This patch adds in an array to keep track of threads created by AcpiOsExecute and also a pthread join on these running threads before we start counting any used semaphores. Note that we have to deprecate the ACPICA verison of AcpiOsExecute and re-implement this in fwts to allow us to do the thread creation tracking. Signed-off-by: Colin Ian King Acked-by: Ivan Hu Acked-by: Keng-Yu Lin --- src/acpica/Makefile.am | 3 +- src/acpica/fwts_acpica.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 1 deletion(-) diff --git a/src/acpica/Makefile.am b/src/acpica/Makefile.am index e2213d5..6b3bfa5 100644 --- a/src/acpica/Makefile.am +++ b/src/acpica/Makefile.am @@ -24,7 +24,8 @@ osunixxf_munged.c: $(ACPICA_OSL)/osunixxf.c sed 's/^AcpiOsDeleteSemaphore/__AcpiOsDeleteSemaphore/' | \ sed 's/^AcpiOsVprintf/__AcpiOsVprintf/' | \ sed 's/^AcpiOsSignal/__AcpiOsSignal/' | \ - sed 's/^AcpiOsSleep/__AcpiOsSleep/' \ + sed 's/^AcpiOsSleep/__AcpiOsSleep/' | \ + sed 's/^AcpiOsExecute/__AcpiOsExecute/' \ > osunixxf_munged.c # diff --git a/src/acpica/fwts_acpica.c b/src/acpica/fwts_acpica.c index cf9a4fe..08b012d 100644 --- a/src/acpica/fwts_acpica.c +++ b/src/acpica/fwts_acpica.c @@ -32,6 +32,7 @@ #include static pthread_mutex_t mutex_lock_count; +static pthread_mutex_t mutex_thread_info; #include "fwts.h" @@ -54,11 +55,15 @@ static pthread_mutex_t mutex_lock_count; #define MAX_SEMAPHORES (1009) #define HASH_FULL (0xffffffff) +#define MAX_THREADS (128) + typedef struct { sem_t *sem; /* Semaphore handle */ int count; /* count > 0 if acquired */ } sem_hash; +typedef void * (*PTHREAD_CALLBACK)(void *); + BOOLEAN AcpiGbl_IgnoreErrors = FALSE; UINT8 AcpiGbl_RegionFillValue = 0; @@ -70,6 +75,16 @@ static sem_hash sem_hash_table[MAX_SEMAPHORES]; static ACPI_TABLE_DESC Tables[ACPI_MAX_INIT_TABLES]; /* + * Used to account for threads used by AcpiOsExecute + */ +typedef struct { + bool used; /* true if the thread accounting info in use by a thread */ + pthread_t thread; /* thread info */ +} fwts_thread; + +static fwts_thread threads[MAX_THREADS]; + +/* * Static copies of ACPI tables used by ACPICA execution engine */ static ACPI_TABLE_XSDT *fwts_acpica_XSDT; @@ -133,6 +148,27 @@ void fwts_acpica_sem_count_get(int *acquired, int *released) *acquired = 0; *released = 0; + /* Wait for any pending threads to complete */ + + for (i = 0; i < MAX_THREADS; i++) { + pthread_mutex_lock(&mutex_thread_info); + if (threads[i].used) { + pthread_mutex_unlock(&mutex_thread_info); + + /* Wait for thread to complete */ + pthread_join(threads[i].thread, NULL); + + pthread_mutex_lock(&mutex_thread_info); + threads[i].used = false; + pthread_mutex_unlock(&mutex_thread_info); + } + pthread_mutex_unlock(&mutex_thread_info); + } + + /* + * All threads (such as Notify() calls now complete, so + * we can now do the semaphore accounting calculations + */ for (i=0;ifunc(ctx->context); + + pthread_mutex_lock(&mutex_thread_info); + threads[ctx->thread_index].used = false; + pthread_mutex_unlock(&mutex_thread_info); + + free(ctx); + + return ret; +} + +ACPI_STATUS AcpiOsExecute( + ACPI_EXECUTE_TYPE type, + ACPI_OSD_EXEC_CALLBACK function, + void *func_context) +{ + int ret; + int i; + + pthread_mutex_lock(&mutex_thread_info); + + /* Find a free slot to do per-thread join tracking */ + for (i = 0; i < MAX_THREADS; i++) { + if (!threads[i].used) { + fwts_func_wrapper_context *ctx; + + /* We need some context to pass through to the thread wrapper */ + if ((ctx = malloc(sizeof(fwts_func_wrapper_context))) == NULL) { + pthread_mutex_unlock(&mutex_thread_info); + return AE_NO_MEMORY; + } + + ctx->func = (PTHREAD_CALLBACK)function; + ctx->context = func_context; + ctx->thread_index = i; + threads[i].used = true; + + ret = pthread_create(&threads[i].thread, NULL, + (PTHREAD_CALLBACK)fwts_pthread_func_wrapper, ctx); + pthread_mutex_unlock(&mutex_thread_info); + + if (ret) + return AE_ERROR; + + return AE_OK; + } + } + + /* No free slots, failed! */ + pthread_mutex_unlock(&mutex_thread_info); + return AE_NO_MEMORY; +} + /* * AcpiOsReadPciConfiguration() * Override ACPICA AcpiOsReadPciConfiguration to fake PCI reads @@ -802,6 +906,7 @@ int fwts_acpica_init(fwts_framework *fw) return FWTS_ERROR; pthread_mutex_init(&mutex_lock_count, NULL); + pthread_mutex_init(&mutex_thread_info, NULL); fwts_acpica_fw = fw; @@ -990,6 +1095,7 @@ int fwts_acpica_deinit(void) AcpiTerminate(); pthread_mutex_destroy(&mutex_lock_count); + pthread_mutex_destroy(&mutex_thread_info); FWTS_ACPICA_FREE(fwts_acpica_XSDT); FWTS_ACPICA_FREE(fwts_acpica_RSDT);