aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mn10300
diff options
context:
space:
mode:
authorMatthew Wilcox <matthew@wil.cx>2008-03-07 21:55:58 -0500
committerMatthew Wilcox <willy@linux.intel.com>2008-04-17 10:42:34 -0400
commit64ac24e738823161693bf791f87adc802cf529ff (patch)
tree19c0b0cf314d4394ca580c05b86cdf874ce0a167 /arch/mn10300
parente48b3deee475134585eed03e7afebe4bf9e0dba9 (diff)
Generic semaphore implementation
Semaphores are no longer performance-critical, so a generic C implementation is better for maintainability, debuggability and extensibility. Thanks to Peter Zijlstra for fixing the lockdep warning. Thanks to Harvey Harrison for pointing out that the unlikely() was unnecessary. Signed-off-by: Matthew Wilcox <willy@linux.intel.com> Acked-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/mn10300')
-rw-r--r--arch/mn10300/kernel/Makefile2
-rw-r--r--arch/mn10300/kernel/semaphore.c149
2 files changed, 1 insertions, 150 deletions
diff --git a/arch/mn10300/kernel/Makefile b/arch/mn10300/kernel/Makefile
index ef07c956170a..23f2ab67574c 100644
--- a/arch/mn10300/kernel/Makefile
+++ b/arch/mn10300/kernel/Makefile
@@ -3,7 +3,7 @@
3# 3#
4extra-y := head.o init_task.o vmlinux.lds 4extra-y := head.o init_task.o vmlinux.lds
5 5
6obj-y := process.o semaphore.o signal.o entry.o fpu.o traps.o irq.o \ 6obj-y := process.o signal.o entry.o fpu.o traps.o irq.o \
7 ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \ 7 ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \
8 switch_to.o mn10300_ksyms.o kernel_execve.o 8 switch_to.o mn10300_ksyms.o kernel_execve.o
9 9
diff --git a/arch/mn10300/kernel/semaphore.c b/arch/mn10300/kernel/semaphore.c
deleted file mode 100644
index 9153c4039fd2..000000000000
--- a/arch/mn10300/kernel/semaphore.c
+++ /dev/null
@@ -1,149 +0,0 @@
1/* MN10300 Semaphore implementation
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/sched.h>
12#include <linux/module.h>
13#include <asm/semaphore.h>
14
15struct sem_waiter {
16 struct list_head list;
17 struct task_struct *task;
18};
19
20#if SEMAPHORE_DEBUG
21void semtrace(struct semaphore *sem, const char *str)
22{
23 if (sem->debug)
24 printk(KERN_DEBUG "[%d] %s({%d,%d})\n",
25 current->pid,
26 str,
27 atomic_read(&sem->count),
28 list_empty(&sem->wait_list) ? 0 : 1);
29}
30#else
31#define semtrace(SEM, STR) do { } while (0)
32#endif
33
34/*
35 * wait for a token to be granted from a semaphore
36 * - entered with lock held and interrupts disabled
37 */
38void __down(struct semaphore *sem, unsigned long flags)
39{
40 struct task_struct *tsk = current;
41 struct sem_waiter waiter;
42
43 semtrace(sem, "Entering __down");
44
45 /* set up my own style of waitqueue */
46 waiter.task = tsk;
47 get_task_struct(tsk);
48
49 list_add_tail(&waiter.list, &sem->wait_list);
50
51 /* we don't need to touch the semaphore struct anymore */
52 spin_unlock_irqrestore(&sem->wait_lock, flags);
53
54 /* wait to be given the semaphore */
55 set_task_state(tsk, TASK_UNINTERRUPTIBLE);
56
57 for (;;) {
58 if (!waiter.task)
59 break;
60 schedule();
61 set_task_state(tsk, TASK_UNINTERRUPTIBLE);
62 }
63
64 tsk->state = TASK_RUNNING;
65 semtrace(sem, "Leaving __down");
66}
67EXPORT_SYMBOL(__down);
68
69/*
70 * interruptibly wait for a token to be granted from a semaphore
71 * - entered with lock held and interrupts disabled
72 */
73int __down_interruptible(struct semaphore *sem, unsigned long flags)
74{
75 struct task_struct *tsk = current;
76 struct sem_waiter waiter;
77 int ret;
78
79 semtrace(sem, "Entering __down_interruptible");
80
81 /* set up my own style of waitqueue */
82 waiter.task = tsk;
83 get_task_struct(tsk);
84
85 list_add_tail(&waiter.list, &sem->wait_list);
86
87 /* we don't need to touch the semaphore struct anymore */
88 set_task_state(tsk, TASK_INTERRUPTIBLE);
89
90 spin_unlock_irqrestore(&sem->wait_lock, flags);
91
92 /* wait to be given the semaphore */
93 ret = 0;
94 for (;;) {
95 if (!waiter.task)
96 break;
97 if (unlikely(signal_pending(current)))
98 goto interrupted;
99 schedule();
100 set_task_state(tsk, TASK_INTERRUPTIBLE);
101 }
102
103 out:
104 tsk->state = TASK_RUNNING;
105 semtrace(sem, "Leaving __down_interruptible");
106 return ret;
107
108 interrupted:
109 spin_lock_irqsave(&sem->wait_lock, flags);
110 list_del(&waiter.list);
111 spin_unlock_irqrestore(&sem->wait_lock, flags);
112
113 ret = 0;
114 if (!waiter.task) {
115 put_task_struct(current);
116 ret = -EINTR;
117 }
118 goto out;
119}
120EXPORT_SYMBOL(__down_interruptible);
121
122/*
123 * release a single token back to a semaphore
124 * - entered with lock held and interrupts disabled
125 */
126void __up(struct semaphore *sem)
127{
128 struct task_struct *tsk;
129 struct sem_waiter *waiter;
130
131 semtrace(sem, "Entering __up");
132
133 /* grant the token to the process at the front of the queue */
134 waiter = list_entry(sem->wait_list.next, struct sem_waiter, list);
135
136 /* We must be careful not to touch 'waiter' after we set ->task = NULL.
137 * It is an allocated on the waiter's stack and may become invalid at
138 * any time after that point (due to a wakeup from another source).
139 */
140 list_del_init(&waiter->list);
141 tsk = waiter->task;
142 smp_mb();
143 waiter->task = NULL;
144 wake_up_process(tsk);
145 put_task_struct(tsk);
146
147 semtrace(sem, "Leaving __up");
148}
149EXPORT_SYMBOL(__up);