diff options
Diffstat (limited to 'arch/arm/common/fiq_debugger_ringbuf.h')
-rw-r--r-- | arch/arm/common/fiq_debugger_ringbuf.h | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/arch/arm/common/fiq_debugger_ringbuf.h b/arch/arm/common/fiq_debugger_ringbuf.h new file mode 100644 index 00000000000..2649b558108 --- /dev/null +++ b/arch/arm/common/fiq_debugger_ringbuf.h | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | * arch/arm/common/fiq_debugger_ringbuf.c | ||
3 | * | ||
4 | * simple lockless ringbuffer | ||
5 | * | ||
6 | * Copyright (C) 2010 Google, Inc. | ||
7 | * | ||
8 | * This software is licensed under the terms of the GNU General Public | ||
9 | * License version 2, as published by the Free Software Foundation, and | ||
10 | * may be copied, distributed, and modified under those terms. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/slab.h> | ||
20 | |||
21 | struct fiq_debugger_ringbuf { | ||
22 | int len; | ||
23 | int head; | ||
24 | int tail; | ||
25 | u8 buf[]; | ||
26 | }; | ||
27 | |||
28 | |||
29 | static inline struct fiq_debugger_ringbuf *fiq_debugger_ringbuf_alloc(int len) | ||
30 | { | ||
31 | struct fiq_debugger_ringbuf *rbuf; | ||
32 | |||
33 | rbuf = kzalloc(sizeof(*rbuf) + len, GFP_KERNEL); | ||
34 | if (rbuf == NULL) | ||
35 | return NULL; | ||
36 | |||
37 | rbuf->len = len; | ||
38 | rbuf->head = 0; | ||
39 | rbuf->tail = 0; | ||
40 | smp_mb(); | ||
41 | |||
42 | return rbuf; | ||
43 | } | ||
44 | |||
45 | static inline void fiq_debugger_ringbuf_free(struct fiq_debugger_ringbuf *rbuf) | ||
46 | { | ||
47 | kfree(rbuf); | ||
48 | } | ||
49 | |||
50 | static inline int fiq_debugger_ringbuf_level(struct fiq_debugger_ringbuf *rbuf) | ||
51 | { | ||
52 | int level = rbuf->head - rbuf->tail; | ||
53 | |||
54 | if (level < 0) | ||
55 | level = rbuf->len + level; | ||
56 | |||
57 | return level; | ||
58 | } | ||
59 | |||
60 | static inline int fiq_debugger_ringbuf_room(struct fiq_debugger_ringbuf *rbuf) | ||
61 | { | ||
62 | return rbuf->len - fiq_debugger_ringbuf_level(rbuf) - 1; | ||
63 | } | ||
64 | |||
65 | static inline u8 | ||
66 | fiq_debugger_ringbuf_peek(struct fiq_debugger_ringbuf *rbuf, int i) | ||
67 | { | ||
68 | return rbuf->buf[(rbuf->tail + i) % rbuf->len]; | ||
69 | } | ||
70 | |||
71 | static inline int | ||
72 | fiq_debugger_ringbuf_consume(struct fiq_debugger_ringbuf *rbuf, int count) | ||
73 | { | ||
74 | count = min(count, fiq_debugger_ringbuf_level(rbuf)); | ||
75 | |||
76 | rbuf->tail = (rbuf->tail + count) % rbuf->len; | ||
77 | smp_mb(); | ||
78 | |||
79 | return count; | ||
80 | } | ||
81 | |||
82 | static inline int | ||
83 | fiq_debugger_ringbuf_push(struct fiq_debugger_ringbuf *rbuf, u8 datum) | ||
84 | { | ||
85 | if (fiq_debugger_ringbuf_room(rbuf) == 0) | ||
86 | return 0; | ||
87 | |||
88 | rbuf->buf[rbuf->head] = datum; | ||
89 | smp_mb(); | ||
90 | rbuf->head = (rbuf->head + 1) % rbuf->len; | ||
91 | smp_mb(); | ||
92 | |||
93 | return 1; | ||
94 | } | ||