Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 46341
b: refs/heads/master
c: c81da66
h: refs/heads/master
i:
  46339: 43f69f8
v: v3
  • Loading branch information
Bob Moore authored and Len Brown committed Feb 3, 2007
1 parent 59d9a4c commit 2095334
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 199 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8f9337c88335846b01801b1047a4caf10527a320
refs/heads/master: c81da66608d65dab04730582dfdfcdcab779e2fe
113 changes: 59 additions & 54 deletions trunk/drivers/acpi/events/evmisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,19 +298,13 @@ static void ACPI_SYSTEM_XFACE acpi_ev_global_lock_thread(void *context)
{
acpi_status status;

/* Signal threads that are waiting for the lock */
/* Signal the thread that is waiting for the lock */

if (acpi_gbl_global_lock_thread_count) {
/* Send a unit to the semaphore */

/* Send sufficient units to the semaphore */

status =
acpi_os_signal_semaphore(acpi_gbl_global_lock_semaphore,
acpi_gbl_global_lock_thread_count);
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO,
"Could not signal Global Lock semaphore"));
}
status = acpi_os_signal_semaphore(acpi_gbl_global_lock_semaphore, 1);
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO, "Could not signal Global Lock semaphore"));
}
}

Expand All @@ -333,14 +327,16 @@ static u32 acpi_ev_global_lock_handler(void *context)
u8 acquired = FALSE;

/*
* Attempt to get the lock
* Attempt to get the lock.
*
* If we don't get it now, it will be marked pending and we will
* take another interrupt when it becomes free.
*/
ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, acquired);
if (acquired) {

/* Got the lock, now wake all threads waiting for it */

acpi_gbl_global_lock_acquired = TRUE;
acpi_ev_global_lock_thread(context);
}
Expand Down Expand Up @@ -399,6 +395,16 @@ acpi_status acpi_ev_init_global_lock_handler(void)
*
* DESCRIPTION: Attempt to gain ownership of the Global Lock.
*
* MUTEX: Interpreter must be locked
*
* Note: The original implementation allowed multiple threads to "acquire" the
* Global Lock, and the OS would hold the lock until the last thread had
* released it. However, this could potentially starve the BIOS out of the
* lock, especially in the case where there is a tight handshake between the
* Embedded Controller driver and the BIOS. Therefore, this implementation
* allows only one thread to acquire the HW Global Lock at a time, and makes
* the global lock appear as a standard mutex on the OS side.
*
*****************************************************************************/

acpi_status acpi_ev_acquire_global_lock(u16 timeout)
Expand All @@ -408,53 +414,50 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)

ACPI_FUNCTION_TRACE(ev_acquire_global_lock);

#ifndef ACPI_APPLICATION
/* Make sure that we actually have a global lock */

if (!acpi_gbl_global_lock_present) {
return_ACPI_STATUS(AE_NO_GLOBAL_LOCK);
/*
* Only one thread can acquire the GL at a time, the global_lock_mutex
* enforces this. This interface releases the interpreter if we must wait.
*/
status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, timeout);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
#endif

/* One more thread wants the global lock */

acpi_gbl_global_lock_thread_count++;

/*
* If we (OS side vs. BIOS side) have the hardware lock already,
* we are done
* Make sure that a global lock actually exists. If not, just treat
* the lock as a standard mutex.
*/
if (acpi_gbl_global_lock_acquired) {
if (!acpi_gbl_global_lock_present) {
acpi_gbl_global_lock_acquired = TRUE;
return_ACPI_STATUS(AE_OK);
}

/* We must acquire the actual hardware lock */
/* Attempt to acquire the actual hardware lock */

ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, acquired);
if (acquired) {

/* We got the lock */

ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Acquired the HW Global Lock\n"));
"Acquired hardware Global Lock\n"));

acpi_gbl_global_lock_acquired = TRUE;
return_ACPI_STATUS(AE_OK);
}

/*
* Did not get the lock. The pending bit was set above, and we must now
* Did not get the lock. The pending bit was set above, and we must now
* wait until we get the global lock released interrupt.
*/
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Waiting for the HW Global Lock\n"));
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Waiting for hardware Global Lock\n"));

/*
* Acquire the global lock semaphore first.
* Since this wait will block, we must release the interpreter
* Wait for handshake with the global lock interrupt handler.
* This interface releases the interpreter if we must wait.
*/
status =
acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore,
timeout);
status = acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore,
ACPI_WAIT_FOREVER);
return_ACPI_STATUS(status);
}

Expand All @@ -477,38 +480,40 @@ acpi_status acpi_ev_release_global_lock(void)

ACPI_FUNCTION_TRACE(ev_release_global_lock);

if (!acpi_gbl_global_lock_thread_count) {
/* Lock must be acquired */

if (!acpi_gbl_global_lock_acquired) {
ACPI_WARNING((AE_INFO,
"Cannot release HW Global Lock, it has not been acquired"));
"Cannot release the ACPI Global Lock, it has not been acquired"));
return_ACPI_STATUS(AE_NOT_ACQUIRED);
}

/* One fewer thread has the global lock */
if (acpi_gbl_global_lock_present) {

acpi_gbl_global_lock_thread_count--;
if (acpi_gbl_global_lock_thread_count) {
/* Allow any thread to release the lock */

/* There are still some threads holding the lock, cannot release */
ACPI_RELEASE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock,
pending);

return_ACPI_STATUS(AE_OK);
/*
* If the pending bit was set, we must write GBL_RLS to the control
* register
*/
if (pending) {
status =
acpi_set_register(ACPI_BITREG_GLOBAL_LOCK_RELEASE,
1, ACPI_MTX_LOCK);
}

ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Released hardware Global Lock\n"));
}

