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

4.104.114.84.95
Last change on this file since eb5a7e07 was ac7d5ef0, checked in by Joel Sherrill <joel.sherrill@…>, on 05/11/95 at 17:39:37

Initial revision

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