Xenomai  3.1
rtskb_fifo.h
1 /***
2  *
3  * include/rtskb_fifo.h
4  *
5  * RTnet - real-time networking subsystem
6  * Copyright (C) 2006 Jan Kiszka <jan.kiszka@web.de>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  *
22  */
23 
24 #ifndef __RTSKB_FIFO_H_
25 #define __RTSKB_FIFO_H_
26 
27 #include <rtskb.h>
28 
29 struct rtskb_fifo {
30  unsigned long read_pos ____cacheline_aligned_in_smp;
31  rtdm_lock_t read_lock;
32  unsigned long size_mask;
33  unsigned long write_pos ____cacheline_aligned_in_smp;
34  rtdm_lock_t write_lock;
35  struct rtskb *buffer[0];
36 };
37 
38 #define DECLARE_RTSKB_FIFO(name_prefix, size) \
39  struct { \
40  struct rtskb_fifo fifo; \
41  struct rtskb *__buffer[(size)]; \
42  } name_prefix
43 
44 static inline int __rtskb_fifo_insert(struct rtskb_fifo *fifo,
45  struct rtskb *rtskb)
46 {
47  unsigned long pos = fifo->write_pos;
48  unsigned long new_pos = (pos + 1) & fifo->size_mask;
49 
50  if (unlikely(new_pos == fifo->read_pos))
51  return -EAGAIN;
52 
53  fifo->buffer[pos] = rtskb;
54 
55  /* rtskb must have been written before write_pos update */
56  smp_wmb();
57 
58  fifo->write_pos = new_pos;
59 
60  return 0;
61 }
62 
63 static inline int rtskb_fifo_insert(struct rtskb_fifo *fifo,
64  struct rtskb *rtskb)
65 {
66  rtdm_lockctx_t context;
67  int result;
68 
69  rtdm_lock_get_irqsave(&fifo->write_lock, context);
70  result = __rtskb_fifo_insert(fifo, rtskb);
71  rtdm_lock_put_irqrestore(&fifo->write_lock, context);
72 
73  return result;
74 }
75 
76 static inline int rtskb_fifo_insert_inirq(struct rtskb_fifo *fifo,
77  struct rtskb *rtskb)
78 {
79  int result;
80 
81  rtdm_lock_get(&fifo->write_lock);
82  result = __rtskb_fifo_insert(fifo, rtskb);
83  rtdm_lock_put(&fifo->write_lock);
84 
85  return result;
86 }
87 
88 static inline struct rtskb *__rtskb_fifo_remove(struct rtskb_fifo *fifo)
89 {
90  unsigned long pos = fifo->read_pos;
91  struct rtskb *result;
92 
93  /* check FIFO status first */
94  if (unlikely(pos == fifo->write_pos))
95  return NULL;
96 
97  /* at least one rtskb is enqueued, so get the next one */
98  result = fifo->buffer[pos];
99 
100  /* result must have been read before read_pos update */
101  smp_rmb();
102 
103  fifo->read_pos = (pos + 1) & fifo->size_mask;
104 
105  /* read_pos must have been written for a consitent fifo state on exit */
106  smp_wmb();
107 
108  return result;
109 }
110 
111 static inline struct rtskb *rtskb_fifo_remove(struct rtskb_fifo *fifo)
112 {
113  rtdm_lockctx_t context;
114  struct rtskb *result;
115 
116  rtdm_lock_get_irqsave(&fifo->read_lock, context);
117  result = __rtskb_fifo_remove(fifo);
118  rtdm_lock_put_irqrestore(&fifo->read_lock, context);
119 
120  return result;
121 }
122 
123 static inline struct rtskb *rtskb_fifo_remove_inirq(struct rtskb_fifo *fifo)
124 {
125  struct rtskb *result;
126 
127  rtdm_lock_get(&fifo->read_lock);
128  result = __rtskb_fifo_remove(fifo);
129  rtdm_lock_put(&fifo->read_lock);
130 
131  return result;
132 }
133 
134 /* for now inlined... */
135 static inline void rtskb_fifo_init(struct rtskb_fifo *fifo, unsigned long size)
136 {
137  fifo->read_pos = 0;
138  fifo->write_pos = 0;
139  fifo->size_mask = size - 1;
140  rtdm_lock_init(&fifo->read_lock);
141  rtdm_lock_init(&fifo->write_lock);
142 }
143 
144 #endif /* __RTSKB_FIFO_H_ */
static void rtdm_lock_put_irqrestore(rtdm_lock_t *lock, rtdm_lockctx_t context)
Release lock and restore preemption state
Definition: driver.h:631
ipipe_spinlock_t rtdm_lock_t
Lock variable.
Definition: driver.h:551
static void rtdm_lock_put(rtdm_lock_t *lock)
Release lock without preemption restoration
Definition: driver.h:592
#define rtdm_lock_get_irqsave(__lock, __context)
Acquire lock and disable preemption, by stalling the head domain.
Definition: driver.h:607
static void rtdm_lock_init(rtdm_lock_t *lock)
Dynamic lock initialisation
Definition: driver.h:564
unsigned long rtdm_lockctx_t
Variable to save the context while holding a lock.
Definition: driver.h:554
static void rtdm_lock_get(rtdm_lock_t *lock)
Acquire lock from non-preemptible contexts
Definition: driver.h:577