Skip to content

Commit 7c3f05a

Browse files
committed
Implementation of board drawing
Instead of drawing the board into fast_buf, we design a buffer called draw_buffer which only takes space of DRAWBUFFER_SIZE bytes, it consumes less memory space and meanwhile we utilize "produce_board()" to copy the data into kfifo buffer rather than using "produce_data()", which can copy the whole board data at once. Consumer in simrupt_work_func() is removed since we do not consume the data one byte at a time, we simply consume them all at once, that's why we remove the loop ,too.
1 parent 6093cdd commit 7c3f05a

File tree

4 files changed

+127
-56
lines changed

4 files changed

+127
-56
lines changed

Makefile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
NAME = simrupt
2-
obj-m := $(NAME).o
1+
TARGET = kmldrv
2+
kmldrv-objs = simrupt.o
3+
obj-m := $(TARGET).o
34

45
KDIR ?= /lib/modules/$(shell uname -r)/build
56
PWD := $(shell pwd)

game.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#pragma once
2+
3+
#define BOARD_SIZE 4
4+
#define GOAL 3
5+
#define ALLOW_EXCEED 1
6+
#define N_GRIDS (BOARD_SIZE * BOARD_SIZE)
7+
#define GET_INDEX(i, j) ((i) * (BOARD_SIZE) + (j))
8+
#define GET_COL(x) ((x) % BOARD_SIZE)
9+
#define GET_ROW(x) ((x) / BOARD_SIZE)
10+
11+
#define for_each_empty_grid(i, table) \
12+
for (int i = 0; i < N_GRIDS; i++) \
13+
if (table[i] == ' ')
14+
15+
typedef struct {
16+
int i_shift, j_shift;
17+
int i_lower_bound, j_lower_bound, i_upper_bound, j_upper_bound;
18+
} line_t;
19+
20+
#define DRAW_SIZE (N_GRIDS + BOARD_SIZE)
21+
#define DRAWBUFFER_SIZE \
22+
((BOARD_SIZE * (BOARD_SIZE + 1) << 1) + (BOARD_SIZE * BOARD_SIZE) + \
23+
((BOARD_SIZE << 1) + 1))
24+
25+
extern const line_t lines[4];
26+
27+
// void draw_board(const char *t);

scripts/pre-commit.hook

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
CPPCHECK_suppresses="--suppress=unmatchedSuppression \
44
--suppress=missingIncludeSystem -i ksort.mod.c --suppress=variableScope \
5+
--suppress=unmatchedSuppression:simrupt.c \
56
--suppress=constParameterPointer:simrupt.c \
67
--suppress=constParameterCallback:simrupt.c"
78
CPPCHECK_OPTS="-I. --enable=all --error-exitcode=1 --force $CPPCHECK_suppresses ."

simrupt.c

Lines changed: 96 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#include <linux/version.h>
1111
#include <linux/workqueue.h>
1212

13+
#include "game.h"
14+
1315
MODULE_LICENSE("Dual MIT/GPL");
1416
MODULE_AUTHOR("National Cheng Kung University, Taiwan");
1517
MODULE_DESCRIPTION("A device that simulates interrupts");
@@ -38,6 +40,8 @@ static int major;
3840
static struct class *simrupt_class;
3941
static struct cdev simrupt_cdev;
4042

43+
static char draw_buffer[DRAWBUFFER_SIZE];
44+
4145
/* Data are stored into a kfifo buffer before passing them to the userspace */
4246
static DECLARE_KFIFO_PTR(rx_fifo, unsigned char);
4347

@@ -58,14 +62,25 @@ static inline int update_simrupt_data(void)
5862
}
5963

