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/] [or32/] [kernel/] [semaphore.c] - Blame information for rev 7

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 7 xianfeng
/*
2
 *  linux/arch/or32/kernel/semaphore.c
3
 *
4
 *  or32 version
5
 *
6
 * taken from: arch/cris/kernel/semaphore.c
7
 *
8
 */
9
 
10
/*
11
 *  Generic semaphore code. Buyer beware. Do your own
12
 * specific changes in <asm/semaphore-helper.h>
13
 */
14
 
15
#include <linux/sched.h>
16
#include <asm/semaphore-helper.h>
17
 
18
/*
19
 * Semaphores are implemented using a two-way counter:
20
 * The "count" variable is decremented for each process
21
 * that tries to sleep, while the "waking" variable is
22
 * incremented when the "up()" code goes to wake up waiting
23
 * processes.
24
 *
25
 * Notably, the inline "up()" and "down()" functions can
26
 * efficiently test if they need to do any extra work (up
27
 * needs to do something only if count was negative before
28
 * the increment operation.
29
 *
30
 * waking_non_zero() (from asm/semaphore.h) must execute
31
 * atomically.
32
 *
33
 * When __up() is called, the count was negative before
34
 * incrementing it, and we need to wake up somebody.
35
 *
36
 * This routine adds one to the count of processes that need to
37
 * wake up and exit.  ALL waiting processes actually wake up but
38
 * only the one that gets to the "waking" field first will gate
39
 * through and acquire the semaphore.  The others will go back
40
 * to sleep.
41
 *
42
 * Note that these functions are only called when there is
43
 * contention on the lock, and as such all this is the
44
 * "non-critical" part of the whole semaphore business. The
45
 * critical part is the inline stuff in <asm/semaphore.h>
46
 * where we want to avoid any extra jumps and calls.
47
 */
48
void __up(struct semaphore *sem)
49
{
50
        wake_one_more(sem);
51
        wake_up(&sem->wait);
52
}
53
 
54
/*
55
 * Perform the "down" function.  Return zero for semaphore acquired,
56
 * return negative for signalled out of the function.
57
 *
58
 * If called from __down, the return is ignored and the wait loop is
59
 * not interruptible.  This means that a task waiting on a semaphore
60
 * using "down()" cannot be killed until someone does an "up()" on
61
 * the semaphore.
62
 *
63
 * If called from __down_interruptible, the return value gets checked
64
 * upon return.  If the return value is negative then the task continues
65
 * with the negative value in the return register (it can be tested by
66
 * the caller).
67
 *
68
 * Either form may be used in conjunction with "up()".
69
 *
70
 */
71
 
72
#define DOWN_VAR                                \
73
        struct task_struct *tsk = current;      \
74
        wait_queue_t wait;                      \
75
        init_waitqueue_entry(&wait, tsk);
76
 
77
#define DOWN_HEAD(task_state)                                           \
78
                                                                        \
79
                                                                        \
80
        tsk->state = (task_state);                                      \
81
        add_wait_queue(&sem->wait, &wait);                              \
82
                                                                        \
83
        /*                                                              \
84
         * Ok, we're set up.  sem->count is known to be less than zero  \
85
         * so we must wait.                                             \
86
         *                                                              \
87
         * We can let go the lock for purposes of waiting.              \
88
         * We re-acquire it after awaking so as to protect              \
89
         * all semaphore operations.                                    \
90
         *                                                              \
91
         * If "up()" is called before we call waking_non_zero() then    \
92
         * we will catch it right away.  If it is called later then     \
93
         * we will have to go through a wakeup cycle to catch it.       \
94
         *                                                              \
95
         * Multiple waiters contend for the semaphore lock to see       \
96
         * who gets to gate through and who has to wait some more.      \
97
         */                                                             \
98
        for (;;) {
99
 
100
#define DOWN_TAIL(task_state)                   \
101
                tsk->state = (task_state);      \
102
        }                                       \
103
        tsk->state = TASK_RUNNING;              \
104
        remove_wait_queue(&sem->wait, &wait);
105
 
106
void __down(struct semaphore * sem)
107
{
108
        DOWN_VAR
109
        DOWN_HEAD(TASK_UNINTERRUPTIBLE)
110
        if (waking_non_zero(sem))
111
                break;
112
        schedule();
113
        DOWN_TAIL(TASK_UNINTERRUPTIBLE)
114
}
115
 
116
int __down_interruptible(struct semaphore * sem)
117
{
118
        int ret = 0;
119
        DOWN_VAR
120
        DOWN_HEAD(TASK_INTERRUPTIBLE)
121
 
122
        ret = waking_non_zero_interruptible(sem, tsk);
123
        if (ret)
124
        {
125
                if (ret == 1)
126
                        /* ret != 0 only if we get interrupted -arca */
127
                        ret = 0;
128
                break;
129
        }
130
        schedule();
131
        DOWN_TAIL(TASK_INTERRUPTIBLE)
132
        return ret;
133
}
134
 
135
int __down_trylock(struct semaphore * sem)
136
{
137
        return waking_non_zero_trylock(sem);
138
}

powered by: WebSVN 2.1.0

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