Xenomai  3.0.8
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 
30 struct rtskb_fifo {
31  unsigned long read_pos ____cacheline_aligned_in_smp;
32  rtdm_lock_t read_lock;
33  unsigned long size_mask;
34  unsigned long write_pos ____cacheline_aligned_in_smp;
35  rtdm_lock_t write_lock;
36  struct rtskb *buffer[0];
37 };
38 
39 #define DECLARE_RTSKB_FIFO(name_prefix, size) \
40 struct { \
41  struct rtskb_fifo fifo; \
42  struct rtskb *__buffer[(size)]; \
43 } name_prefix \
44 
45 
46 static inline int __rtskb_fifo_insert(struct rtskb_fifo *fifo,
47  struct rtskb *rtskb)
48 {
49  unsigned long pos = fifo->write_pos;
50  unsigned long new_pos = (pos + 1) & fifo->size_mask;
51 
52  if (unlikely(new_pos == fifo->read_pos))
53  return -EAGAIN;
54 
55  fifo->buffer[pos] = rtskb;
56 
57  /* rtskb must have been written before write_pos update */
58  smp_wmb();
59 
60  fifo->write_pos = new_pos;
61 
62  return 0;
63 }
64 
65 static inline int rtskb_fifo_insert(struct rtskb_fifo *fifo,
66  struct rtskb *rtskb)
67 {
68  rtdm_lockctx_t context;
69  int result;
70 
71  rtdm_lock_get_irqsave(&fifo->write_lock, context);
72  result = __rtskb_fifo_insert(fifo, rtskb);
73  rtdm_lock_put_irqrestore(&fifo->write_lock, context);
74 
75  return result;
76 }
77 
78 static inline int rtskb_fifo_insert_inirq(struct rtskb_fifo *fifo,
79  struct rtskb *rtskb)
80 {
81  int result;
82 
83  rtdm_lock_get(&fifo->write_lock);
84  result = __rtskb_fifo_insert(fifo, rtskb);
85  rtdm_lock_put(&fifo->write_lock);
86 
87  return result;
88 }
89 
90 static inline struct rtskb *__rtskb_fifo_remove(struct rtskb_fifo *fifo)
91 {
92  unsigned long pos = fifo->read_pos;
93  struct rtskb *result;
94 
95  /* check FIFO status first */
96  if (unlikely(pos == fifo->write_pos))
97  return NULL;
98 
99  /* at least one rtskb is enqueued, so get the next one */
100  result = fifo->buffer[pos];
101 
102  /* result must have been read before read_pos update */
103  smp_rmb();
104 
105  fifo->read_pos = (pos + 1) & fifo->size_mask;
106 
107  /* read_pos must have been written for a consitent fifo state on exit */
108  smp_wmb();
109 
110  return result;
111 }
112 
113 static inline struct rtskb *rtskb_fifo_remove(struct rtskb_fifo *fifo)
114 {
115  rtdm_lockctx_t context;
116  struct rtskb *result;
117 
118  rtdm_lock_get_irqsave(&fifo->read_lock, context);
119  result = __rtskb_fifo_remove(fifo);
120  rtdm_lock_put_irqrestore(&fifo->read_lock, context);
121 
122  return result;
123 }
124 
125 static inline struct rtskb *rtskb_fifo_remove_inirq(struct rtskb_fifo *fifo)
126 {
127  struct rtskb *result;
128 
129  rtdm_lock_get(&fifo->read_lock);
130  result = __rtskb_fifo_remove(fifo);
131  rtdm_lock_put(&fifo->read_lock);
132 
133  return result;
134 }
135 
136 /* for now inlined... */
137 static inline void rtskb_fifo_init(struct rtskb_fifo *fifo,
138  unsigned long size)
139 {
140  fifo->read_pos = 0;
141  fifo->write_pos = 0;
142  fifo->size_mask = size - 1;
143  rtdm_lock_init(&fifo->read_lock);
144  rtdm_lock_init(&fifo->write_lock);
145 }
146 
147 #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:626
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:589
#define rtdm_lock_get_irqsave(__lock, __context)
Acquire lock and disable preemption, by stalling the head domain.
Definition: driver.h:603
static void rtdm_lock_init(rtdm_lock_t *lock)
Dynamic lock initialisation.
Definition: driver.h:563
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:575