diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-18 11:25:29 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-18 11:25:29 -0400 |
| commit | d7bb545d86825e635cab33a1dd81ca0ad7b92887 (patch) | |
| tree | 34da4139ef06ceab6549aea3906639c7413978c8 /drivers | |
| parent | 75e98b34155264d943aa53edce465e87f3ccbadf (diff) | |
| parent | 2342e51ba2b52a7f5b78227e6faa4603ed3632a0 (diff) | |
Merge branch 'semaphore' of git://git.kernel.org/pub/scm/linux/kernel/git/willy/misc
* 'semaphore' of git://git.kernel.org/pub/scm/linux/kernel/git/willy/misc:
Remove DEBUG_SEMAPHORE from Kconfig
Improve semaphore documentation
Simplify semaphore implementation
Add down_timeout and change ACPI to use it
Introduce down_killable()
Generic semaphore implementation
Add semaphore.h to kernel_lock.c
Fix quota.h includes
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/acpi/osl.c | 89 |
1 files changed, 21 insertions, 68 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index a697fb6cf050..a498a6cc68fe 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
| @@ -4,6 +4,8 @@ | |||
| 4 | * Copyright (C) 2000 Andrew Henroid | 4 | * Copyright (C) 2000 Andrew Henroid |
| 5 | * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> | 5 | * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> |
| 6 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> | 6 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> |
| 7 | * Copyright (c) 2008 Intel Corporation | ||
| 8 | * Author: Matthew Wilcox <willy@linux.intel.com> | ||
| 7 | * | 9 | * |
| 8 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 10 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 9 | * | 11 | * |
| @@ -37,15 +39,18 @@ | |||
| 37 | #include <linux/workqueue.h> | 39 | #include <linux/workqueue.h> |
| 38 | #include <linux/nmi.h> | 40 | #include <linux/nmi.h> |
| 39 | #include <linux/acpi.h> | 41 | #include <linux/acpi.h> |
| 40 | #include <acpi/acpi.h> | ||
| 41 | #include <asm/io.h> | ||
| 42 | #include <acpi/acpi_bus.h> | ||
| 43 | #include <acpi/processor.h> | ||
| 44 | #include <asm/uaccess.h> | ||
| 45 | |||
| 46 | #include <linux/efi.h> | 42 | #include <linux/efi.h> |
| 47 | #include <linux/ioport.h> | 43 | #include <linux/ioport.h> |
| 48 | #include <linux/list.h> | 44 | #include <linux/list.h> |
| 45 | #include <linux/jiffies.h> | ||
| 46 | #include <linux/semaphore.h> | ||
| 47 | |||
| 48 | #include <asm/io.h> | ||
| 49 | #include <asm/uaccess.h> | ||
| 50 | |||
| 51 | #include <acpi/acpi.h> | ||
| 52 | #include <acpi/acpi_bus.h> | ||
| 53 | #include <acpi/processor.h> | ||
| 49 | 54 | ||
| 50 | #define _COMPONENT ACPI_OS_SERVICES | 55 | #define _COMPONENT ACPI_OS_SERVICES |
| 51 | ACPI_MODULE_NAME("osl"); | 56 | ACPI_MODULE_NAME("osl"); |
| @@ -764,7 +769,6 @@ acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle) | |||
| 764 | { | 769 | { |
| 765 | struct semaphore *sem = NULL; | 770 | struct semaphore *sem = NULL; |
| 766 | 771 | ||
| 767 | |||
| 768 | sem = acpi_os_allocate(sizeof(struct semaphore)); | 772 | sem = acpi_os_allocate(sizeof(struct semaphore)); |
| 769 | if (!sem) | 773 | if (!sem) |
| 770 | return AE_NO_MEMORY; | 774 | return AE_NO_MEMORY; |
| @@ -791,12 +795,12 @@ acpi_status acpi_os_delete_semaphore(acpi_handle handle) | |||
| 791 | { | 795 | { |
| 792 | struct semaphore *sem = (struct semaphore *)handle; | 796 | struct semaphore *sem = (struct semaphore *)handle; |
| 793 | 797 | ||
| 794 | |||
| 795 | if (!sem) | 798 | if (!sem) |
| 796 | return AE_BAD_PARAMETER; | 799 | return AE_BAD_PARAMETER; |
| 797 | 800 | ||
| 798 | ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle)); | 801 | ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle)); |
| 799 | 802 | ||
| 803 | BUG_ON(!list_empty(&sem->wait_list)); | ||
| 800 | kfree(sem); | 804 | kfree(sem); |
| 801 | sem = NULL; | 805 | sem = NULL; |
| 802 | 806 | ||
| @@ -804,21 +808,15 @@ acpi_status acpi_os_delete_semaphore(acpi_handle handle) | |||
| 804 | } | 808 | } |
| 805 | 809 | ||
| 806 | /* | 810 | /* |
| 807 | * TODO: The kernel doesn't have a 'down_timeout' function -- had to | ||
| 808 | * improvise. The process is to sleep for one scheduler quantum | ||
| 809 | * until the semaphore becomes available. Downside is that this | ||
| 810 | * may result in starvation for timeout-based waits when there's | ||
| 811 | * lots of semaphore activity. | ||
| 812 | * | ||
| 813 | * TODO: Support for units > 1? | 811 | * TODO: Support for units > 1? |
| 814 | */ | 812 | */ |
| 815 | acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout) | 813 | acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout) |
| 816 | { | 814 | { |
| 817 | acpi_status status = AE_OK; | 815 | acpi_status status = AE_OK; |
| 818 | struct semaphore *sem = (struct semaphore *)handle; | 816 | struct semaphore *sem = (struct semaphore *)handle; |
| 817 | long jiffies; | ||
| 819 | int ret = 0; | 818 | int ret = 0; |
| 820 | 819 | ||
| 821 | |||
| 822 | if (!sem || (units < 1)) | 820 | if (!sem || (units < 1)) |
| 823 | return AE_BAD_PARAMETER; | 821 | return AE_BAD_PARAMETER; |
| 824 | 822 | ||
| @@ -828,58 +826,14 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout) | |||
| 828 | ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n", | 826 | ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n", |
| 829 | handle, units, timeout)); | 827 | handle, units, timeout)); |
| 830 | 828 | ||
| 831 | /* | 829 | if (timeout == ACPI_WAIT_FOREVER) |
| 832 | * This can be called during resume with interrupts off. | 830 | jiffies = MAX_SCHEDULE_TIMEOUT; |
| 833 | * Like boot-time, we should be single threaded and will | 831 | else |
| 834 | * always get the lock if we try -- timeout or not. | 832 | jiffies = msecs_to_jiffies(timeout); |
| 835 | * If this doesn't succeed, then we will oops courtesy of | 833 | |
| 836 | * might_sleep() in down(). | 834 | ret = down_timeout(sem, jiffies); |
| 837 | */ | 835 | if (ret) |
| 838 | if (!down_trylock(sem)) | 836 | status = AE_TIME; |
| 839 | return AE_OK; | ||
| 840 | |||
| 841 | switch (timeout) { | ||
| 842 | /* | ||
| 843 | * No Wait: | ||
| 844 | * -------- | ||
| 845 | * A zero timeout value indicates that we shouldn't wait - just | ||
| 846 | * acquire the semaphore if available otherwise return AE_TIME | ||
| 847 | * (a.k.a. 'would block'). | ||
| 848 | */ | ||
| 849 | case 0: | ||
| 850 | if (down_trylock(sem)) | ||
| 851 | status = AE_TIME; | ||
| 852 | break; | ||
| 853 | |||
| 854 | /* | ||
| 855 | * Wait Indefinitely: | ||
| 856 | * ------------------ | ||
| 857 | */ | ||
| 858 | case ACPI_WAIT_FOREVER: | ||
| 859 | down(sem); | ||
| 860 | break; | ||
| 861 | |||
| 862 | /* | ||
| 863 | * Wait w/ Timeout: | ||
| 864 | * ---------------- | ||
| 865 | */ | ||
| 866 | default: | ||
| 867 | // TODO: A better timeout algorithm? | ||
| 868 | { | ||
| 869 | int i = 0; | ||
| 870 | static const int quantum_ms = 1000 / HZ; | ||
| 871 | |||
| 872 | ret = down_trylock(sem); | ||
| 873 | for (i = timeout; (i > 0 && ret != 0); i -= quantum_ms) { | ||
| 874 | schedule_timeout_interruptible(1); | ||
| 875 | ret = down_trylock(sem); | ||
| 876 | } | ||
| 877 | |||
| 878 | if (ret != 0) | ||
| 879 | status = AE_TIME; | ||
| 880 | } | ||
| 881 | break; | ||
| 882 | } | ||
| 883 | 837 | ||
| 884 | if (ACPI_FAILURE(status)) { | 838 | if (ACPI_FAILURE(status)) { |
| 885 | ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, | 839 | ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, |
| @@ -902,7 +856,6 @@ acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units) | |||
| 902 | { | 856 | { |
| 903 | struct semaphore *sem = (struct semaphore *)handle; | 857 | struct semaphore *sem = (struct semaphore *)handle; |
| 904 | 858 | ||
| 905 | |||
| 906 | if (!sem || (units < 1)) | 859 | if (!sem || (units < 1)) |
| 907 | return AE_BAD_PARAMETER; | 860 | return AE_BAD_PARAMETER; |
| 908 | 861 | ||
