source: rtems/c/src/lib/libcpu/hppa1.1/semaphore/semaphore.c @ e71ce071

4.104.114.84.95
Last change on this file since e71ce071 was e71ce071, checked in by Joel Sherrill <joel.sherrill@…>, on 04/22/97 at 17:47:16

updated with new license information per Tony Bennett.

  • Property mode set to 100644
File size: 6.2 KB
Line 
1/*
2 *  Description:
3 *      HPPA fast spinlock semaphores based on LDCWX instruction.
4 *      These semaphores are not known to RTEMS.
5 *
6 *  TODO:
7 *      Put node number in high 16 bits of flag??
8 *      XXX: Need h_s_deallocate
9 *
10 *  COPYRIGHT (c) 1994 by Division Incorporated
11 *
12 *  The license and distribution terms for this file may in
13 *  the file LICENSE in this distribution or at
14 *  http://www.OARcorp.com/rtems/license.html.
15 *
16 *  $Id$
17 */
18
19#include <bsp.h>
20
21#include "semaphore.h"
22
23/*
24 * Report fatal semaphore error
25 */
26
27#define SEM_FATAL_ERROR(sp)  rtems_fatal_error_occurred((rtems_unsigned32) sp)
28
29#define SEM_CHECK(sp)   do { \
30                              if (((sp) == 0) || (int) (sp) & 0xf) \
31                              { \
32                                  SEM_FATAL_ERROR(sp); \
33                              } \
34                         } while (0)
35
36/*
37 * Init a semaphore to be free
38 */
39
40#define SEM_FREE_INIT(sp) \
41    do { \
42        (sp)->lock = 1; \
43        (sp)->flags = 0; \
44        (sp)->owner_tcb  = 0; \
45    } while (0)
46
47/*
48 * Grab a semaphore recording its owner.
49 */
50
51#define SEM_MARK_GRABBED(sp) \
52    do { \
53        (sp)->owner_tcb  = _Thread_Executing; \
54    } while (0)
55
56/*
57 * Mark the semaphore busy
58 */
59
60#define SEM_MARK_BUSY(sp)    ((sp)->flags |= HPPA_SEM_IN_USE)
61
62/*
63 * Is a semaphore available?
64 */
65
66#define SEM_IS_AVAILABLE(sp)  ((sp)->owner_tcb == 0)
67
68/*
69 * The pool control semaphore is the first in the pool
70 */
71
72#define SEM_CONTROL  (&hppa_semaphore_pool[0])
73#define SEM_FIRST    (&hppa_semaphore_pool[1])
74
75#define SEM_PRIVATE(cookie)  rtems_interrupt_disable(cookie)
76
77#define SEM_PUBLIC(cookie)   rtems_interrupt_enable(cookie)
78
79
80/*
81 * Control variables for the pool
82 */
83
84hppa_semaphore_t *hppa_semaphore_pool;        /* ptr to first */
85int               hppa_semaphores;
86int               hppa_semaphores_available;
87
88void
89hppa_semaphore_pool_initialize(void *pool_base,
90                               int   pool_size)
91{
92    hppa_semaphore_t *sp;
93    int align_factor;
94    rtems_unsigned32 isr_level;
95
96    /*
97     * round pool_base up to be a multiple of SEM_ALIGN
98     */
99
100    align_factor = SEM_ALIGN - (((int) pool_base) & (SEM_ALIGN-1));
101    if (align_factor != SEM_ALIGN)
102    {
103        pool_base += align_factor;
104        pool_size -= align_factor;
105    }
106
107    /*
108     * How many can the pool hold?
109     * Assumes the semaphores are SEM_ALIGN bytes each
110     */
111
112    if (sizeof(hppa_semaphore_t) != SEM_ALIGN)
113        rtems_fatal_error_occurred(RTEMS_INVALID_SIZE);
114
115    pool_size &= ~(SEM_ALIGN - 1);
116
117    SEM_PRIVATE(isr_level);
118
119    hppa_semaphore_pool = pool_base;
120    hppa_semaphores = pool_size / SEM_ALIGN;
121
122    /*
123     * If we are node0, then init all in the pool
124     */
125
126    if (cpu_number == 0)
127    {
128        /*
129         * Tell other cpus we are not done, jic
130         */
131        SEM_CONTROL->user = rtems_build_name('!', 'D', 'N', 'E');
132
133        for (sp=SEM_FIRST; sp < &hppa_semaphore_pool[hppa_semaphores]; sp++)
134            SEM_FREE_INIT(sp);
135        SEM_FREE_INIT(SEM_CONTROL);
136    }
137
138    /*
139     * Tell other cpus we are done, or wait for it to be done if on another cpu
140     */
141
142    if (cpu_number == 0)
143        SEM_CONTROL->user = rtems_build_name('D', 'O', 'N', 'E');
144    else
145        while (SEM_CONTROL->user != rtems_build_name('D', 'O', 'N', 'E'))
146            ;
147
148    hppa_semaphores_available = hppa_semaphores;
149
150    SEM_PUBLIC(isr_level);
151}
152
153/*
154 *  Function:   hppa_semaphore_acquire
155 *  Created:    94/11/29
156 *  RespEngr:   tony bennett
157 *
158 *  Description:
159 *      Acquire a semaphore.   Will spin on the semaphore unless
160 *      'flag' says not to.
161 *
162 *  Parameters:
163 *
164 *
165 *  Returns:
166 *      0        -- if did not acquire
167 *      non-zero -- if acquired semaphore
168 *                      (actually this is the spin count)
169 *
170 *  Notes:
171 *      There is no requirement that the semaphore be within the pool
172 *
173 *  Deficiencies/ToDo:
174 *
175 */
176
177
178rtems_unsigned32
179hppa_semaphore_acquire(hppa_semaphore_t *sp,
180                       int               flag)
181{
182    rtems_unsigned32 lock_value;
183    rtems_unsigned32 spin_count = 1;
184
185    SEM_CHECK(sp);
186
187    for (;;)
188    {
189        HPPA_ASM_LDCWS(0, 0, sp, lock_value);
190
191        if (lock_value)         /* we now own the lock */
192        {
193            SEM_MARK_GRABBED(sp);
194            return spin_count ? spin_count : ~0;        /* jic */
195        }
196
197        if (flag & HPPA_SEM_NO_SPIN)
198            return 0;
199
200        spin_count++;
201    }
202}
203
204void
205hppa_semaphore_release(hppa_semaphore_t *sp)
206{
207    SEM_CHECK(sp);
208
209    if (sp->owner_tcb != _Thread_Executing)
210        SEM_FATAL_ERROR("owner mismatch");
211
212    sp->lock = 1;
213}
214
215
216/*
217 *  Function:   hppa_semaphore_allocate
218 *  Created:    94/11/29
219 *  RespEngr:   tony bennett
220 *
221 *  Description:
222 *      Get a pointer to a semaphore.
223 *
224 *  Parameters:
225 *      which -- if 0, then allocate a free semaphore from the pool
226 *               if non-zero, then return pointer to that one, even
227 *                  if it is already busy.
228 *
229 *  Returns:
230 *      successful -- pointer to semaphore
231 *                    NULL otherwise
232 *
233 *  Notes:
234 *
235 *
236 *  Deficiencies/ToDo:
237 *
238 *
239 */
240
241hppa_semaphore_t *
242hppa_semaphore_allocate(rtems_unsigned32 which,
243                        int              flag)
244{
245    hppa_semaphore_t *sp = 0;
246
247    /*
248     * grab the control semaphore
249     */
250
251    if (hppa_semaphore_acquire(SEM_CONTROL, 0) == 0)
252        SEM_FATAL_ERROR("could not grab control semaphore");
253
254    /*
255     * Find a free one and init it
256     */
257
258    if (which)
259    {
260        if (which >= hppa_semaphores)
261            SEM_FATAL_ERROR("requested non-existent semaphore");
262        sp = &hppa_semaphore_pool[which];
263
264        /*
265         * if it is "free", then mark it claimed now.
266         * If it is not free then we are done.
267         */
268
269        if (SEM_IS_AVAILABLE(sp))
270            goto allmine;
271    }
272    else for (sp = SEM_FIRST;
273              sp < &hppa_semaphore_pool[hppa_semaphores];
274              sp++)
275    {
276        if (SEM_IS_AVAILABLE(sp))
277        {
278allmine:    SEM_FREE_INIT(sp);
279            SEM_MARK_BUSY(sp);
280            if ( ! (flag & HPPA_SEM_INITIALLY_FREE))
281                SEM_MARK_GRABBED(sp);
282            break;
283        }
284    }
285
286    /*
287     * Free up the control semaphore
288     */
289
290    hppa_semaphore_release(SEM_CONTROL);
291
292    return sp;
293}
294
Note: See TracBrowser for help on using the repository browser.