Xenomai 3.3.2
Loading...
Searching...
No Matches
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
29struct 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
44static 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
63static 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
76static 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
88static 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
111static 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
123static 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... */
135static 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_ */
#define rtdm_lock_get_irqsave(__lock, __context)
Acquire lock and disable preemption, by stalling the head domain.
Definition driver.h:604
unsigned long rtdm_lockctx_t
Variable to save the context while holding a lock.
Definition driver.h:555
static void rtdm_lock_get(rtdm_lock_t *lock)
Acquire lock from non-preemptible contexts.
Definition driver.h:576
pipeline_spinlock_t rtdm_lock_t
Lock variable.
Definition driver.h:552
static void rtdm_lock_init(rtdm_lock_t *lock)
Dynamic lock initialisation.
Definition driver.h:564
static void rtdm_lock_put(rtdm_lock_t *lock)
Release lock without preemption restoration.
Definition driver.h:590
static void rtdm_lock_put_irqrestore(rtdm_lock_t *lock, rtdm_lockctx_t context)
Release lock and restore preemption state.
Definition driver.h:627