Voxia OS v0.0.1
Hobby Project Operating System Targeting x86-64
Loading...
Searching...
No Matches
console.c
Go to the documentation of this file.
1#include <console/console.h>
3#include <libk/serial.h>
4#include <memory/kalloc.h>
5#include <spinlock.h>
6#include <str.h>
7#include <type.h>
8
9#define SLOT_EMPTY 0x00
10#define SLOT_WRITING 0xFE
11#define SLOT_DROPPED 0xFF
12
13#define CONSOLE_BUFFER_SIZE 2048
14#define CONSOLE_BUFFER_MASK (CONSOLE_BUFFER_SIZE - 1)
15#define SPIN_LIMIT 500000u
16
17typedef struct {
18 char data[128];
22
28
30static volatile unsigned char __console_flush_lock = 0;
32
33static int pos_x = 0;
34static int pos_y = 0;
35static uint32_t fgcolor = 0xFFFFFFFF;
36
37static void do_scroll(void) {
38 int rows = (int)screen_rows();
40 pos_y = rows > 0 ? rows - 1 : 0;
41 pos_x = 0;
42}
43
44static void advance_cursor(void) {
45 pos_x++;
46 if (pos_x >= (int)screen_cols()) {
47 pos_x = 0;
48 pos_y++;
49 }
50 if (pos_y >= (int)screen_rows())
51 do_scroll();
52}
53
54static void put_char_raw(char c, uint32_t color) {
55 if (c == '\n') {
56 pos_x = 0;
57 pos_y++;
58 if (pos_y >= (int)screen_rows())
59 do_scroll();
60 return;
61 }
62 if (c == '\r') {
63 pos_x = 0;
64 return;
65 }
66 if (c == '\t') {
67 int next = (pos_x + 8) & ~7;
68 while (pos_x < next)
70 return;
71 }
72 putc(c, pos_x, pos_y, color, BLACK);
74}
75
76static bool reserve_slot(uint32_t* out_idx) {
78 for (;;) {
79 head =
80 __atomic_load_n(&__console_buffer.head, __ATOMIC_RELAXED);
81 tail =
82 __atomic_load_n(&__console_buffer.tail, __ATOMIC_ACQUIRE);
83
84 if ((head - tail) >= CONSOLE_BUFFER_SIZE)
85 return false;
86
87 if (__atomic_compare_exchange_n(
88 &__console_buffer.head, &head, head + 1, true,
89 __ATOMIC_ACQ_REL, __ATOMIC_RELAXED))
90 break;
91 __asm__ volatile("pause");
92 }
93 *out_idx = head & CONSOLE_BUFFER_MASK;
94 return true;
95}
96
97static void put_into_buffer(const char* str, uint8_t len, uint32_t color) {
99 if (!reserve_slot(&idx))
100 return;
101
102 console_entry_t* entry = &__console_buffer.buffer[idx];
103
104 uint32_t spin = 0;
105 while (__atomic_load_n(&entry->len, __ATOMIC_ACQUIRE) != SLOT_EMPTY) {
106 if (++spin >= SPIN_LIMIT) {
107 __atomic_store_n(&entry->len, SLOT_DROPPED,
108 __ATOMIC_RELEASE);
109 return;
110 }
111 __asm__ volatile("pause");
112 }
113
114 __atomic_store_n(&entry->len, SLOT_WRITING, __ATOMIC_RELEASE);
115 entry->fg = color;
116
117 if (len > 128)
118 len = 128;
119 for (uint8_t i = 0; i < len; i++)
120 entry->data[i] = str[i];
121
122 __atomic_store_n(&entry->len, len, __ATOMIC_RELEASE);
123}
124
125static void console_flush(void) {
126 if (__atomic_test_and_set(&__console_flush_lock, __ATOMIC_ACQUIRE))
127 return;
128
129 for (;;) {
130 uint32_t tail =
131 __atomic_load_n(&__console_buffer.tail, __ATOMIC_RELAXED);
132 uint32_t head =
133 __atomic_load_n(&__console_buffer.head, __ATOMIC_ACQUIRE);
134
135 if (tail == head)
136 break;
137
138 console_entry_t* entry =
140
141 uint32_t spin = 0;
142 uint8_t len;
143 for (;;) {
144 len = __atomic_load_n(&entry->len, __ATOMIC_ACQUIRE);
145 if (len != SLOT_EMPTY && len != SLOT_WRITING)
146 break;
147 if (len == SLOT_EMPTY)
148 break;
149 if (++spin >= SPIN_LIMIT)
150 break;
151 __asm__ volatile("pause");
152 }
153
154 if (len != SLOT_EMPTY && len != SLOT_WRITING &&
155 len != SLOT_DROPPED) {
156 for (uint8_t i = 0; i < len; i++) {
157 put_char_raw(entry->data[i], entry->fg);
158 }
159 }
160
161 __atomic_store_n(&entry->len, SLOT_EMPTY, __ATOMIC_RELEASE);
162 __atomic_store_n(&__console_buffer.tail, tail + 1,
163 __ATOMIC_RELEASE);
164 }
165
166 __atomic_clear(&__console_flush_lock, __ATOMIC_RELEASE);
167}
168
169int console_get_pos_x(void) { return pos_x; }
170int console_get_pos_y(void) { return pos_y; }
171
172void console_println(const char* str) {
173 size_t len = strlen(str);
175 put_into_buffer("\n", 1, fgcolor);
177}
178
179void console_print(const char* str, uint64_t len) {
180 while (len > 0) {
181 uint8_t chunk = (len > 128) ? 128 : (uint8_t)len;
182 put_into_buffer(str, chunk, fgcolor);
183 str += chunk;
184 len -= chunk;
185 }
187}
188
189static char* val_to_str(uint64_t val, uint64_t base) {
190 char* out = (char*)kalloc(65);
191 if (!out)
192 return NULL;
193
194 if (val == 0) {
195 out[0] = '0';
196 out[1] = '\0';
197 return out;
198 }
199
200 char buf[65];
201 int i = 0, j = 0;
202 const char* digits = "0123456789ABCDEF";
203 while (val > 0) {
204 buf[i++] = digits[val % base];
205 val /= base;
206 }
207
208 for (i = i - 1; i >= 0; i--)
209 out[j++] = buf[i];
210 out[j] = '\0';
211 return out;
212}
213
214static void vprintf_internal(const char* fmt, __builtin_va_list args) {
215 char temp[128];
216 int tidx = 0;
217
218#define FLUSH_TEMP() \
219 if (tidx > 0) { \
220 put_into_buffer(temp, (uint8_t)tidx, fgcolor); \
221 tidx = 0; \
222 }
223
224 while (*fmt) {
225 if (*fmt == '%') {
226 FLUSH_TEMP();
227 fmt++;
228 if (*fmt == '\0') {
229 break;
230 }
231 switch (*fmt) {
232 case 's': {
233 char* s = __builtin_va_arg(args, char*);
234 if (!s)
235 s = "(null)";
236 size_t slen = strlen(s);
237 while (slen > 0) {
238 uint8_t c =
239 (slen > 128) ? 128 : (uint8_t)slen;
241 s += c;
242 slen -= c;
243 }
244 break;
245 }
246 case 'd': {
247 int64_t n = __builtin_va_arg(args, int64_t);
248 if (n < 0) {
249 put_into_buffer("-", 1, fgcolor);
250 n = -n;
251 }
252 char* s = val_to_str((uint64_t)n, 10);
253 if (s) {
255 fgcolor);
256 kfree2(s);
257 }
258 break;
259 }
260 case 'u': {
261 char* s = val_to_str(
262 __builtin_va_arg(args, uint64_t), 10);
263 if (s) {
265 fgcolor);
266 kfree2(s);
267 }
268 break;
269 }
270 case 'x': {
271 char* s = val_to_str(
272 __builtin_va_arg(args, uint64_t), 16);
273 if (s) {
275 fgcolor);
276 kfree2(s);
277 }
278 break;
279 }
280 case 'b': {
281 char* s = val_to_str(
282 __builtin_va_arg(args, uint64_t), 2);
283 if (s) {
285 fgcolor);
286 kfree2(s);
287 }
288 break;
289 }
290 case 'c': {
291 char c = (char)__builtin_va_arg(args, int);
292 put_into_buffer(&c, 1, fgcolor);
293 break;
294 }
295 case '%':
296 put_into_buffer("%", 1, fgcolor);
297 break;
298 default:
299 put_into_buffer("%", 1, fgcolor);
300 put_into_buffer(fmt, 1, fgcolor);
301 break;
302 }
303 } else {
304 temp[tidx++] = *fmt;
305 if (tidx == 128)
306 FLUSH_TEMP();
307 }
308 fmt++;
309 }
310 FLUSH_TEMP();
311}
312
313#include <hal/cpu/irq_lock.h>
314
315void console_printf(const char* fmt, ...) {
318
319 __builtin_va_list args;
320 __builtin_va_start(args, fmt);
321 vprintf_internal(fmt, args);
322 __builtin_va_end(args);
324
327}
328
329void console_vaprintf(const char* fmt, __builtin_va_list args) {
332
333 vprintf_internal(fmt, args);
335
338}
339
350
351void console_chfg(uint32_t color) { fgcolor = color; }
352
353void console_add_space(int n) {
356
357 while (n > 0) {
358 int c = (n > 128) ? 128 : n;
359 char spaces[128];
360 for (int i = 0; i < c; i++)
361 spaces[i] = ' ';
362 put_into_buffer(spaces, (uint8_t)c, fgcolor);
363 n -= c;
364 }
366
369}
370
371void console_set_pos(int x, int y) {
372 pos_x = x;
373 pos_y = y;
374}
void console_chfg(uint32_t color)
Definition console.c:351
static void do_scroll(void)
Definition console.c:37
static spinlock_t __console_producer_lock
Definition console.c:31
void console_add_space(int n)
Definition console.c:353
void console_set_pos(int x, int y)
Definition console.c:371
static void console_flush(void)
Definition console.c:125
void console_vaprintf(const char *fmt, __builtin_va_list args)
Definition console.c:329
static uint32_t fgcolor
Definition console.c:35
static void vprintf_internal(const char *fmt, __builtin_va_list args)
Definition console.c:214
void console_printf(const char *fmt,...)
Definition console.c:315
#define SLOT_WRITING
Definition console.c:10
void console_print(const char *str, uint64_t len)
Definition console.c:179
int console_get_pos_x(void)
Definition console.c:169
#define CONSOLE_BUFFER_SIZE
Definition console.c:13
static int pos_y
Definition console.c:34
void console_newline(void)
Definition console.c:340
static char * val_to_str(uint64_t val, uint64_t base)
Definition console.c:189
static int pos_x
Definition console.c:33
static volatile unsigned char __console_flush_lock
Definition console.c:30
static bool reserve_slot(uint32_t *out_idx)
Definition console.c:76
static void put_char_raw(char c, uint32_t color)
Definition console.c:54
void console_println(const char *str)
Definition console.c:172
#define SPIN_LIMIT
Definition console.c:15
static console_ring_buffer_t __console_buffer
Definition console.c:29
#define FLUSH_TEMP()
#define SLOT_EMPTY
Definition console.c:9
static void put_into_buffer(const char *str, uint8_t len, uint32_t color)
Definition console.c:97
#define SLOT_DROPPED
Definition console.c:11
int console_get_pos_y(void)
Definition console.c:170
static void advance_cursor(void)
Definition console.c:44
#define CONSOLE_BUFFER_MASK
Definition console.c:14
@ BLACK
Definition console.h:11
struct cdev * next
Definition dev.h:4
elf_section_map uintptr_t base
Definition elf.h:296
uint32_t screen_cols(void)
Definition graphic.c:327
uint32_t screen_rows(void)
Definition graphic.c:333
void vxScroll(int px)
Definition graphic.c:318
void putc(char c, int col, int row, uint32_t fg, uint32_t bg)
Definition graphic.c:151
#define FONT_SIZE
Definition graphic.h:26
uint16_t flags
Definition thread.h:5
static void irq_restore(uintptr_t flags)
Definition irq_lock.h:20
static uintptr_t irq_save(void)
Definition irq_lock.h:6
void * kalloc(size_t size)
void kfree2(void *ptr)
size_t len
Definition oct2bin.h:7
void spin_acquire(spinlock_t *lock)
Definition spinlock.c:8
void spin_release(spinlock_t *lock)
Definition spinlock.c:19
size_t strlen(const char *s)
Definition str.c:105
kstring str(const char *str)
Definition console.c:17
uint8_t len
Definition console.c:20
char data[128]
Definition console.c:18
uint32_t fg
Definition console.c:19
console_entry_t buffer[2048]
Definition console.c:24
uint32_t rows
Definition tty.h:4
uint32_t tail
Definition tty.h:11
uint32_t head
Definition tty.h:10
#define NULL
Definition type.h:76
unsigned int uint32_t
Definition type.h:19
unsigned long uintptr_t
Definition type.h:73
unsigned long uint64_t
Definition type.h:25
unsigned char uint8_t
Definition type.h:7
signed long int64_t
Definition type.h:49
uint16_t idx
Definition virtio-gpu.hpp:1
uint32_t y
Definition virtio-gpu.hpp:1
uint32_t x
Definition virtio-gpu.hpp:0