1 /* MN10300 Semaphore implementation
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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.
11 #include <linux/sched.h>
12 #include <linux/module.h>
13 #include <asm/semaphore.h>
16 struct list_head list
;
17 struct task_struct
*task
;
21 void semtrace(struct semaphore
*sem
, const char *str
)
24 printk(KERN_DEBUG
"[%d] %s({%d,%d})\n",
27 atomic_read(&sem
->count
),
28 list_empty(&sem
->wait_list
) ? 0 : 1);
31 #define semtrace(SEM, STR) do { } while (0)
35 * wait for a token to be granted from a semaphore
36 * - entered with lock held and interrupts disabled
38 void __down(struct semaphore
*sem
, unsigned long flags
)
40 struct task_struct
*tsk
= current
;
41 struct sem_waiter waiter
;
43 semtrace(sem
, "Entering __down");
45 /* set up my own style of waitqueue */
49 list_add_tail(&waiter
.list
, &sem
->wait_list
);
51 /* we don't need to touch the semaphore struct anymore */
52 spin_unlock_irqrestore(&sem
->wait_lock
, flags
);
54 /* wait to be given the semaphore */
55 set_task_state(tsk
, TASK_UNINTERRUPTIBLE
);
61 set_task_state(tsk
, TASK_UNINTERRUPTIBLE
);
64 tsk
->state
= TASK_RUNNING
;
65 semtrace(sem
, "Leaving __down");
67 EXPORT_SYMBOL(__down
);
70 * interruptibly wait for a token to be granted from a semaphore
71 * - entered with lock held and interrupts disabled
73 int __down_interruptible(struct semaphore
*sem
, unsigned long flags
)
75 struct task_struct
*tsk
= current
;
76 struct sem_waiter waiter
;
79 semtrace(sem
, "Entering __down_interruptible");
81 /* set up my own style of waitqueue */
85 list_add_tail(&waiter
.list
, &sem
->wait_list
);
87 /* we don't need to touch the semaphore struct anymore */
88 set_task_state(tsk
, TASK_INTERRUPTIBLE
);
90 spin_unlock_irqrestore(&sem
->wait_lock
, flags
);
92 /* wait to be given the semaphore */
97 if (unlikely(signal_pending(current
)))
100 set_task_state(tsk
, TASK_INTERRUPTIBLE
);
104 tsk
->state
= TASK_RUNNING
;
105 semtrace(sem
, "Leaving __down_interruptible");
109 spin_lock_irqsave(&sem
->wait_lock
, flags
);
110 list_del(&waiter
.list
);
111 spin_unlock_irqrestore(&sem
->wait_lock
, flags
);
115 put_task_struct(current
);
120 EXPORT_SYMBOL(__down_interruptible
);
123 * release a single token back to a semaphore
124 * - entered with lock held and interrupts disabled
126 void __up(struct semaphore
*sem
)
128 struct task_struct
*tsk
;
129 struct sem_waiter
*waiter
;
131 semtrace(sem
, "Entering __up");
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
);
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).
140 list_del_init(&waiter
->list
);
144 wake_up_process(tsk
);
145 put_task_struct(tsk
);
147 semtrace(sem
, "Leaving __up");