• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
fiq_debugger_ringbuf_alloc(int len)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 
fiq_debugger_ringbuf_free(struct fiq_debugger_ringbuf * rbuf)45 static inline void fiq_debugger_ringbuf_free(struct fiq_debugger_ringbuf *rbuf)
46 {
47 	kfree(rbuf);
48 }
49 
fiq_debugger_ringbuf_level(struct fiq_debugger_ringbuf * rbuf)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 
fiq_debugger_ringbuf_room(struct fiq_debugger_ringbuf * rbuf)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
fiq_debugger_ringbuf_peek(struct fiq_debugger_ringbuf * rbuf,int i)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
fiq_debugger_ringbuf_consume(struct fiq_debugger_ringbuf * rbuf,int count)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
fiq_debugger_ringbuf_push(struct fiq_debugger_ringbuf * rbuf,u8 datum)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 }
95