source: rtems-libbsd/rtemsbsd/rtems/rtems-bsd-synch.c @ e599318

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since e599318 was e599318, checked in by Sebastian Huber <sebastian.huber@…>, on 10/09/13 at 20:52:54

Update files to match FreeBSD layout

Add compatibility with Newlib header files. Some FreeBSD header files
are mapped by the translation script:

o rtems/bsd/sys/_types.h
o rtems/bsd/sys/errno.h
o rtems/bsd/sys/lock.h
o rtems/bsd/sys/param.h
o rtems/bsd/sys/resource.h
o rtems/bsd/sys/time.h
o rtems/bsd/sys/timespec.h
o rtems/bsd/sys/types.h
o rtems/bsd/sys/unistd.h

It is now possible to include <sys/socket.h> directly for example.

Generate one Makefile which builds everything including tests.

  • Property mode set to 100644
File size: 8.4 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup rtems_bsd_rtems
5 *
6 * @brief TODO.
7 */
8
9/*
10 * Copyright (c) 2009, 2010 embedded brains GmbH.  All rights reserved.
11 *
12 *  embedded brains GmbH
13 *  Obere Lagerstr. 30
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 * 1. Redistributions of source code must retain the above copyright
22 *    notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 *    notice, this list of conditions and the following disclaimer in the
25 *    documentation and/or other materials provided with the distribution.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 */
39
40/*
41 * FIXME: This seems to be a completely broken implementation.
42 */
43
44#include <machine/rtems-bsd-config.h>
45
46#include <rtems/score/statesimpl.h>
47#include <rtems/score/threaddispatch.h>
48#include <rtems/score/thread.h>
49#include <rtems/score/threadqimpl.h>
50
51#include <rtems/bsd/sys/param.h>
52#include <rtems/bsd/sys/types.h>
53#include <sys/systm.h>
54#include <sys/kernel.h>
55#include <sys/ktr.h>
56#include <rtems/bsd/sys/lock.h>
57#include <sys/mutex.h>
58#include <sys/proc.h>
59#include <machine/pcpu.h>
60
61#define STATES_WAITING_FOR_SLEEP              0x40000
62
63static int pause_wchan;
64
65typedef struct
66{
67  Chain_Node node;
68  void *ident;
69  Thread_queue_Control queue;
70}sleep_queue_control_t;
71
72sleep_queue_control_t sleep_queue[BSD_MAXIMUM_SLEEP_QUEUES]; //this memory allocation could use _Workspace_Allocate once inside RTEMS tree
73Chain_Control sleep_queue_inactive_nodes;  //chain of inactive nodes
74Chain_Control sleep_queue_active_nodes;    //chain of active nodes
75
76void
77sleepinit(void)
78{
79  int ii;
80
81  /* initialize the sleep queue */
82  for( ii = 0; ii < BSD_MAXIMUM_SLEEP_QUEUES; ii++ )
83  {
84    sleep_queue[ii].ident = NULL;
85    /*
86     *  Initialize the queue we use to block for signals
87     */
88    _Thread_queue_Initialize(
89      &sleep_queue[ii].queue,
90      THREAD_QUEUE_DISCIPLINE_PRIORITY,
91      STATES_WAITING_FOR_SLEEP | STATES_INTERRUPTIBLE_BY_SIGNAL,
92      EAGAIN
93    );
94  }
95  //initialize active chain
96  _Chain_Initialize_empty( &sleep_queue_active_nodes );
97  //initialize inactive chain
98  _Chain_Initialize( &sleep_queue_inactive_nodes, sleep_queue, BSD_MAXIMUM_SLEEP_QUEUES, sizeof( sleep_queue_control_t ));
99}
100
101sleep_queue_control_t*
102sleep_queue_lookup(void *ident)
103{
104  int ii;
105
106  /* initialize the sleep queue */
107  for( ii = 0; ii < BSD_MAXIMUM_SLEEP_QUEUES; ii++ )
108  {
109    if( sleep_queue[ii].ident == ident )
110    {
111      return &sleep_queue[ii];
112    }
113  }
114  return NULL;
115}
116
117sleep_queue_control_t*
118sleep_queue_get(void *ident)
119{
120  sleep_queue_control_t *sq;
121
122  sq = sleep_queue_lookup( ident );
123  if (sq == NULL)
124  {
125    KASSERT(!_Chain_Is_empty( &inactive_nodes ), ("sleep_queue_get"));
126    //get a control from the inactive chain
127    sq = ( sleep_queue_control_t * )_Chain_Get( &sleep_queue_inactive_nodes );
128    sq->ident = ident;
129    _Chain_Append( &sleep_queue_active_nodes, &sq->node );
130  }
131  return sq;
132}
133
134/*
135 * Block the current thread until it is awakened from its sleep queue
136 * or it times out while waiting.
137 */
138int
139sleep_queue_timedwait(void *wchan, int pri, int timeout, int catch)
140{
141  sleep_queue_control_t *sq;
142  Thread_Control *executing;
143  ISR_Level       level;
144
145  _Thread_Disable_dispatch();
146
147  sq = sleep_queue_get( wchan );
148
149  executing = _Thread_Executing;
150  if( timeout )
151  {
152    executing->Wait.return_code = EWOULDBLOCK;
153  }
154  else
155  {
156    executing->Wait.return_code = 0;
157  }
158  _ISR_Disable( level );
159  _Thread_queue_Enter_critical_section( &sq->queue );
160  if( catch )
161  {
162    sq->queue.state |= STATES_INTERRUPTIBLE_BY_SIGNAL;
163  }
164  else
165  {
166    sq->queue.state &= ~STATES_INTERRUPTIBLE_BY_SIGNAL;
167  }
168  executing->Wait.queue = &sq->queue;
169  _ISR_Enable( level );
170
171  _Thread_queue_Enqueue( &sq->queue, executing, timeout );
172  _Thread_Enable_dispatch();
173  return _Thread_Executing->Wait.return_code;
174}
175
176/*
177 * General sleep call.  Suspends the current thread until a wakeup is
178 * performed on the specified identifier.  The thread will then be made
179 * runnable with the specified priority.  Sleeps at most timo/hz seconds
180 * (0 means no timeout).  If pri includes PCATCH flag, signals are checked
181 * before and after sleeping, else signals are not checked.  Returns 0 if
182 * awakened, EWOULDBLOCK if the timeout expires.  If PCATCH is set and a
183 * signal needs to be delivered, ERESTART is returned if the current system
184 * call should be restarted if possible, and EINTR is returned if the system
185 * call should be interrupted by the signal (return EINTR).
186 *
187 * The lock argument is unlocked before the caller is suspended, and
188 * re-locked before _sleep() returns.  If priority includes the PDROP
189 * flag the lock is not re-locked before returning.
190 */
191int
192_sleep(void *ident, struct lock_object *lock, int priority, const char *wmesg, int timo)
193{
194  struct thread *td;
195  struct lock_class *class;
196  int catch, flags, lock_state, pri, rval;
197
198  td = curthread;
199#ifdef KTRACE
200  if (KTRPOINT(td, KTR_CSW))
201    ktrcsw(1, 0);
202#endif
203  KASSERT(timo != 0 || mtx_owned(&Giant) || lock != NULL,
204      ("sleeping without a lock"));
205  KASSERT(ident != NULL && TD_IS_RUNNING(td), ("msleep"));
206  if (priority & PDROP)
207    KASSERT(lock != NULL && lock != &Giant.lock_object,
208        ("PDROP requires a non-Giant lock"));
209  if (lock != NULL)
210    class = LOCK_CLASS(lock);
211  else
212    class = NULL;
213
214  if (cold) {
215    /*
216     * During autoconfiguration, just return;
217     * don't run any other threads or panic below,
218     * in case this is the idle thread and already asleep.
219     * XXX: this used to do "s = splhigh(); splx(safepri);
220     * splx(s);" to give interrupts a chance, but there is
221     * no way to give interrupts a chance now.
222     */
223    if (lock != NULL && priority & PDROP)
224      class->lc_unlock(lock);
225    return (0);
226  }
227  catch = priority & PCATCH;
228  pri = priority & PRIMASK;
229
230  if (lock == &Giant.lock_object)
231    mtx_assert(&Giant, MA_OWNED);
232  DROP_GIANT();
233  if (lock != NULL && lock != &Giant.lock_object &&
234      !(class->lc_flags & LC_SLEEPABLE)) {
235    lock_state = class->lc_unlock(lock);
236  } else
237    /* GCC needs to follow the Yellow Brick Road */
238    lock_state = -1;
239
240  if (lock != NULL && class->lc_flags & LC_SLEEPABLE) {
241    lock_state = class->lc_unlock(lock);
242  }
243
244  rval = sleep_queue_timedwait(ident, pri, timo, catch);
245
246#ifdef KTRACE
247  if (KTRPOINT(td, KTR_CSW))
248    ktrcsw(0, 0);
249#endif
250  PICKUP_GIANT();
251  if (lock != NULL && lock != &Giant.lock_object && !(priority & PDROP)) {
252    class->lc_lock(lock, lock_state);
253  }
254  return (rval);
255}
256
257/*
258 * pause() is like tsleep() except that the intention is to not be
259 * explicitly woken up by another thread.  Instead, the current thread
260 * simply wishes to sleep until the timeout expires.  It is
261 * implemented using a dummy wait channel.
262 */
263int
264pause(const char *wmesg, int timo)
265{
266
267  KASSERT(timo != 0, ("pause: timeout required"));
268  return (tsleep(&pause_wchan, 0, wmesg, timo));
269}
270
271/*
272 * Make all threads sleeping on the specified identifier runnable.
273 */
274void
275wakeup(void *ident)
276{
277  sleep_queue_control_t *sq;
278  Thread_Control *the_thread;
279
280  sq = sleep_queue_lookup( ident );
281  if (sq == NULL)
282  {
283    return (0);
284  }
285
286  while ( (the_thread = _Thread_queue_Dequeue(&sq->queue)) )
287  {
288  }
289  return 0;
290}
291
292/*
293 * Make a thread sleeping on the specified identifier runnable.
294 * May wake more than one thread if a target thread is currently
295 * swapped out.
296 */
297void
298wakeup_one(void *ident)
299{
300  sleep_queue_control_t *sq;
301  Thread_Control *the_thread;
302
303  sq = sleep_queue_lookup( ident );
304  if (sq == NULL)
305  {
306    return (0);
307  }
308  the_thread = _Thread_queue_Dequeue(&sq->queue);
309  return 0;
310
311}
312
Note: See TracBrowser for help on using the repository browser.