diff options
author | John M. Calandrino <jmc@jupiter-cs.cs.unc.edu> | 2007-04-23 17:02:30 -0400 |
---|---|---|
committer | John M. Calandrino <jmc@jupiter-cs.cs.unc.edu> | 2007-04-23 17:02:30 -0400 |
commit | f6f293bee0fd39c2ffe3cd945da961f1470ad52c (patch) | |
tree | 35cad69787bcde37b9c31376a7b609f28277661d /arch/i386 | |
parent | ca16fd5c25326ebaf3672155df7058d98cade764 (diff) |
Fixed priority inheritance issues with PI semaphores. Added regular
semaphores accessible through system calls, so that they can be used with
the LSO (for partitioned FMLP).
Diffstat (limited to 'arch/i386')
-rw-r--r-- | arch/i386/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/i386/kernel/pi_sem_syscalls.c | 4 | ||||
-rw-r--r-- | arch/i386/kernel/sem_syscalls.c | 78 | ||||
-rw-r--r-- | arch/i386/kernel/syscall_table.S | 8 |
4 files changed, 86 insertions, 6 deletions
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile index 46cf523b44..b8815ad4e8 100644 --- a/arch/i386/kernel/Makefile +++ b/arch/i386/kernel/Makefile | |||
@@ -8,7 +8,7 @@ obj-y := process.o signal.o entry.o traps.o irq.o \ | |||
8 | ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \ | 8 | ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \ |
9 | pci-dma.o i386_ksyms.o i387.o bootflag.o e820.o\ | 9 | pci-dma.o i386_ksyms.o i387.o bootflag.o e820.o\ |
10 | quirks.o i8237.o topology.o alternative.o i8253.o tsc.o \ | 10 | quirks.o i8237.o topology.o alternative.o i8253.o tsc.o \ |
11 | pi_sem_syscalls.o | 11 | pi_sem_syscalls.o sem_syscalls.o |
12 | 12 | ||
13 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | 13 | obj-$(CONFIG_STACKTRACE) += stacktrace.o |
14 | obj-y += cpu/ | 14 | obj-y += cpu/ |
diff --git a/arch/i386/kernel/pi_sem_syscalls.c b/arch/i386/kernel/pi_sem_syscalls.c index 06317c7145..f7a66da110 100644 --- a/arch/i386/kernel/pi_sem_syscalls.c +++ b/arch/i386/kernel/pi_sem_syscalls.c | |||
@@ -1,5 +1,3 @@ | |||
1 | #include <linux/linkage.h> | ||
2 | |||
3 | #ifdef __KERNEL__ | 1 | #ifdef __KERNEL__ |
4 | 2 | ||
5 | /* | 3 | /* |
@@ -40,7 +38,7 @@ asmlinkage long sys_pi_sema_init (void) | |||
40 | atomic_set(&pi_sems[sem_id].count, 1); | 38 | atomic_set(&pi_sems[sem_id].count, 1); |
41 | pi_sems[sem_id].sleepers = 0; | 39 | pi_sems[sem_id].sleepers = 0; |
42 | init_waitqueue_head(&pi_sems[sem_id].wait); | 40 | init_waitqueue_head(&pi_sems[sem_id].wait); |
43 | pi_sems[sem_id].sem_prio = LOWEST_SEM_PRIO; | 41 | pi_sems[sem_id].sem_hp_task = NULL; |
44 | return sem_id; | 42 | return sem_id; |
45 | } | 43 | } |
46 | } | 44 | } |
diff --git a/arch/i386/kernel/sem_syscalls.c b/arch/i386/kernel/sem_syscalls.c new file mode 100644 index 0000000000..2bdbc5fd96 --- /dev/null +++ b/arch/i386/kernel/sem_syscalls.c | |||
@@ -0,0 +1,78 @@ | |||
1 | /* | ||
2 | * SMP- and interrupt-safe semaphores, using system calls from user space, | ||
3 | * so that they work with the LSO. Uses semaphores as described in | ||
4 | * include/asm-i386/semaphore.h. | ||
5 | */ | ||
6 | |||
7 | #include <asm/semaphore.h> | ||
8 | #include <linux/sched.h> | ||
9 | |||
10 | #define MAX_SEMAPHORES 256 | ||
11 | |||
12 | struct semaphore sems[MAX_SEMAPHORES]; /* all sems */ | ||
13 | typedef int sema_id; /* Userspace ID of a semaphore */ | ||
14 | |||
15 | /* Initialize semaphores at boot time. */ | ||
16 | static int __init sema_boot_init(void) | ||
17 | { | ||
18 | sema_id sem_id; | ||
19 | |||
20 | printk("Initializing semaphores..."); | ||
21 | for (sem_id = 0; sem_id < MAX_SEMAPHORES; sem_id++) | ||
22 | sems[sem_id].used = 0; | ||
23 | printk(" complete!\n"); | ||
24 | |||
25 | return 0; | ||
26 | } | ||
27 | __initcall(sema_boot_init); | ||
28 | |||
29 | /* Find a free semaphore and assign to sem. */ | ||
30 | asmlinkage long sys_sema_init (void) | ||
31 | { | ||
32 | sema_id sem_id; | ||
33 | |||
34 | for (sem_id = 0; sem_id < MAX_SEMAPHORES; sem_id++) { | ||
35 | if (!cmpxchg(&sems[sem_id].used, 0, 1)) { | ||
36 | sema_init(&sems[sem_id], 1); | ||
37 | return sem_id; | ||
38 | } | ||
39 | } | ||
40 | return -ENOMEM; | ||
41 | } | ||
42 | |||
43 | asmlinkage long sys_down(sema_id sem_id) | ||
44 | { | ||
45 | if (sem_id < 0 || sem_id >= MAX_SEMAPHORES) | ||
46 | return -EINVAL; | ||
47 | |||
48 | down(&sems[sem_id]); | ||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | asmlinkage long sys_up(sema_id sem_id) | ||
53 | { | ||
54 | if (sem_id < 0 || sem_id >= MAX_SEMAPHORES) | ||
55 | return -EINVAL; | ||
56 | |||
57 | up(&sems[sem_id]); | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | asmlinkage long sys_sema_free(sema_id sem_id) | ||
62 | { | ||
63 | struct list_head *tmp, *next; | ||
64 | unsigned long flags; | ||
65 | |||
66 | spin_lock_irqsave(&sems[sem_id].wait.lock, flags); | ||
67 | list_for_each_safe(tmp, next, &sems[sem_id].wait.task_list) { | ||
68 | wait_queue_t *curr = list_entry(tmp, wait_queue_t, task_list); | ||
69 | list_del(tmp); | ||
70 | curr->func(curr, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, | ||
71 | 0, NULL); | ||
72 | } | ||
73 | spin_unlock_irqrestore(&sems[sem_id].wait.lock, flags); | ||
74 | sems[sem_id].used = 0; | ||
75 | |||
76 | return 0; | ||
77 | } | ||
78 | |||
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S index 297a511c37..10e0ce444d 100644 --- a/arch/i386/kernel/syscall_table.S +++ b/arch/i386/kernel/syscall_table.S | |||
@@ -335,5 +335,9 @@ ENTRY(sys_call_table) | |||
335 | .long sys_pi_down | 335 | .long sys_pi_down |
336 | .long sys_pi_up | 336 | .long sys_pi_up |
337 | .long sys_pi_sema_free | 337 | .long sys_pi_sema_free |
338 | .long sys_in_blocking_zone /* 335 */ | 338 | .long sys_sema_init /* 335 */ |
339 | .long sys_wait_for_zone_exit /* 336 */ | 339 | .long sys_down |
340 | .long sys_up | ||
341 | .long sys_sema_free | ||
342 | .long sys_in_blocking_zone | ||
343 | .long sys_wait_for_zone_exit /* 340 */ | ||