aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJohn M. Calandrino <jmc@jupiter-cs.cs.unc.edu>2007-04-19 15:32:52 -0400
committerJohn M. Calandrino <jmc@jupiter-cs.cs.unc.edu>2007-04-19 15:32:52 -0400
commit1263c9776c7eed5b8654e68eb847e7459f7ad240 (patch)
treecc31cc1b8435bbb21cffe21a4cc2299de1845023 /arch
parentf799d49688e4bfc27b45a64b32749ee82cc70248 (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.c67
-rw-r--r--arch/i386/kernel/syscall_table.S10
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
14asmlinkage long sys_pi_sema_init (struct pi_semaphore *sem) 14#define MAX_PI_SEMAPHORES 256
15
16struct pi_semaphore pi_sems[MAX_PI_SEMAPHORES]; /* all PI sems */
17typedef int pi_sema_id; /* Userspace ID of a pi_semaphore */
18
19/* Initialize PI semaphores at boot time. */
20void __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. */
31asmlinkage 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
23fastcall void __pi_down_failed(void /* special register calling convention */); 45fastcall 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 */
31asmlinkage long sys_pi_down(struct pi_semaphore * sem) 53void __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
68asmlinkage 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 */
51asmlinkage long sys_pi_up(struct pi_semaphore * sem) 81void __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
95asmlinkage 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. */
67asmlinkage long sys_pi_sema_free_wq(struct pi_semaphore * sem) 105asmlinkage 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 */