OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [powerpc/] [kernel/] [semaphore.c] - Blame information for rev 17

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 * PowerPC-specific semaphore code.
3
 *
4
 * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version
9
 * 2 of the License, or (at your option) any later version.
10
 *
11
 * April 2001 - Reworked by Paul Mackerras <paulus@samba.org>
12
 * to eliminate the SMP races in the old version between the updates
13
 * of `count' and `waking'.  Now we use negative `count' values to
14
 * indicate that some process(es) are waiting for the semaphore.
15
 */
16
 
17
#include <linux/sched.h>
18
#include <linux/init.h>
19
#include <linux/module.h>
20
 
21
#include <asm/atomic.h>
22
#include <asm/semaphore.h>
23
#include <asm/errno.h>
24
 
25
/*
26
 * Atomically update sem->count.
27
 * This does the equivalent of the following:
28
 *
29
 *      old_count = sem->count;
30
 *      tmp = MAX(old_count, 0) + incr;
31
 *      sem->count = tmp;
32
 *      return old_count;
33
 */
34
static inline int __sem_update_count(struct semaphore *sem, int incr)
35
{
36
        int old_count, tmp;
37
 
38
        __asm__ __volatile__("\n"
39
"1:     lwarx   %0,0,%3\n"
40
"       srawi   %1,%0,31\n"
41
"       andc    %1,%0,%1\n"
42
"       add     %1,%1,%4\n"
43
        PPC405_ERR77(0,%3)
44
"       stwcx.  %1,0,%3\n"
45
"       bne     1b"
46
        : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
47
        : "r" (&sem->count), "r" (incr), "m" (sem->count)
48
        : "cc");
49
 
50
        return old_count;
51
}
52
 
53
void __up(struct semaphore *sem)
54
{
55
        /*
56
         * Note that we incremented count in up() before we came here,
57
         * but that was ineffective since the result was <= 0, and
58
         * any negative value of count is equivalent to 0.
59
         * This ends up setting count to 1, unless count is now > 0
60
         * (i.e. because some other cpu has called up() in the meantime),
61
         * in which case we just increment count.
62
         */
63
        __sem_update_count(sem, 1);
64
        wake_up(&sem->wait);
65
}
66
EXPORT_SYMBOL(__up);
67
 
68
/*
69
 * Note that when we come in to __down or __down_interruptible,
70
 * we have already decremented count, but that decrement was
71
 * ineffective since the result was < 0, and any negative value
72
 * of count is equivalent to 0.
73
 * Thus it is only when we decrement count from some value > 0
74
 * that we have actually got the semaphore.
75
 */
76
void __sched __down(struct semaphore *sem)
77
{
78
        struct task_struct *tsk = current;
79
        DECLARE_WAITQUEUE(wait, tsk);
80
 
81
        __set_task_state(tsk, TASK_UNINTERRUPTIBLE);
82
        add_wait_queue_exclusive(&sem->wait, &wait);
83
 
84
        /*
85
         * Try to get the semaphore.  If the count is > 0, then we've
86
         * got the semaphore; we decrement count and exit the loop.
87
         * If the count is 0 or negative, we set it to -1, indicating
88
         * that we are asleep, and then sleep.
89
         */
90
        while (__sem_update_count(sem, -1) <= 0) {
91
                schedule();
92
                set_task_state(tsk, TASK_UNINTERRUPTIBLE);
93
        }
94
        remove_wait_queue(&sem->wait, &wait);
95
        __set_task_state(tsk, TASK_RUNNING);
96
 
97
        /*
98
         * If there are any more sleepers, wake one of them up so
99
         * that it can either get the semaphore, or set count to -1
100
         * indicating that there are still processes sleeping.
101
         */
102
        wake_up(&sem->wait);
103
}
104
EXPORT_SYMBOL(__down);
105
 
106
int __sched __down_interruptible(struct semaphore * sem)
107
{
108
        int retval = 0;
109
        struct task_struct *tsk = current;
110
        DECLARE_WAITQUEUE(wait, tsk);
111
 
112
        __set_task_state(tsk, TASK_INTERRUPTIBLE);
113
        add_wait_queue_exclusive(&sem->wait, &wait);
114
 
115
        while (__sem_update_count(sem, -1) <= 0) {
116
                if (signal_pending(current)) {
117
                        /*
118
                         * A signal is pending - give up trying.
119
                         * Set sem->count to 0 if it is negative,
120
                         * since we are no longer sleeping.
121
                         */
122
                        __sem_update_count(sem, 0);
123
                        retval = -EINTR;
124
                        break;
125
                }
126
                schedule();
127
                set_task_state(tsk, TASK_INTERRUPTIBLE);
128
        }
129
        remove_wait_queue(&sem->wait, &wait);
130
        __set_task_state(tsk, TASK_RUNNING);
131
 
132
        wake_up(&sem->wait);
133
        return retval;
134
}
135
EXPORT_SYMBOL(__down_interruptible);

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.