/*
* No more threads holding lock, we can do the actual hardware
* release
*/
ACPI_RELEASE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, pending);
acpi_gbl_global_lock_acquired = FALSE;

/*
* If the pending bit was set, we must write GBL_RLS to the control
* register
*/
if (pending) {
status = acpi_set_register(ACPI_BITREG_GLOBAL_LOCK_RELEASE,
1, ACPI_MTX_LOCK);
}
/* Release the local GL mutex */

acpi_os_release_mutex(acpi_gbl_global_lock_mutex);
return_ACPI_STATUS(status);
}

Expand Down
78 changes: 45 additions & 33 deletions trunk/drivers/acpi/executer/exmutex.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@

#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/acevents.h>

#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exmutex")
Expand Down Expand Up @@ -150,7 +151,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
return_ACPI_STATUS(AE_BAD_PARAMETER);
}

/* Sanity check -- we must have a valid thread ID */
/* Sanity check: we must have a valid thread ID */

if (!walk_state->thread) {
ACPI_ERROR((AE_INFO,
Expand All @@ -174,24 +175,28 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
/* Support for multiple acquires by the owning thread */

if (obj_desc->mutex.owner_thread) {

/* Special case for Global Lock, allow all threads */

if ((obj_desc->mutex.owner_thread->thread_id ==
walk_state->thread->thread_id) ||
(obj_desc->mutex.os_mutex == ACPI_GLOBAL_LOCK)) {
if (obj_desc->mutex.owner_thread->thread_id ==
walk_state->thread->thread_id) {
/*
* The mutex is already owned by this thread,
* just increment the acquisition depth
* The mutex is already owned by this thread, just increment the
* acquisition depth
*/
obj_desc->mutex.acquisition_depth++;
return_ACPI_STATUS(AE_OK);
}
}

/* Acquire the mutex, wait if necessary */
/* Acquire the mutex, wait if necessary. Special case for Global Lock */

if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) {
status =
acpi_ev_acquire_global_lock((u16) time_desc->integer.value);
} else {
status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex,
(u16) time_desc->integer.
value);
}

status = acpi_ex_system_acquire_mutex(time_desc, obj_desc);
if (ACPI_FAILURE(status)) {

/* Includes failure from a timeout on time_desc */
Expand All @@ -211,7 +216,6 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
/* Link the mutex to the current thread for force-unlock at method exit */

acpi_ex_link_mutex(obj_desc, walk_state->thread);

return_ACPI_STATUS(AE_OK);
}

Expand All @@ -232,7 +236,7 @@ acpi_status
acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state)
{
acpi_status status;
acpi_status status = AE_OK;

ACPI_FUNCTION_TRACE(ex_release_mutex);

Expand All @@ -249,7 +253,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED);
}

/* Sanity check -- we must have a valid thread ID */
/* Sanity check: we must have a valid thread ID */

if (!walk_state->thread) {
ACPI_ERROR((AE_INFO,
Expand All @@ -264,7 +268,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
*/
if ((obj_desc->mutex.owner_thread->thread_id !=
walk_state->thread->thread_id)
&& (obj_desc->mutex.os_mutex != ACPI_GLOBAL_LOCK)) {
&& (obj_desc->mutex.os_mutex != acpi_gbl_global_lock_mutex)) {
ACPI_ERROR((AE_INFO,
"Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX",
(unsigned long)walk_state->thread->thread_id,
Expand All @@ -274,8 +278,8 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
}

/*
* The sync level of the mutex must be less than or
* equal to the current sync level
* The sync level of the mutex must be less than or equal to the current
* sync level
*/
if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) {
ACPI_ERROR((AE_INFO,
Expand All @@ -298,11 +302,15 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,

acpi_ex_unlink_mutex(obj_desc);

/* Release the mutex */
/* Release the mutex, special case for Global Lock */

status = acpi_ex_system_release_mutex(obj_desc);
if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) {
status = acpi_ev_release_global_lock();
} else {
acpi_os_release_mutex(obj_desc->mutex.os_mutex);
}

/* Update the mutex and walk state, restore sync_level before acquire */
/* Update the mutex and restore sync_level */

obj_desc->mutex.owner_thread = NULL;
walk_state->thread->current_sync_level =
Expand All @@ -326,34 +334,38 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
{
union acpi_operand_object *next = thread->acquired_mutex_list;
union acpi_operand_object *this;
acpi_status status;
union acpi_operand_object *obj_desc;

ACPI_FUNCTION_ENTRY();

/* Traverse the list of owned mutexes, releasing each one */

while (next) {
this = next;
next = this->mutex.next;
obj_desc = next;
next = obj_desc->mutex.next;

obj_desc->mutex.prev = NULL;
obj_desc->mutex.next = NULL;
obj_desc->mutex.acquisition_depth = 1;

/* Release the mutex, special case for Global Lock */

this->mutex.acquisition_depth = 1;
this->mutex.prev = NULL;
this->mutex.next = NULL;
if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) {

/* Release the mutex */
/* Ignore errors */

status = acpi_ex_system_release_mutex(this);
if (ACPI_FAILURE(status)) {
continue;
(void)acpi_ev_release_global_lock();
} else {
acpi_os_release_mutex(obj_desc->mutex.os_mutex);
}

/* Mark mutex unowned */

this->mutex.owner_thread = NULL;
obj_desc->mutex.owner_thread = NULL;

/* Update Thread sync_level (Last mutex is the important one) */

thread->current_sync_level = this->mutex.original_sync_level;
thread->current_sync_level =
obj_desc->mutex.original_sync_level;
}
}
Loading

0 comments on commit 2095334

Please sign in to comment.