diff options
author | John M. Calandrino <jmc@jupiter-cs.cs.unc.edu> | 2007-04-19 15:32:52 -0400 |
---|---|---|
committer | John M. Calandrino <jmc@jupiter-cs.cs.unc.edu> | 2007-04-19 15:32:52 -0400 |
commit | 1263c9776c7eed5b8654e68eb847e7459f7ad240 (patch) | |
tree | cc31cc1b8435bbb21cffe21a4cc2299de1845023 /arch | |
parent | f799d49688e4bfc27b45a64b32749ee82cc70248 (diff) |
Made changes in Litmus so that user-space semaphores can work.
A user now makes a system call where a semaphore ID is specified, and
the semaphore implementation is hidden away in the kernel. There are a
finite number of semaphores and the kernel system call will return an error
if it cannot claim one, however user space code in libso does not yet
acknowledge this.
Diffstat (limited to 'arch')
-rw-r--r-- | arch/i386/kernel/pi_sem_syscalls.c | 67 | ||||
-rw-r--r-- | arch/i386/kernel/syscall_table.S | 10 |
2 files changed, 59 insertions, 18 deletions
diff --git a/arch/i386/kernel/pi_sem_syscalls.c b/arch/i386/kernel/pi_sem_syscalls.c index 07c11fd327..5f474d2779 100644 --- a/arch/i386/kernel/pi_sem_syscalls.c +++ b/arch/i386/kernel/pi_sem_syscalls.c | |||
@@ -11,13 +11,35 @@ | |||
11 | #include <linux/sched.h> | 11 | #include <linux/sched.h> |
12 | #include <linux/wait.h> | 12 | #include <linux/wait.h> |
13 | 13 | ||
14 | asmlinkage long sys_pi_sema_init (struct pi_semaphore *sem) | 14 | #define MAX_PI_SEMAPHORES 256 |
15 | |||
16 | struct pi_semaphore pi_sems[MAX_PI_SEMAPHORES]; /* all PI sems */ | ||
17 | typedef int pi_sema_id; /* Userspace ID of a pi_semaphore */ | ||
18 | |||
19 | /* Initialize PI semaphores at boot time. */ | ||
20 | void __init pi_sema_boot_init(void) | ||
15 | { | 21 | { |
16 | atomic_set(&sem->count, 1); | 22 | int sem_id; |
17 | sem->sleepers = 0; | 23 | |
18 | init_waitqueue_head(&sem->wait); | 24 | printk("Initializing PI semaphores..."); |
19 | sem->sem_prio = LOWEST_SEM_PRIO; | 25 | for (sem_id = 0; sem_id < MAX_PI_SEMAPHORES; sem_id++) |
20 | return 0; | 26 | pi_sems[sem_id].used = 0; |
27 | printk(" complete!\n"); | ||
28 | } | ||
29 | |||
30 | /* Find a free semaphore and assign to sem. */ | ||
31 | asmlinkage long sys_pi_sema_init (pi_sema_id *sem_id) | ||
32 | { | ||
33 | for (*sem_id = 0; *sem_id < MAX_PI_SEMAPHORES; (*sem_id)++) { | ||
34 | if (!cmpxchg(&pi_sems[*sem_id].used, 0, 1)) { | ||
35 | atomic_set(&pi_sems[*sem_id].count, 1); | ||
36 | pi_sems[*sem_id].sleepers = 0; | ||
37 | init_waitqueue_head(&pi_sems[*sem_id].wait); | ||
38 | pi_sems[*sem_id].sem_prio = LOWEST_SEM_PRIO; | ||
39 | return 0; | ||
40 | } | ||
41 | } | ||
42 | return -ENOMEM; | ||
21 | } | 43 | } |
22 | 44 | ||
23 | fastcall void __pi_down_failed(void /* special register calling convention */); | 45 | fastcall void __pi_down_failed(void /* special register calling convention */); |
@@ -28,7 +50,7 @@ fastcall void __pi_up_wakeup(void /* special register calling convention */); | |||
28 | * "__down_failed" is a special asm handler that calls the C | 50 | * "__down_failed" is a special asm handler that calls the C |
29 | * routine that actually waits. See arch/i386/kernel/semaphore.c | 51 | * routine that actually waits. See arch/i386/kernel/semaphore.c |
30 | */ | 52 | */ |
31 | asmlinkage long sys_pi_down(struct pi_semaphore * sem) | 53 | void __sys_pi_down(struct pi_semaphore * sem) |
32 | { | 54 | { |
33 | might_sleep(); | 55 | might_sleep(); |
34 | __asm__ __volatile__( | 56 | __asm__ __volatile__( |
@@ -41,6 +63,14 @@ asmlinkage long sys_pi_down(struct pi_semaphore * sem) | |||
41 | :"+m" (sem->count) | 63 | :"+m" (sem->count) |
42 | : | 64 | : |
43 | :"memory","ax"); | 65 | :"memory","ax"); |
66 | } | ||
67 | |||
68 | asmlinkage long sys_pi_down(pi_sema_id sem_id) | ||
69 | { | ||
70 | if (sem_id < 0 || sem_id >= MAX_PI_SEMAPHORES) | ||
71 | return -EINVAL; | ||
72 | |||
73 | __sys_pi_down(&pi_sems[sem_id]); | ||
44 | return 0; | 74 | return 0; |
45 | } | 75 | } |
46 | 76 | ||
@@ -48,7 +78,7 @@ asmlinkage long sys_pi_down(struct pi_semaphore * sem) | |||
48 | * Note! This is subtle. We jump to wake people up only if | 78 | * Note! This is subtle. We jump to wake people up only if |
49 | * the semaphore was negative (== somebody was waiting on it). | 79 | * the semaphore was negative (== somebody was waiting on it). |
50 | */ | 80 | */ |
51 | asmlinkage long sys_pi_up(struct pi_semaphore * sem) | 81 | void __sys_pi_up(struct pi_semaphore * sem) |
52 | { | 82 | { |
53 | __asm__ __volatile__( | 83 | __asm__ __volatile__( |
54 | "# atomic up operation\n\t" | 84 | "# atomic up operation\n\t" |
@@ -60,23 +90,32 @@ asmlinkage long sys_pi_up(struct pi_semaphore * sem) | |||
60 | :"+m" (sem->count) | 90 | :"+m" (sem->count) |
61 | : | 91 | : |
62 | :"memory","ax"); | 92 | :"memory","ax"); |
93 | } | ||
94 | |||
95 | asmlinkage long sys_pi_up(pi_sema_id sem_id) | ||
96 | { | ||
97 | if (sem_id < 0 || sem_id >= MAX_PI_SEMAPHORES) | ||
98 | return -EINVAL; | ||
99 | |||
100 | __sys_pi_up(&pi_sems[sem_id]); | ||
63 | return 0; | 101 | return 0; |
64 | } | 102 | } |
65 | 103 | ||
66 | /* Clear wait queue and wakeup waiting tasks. */ | 104 | /* Clear wait queue and wakeup waiting tasks, and free semaphore. */ |
67 | asmlinkage long sys_pi_sema_free_wq(struct pi_semaphore * sem) | 105 | asmlinkage long sys_pi_sema_free(pi_sema_id sem_id) |
68 | { | 106 | { |
69 | struct list_head *tmp, *next; | 107 | struct list_head *tmp, *next; |
70 | unsigned long flags; | 108 | unsigned long flags; |
71 | 109 | ||
72 | spin_lock_irqsave(&sem->wait.lock, flags); | 110 | spin_lock_irqsave(&pi_sems[sem_id].wait.lock, flags); |
73 | list_for_each_safe(tmp, next, &sem->wait.task_list) { | 111 | list_for_each_safe(tmp, next, &pi_sems[sem_id].wait.task_list) { |
74 | wait_queue_t *curr = list_entry(tmp, wait_queue_t, task_list); | 112 | wait_queue_t *curr = list_entry(tmp, wait_queue_t, task_list); |
75 | list_del(tmp); | 113 | list_del(tmp); |
76 | curr->func(curr, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 0, NULL); | 114 | curr->func(curr, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 0, NULL); |
77 | } | 115 | } |
78 | spin_unlock_irqrestore(&sem->wait.lock, flags); | 116 | spin_unlock_irqrestore(&pi_sems[sem_id].wait.lock, flags); |
79 | 117 | pi_sems[sem_id].used = 0; | |
118 | |||
80 | return 0; | 119 | return 0; |
81 | } | 120 | } |
82 | 121 | ||
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S index 674fe443e8..297a511c37 100644 --- a/arch/i386/kernel/syscall_table.S +++ b/arch/i386/kernel/syscall_table.S | |||
@@ -329,9 +329,11 @@ ENTRY(sys_call_table) | |||
329 | .long sys_ni_syscall /* CLEANUP: sys_reset_stat */ | 329 | .long sys_ni_syscall /* CLEANUP: sys_reset_stat */ |
330 | .long sys_sleep_next_period | 330 | .long sys_sleep_next_period |
331 | .long sys_scheduler_setup | 331 | .long sys_scheduler_setup |
332 | .long sys_ni_syscall /* to be replaced... */ | ||
333 | .long sys_ni_syscall /* 330 */ | ||
332 | .long sys_pi_sema_init | 334 | .long sys_pi_sema_init |
333 | .long sys_pi_down /* 330 */ | 335 | .long sys_pi_down |
334 | .long sys_pi_up | 336 | .long sys_pi_up |
335 | .long sys_pi_sema_free_wq | 337 | .long sys_pi_sema_free |
336 | .long sys_in_blocking_zone | 338 | .long sys_in_blocking_zone /* 335 */ |
337 | .long sys_wait_for_zone_exit /* 334 */ | 339 | .long sys_wait_for_zone_exit /* 336 */ |