aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJohn M. Calandrino <jmc@jupiter-cs.cs.unc.edu>2007-04-23 17:02:30 -0400
committerJohn M. Calandrino <jmc@jupiter-cs.cs.unc.edu>2007-04-23 17:02:30 -0400
commitf6f293bee0fd39c2ffe3cd945da961f1470ad52c (patch)
tree35cad69787bcde37b9c31376a7b609f28277661d /arch
parentca16fd5c25326ebaf3672155df7058d98cade764 (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')
-rw-r--r--arch/i386/kernel/Makefile2
-rw-r--r--arch/i386/kernel/pi_sem_syscalls.c4
-rw-r--r--arch/i386/kernel/sem_syscalls.c78
-rw-r--r--arch/i386/kernel/syscall_table.S8
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
13obj-$(CONFIG_STACKTRACE) += stacktrace.o 13obj-$(CONFIG_STACKTRACE) += stacktrace.o
14obj-y += cpu/ 14obj-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
12struct semaphore sems[MAX_SEMAPHORES]; /* all sems */
13typedef int sema_id; /* Userspace ID of a semaphore */
14
15/* Initialize semaphores at boot time. */
16static 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. */
30asmlinkage 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
43asmlinkage 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
52asmlinkage 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
61asmlinkage 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 */