6064
/* Insert a value into the kfifo buffer */
61-
static void produce_data(unsigned char val)
65+
// static void produce_data(unsigned char val)
66+
// {
67+
// /* Implement a kind of circular FIFO here (skip oldest element if kfifo
68+
// * buffer is full).
69+
// */
70+
// unsigned int len = kfifo_in(&rx_fifo, &val, sizeof(val));
71+
// if (unlikely(len < sizeof(val)) && printk_ratelimit())
72+
// pr_warn("%s: %zu bytes dropped\n", __func__, sizeof(val) - len);
73+
74+
// pr_debug("simrupt: %s: in %u/%u bytes\n", __func__, len,
75+
// kfifo_len(&rx_fifo));
76+
// }
77+
78+
/* Insert the whole chess board into the kfifo buffer */
79+
static void produce_board(void)
6280
{
63-
/* Implement a kind of circular FIFO here (skip oldest element if kfifo
64-
* buffer is full).
65-
*/
66-
unsigned int len = kfifo_in(&rx_fifo, &val, sizeof(val));
67-
if (unlikely(len < sizeof(val)) && printk_ratelimit())
68-
pr_warn("%s: %zu bytes dropped\n", __func__, sizeof(val) - len);
81+
unsigned int len = kfifo_in(&rx_fifo, draw_buffer, sizeof(draw_buffer));
82+
if (unlikely(len < sizeof(draw_buffer)) && printk_ratelimit())
83+
pr_warn("%s: %zu bytes dropped\n", __func__, sizeof(draw_buffer) - len);
6984

7085
pr_debug("simrupt: %s: in %u/%u bytes\n", __func__, len,
7186
kfifo_len(&rx_fifo));
@@ -84,55 +99,89 @@ static DEFINE_MUTEX(consumer_lock);
8499
*/
85100
static struct circ_buf fast_buf;
86101

87-
static int fast_buf_get(void)
88-
{
89-
struct circ_buf *ring = &fast_buf;
102+
// static int fast_buf_get(void)
103+
// {
104+
// struct circ_buf *ring = &fast_buf;
90105

91-
/* prevent the compiler from merging or refetching accesses for tail */
92-
unsigned long head = READ_ONCE(ring->head), tail = ring->tail;
93-
int ret;
106+
// /* prevent the compiler from merging or refetching accesses for tail */
107+
// unsigned long head = READ_ONCE(ring->head), tail = ring->tail;
108+
// int ret;
94109

95-
if (unlikely(!CIRC_CNT(head, tail, PAGE_SIZE)))
96-
return -ENOENT;
110+
// if (unlikely(!CIRC_CNT(head, tail, PAGE_SIZE)))
111+
// return -ENOENT;
97112

98-
/* read index before reading contents at that index */
99-
smp_rmb();
113+
// /* read index before reading contents at that index */
114+
// smp_rmb();
100115

101-
/* extract item from the buffer */
102-
ret = ring->buf[tail];
116+
// /* extract item from the buffer */
117+
// ret = ring->buf[tail];
103118

104-
/* finish reading descriptor before incrementing tail */
105-
smp_mb();
119+
// /* finish reading descriptor before incrementing tail */
120+
// smp_mb();
106121

107-
/* increment the tail pointer */
108-
ring->tail = (tail + 1) & (PAGE_SIZE - 1);
122+
// /* increment the tail pointer */
123+
// ring->tail = (tail + 1) & (PAGE_SIZE - 1);
109124

110-
return ret;
111-
}
125+
// return ret;
126+
// }
112127

113-
static int fast_buf_put(unsigned char val)
128+
/* Draw the board into draw_buffer */
129+
static int draw_board(int pos)
114130
{
115-
struct circ_buf *ring = &fast_buf;
116-
unsigned long head = ring->head;
131+
WRITE_ONCE(pos, pos % N_GRIDS);
132+
WRITE_ONCE(pos, 2 + (pos >> 2) * 16 + ((pos & 3) << 1));
117133

118-
/* prevent the compiler from merging or refetching accesses for tail */
119-
unsigned long tail = READ_ONCE(ring->tail);
134+
pr_info("%d", pos);
120135

121-
/* is circular buffer full? */
122-
if (unlikely(!CIRC_SPACE(head, tail, PAGE_SIZE)))
123-
return -ENOMEM;
124-
125-
ring->buf[ring->head] = val;
126-
127-
/* commit the item before incrementing the head */
136+
int i = 0;
137+
draw_buffer[i++] = '\n';
138+
smp_wmb();
139+
draw_buffer[i++] = '\n';
128140
smp_wmb();
129141

130-
/* update header pointer */
131-
ring->head = (ring->head + 1) & (PAGE_SIZE - 1);
142+
while (i < DRAWBUFFER_SIZE) {
143+
for (int j = 0; j < (BOARD_SIZE << 1) - 1; j++) {
144+
draw_buffer[i++] = j & 1 ? '|' : ' ';
145+
smp_wmb();
146+
}
147+
draw_buffer[i++] = '\n';
148+
smp_wmb();
149+
for (int j = 0; j < (BOARD_SIZE << 1) - 1; j++) {
150+
draw_buffer[i++] = '-';
151+
smp_wmb();
152+
}
153+
draw_buffer[i++] = '\n';
154+
smp_wmb();
155+
}
156+
157+
WRITE_ONCE(draw_buffer[pos], 'O');
132158

133159
return 0;
134160
}
135161

162+
// static int fast_buf_put(unsigned char val)
163+
// {
164+
// struct circ_buf *ring = &fast_buf;
165+
// unsigned long head = ring->head;
166+
167+
// /* prevent the compiler from merging or refetching accesses for tail */
168+
// unsigned long tail = READ_ONCE(ring->tail);
169+
170+
// /* is circular buffer full? */
171+
// if (unlikely(!CIRC_SPACE(head, tail, PAGE_SIZE)))
172+
// return -ENOMEM;
173+
174+
// ring->buf[ring->head] = val;
175+
176+
// /* commit the item before incrementing the head */
177+
// smp_wmb();
178+
179+
// /* update header pointer */
180+
// ring->head = (ring->head + 1) & (PAGE_SIZE - 1);
181+
182+
// return 0;
183+
// }
184+
136185
/* Clear all data from the circular buffer fast_buf */
137186
static void fast_buf_clear(void)
138187
{
@@ -142,7 +191,7 @@ static void fast_buf_clear(void)
142191
/* Workqueue handler: executed by a kernel thread */
143192
static void simrupt_work_func(struct work_struct *w)
144193
{
145-
int val, cpu;
194+
int cpu;
146195

147196
/* This code runs from a kernel thread, so softirqs and hard-irqs must
148197
* be enabled.
@@ -157,20 +206,11 @@ static void simrupt_work_func(struct work_struct *w)
157206
pr_info("simrupt: [CPU#%d] %s\n", cpu, __func__);
158207
put_cpu();
159208

160-
while (1) {
161-
/* Consume data from the circular buffer */
162-
mutex_lock(&consumer_lock);
163-
val = fast_buf_get();
164-
mutex_unlock(&consumer_lock);
209+
/* Store data to the kfifo buffer */
210+
mutex_lock(&producer_lock);
211+
produce_board();
212+
mutex_unlock(&producer_lock);
165213

166-
if (val < 0)
167-
break;
168-
169-
/* Store data to the kfifo buffer */
170-
mutex_lock(&producer_lock);
171-
produce_data(val);
172-
mutex_unlock(&producer_lock);
173-
}
174214
wake_up_interruptible(&rx_wait);
175215
}
176216

@@ -214,7 +254,9 @@ static void process_data(void)
214254
WARN_ON_ONCE(!irqs_disabled());
215255

216256
pr_info("simrupt: [CPU#%d] produce data\n", smp_processor_id());
217-
fast_buf_put(update_simrupt_data());
257+
mutex_lock(&producer_lock);
258+
draw_board(update_simrupt_data());
259+
mutex_unlock(&producer_lock);
218260

219261
pr_info("simrupt: [CPU#%d] scheduling tasklet\n", smp_processor_id());
220262
tasklet_schedule(&simrupt_tasklet);

0 commit comments

Comments
 (0)