Merge branch 'strawberry-dev' of https://github.com/graphitemaster/toaruos into graphitemaster-strawberry-dev
This commit is contained in:
commit
25807666f9
3
Makefile
3
Makefile
@ -164,8 +164,7 @@ test: system
|
||||
toolchain:
|
||||
@cd toolchain; ./toolchain-build.sh
|
||||
|
||||
# boot.omust be first
|
||||
KERNEL_ASMOBJS += $(filter-out kernel/symbols.o,$(patsubst %.S,%.o,$(wildcard kernel/*.S)))
|
||||
KERNEL_ASMOBJS = $(filter-out kernel/symbols.o,$(patsubst %.S,%.o,$(wildcard kernel/*.S)))
|
||||
|
||||
################
|
||||
# Kernel #
|
||||
|
@ -41,8 +41,11 @@ stack_top:
|
||||
start:
|
||||
/* Setup our stack */
|
||||
mov $stack_top, %esp
|
||||
pushl %esp
|
||||
|
||||
/* Make sure our stack is 16-byte aligned */
|
||||
and $-16, %esp
|
||||
|
||||
pushl %esp
|
||||
pushl %eax /* Multiboot header magic */
|
||||
pushl %ebx /* Multiboot header pointer */
|
||||
|
||||
|
@ -74,7 +74,7 @@ void gdt_install(void) {
|
||||
}
|
||||
|
||||
static void write_tss(int32_t num, uint16_t ss0, uint32_t esp0) {
|
||||
tss_entry_t *tss = &gdt.tss;
|
||||
tss_entry_t * tss = &gdt.tss;
|
||||
uintptr_t base = (uintptr_t)tss;
|
||||
uintptr_t limit = base + sizeof *tss;
|
||||
|
||||
|
@ -44,7 +44,7 @@ void idt_set_gate(uint8_t num, idt_gate_t base, uint16_t sel, uint8_t flags) {
|
||||
}
|
||||
|
||||
void idt_install(void) {
|
||||
idt_pointer_t *idtp = &idt.pointer;
|
||||
idt_pointer_t * idtp = &idt.pointer;
|
||||
idtp->limit = sizeof idt.entries - 1;
|
||||
idtp->base = (uintptr_t)&ENTRY(0);
|
||||
memset(&ENTRY(0), 0, sizeof idt.entries);
|
||||
|
185
kernel/cpu/irq.c
185
kernel/cpu/irq.c
@ -9,35 +9,81 @@
|
||||
*/
|
||||
#include <system.h>
|
||||
#include <logging.h>
|
||||
#include <module.h>
|
||||
#include <printf.h>
|
||||
|
||||
extern void _irq0(void);
|
||||
extern void _irq1(void);
|
||||
extern void _irq2(void);
|
||||
extern void _irq3(void);
|
||||
extern void _irq4(void);
|
||||
extern void _irq5(void);
|
||||
extern void _irq6(void);
|
||||
extern void _irq7(void);
|
||||
extern void _irq8(void);
|
||||
extern void _irq9(void);
|
||||
extern void _irq10(void);
|
||||
extern void _irq11(void);
|
||||
extern void _irq12(void);
|
||||
extern void _irq13(void);
|
||||
extern void _irq14(void);
|
||||
extern void _irq15(void);
|
||||
/* Programmable interrupt controller */
|
||||
#define PIC1 0x20
|
||||
#define PIC1_COMMAND PIC1
|
||||
#define PIC1_OFFSET 0x20
|
||||
#define PIC1_DATA (PIC1+1)
|
||||
|
||||
static void (*irqs[])(void) = {
|
||||
_irq0, _irq1, _irq2, _irq3, _irq4, _irq5, _irq6, _irq7,
|
||||
_irq8, _irq9, _irq10, _irq11, _irq12, _irq13, _irq14, _irq15
|
||||
};
|
||||
#define PIC2 0xA0
|
||||
#define PIC2_COMMAND PIC2
|
||||
#define PIC2_OFFSET 0x28
|
||||
#define PIC2_DATA (PIC2+1)
|
||||
|
||||
#define IRQ_CHAIN_SIZE (sizeof(irqs)/sizeof(*irqs))
|
||||
#define IRQ_CHAIN_DEPTH 4
|
||||
#define PIC_EOI 0x20
|
||||
|
||||
#define ICW1_ICW4 0x01
|
||||
#define ICW1_INIT 0x10
|
||||
|
||||
#define PIC_WAIT() \
|
||||
do { \
|
||||
/* May be fragile */ \
|
||||
asm volatile("jmp 1f\n\t" \
|
||||
"1:\n\t" \
|
||||
" jmp 2f\n\t" \
|
||||
"2:"); \
|
||||
} while (0)
|
||||
|
||||
/* Interrupts */
|
||||
static volatile int sync_depth = 0;
|
||||
|
||||
#define SYNC_CLI() asm volatile("cli")
|
||||
#define SYNC_STI() asm volatile("sti")
|
||||
|
||||
void int_disable(void) {
|
||||
/* Check if interrupts are enabled */
|
||||
uint32_t flags;
|
||||
asm volatile("pushf\n\t"
|
||||
"pop %%eax\n\t"
|
||||
"movl %%eax, %0\n\t"
|
||||
: "=r"(flags)
|
||||
:
|
||||
: "%eax");
|
||||
|
||||
/* Disable interrupts */
|
||||
SYNC_CLI();
|
||||
|
||||
/* If interrupts were enabled, then this is the first call depth */
|
||||
if (flags & (1 << 9)) {
|
||||
sync_depth = 1;
|
||||
} else {
|
||||
/* Otherwise there is now an additional call depth */
|
||||
sync_depth++;
|
||||
}
|
||||
}
|
||||
|
||||
void int_resume(void) {
|
||||
/* If there is one or no call depths, reenable interrupts */
|
||||
if (sync_depth == 0 || sync_depth == 1) {
|
||||
SYNC_STI();
|
||||
} else {
|
||||
sync_depth--;
|
||||
}
|
||||
}
|
||||
|
||||
void int_enable(void) {
|
||||
sync_depth = 0;
|
||||
SYNC_STI();
|
||||
}
|
||||
|
||||
/* Interrupt Requests */
|
||||
#define IRQ_CHAIN_SIZE 16
|
||||
#define IRQ_CHAIN_DEPTH 4
|
||||
|
||||
static void (*irqs[IRQ_CHAIN_SIZE])(void);
|
||||
static irq_handler_chain_t irq_routines[IRQ_CHAIN_SIZE * IRQ_CHAIN_DEPTH] = { NULL };
|
||||
|
||||
void irq_install_handler(size_t irq, irq_handler_chain_t handler) {
|
||||
@ -52,7 +98,6 @@ void irq_install_handler(size_t irq, irq_handler_chain_t handler) {
|
||||
SYNC_STI();
|
||||
}
|
||||
|
||||
|
||||
void irq_uninstall_handler(size_t irq) {
|
||||
/* Disable interrupts when changing handlers */
|
||||
SYNC_CLI();
|
||||
@ -61,83 +106,59 @@ void irq_uninstall_handler(size_t irq) {
|
||||
SYNC_STI();
|
||||
}
|
||||
|
||||
static void irq_remap(void) {
|
||||
/* Cascade initialization */
|
||||
outportb(PIC1_COMMAND, ICW1_INIT|ICW1_ICW4); PIC_WAIT();
|
||||
outportb(PIC2_COMMAND, ICW1_INIT|ICW1_ICW4); PIC_WAIT();
|
||||
|
||||
void irq_remap(void) {
|
||||
outportb(0x20, 0x11);
|
||||
outportb(0xA0, 0x11);
|
||||
outportb(0x21, 0x20);
|
||||
outportb(0xA1, 0x28);
|
||||
outportb(0x21, 0x04);
|
||||
outportb(0xA1, 0x02);
|
||||
outportb(0x21, 0x01);
|
||||
outportb(0xA1, 0x01);
|
||||
outportb(0x21, 0x0);
|
||||
outportb(0xA1, 0x0);
|
||||
/* Remap */
|
||||
outportb(PIC1_DATA, PIC1_OFFSET); PIC_WAIT();
|
||||
outportb(PIC2_DATA, PIC2_OFFSET); PIC_WAIT();
|
||||
|
||||
/* Cascade identity with slave PIC at IRQ2 */
|
||||
outportb(PIC1_DATA, 0x04); PIC_WAIT();
|
||||
outportb(PIC2_DATA, 0x02); PIC_WAIT();
|
||||
|
||||
/* Request 8086 mode on each PIC */
|
||||
outportb(PIC1_DATA, 0x01); PIC_WAIT();
|
||||
outportb(PIC2_DATA, 0x01); PIC_WAIT();
|
||||
}
|
||||
|
||||
static void irq_setup_gates(void) {
|
||||
for (size_t i = 0; i < IRQ_CHAIN_SIZE; i++)
|
||||
for (size_t i = 0; i < IRQ_CHAIN_SIZE; i++) {
|
||||
idt_set_gate(32 + i, irqs[i], 0x08, 0x8E);
|
||||
}
|
||||
}
|
||||
|
||||
void irq_install(void) {
|
||||
char buffer[16];
|
||||
for (int i = 0; i < IRQ_CHAIN_SIZE; i++) {
|
||||
sprintf(buffer, "_irq%d", i);
|
||||
irqs[i] = symbol_find(buffer);
|
||||
}
|
||||
irq_remap();
|
||||
irq_setup_gates();
|
||||
}
|
||||
|
||||
/* TODO: Clean up everything below */
|
||||
void irq_ack(size_t irq_no) {
|
||||
if (irq_no >= 8) {
|
||||
outportb(0xA0, 0x20);
|
||||
outportb(PIC2_COMMAND, PIC_EOI);
|
||||
}
|
||||
outportb(0x20, 0x20);
|
||||
outportb(PIC1_COMMAND, PIC_EOI);
|
||||
}
|
||||
|
||||
void irq_handler(struct regs *r) {
|
||||
IRQ_OFF;
|
||||
if (r->int_no > 47 || r->int_no < 32) {
|
||||
IRQ_RES;
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < IRQ_CHAIN_DEPTH; i++) {
|
||||
irq_handler_chain_t handler = irq_routines[i * IRQ_CHAIN_SIZE + (r->int_no - 32)];
|
||||
if (handler && handler(r)) {
|
||||
goto _done;
|
||||
/* Disable interrupts when handling */
|
||||
int_disable();
|
||||
if (r->int_no <= 47 && r->int_no >= 32) {
|
||||
for (size_t i = 0; i < IRQ_CHAIN_DEPTH; i++) {
|
||||
irq_handler_chain_t handler = irq_routines[i * IRQ_CHAIN_SIZE + (r->int_no - 32)];
|
||||
if (handler && handler(r)) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
irq_ack(r->int_no - 32);
|
||||
}
|
||||
irq_ack(r->int_no - 32);
|
||||
_done:
|
||||
IRQ_RES;
|
||||
}
|
||||
|
||||
static int _irq_sem = 0;
|
||||
void irq_off(void) {
|
||||
uint32_t eflags;
|
||||
asm volatile(
|
||||
"pushf\n"
|
||||
"pop %0\n"
|
||||
"cli"
|
||||
: "=r" (eflags));
|
||||
|
||||
if (eflags & (1 << 9)) {
|
||||
_irq_sem = 1;
|
||||
} else {
|
||||
_irq_sem++;
|
||||
}
|
||||
}
|
||||
|
||||
void irq_res(void) {
|
||||
if (_irq_sem == 0) {
|
||||
asm volatile ("sti");
|
||||
return;
|
||||
}
|
||||
_irq_sem--;
|
||||
if (_irq_sem == 0) {
|
||||
asm volatile ("sti");
|
||||
}
|
||||
}
|
||||
|
||||
void irq_on(void) {
|
||||
_irq_sem = 0;
|
||||
asm volatile ("sti");
|
||||
done:
|
||||
int_resume();
|
||||
}
|
||||
|
94
kernel/cpu/isr.c
Normal file
94
kernel/cpu/isr.c
Normal file
@ -0,0 +1,94 @@
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* This file is part of ToaruOS and is released under the terms
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
* Copyright (C) 2011-2014 Kevin Lange
|
||||
* Copyright (C) 2015 Dale Weiler
|
||||
*
|
||||
* Interrupt Service Requests
|
||||
*/
|
||||
#include <system.h>
|
||||
#include <logging.h>
|
||||
#include <module.h>
|
||||
#include <printf.h>
|
||||
|
||||
/* The count is treated as is when setting up IDT gates. However there is an
|
||||
* additional ISR for the system call vector which is handled explicitly since
|
||||
* it's mapped at a different address.
|
||||
*/
|
||||
#define ISR_COUNT 32
|
||||
|
||||
static struct {
|
||||
size_t index;
|
||||
void (*stub)(void);
|
||||
} isrs[32 + 1] __attribute__((used));
|
||||
|
||||
static irq_handler_t isr_routines[256] = { 0 };
|
||||
|
||||
void isrs_install_handler(size_t isrs, irq_handler_t handler) {
|
||||
isr_routines[isrs] = handler;
|
||||
}
|
||||
|
||||
void isrs_uninstall_handler(size_t isrs) {
|
||||
isr_routines[isrs] = 0;
|
||||
}
|
||||
|
||||
void isrs_install(void) {
|
||||
char buffer[16];
|
||||
for (int i = 0; i < ISR_COUNT; i++) {
|
||||
sprintf(buffer, "_isr%d", i);
|
||||
isrs[i].index = i;
|
||||
isrs[i].stub = symbol_find(buffer);
|
||||
}
|
||||
isrs[ISR_COUNT].index = SYSCALL_VECTOR;
|
||||
isrs[ISR_COUNT].stub = symbol_find("_isr127");
|
||||
|
||||
for (int i = 0; i < ISR_COUNT + 1; i++) {
|
||||
idt_set_gate(isrs[i].index, isrs[i].stub, 0x08, 0x8E);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *exception_messages[32] = {
|
||||
"Division by zero",
|
||||
"Debug",
|
||||
"Non-maskable interrupt",
|
||||
"Breakpoint",
|
||||
"Detected overflow",
|
||||
"Out-of-bounds",
|
||||
"Invalid opcode",
|
||||
"No coprocessor",
|
||||
"Double fault",
|
||||
"Coprocessor segment overrun",
|
||||
"Bad TSS",
|
||||
"Segment not present",
|
||||
"Stack fault",
|
||||
"General protection fault",
|
||||
"Page fault",
|
||||
"Unknown interrupt",
|
||||
"Coprocessor fault",
|
||||
"Alignment check",
|
||||
"Machine check",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved"
|
||||
};
|
||||
|
||||
void fault_handler(struct regs * r) {
|
||||
irq_handler_t handler = isr_routines[r->int_no];
|
||||
if (handler) {
|
||||
handler(r);
|
||||
} else {
|
||||
debug_print(CRITICAL, "Unhandled exception: [%d] %s", r->int_no, exception_messages[r->int_no]);
|
||||
HALT_AND_CATCH_FIRE("Process caused an unhandled exception", r);
|
||||
STOP;
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* This file is part of ToaruOS and is released under the terms
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
* Copyright (C) 2011-2014 Kevin Lange
|
||||
*
|
||||
* Interrupt Services Requests
|
||||
*/
|
||||
#include <system.h>
|
||||
#include <logging.h>
|
||||
|
||||
extern irq_handler_t isrs_routines[256];
|
||||
extern void fault_error(struct regs *r);
|
||||
|
||||
void fault_handler(struct regs *r) {
|
||||
irq_handler_t handler;
|
||||
handler = isrs_routines[r->int_no];
|
||||
if (handler) {
|
||||
handler(r);
|
||||
} else {
|
||||
fault_error(r);
|
||||
}
|
||||
}
|
@ -1,134 +0,0 @@
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* This file is part of ToaruOS and is released under the terms
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
* Copyright (C) 2013-2014 Kevin Lange
|
||||
*/
|
||||
#include <system.h>
|
||||
#include <logging.h>
|
||||
|
||||
/*
|
||||
* Exception Handlers
|
||||
*/
|
||||
extern void _isr0 (void);
|
||||
extern void _isr1 (void);
|
||||
extern void _isr2 (void);
|
||||
extern void _isr3 (void);
|
||||
extern void _isr4 (void);
|
||||
extern void _isr5 (void);
|
||||
extern void _isr6 (void);
|
||||
extern void _isr7 (void);
|
||||
extern void _isr8 (void);
|
||||
extern void _isr9 (void);
|
||||
extern void _isr10(void);
|
||||
extern void _isr11(void);
|
||||
extern void _isr12(void);
|
||||
extern void _isr13(void);
|
||||
extern void _isr14(void);
|
||||
extern void _isr15(void);
|
||||
extern void _isr16(void);
|
||||
extern void _isr17(void);
|
||||
extern void _isr18(void);
|
||||
extern void _isr19(void);
|
||||
extern void _isr20(void);
|
||||
extern void _isr21(void);
|
||||
extern void _isr22(void);
|
||||
extern void _isr23(void);
|
||||
extern void _isr24(void);
|
||||
extern void _isr25(void);
|
||||
extern void _isr26(void);
|
||||
extern void _isr27(void);
|
||||
extern void _isr28(void);
|
||||
extern void _isr29(void);
|
||||
extern void _isr30(void);
|
||||
extern void _isr31(void);
|
||||
extern void _isr127(void);
|
||||
|
||||
irq_handler_t isrs_routines[256] = { NULL };
|
||||
|
||||
void isrs_install_handler(size_t isrs, irq_handler_t handler) {
|
||||
isrs_routines[isrs] = handler;
|
||||
}
|
||||
|
||||
void isrs_uninstall_handler(size_t isrs) {
|
||||
isrs_routines[isrs] = 0;
|
||||
}
|
||||
|
||||
void isrs_install(void) {
|
||||
/* Exception Handlers */
|
||||
memset(isrs_routines, 0x00, sizeof(isrs_routines));
|
||||
idt_set_gate(0, _isr0, 0x08, 0x8E);
|
||||
idt_set_gate(1, _isr1, 0x08, 0x8E);
|
||||
idt_set_gate(2, _isr2, 0x08, 0x8E);
|
||||
idt_set_gate(3, _isr3, 0x08, 0x8E);
|
||||
idt_set_gate(4, _isr4, 0x08, 0x8E);
|
||||
idt_set_gate(5, _isr5, 0x08, 0x8E);
|
||||
idt_set_gate(6, _isr6, 0x08, 0x8E);
|
||||
idt_set_gate(7, _isr7, 0x08, 0x8E);
|
||||
idt_set_gate(8, _isr8, 0x08, 0x8E);
|
||||
idt_set_gate(9, _isr9, 0x08, 0x8E);
|
||||
idt_set_gate(10, _isr10, 0x08, 0x8E);
|
||||
idt_set_gate(11, _isr11, 0x08, 0x8E);
|
||||
idt_set_gate(12, _isr12, 0x08, 0x8E);
|
||||
idt_set_gate(13, _isr13, 0x08, 0x8E);
|
||||
idt_set_gate(14, _isr14, 0x08, 0x8E);
|
||||
idt_set_gate(15, _isr15, 0x08, 0x8E);
|
||||
idt_set_gate(16, _isr16, 0x08, 0x8E);
|
||||
idt_set_gate(17, _isr17, 0x08, 0x8E);
|
||||
idt_set_gate(18, _isr18, 0x08, 0x8E);
|
||||
idt_set_gate(19, _isr19, 0x08, 0x8E);
|
||||
idt_set_gate(20, _isr20, 0x08, 0x8E);
|
||||
idt_set_gate(21, _isr21, 0x08, 0x8E);
|
||||
idt_set_gate(22, _isr22, 0x08, 0x8E);
|
||||
idt_set_gate(23, _isr23, 0x08, 0x8E);
|
||||
idt_set_gate(24, _isr24, 0x08, 0x8E);
|
||||
idt_set_gate(25, _isr25, 0x08, 0x8E);
|
||||
idt_set_gate(26, _isr26, 0x08, 0x8E);
|
||||
idt_set_gate(27, _isr27, 0x08, 0x8E);
|
||||
idt_set_gate(28, _isr28, 0x08, 0x8E);
|
||||
idt_set_gate(29, _isr29, 0x08, 0x8E);
|
||||
idt_set_gate(30, _isr30, 0x08, 0x8E);
|
||||
idt_set_gate(31, _isr31, 0x08, 0x8E);
|
||||
idt_set_gate(SYSCALL_VECTOR, _isr127, 0x08, 0x8E);
|
||||
}
|
||||
|
||||
static const char *exception_messages[32] = {
|
||||
"Division by zero", /* 0 */
|
||||
"Debug",
|
||||
"Non-maskable interrupt",
|
||||
"Breakpoint",
|
||||
"Detected overflow",
|
||||
"Out-of-bounds", /* 5 */
|
||||
"Invalid opcode",
|
||||
"No coprocessor",
|
||||
"Double fault",
|
||||
"Coprocessor segment overrun",
|
||||
"Bad TSS", /* 10 */
|
||||
"Segment not present",
|
||||
"Stack fault",
|
||||
"General protection fault",
|
||||
"Page fault",
|
||||
"Unknown interrupt", /* 15 */
|
||||
"Coprocessor fault",
|
||||
"Alignment check",
|
||||
"Machine check",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved"
|
||||
};
|
||||
|
||||
void fault_error(struct regs *r) {
|
||||
debug_print(CRITICAL, "Unhandled exception: [%d] %s", r->int_no, exception_messages[r->int_no]);
|
||||
HALT_AND_CATCH_FIRE("Process caused an unhandled exception", r);
|
||||
STOP;
|
||||
}
|
||||
|
64
kernel/ds/bitset.c
Normal file
64
kernel/ds/bitset.c
Normal file
@ -0,0 +1,64 @@
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* This file is part of ToaruOS and is released under the terms
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
* Copyright (C) 2015 Dale Weiler
|
||||
*/
|
||||
#include "bitset.h"
|
||||
|
||||
#define CEIL(NUMBER, BASE) \
|
||||
(((NUMBER) + (BASE) - 1) & ~((BASE) - 1))
|
||||
|
||||
void bitset_init(bitset_t *set, size_t size) {
|
||||
set->size = CEIL(size, 8);
|
||||
set->data = malloc(set->size);
|
||||
}
|
||||
|
||||
void bitset_free(bitset_t *set) {
|
||||
free(set->data);
|
||||
}
|
||||
|
||||
static void bitset_resize(bitset_t *set, size_t size) {
|
||||
if (set->size >= size) {
|
||||
return;
|
||||
}
|
||||
unsigned char *temp = malloc(size);
|
||||
memcpy(temp, set->data, set->size);
|
||||
free(set->data);
|
||||
set->data = temp;
|
||||
set->size = size;
|
||||
}
|
||||
|
||||
void bitset_set(bitset_t *set, size_t bit) {
|
||||
size_t index = bit >> 3;
|
||||
if (set->size <= index) {
|
||||
bitset_resize(set, set->size << 1);
|
||||
}
|
||||
size_t offset = index & 7;
|
||||
size_t mask = 1 << offset;
|
||||
set->data[index] |= mask;
|
||||
}
|
||||
|
||||
int bitset_ffub(bitset_t *set) {
|
||||
for (size_t i = 0; i < set->size * 8; i++) {
|
||||
if (bitset_test(set, i)) {
|
||||
continue;
|
||||
}
|
||||
return (int)i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void bitset_clear(bitset_t *set, size_t bit) {
|
||||
size_t index = bit >> 3;
|
||||
size_t offset = index & 7;
|
||||
size_t mask = 1 << offset;
|
||||
set->data[index] &= ~mask;
|
||||
}
|
||||
|
||||
int bitset_test(bitset_t *set, size_t bit) {
|
||||
size_t index = bit >> 3;
|
||||
size_t offset = index & 7;
|
||||
size_t mask = 1 << offset;
|
||||
return mask & set->data[index];
|
||||
}
|
||||
|
@ -51,13 +51,13 @@ static inline void ring_buffer_increment_write(ring_buffer_t * ring_buffer) {
|
||||
size_t ring_buffer_read(ring_buffer_t * ring_buffer, size_t size, uint8_t * buffer) {
|
||||
size_t collected = 0;
|
||||
while (collected == 0) {
|
||||
spin_lock(&ring_buffer->lock);
|
||||
spin_lock(ring_buffer->lock);
|
||||
while (ring_buffer_unread(ring_buffer) > 0 && collected < size) {
|
||||
buffer[collected] = ring_buffer->buffer[ring_buffer->read_ptr];
|
||||
ring_buffer_increment_read(ring_buffer);
|
||||
collected++;
|
||||
}
|
||||
spin_unlock(&ring_buffer->lock);
|
||||
spin_unlock(ring_buffer->lock);
|
||||
wakeup_queue(ring_buffer->wait_queue_writers);
|
||||
if (collected == 0) {
|
||||
if (sleep_on(ring_buffer->wait_queue_readers) && ring_buffer->internal_stop) {
|
||||
@ -73,7 +73,7 @@ size_t ring_buffer_read(ring_buffer_t * ring_buffer, size_t size, uint8_t * buff
|
||||
size_t ring_buffer_write(ring_buffer_t * ring_buffer, size_t size, uint8_t * buffer) {
|
||||
size_t written = 0;
|
||||
while (written < size) {
|
||||
spin_lock(&ring_buffer->lock);
|
||||
spin_lock(ring_buffer->lock);
|
||||
|
||||
while (ring_buffer_available(ring_buffer) > 0 && written < size) {
|
||||
ring_buffer->buffer[ring_buffer->write_ptr] = buffer[written];
|
||||
@ -81,7 +81,7 @@ size_t ring_buffer_write(ring_buffer_t * ring_buffer, size_t size, uint8_t * buf
|
||||
written++;
|
||||
}
|
||||
|
||||
spin_unlock(&ring_buffer->lock);
|
||||
spin_unlock(ring_buffer->lock);
|
||||
wakeup_queue(ring_buffer->wait_queue_readers);
|
||||
if (written < size) {
|
||||
if (sleep_on(ring_buffer->wait_queue_writers) && ring_buffer->internal_stop) {
|
||||
@ -101,9 +101,10 @@ ring_buffer_t * ring_buffer_create(size_t size) {
|
||||
out->buffer = malloc(size);
|
||||
out->write_ptr = 0;
|
||||
out->read_ptr = 0;
|
||||
out->lock = 0;
|
||||
out->size = size;
|
||||
|
||||
spin_init(out->lock);
|
||||
|
||||
out->internal_stop = 0;
|
||||
|
||||
out->wait_queue_readers = list_create();
|
||||
|
@ -97,13 +97,13 @@ uint32_t read_pipe(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buf
|
||||
|
||||
size_t collected = 0;
|
||||
while (collected == 0) {
|
||||
spin_lock(&pipe->lock_read);
|
||||
spin_lock(pipe->lock_read);
|
||||
while (pipe_unread(pipe) > 0 && collected < size) {
|
||||
buffer[collected] = pipe->buffer[pipe->read_ptr];
|
||||
pipe_increment_read(pipe);
|
||||
collected++;
|
||||
}
|
||||
spin_unlock(&pipe->lock_read);
|
||||
spin_unlock(pipe->lock_read);
|
||||
wakeup_queue(pipe->wait_queue_writers);
|
||||
/* Deschedule and switch */
|
||||
if (collected == 0) {
|
||||
@ -141,7 +141,7 @@ uint32_t write_pipe(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *bu
|
||||
|
||||
size_t written = 0;
|
||||
while (written < size) {
|
||||
spin_lock(&pipe->lock_write);
|
||||
spin_lock(pipe->lock_write);
|
||||
|
||||
#if 0
|
||||
size_t available = 0;
|
||||
@ -164,7 +164,7 @@ uint32_t write_pipe(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *bu
|
||||
}
|
||||
#endif
|
||||
|
||||
spin_unlock(&pipe->lock_write);
|
||||
spin_unlock(pipe->lock_write);
|
||||
wakeup_queue(pipe->wait_queue_readers);
|
||||
if (written < size) {
|
||||
sleep_on(pipe->wait_queue_writers);
|
||||
@ -242,10 +242,11 @@ fs_node_t * make_pipe(size_t size) {
|
||||
pipe->read_ptr = 0;
|
||||
pipe->size = size;
|
||||
pipe->refcount = 0;
|
||||
pipe->lock_read = 0;
|
||||
pipe->lock_write= 0;
|
||||
pipe->dead = 0;
|
||||
|
||||
spin_init(pipe->lock_read);
|
||||
spin_init(pipe->lock_write);
|
||||
|
||||
pipe->wait_queue_writers = list_create();
|
||||
pipe->wait_queue_readers = list_create();
|
||||
|
||||
|
@ -202,8 +202,6 @@ int pty_ioctl(pty_t * pty, int request, void * argp) {
|
||||
}
|
||||
}
|
||||
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
uint32_t read_pty_master(fs_node_t * node, uint32_t offset, uint32_t size, uint8_t *buffer) {
|
||||
pty_t * pty = (pty_t *)node->device;
|
||||
|
||||
|
@ -48,7 +48,8 @@ static struct dirent * readdir_mapper(fs_node_t *node, uint32_t index) {
|
||||
struct vfs_entry * n = (struct vfs_entry *)tchild->value;
|
||||
struct dirent * dir = malloc(sizeof(struct dirent));
|
||||
|
||||
memcpy(&dir->name, n->name, min(256, strlen(n->name)+1));
|
||||
size_t len = strlen(n->name) + 1;
|
||||
memcpy(&dir->name, n->name, MIN(256, len));
|
||||
dir->ino = i;
|
||||
return dir;
|
||||
}
|
||||
@ -108,12 +109,13 @@ uint32_t write_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buff
|
||||
}
|
||||
}
|
||||
|
||||
volatile uint8_t tmp_refcount_lock = 0;
|
||||
//volatile uint8_t tmp_refcount_lock = 0;
|
||||
static spin_lock_t tmp_refcount_lock = { 0 };
|
||||
|
||||
void vfs_lock(fs_node_t * node) {
|
||||
spin_lock(&tmp_refcount_lock);
|
||||
spin_lock(tmp_refcount_lock);
|
||||
node->refcount = -1;
|
||||
spin_unlock(&tmp_refcount_lock);
|
||||
spin_unlock(tmp_refcount_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -127,9 +129,9 @@ void open_fs(fs_node_t *node, unsigned int flags) {
|
||||
if (!node) return;
|
||||
|
||||
if (node->refcount >= 0) {
|
||||
spin_lock(&tmp_refcount_lock);
|
||||
spin_lock(tmp_refcount_lock);
|
||||
node->refcount++;
|
||||
spin_unlock(&tmp_refcount_lock);
|
||||
spin_unlock(tmp_refcount_lock);
|
||||
}
|
||||
|
||||
if (node->open) {
|
||||
@ -152,7 +154,7 @@ void close_fs(fs_node_t *node) {
|
||||
|
||||
if (node->refcount == -1) return;
|
||||
|
||||
spin_lock(&tmp_refcount_lock);
|
||||
spin_lock(tmp_refcount_lock);
|
||||
node->refcount--;
|
||||
if (node->refcount == 0) {
|
||||
debug_print(NOTICE, "Node refcount [%s] is now 0: %d", node->name, node->refcount);
|
||||
@ -163,7 +165,7 @@ void close_fs(fs_node_t *node) {
|
||||
|
||||
free(node);
|
||||
}
|
||||
spin_unlock(&tmp_refcount_lock);
|
||||
spin_unlock(tmp_refcount_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -355,9 +357,9 @@ fs_node_t *clone_fs(fs_node_t *source) {
|
||||
if (!source) return NULL;
|
||||
|
||||
if (source->refcount >= 0) {
|
||||
spin_lock(&tmp_refcount_lock);
|
||||
spin_lock(tmp_refcount_lock);
|
||||
source->refcount++;
|
||||
spin_unlock(&tmp_refcount_lock);
|
||||
spin_unlock(tmp_refcount_lock);
|
||||
}
|
||||
|
||||
return source;
|
||||
@ -520,7 +522,8 @@ int vfs_mount_type(char * type, char * arg, char * mountpoint) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
volatile uint8_t tmp_vfs_lock = 0;
|
||||
//volatile uint8_t tmp_vfs_lock = 0;
|
||||
static spin_lock_t tmp_vfs_lock = { 0 };
|
||||
/**
|
||||
* vfs_mount - Mount a file system to the specified path.
|
||||
*
|
||||
@ -542,7 +545,7 @@ void * vfs_mount(char * path, fs_node_t * local_root) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
spin_lock(&tmp_vfs_lock);
|
||||
spin_lock(tmp_vfs_lock);
|
||||
|
||||
local_root->refcount = -1;
|
||||
|
||||
@ -614,7 +617,7 @@ void * vfs_mount(char * path, fs_node_t * local_root) {
|
||||
}
|
||||
|
||||
free(p);
|
||||
spin_unlock(&tmp_vfs_lock);
|
||||
spin_unlock(tmp_vfs_lock);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
20
kernel/include/bitset.h
Normal file
20
kernel/include/bitset.h
Normal file
@ -0,0 +1,20 @@
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
*/
|
||||
#ifndef BITSET_H
|
||||
#define BITSET_H
|
||||
#include <system.h>
|
||||
|
||||
typedef struct {
|
||||
unsigned char *data;
|
||||
size_t size;
|
||||
} bitset_t;
|
||||
|
||||
void bitset_init(bitset_t *set, size_t size);
|
||||
void bitset_free(bitset_t *set);
|
||||
void bitset_set(bitset_t *set, size_t bit);
|
||||
void bitset_clear(bitset_t *set, size_t bit);
|
||||
int bitset_test(bitset_t *set, size_t bit);
|
||||
/* Find first unset bit */
|
||||
int bitset_ffub(bitset_t *set);
|
||||
|
||||
#endif
|
38
kernel/include/libc.h
Normal file
38
kernel/include/libc.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
*/
|
||||
#ifndef __LIBC_H
|
||||
#define __LIBC_H
|
||||
#include <stddef.h>
|
||||
|
||||
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
||||
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
||||
|
||||
extern void * memcpy(void * restrict dest, const void * restrict src, size_t n);
|
||||
extern void * memset(void * dest, int c, size_t n);
|
||||
extern void * memchr(const void * src, int c, size_t n);
|
||||
extern void * memrchr(const void * m, int c, size_t n);
|
||||
extern void * memmove(void *dest, const void *src, size_t n);
|
||||
|
||||
extern int memcmp(const void *vl, const void *vr, size_t n);
|
||||
|
||||
extern char * strdup(const char * s);
|
||||
extern char * stpcpy(char * restrict d, const char * restrict s);
|
||||
extern char * strcpy(char * restrict dest, const char * restrict src);
|
||||
extern char * strchrnul(const char * s, int c);
|
||||
extern char * strchr(const char * s, int c);
|
||||
extern char * strrchr(const char * s, int c);
|
||||
extern char * strpbrk(const char * s, const char * b);
|
||||
extern char * strstr(const char * h, const char * n);
|
||||
|
||||
extern int strcmp(const char * l, const char * r);
|
||||
|
||||
extern size_t strcspn(const char * s, const char * c);
|
||||
extern size_t strspn(const char * s, const char * c);
|
||||
extern size_t strlen(const char * s);
|
||||
|
||||
extern int atoi(const char * s);
|
||||
|
||||
/* Non-standard broken strtok_r */
|
||||
extern char * strtok_r(char * str, const char * delim, char ** saveptr);
|
||||
|
||||
#endif
|
@ -3,7 +3,6 @@
|
||||
#include <fs.h>
|
||||
|
||||
fs_node_t * tmpfs_create(char * name);
|
||||
uint8_t volatile tmpfs_lock;
|
||||
|
||||
struct tmpfs_file {
|
||||
char * name;
|
||||
|
@ -19,6 +19,8 @@ typedef struct {
|
||||
char * deps;
|
||||
} module_data_t;
|
||||
|
||||
void (* symbol_find(const char * name))(void);
|
||||
|
||||
extern int module_quickcheck(void * blob);
|
||||
extern void * module_load_direct(void * blob, size_t size);
|
||||
extern void * module_load(char * filename);
|
||||
|
@ -14,8 +14,8 @@ typedef struct _pipe_device {
|
||||
size_t read_ptr;
|
||||
size_t size;
|
||||
size_t refcount;
|
||||
uint8_t volatile lock_read;
|
||||
uint8_t volatile lock_write;
|
||||
volatile int lock_read[2];
|
||||
volatile int lock_write[2];
|
||||
list_t * wait_queue_readers;
|
||||
list_t * wait_queue_writers;
|
||||
int dead;
|
||||
|
@ -48,7 +48,7 @@ typedef struct image {
|
||||
uintptr_t user_stack; /* User stack */
|
||||
uintptr_t start;
|
||||
uintptr_t shm_heap;
|
||||
volatile uint8_t lock;
|
||||
volatile int lock[2];
|
||||
} image_t;
|
||||
|
||||
/* Resizable descriptor table */
|
||||
|
@ -6,7 +6,7 @@ typedef struct {
|
||||
size_t write_ptr;
|
||||
size_t read_ptr;
|
||||
size_t size;
|
||||
uint8_t volatile lock;
|
||||
volatile int lock[2];
|
||||
list_t * wait_queue_readers;
|
||||
list_t * wait_queue_writers;
|
||||
int internal_stop;
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <list.h>
|
||||
#include <task.h>
|
||||
#include <process.h>
|
||||
#include <libc.h>
|
||||
|
||||
#define STR(x) #x
|
||||
#define STRSTR(x) STR(x)
|
||||
@ -15,15 +16,13 @@
|
||||
#define asm __asm__
|
||||
#define volatile __volatile__
|
||||
|
||||
extern unsigned int __irq_sem;
|
||||
void int_disable(void);
|
||||
void int_resume(void);
|
||||
void int_enable(void);
|
||||
|
||||
void irq_off(void);
|
||||
void irq_res(void);
|
||||
void irq_on(void);
|
||||
|
||||
#define IRQ_OFF irq_off()
|
||||
#define IRQ_RES irq_res()
|
||||
#define IRQ_ON irq_on()
|
||||
#define IRQ_OFF int_disable()
|
||||
#define IRQ_RES int_resume()
|
||||
#define IRQ_ON int_enable()
|
||||
#define PAUSE { asm volatile ("hlt"); }
|
||||
|
||||
#define STOP while (1) { PAUSE; }
|
||||
@ -40,24 +39,17 @@ extern char * boot_arg_extra; /* Extra data to pass to init */
|
||||
|
||||
extern void *sbrk(uintptr_t increment);
|
||||
|
||||
extern void spin_lock(uint8_t volatile * lock);
|
||||
extern void spin_unlock(uint8_t volatile * lock);
|
||||
/* spin.c */
|
||||
typedef volatile int spin_lock_t[2];
|
||||
extern void spin_init(spin_lock_t lock);
|
||||
extern void spin_lock(spin_lock_t lock);
|
||||
extern void spin_unlock(spin_lock_t lock);
|
||||
|
||||
extern void return_to_userspace(void);
|
||||
|
||||
/* Kernel Main */
|
||||
extern int max(int,int);
|
||||
extern int min(int,int);
|
||||
extern int abs(int);
|
||||
extern void swap(int *, int *);
|
||||
extern void *memcpy(void *restrict dest, const void *restrict src, size_t count);
|
||||
extern void *memmove(void *restrict dest, const void *restrict src, size_t count);
|
||||
extern void *memset(void *dest, int val, size_t count);
|
||||
extern unsigned short *memsetw(unsigned short *dest, unsigned short val, int count);
|
||||
extern uint32_t strlen(const char *str);
|
||||
extern char * strdup(const char *str);
|
||||
extern char * strcpy(char * dest, const char * src);
|
||||
extern int atoi(const char *str);
|
||||
|
||||
extern unsigned char inportb(unsigned short _port);
|
||||
extern void outportb(unsigned short _port, unsigned char _data);
|
||||
extern unsigned short inports(unsigned short _port);
|
||||
@ -66,14 +58,13 @@ extern unsigned int inportl(unsigned short _port);
|
||||
extern void outportl(unsigned short _port, unsigned int _data);
|
||||
extern void outportsm(unsigned short port, unsigned char * data, unsigned long size);
|
||||
extern void inportsm(unsigned short port, unsigned char * data, unsigned long size);
|
||||
extern int strcmp(const char *a, const char *b);
|
||||
extern char * strtok_r(char * str, const char * delim, char ** saveptr);
|
||||
|
||||
|
||||
extern size_t lfind(const char * str, const char accept);
|
||||
extern size_t rfind(const char * str, const char accept);
|
||||
extern size_t strspn(const char * str, const char * accept);
|
||||
extern char * strpbrk(const char * str, const char * accept);
|
||||
|
||||
extern uint32_t krand(void);
|
||||
extern char * strstr(const char * haystack, const char * needle);
|
||||
|
||||
extern uint8_t startswith(const char * str, const char * accept);
|
||||
|
||||
/* GDT */
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
#include <types.h>
|
||||
|
||||
|
||||
typedef struct page {
|
||||
unsigned int present:1;
|
||||
unsigned int rw:1;
|
||||
|
@ -48,11 +48,9 @@ irq_common:
|
||||
mov %ax, %gs
|
||||
|
||||
/* Call interrupt handler */
|
||||
mov %esp, %eax
|
||||
push %eax
|
||||
mov $irq_handler, %eax
|
||||
call *%eax
|
||||
pop %eax
|
||||
push %esp
|
||||
call irq_handler
|
||||
add $4, %esp
|
||||
|
||||
/* Restore segment registers */
|
||||
pop %gs
|
||||
|
@ -72,11 +72,9 @@ isr_common:
|
||||
mov %ax, %gs
|
||||
|
||||
/* Call fault handler */
|
||||
mov %esp, %eax
|
||||
push %eax
|
||||
mov $fault_handler, %eax
|
||||
call *%eax
|
||||
pop %eax
|
||||
push %esp
|
||||
call fault_handler
|
||||
add $4, %esp
|
||||
|
||||
/* Restore segment registers */
|
||||
pop %gs
|
||||
|
455
kernel/libc.c
Normal file
455
kernel/libc.c
Normal file
@ -0,0 +1,455 @@
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* This file is part of ToaruOS and is released under the terms
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
* Copyright (C) 2015 Dale Weiler
|
||||
*
|
||||
* Standard C library for kernel
|
||||
*
|
||||
*/
|
||||
|
||||
#include <system.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define ALIGN (sizeof(size_t))
|
||||
#define ONES ((size_t)-1/UCHAR_MAX)
|
||||
#define HIGHS (ONES * (UCHAR_MAX/2+1))
|
||||
#define HASZERO(X) (((X)-ONES) & ~(X) & HIGHS)
|
||||
|
||||
#define BITOP(A, B, OP) \
|
||||
((A)[(size_t)(B)/(8*sizeof *(A))] OP (size_t)1<<((size_t)(B)%(8*sizeof *(A))))
|
||||
|
||||
void * memcpy(void * restrict dest, const void * restrict src, size_t n) {
|
||||
asm volatile("cld; rep movsb"
|
||||
:
|
||||
: "D"(dest), "S"(src), "c"(n)
|
||||
: "cc", "memory");
|
||||
return dest;
|
||||
}
|
||||
|
||||
void * memset(void * dest, int c, size_t n) {
|
||||
asm volatile("cld; rep stosb"
|
||||
:
|
||||
: "D"(dest), "a"(c), "c"(n)
|
||||
: "cc", "memory");
|
||||
return dest;
|
||||
}
|
||||
|
||||
int memcmp(const void * vl, const void * vr, size_t n) {
|
||||
const unsigned char *l = vl;
|
||||
const unsigned char *r = vr;
|
||||
for (; n && *l == *r; n--, l++, r++);
|
||||
return n ? *l-*r : 0;
|
||||
}
|
||||
|
||||
void * memchr(const void * src, int c, size_t n) {
|
||||
const unsigned char * s = src;
|
||||
c = (unsigned char)c;
|
||||
for (; ((uintptr_t)s & (ALIGN - 1)) && n && *s != c; s++, n--);
|
||||
if (n && *s != c) {
|
||||
const size_t * w;
|
||||
size_t k = ONES * c;
|
||||
for (w = (const void *)s; n >= sizeof(size_t) && !HASZERO(*w^k); w++, n -= sizeof(size_t));
|
||||
for (s = (const void *)w; n && *s != c; s++, n--);
|
||||
}
|
||||
return n ? (void *)s : 0;
|
||||
}
|
||||
|
||||
void * memrchr(const void * m, int c, size_t n) {
|
||||
const unsigned char * s = m;
|
||||
c = (unsigned char)c;
|
||||
while (n--) {
|
||||
if (s[n] == c) {
|
||||
return (void*)(s+n);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void * memmove(void * dest, const void * src, size_t n) {
|
||||
char * d = dest;
|
||||
const char * s = src;
|
||||
|
||||
if (d==s) {
|
||||
return d;
|
||||
}
|
||||
|
||||
if (s+n <= d || d+n <= s) {
|
||||
return memcpy(d, s, n);
|
||||
}
|
||||
|
||||
if (d<s) {
|
||||
if ((uintptr_t)s % sizeof(size_t) == (uintptr_t)d % sizeof(size_t)) {
|
||||
while ((uintptr_t)d % sizeof(size_t)) {
|
||||
if (!n--) {
|
||||
return dest;
|
||||
}
|
||||
*d++ = *s++;
|
||||
}
|
||||
for (; n >= sizeof(size_t); n -= sizeof(size_t), d += sizeof(size_t), s += sizeof(size_t)) {
|
||||
*(size_t *)d = *(size_t *)s;
|
||||
}
|
||||
}
|
||||
for (; n; n--) {
|
||||
*d++ = *s++;
|
||||
}
|
||||
} else {
|
||||
if ((uintptr_t)s % sizeof(size_t) == (uintptr_t)d % sizeof(size_t)) {
|
||||
while ((uintptr_t)(d+n) % sizeof(size_t)) {
|
||||
if (!n--) {
|
||||
return dest;
|
||||
}
|
||||
d[n] = s[n];
|
||||
}
|
||||
while (n >= sizeof(size_t)) {
|
||||
n -= sizeof(size_t);
|
||||
*(size_t *)(d+n) = *(size_t *)(s+n);
|
||||
}
|
||||
}
|
||||
while (n) {
|
||||
n--;
|
||||
d[n] = s[n];
|
||||
}
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
int strcmp(const char * l, const char * r) {
|
||||
for (; *l == *r && *l; l++, r++);
|
||||
return *(unsigned char *)l - *(unsigned char *)r;
|
||||
}
|
||||
|
||||
size_t strlen(const char * s) {
|
||||
const char * a = s;
|
||||
const size_t * w;
|
||||
for (; (uintptr_t)s % ALIGN; s++) {
|
||||
if (!*s) {
|
||||
return s-a;
|
||||
}
|
||||
}
|
||||
for (w = (const void *)s; !HASZERO(*w); w++);
|
||||
for (s = (const void *)w; *s; s++);
|
||||
return s-a;
|
||||
}
|
||||
|
||||
char * strdup(const char * s) {
|
||||
size_t l = strlen(s);
|
||||
return memcpy(malloc(l+1), s, l+1);
|
||||
}
|
||||
|
||||
char * stpcpy(char * restrict d, const char * restrict s) {
|
||||
size_t * wd;
|
||||
const size_t * ws;
|
||||
|
||||
if ((uintptr_t)s % ALIGN == (uintptr_t)d % ALIGN) {
|
||||
for (; (uintptr_t)s % ALIGN; s++, d++) {
|
||||
if (!(*d = *s)) {
|
||||
return d;
|
||||
}
|
||||
}
|
||||
wd = (void *)d;
|
||||
ws = (const void *)s;
|
||||
for (; !HASZERO(*ws); *wd++ = *ws++);
|
||||
d = (void *)wd;
|
||||
s = (const void *)ws;
|
||||
}
|
||||
|
||||
for (; (*d=*s); s++, d++);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
char * strcpy(char * restrict dest, const char * restrict src) {
|
||||
stpcpy(dest, src);
|
||||
return dest;
|
||||
}
|
||||
|
||||
size_t strspn(const char * s, const char * c) {
|
||||
const char * a = s;
|
||||
size_t byteset[32/sizeof(size_t)] = { 0 };
|
||||
|
||||
if (!c[0]) {
|
||||
return 0;
|
||||
}
|
||||
if (!c[1]) {
|
||||
for (; *s == *c; s++);
|
||||
return s-a;
|
||||
}
|
||||
|
||||
for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++);
|
||||
for (; *s && BITOP(byteset, *(unsigned char *)s, &); s++);
|
||||
|
||||
return s-a;
|
||||
}
|
||||
|
||||
char * strchrnul(const char * s, int c) {
|
||||
size_t * w;
|
||||
size_t k;
|
||||
|
||||
c = (unsigned char)c;
|
||||
if (!c) {
|
||||
return (char *)s + strlen(s);
|
||||
}
|
||||
|
||||
for (; (uintptr_t)s % ALIGN; s++) {
|
||||
if (!*s || *(unsigned char *)s == c) {
|
||||
return (char *)s;
|
||||
}
|
||||
}
|
||||
|
||||
k = ONES * c;
|
||||
for (w = (void *)s; !HASZERO(*w) && !HASZERO(*w^k); w++);
|
||||
for (s = (void *)w; *s && *(unsigned char *)s != c; s++);
|
||||
return (char *)s;
|
||||
}
|
||||
|
||||
char * strchr(const char * s, int c) {
|
||||
char *r = strchrnul(s, c);
|
||||
return *(unsigned char *)r == (unsigned char)c ? r : 0;
|
||||
}
|
||||
|
||||
char * strrchr(const char * s, int c) {
|
||||
return memrchr(s, c, strlen(s) + 1);
|
||||
}
|
||||
|
||||
size_t strcspn(const char * s, const char * c) {
|
||||
const char *a = s;
|
||||
if (c[0] && c[1]) {
|
||||
size_t byteset[32/sizeof(size_t)] = { 0 };
|
||||
for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++);
|
||||
for (; *s && !BITOP(byteset, *(unsigned char *)s, &); s++);
|
||||
return s-a;
|
||||
}
|
||||
return strchrnul(s, *c)-a;
|
||||
}
|
||||
|
||||
char * strpbrk(const char * s, const char * b) {
|
||||
s += strcspn(s, b);
|
||||
return *s ? (char *)s : 0;
|
||||
}
|
||||
|
||||
static char *strstr_2b(const unsigned char * h, const unsigned char * n) {
|
||||
uint16_t nw = n[0] << 8 | n[1];
|
||||
uint16_t hw = h[0] << 8 | h[1];
|
||||
for (h++; *h && hw != nw; hw = hw << 8 | *++h);
|
||||
return *h ? (char *)h-1 : 0;
|
||||
}
|
||||
|
||||
static char *strstr_3b(const unsigned char * h, const unsigned char * n) {
|
||||
uint32_t nw = n[0] << 24 | n[1] << 16 | n[2] << 8;
|
||||
uint32_t hw = h[0] << 24 | h[1] << 16 | h[2] << 8;
|
||||
for (h += 2; *h && hw != nw; hw = (hw|*++h) << 8);
|
||||
return *h ? (char *)h-2 : 0;
|
||||
}
|
||||
|
||||
static char *strstr_4b(const unsigned char * h, const unsigned char * n) {
|
||||
uint32_t nw = n[0] << 24 | n[1] << 16 | n[2] << 8 | n[3];
|
||||
uint32_t hw = h[0] << 24 | h[1] << 16 | h[2] << 8 | h[3];
|
||||
for (h += 3; *h && hw != nw; hw = hw << 8 | *++h);
|
||||
return *h ? (char *)h-3 : 0;
|
||||
}
|
||||
|
||||
static char *strstr_twoway(const unsigned char * h, const unsigned char * n) {
|
||||
size_t mem;
|
||||
size_t mem0;
|
||||
size_t byteset[32 / sizeof(size_t)] = { 0 };
|
||||
size_t shift[256];
|
||||
size_t l;
|
||||
|
||||
/* Computing length of needle and fill shift table */
|
||||
for (l = 0; n[l] && h[l]; l++) {
|
||||
BITOP(byteset, n[l], |=);
|
||||
shift[n[l]] = l+1;
|
||||
}
|
||||
|
||||
if (n[l]) {
|
||||
return 0; /* hit the end of h */
|
||||
}
|
||||
|
||||
/* Compute maximal suffix */
|
||||
size_t ip = -1;
|
||||
size_t jp = 0;
|
||||
size_t k = 1;
|
||||
size_t p = 1;
|
||||
while (jp+k<l) {
|
||||
if (n[ip+k] == n[jp+k]) {
|
||||
if (k == p) {
|
||||
jp += p;
|
||||
k = 1;
|
||||
} else {
|
||||
k++;
|
||||
}
|
||||
} else if (n[ip+k] > n[jp+k]) {
|
||||
jp += k;
|
||||
k = 1;
|
||||
p = jp - ip;
|
||||
} else {
|
||||
ip = jp++;
|
||||
k = p = 1;
|
||||
}
|
||||
}
|
||||
size_t ms = ip;
|
||||
size_t p0 = p;
|
||||
|
||||
/* And with the opposite comparison */
|
||||
ip = -1;
|
||||
jp = 0;
|
||||
k = p = 1;
|
||||
while (jp+k<l) {
|
||||
if (n[ip+k] == n[jp+k]) {
|
||||
if (k == p) {
|
||||
jp += p;
|
||||
k = 1;
|
||||
} else {
|
||||
k++;
|
||||
}
|
||||
} else if (n[ip+k] < n[jp+k]) {
|
||||
jp += k;
|
||||
k = 1;
|
||||
p = jp - ip;
|
||||
} else {
|
||||
ip = jp++;
|
||||
k = p = 1;
|
||||
}
|
||||
}
|
||||
if (ip+1 > ms+1) {
|
||||
ms = ip;
|
||||
} else {
|
||||
p = p0;
|
||||
}
|
||||
|
||||
/* Periodic needle? */
|
||||
if (memcmp(n, n+p, ms+1)) {
|
||||
mem0 = 0;
|
||||
p = MAX(ms, l-ms-1) + 1;
|
||||
} else {
|
||||
mem0 = l-p;
|
||||
}
|
||||
mem = 0;
|
||||
|
||||
/* Initialize incremental end-of-haystack pointer */
|
||||
const unsigned char * z = h;
|
||||
|
||||
/* Search loop */
|
||||
for (;;) {
|
||||
/* Update incremental end-of-haystack pointer */
|
||||
if ((size_t)(z-h) < l) {
|
||||
/* Fast estimate for MIN(l,63) */
|
||||
size_t grow = l | 63;
|
||||
const unsigned char *z2 = memchr(z, 0, grow);
|
||||
if (z2) {
|
||||
z = z2;
|
||||
if ((size_t)(z-h) < l) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
z += grow;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check last byte first; advance by shift on mismatch */
|
||||
if (BITOP(byteset, h[l-1], &)) {
|
||||
k = l-shift[h[l-1]];
|
||||
if (k) {
|
||||
if (mem0 && mem && k < p) k = l-p;
|
||||
h += k;
|
||||
mem = 0;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
h += l;
|
||||
mem = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Compare right half */
|
||||
for (k=MAX(ms+1,mem); n[k] && n[k] == h[k]; k++);
|
||||
if (n[k]) {
|
||||
h += k-ms;
|
||||
mem = 0;
|
||||
continue;
|
||||
}
|
||||
/* Compare left half */
|
||||
for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--);
|
||||
if (k <= mem) {
|
||||
return (char *)h;
|
||||
}
|
||||
h += p;
|
||||
mem = mem0;
|
||||
}
|
||||
}
|
||||
|
||||
char *strstr(const char * h, const char * n) {
|
||||
/* Return immediately on empty needle */
|
||||
if (!n[0]) {
|
||||
return (char *)h;
|
||||
}
|
||||
|
||||
/* Use faster algorithms for short needles */
|
||||
h = strchr(h, *n);
|
||||
if (!h || !n[1]) {
|
||||
return (char *)h;
|
||||
}
|
||||
|
||||
if (!h[1]) return 0;
|
||||
if (!n[2]) return strstr_2b((void *)h, (void *)n);
|
||||
if (!h[2]) return 0;
|
||||
if (!n[3]) return strstr_3b((void *)h, (void *)n);
|
||||
if (!h[3]) return 0;
|
||||
if (!n[4]) return strstr_4b((void *)h, (void *)n);
|
||||
|
||||
/* Two-way on large needles */
|
||||
return strstr_twoway((void *)h, (void *)n);
|
||||
}
|
||||
|
||||
static inline int isdigit(int ch) {
|
||||
return (unsigned int)ch-'0' < 10;
|
||||
}
|
||||
|
||||
static inline int isspace(int ch) {
|
||||
return ch == ' ' || (unsigned int)ch-'\t' < 5;
|
||||
}
|
||||
|
||||
int atoi(const char * s) {
|
||||
int n = 0;
|
||||
int neg = 0;
|
||||
while (isspace(*s)) {
|
||||
s++;
|
||||
}
|
||||
switch (*s) {
|
||||
case '-':
|
||||
neg = 1;
|
||||
/* Fallthrough is intentional here */
|
||||
case '+':
|
||||
s++;
|
||||
}
|
||||
while (isdigit(*s)) {
|
||||
n = 10*n - (*s++ - '0');
|
||||
}
|
||||
/* The sign order may look incorrect here but this is correct as n is calculated
|
||||
* as a negative number to avoid overflow on INT_MAX.
|
||||
*/
|
||||
return neg ? n : -n;
|
||||
}
|
||||
|
||||
/* Non-standard broken strtok_r */
|
||||
char * strtok_r(char * str, const char * delim, char ** saveptr) {
|
||||
char * token;
|
||||
if (str == NULL) {
|
||||
str = *saveptr;
|
||||
}
|
||||
str += strspn(str, delim);
|
||||
if (*str == '\0') {
|
||||
*saveptr = str;
|
||||
return NULL;
|
||||
}
|
||||
token = str;
|
||||
str = strpbrk(token, delim);
|
||||
if (str == NULL) {
|
||||
*saveptr = (char *)lfind(token, '\0');
|
||||
} else {
|
||||
*str = '\0';
|
||||
*saveptr = str + 1;
|
||||
}
|
||||
return token;
|
||||
}
|
@ -133,42 +133,42 @@ static void * __attribute__ ((malloc)) klcalloc(uintptr_t nmemb, uintptr_t size)
|
||||
static void * __attribute__ ((malloc)) klvalloc(uintptr_t size);
|
||||
static void klfree(void * ptr);
|
||||
|
||||
static uint8_t volatile mem_lock = 0;
|
||||
static spin_lock_t mem_lock = { 0 };
|
||||
|
||||
void * __attribute__ ((malloc)) malloc(uintptr_t size) {
|
||||
spin_lock(&mem_lock);
|
||||
spin_lock(mem_lock);
|
||||
void * ret = klmalloc(size);
|
||||
spin_unlock(&mem_lock);
|
||||
spin_unlock(mem_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void * __attribute__ ((malloc)) realloc(void * ptr, uintptr_t size) {
|
||||
spin_lock(&mem_lock);
|
||||
spin_lock(mem_lock);
|
||||
void * ret = klrealloc(ptr, size);
|
||||
spin_unlock(&mem_lock);
|
||||
spin_unlock(mem_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void * __attribute__ ((malloc)) calloc(uintptr_t nmemb, uintptr_t size) {
|
||||
spin_lock(&mem_lock);
|
||||
spin_lock(mem_lock);
|
||||
void * ret = klcalloc(nmemb, size);
|
||||
spin_unlock(&mem_lock);
|
||||
spin_unlock(mem_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void * __attribute__ ((malloc)) valloc(uintptr_t size) {
|
||||
spin_lock(&mem_lock);
|
||||
spin_lock(mem_lock);
|
||||
void * ret = klvalloc(size);
|
||||
spin_unlock(&mem_lock);
|
||||
spin_unlock(mem_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void free(void * ptr) {
|
||||
spin_lock(&mem_lock);
|
||||
spin_lock(mem_lock);
|
||||
if ((uintptr_t)ptr > placement_pointer) {
|
||||
klfree(ptr);
|
||||
}
|
||||
spin_unlock(&mem_lock);
|
||||
spin_unlock(mem_lock);
|
||||
}
|
||||
|
||||
|
||||
@ -518,7 +518,7 @@ static void * klmalloc_stack_pop(klmalloc_bin_header *header) {
|
||||
assert((uintptr_t)header->head < (uintptr_t)header + PAGE_SIZE);
|
||||
assert((uintptr_t)header->head > (uintptr_t)header + sizeof(klmalloc_bin_header) - 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Remove the current head and point
|
||||
* the head to where the old head pointed.
|
||||
@ -758,7 +758,7 @@ static void klfree(void *ptr) {
|
||||
if (bucket_id > (uintptr_t)NUM_BINS) {
|
||||
bucket_id = BIG_BIN;
|
||||
klmalloc_big_bin_header *bheader = (klmalloc_big_bin_header*)header;
|
||||
|
||||
|
||||
assert(bheader);
|
||||
assert(bheader->head == NULL);
|
||||
assert((bheader->size + sizeof(klmalloc_big_bin_header)) % PAGE_SIZE == 0);
|
||||
@ -955,7 +955,7 @@ static void * __attribute__ ((malloc)) klcalloc(uintptr_t nmemb, uintptr_t size)
|
||||
/*
|
||||
* Allocate memory and zero it before returning
|
||||
* a pointer to the newly allocated memory.
|
||||
*
|
||||
*
|
||||
* Implemented by way of a simple malloc followed
|
||||
* by a memset to 0x00 across the length of the
|
||||
* requested memory chunk.
|
||||
|
@ -23,7 +23,8 @@ uintptr_t placement_pointer = (uintptr_t)&end;
|
||||
uintptr_t heap_end = (uintptr_t)NULL;
|
||||
uintptr_t kernel_heap_alloc_point = KERNEL_HEAP_INIT;
|
||||
|
||||
static volatile uint8_t frame_alloc_lock = 0;
|
||||
//static volatile uint8_t frame_alloc_lock = 0;
|
||||
static spin_lock_t frame_alloc_lock = { 0 };
|
||||
uint32_t first_n_frames(int n);
|
||||
|
||||
void
|
||||
@ -56,9 +57,10 @@ kmalloc_real(
|
||||
clear_frame(map_to_physical(i));
|
||||
}
|
||||
/* XXX This is going to get touchy... */
|
||||
spin_lock(&frame_alloc_lock);
|
||||
spin_lock(frame_alloc_lock);
|
||||
uint32_t index = first_n_frames((size + 0xFFF) / 0x1000);
|
||||
if (index == 0xFFFFFFFF) {
|
||||
spin_unlock(frame_alloc_lock);
|
||||
return 0;
|
||||
}
|
||||
for (unsigned int i = 0; i < (size + 0xFFF) / 0x1000; ++i) {
|
||||
@ -66,7 +68,7 @@ kmalloc_real(
|
||||
page_t * page = get_page((uintptr_t)address + (i * 0x1000),0,kernel_directory);
|
||||
page->frame = index + i;
|
||||
}
|
||||
spin_unlock(&frame_alloc_lock);
|
||||
spin_unlock(frame_alloc_lock);
|
||||
}
|
||||
*phys = map_to_physical((uintptr_t)address);
|
||||
}
|
||||
@ -220,12 +222,12 @@ alloc_frame(
|
||||
page->user = (is_kernel == 1) ? 0 : 1;
|
||||
return;
|
||||
} else {
|
||||
spin_lock(&frame_alloc_lock);
|
||||
spin_lock(frame_alloc_lock);
|
||||
uint32_t index = first_frame();
|
||||
assert(index != (uint32_t)-1 && "Out of frames.");
|
||||
set_frame(index * 0x1000);
|
||||
page->frame = index;
|
||||
spin_unlock(&frame_alloc_lock);
|
||||
spin_unlock(frame_alloc_lock);
|
||||
page->present = 1;
|
||||
page->rw = (is_writeable == 1) ? 1 : 0;
|
||||
page->user = (is_kernel == 1) ? 0 : 1;
|
||||
|
@ -15,7 +15,8 @@
|
||||
#include <list.h>
|
||||
|
||||
|
||||
static volatile uint8_t bsl; // big shm lock
|
||||
//static volatile uint8_t bsl; // big shm lock
|
||||
static spin_lock_t bsl; // big shm lock
|
||||
tree_t * shm_tree = NULL;
|
||||
|
||||
|
||||
@ -250,7 +251,7 @@ static size_t chunk_size (shm_chunk_t * chunk) {
|
||||
|
||||
|
||||
void * shm_obtain (char * path, size_t * size) {
|
||||
spin_lock(&bsl);
|
||||
spin_lock(bsl);
|
||||
process_t * proc = (process_t *)current_process;
|
||||
|
||||
if (proc->group != 0) {
|
||||
@ -268,14 +269,14 @@ void * shm_obtain (char * path, size_t * size) {
|
||||
|
||||
if (size == 0) {
|
||||
// The process doesn't want a chunk...?
|
||||
spin_unlock(&bsl);
|
||||
spin_unlock(bsl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
chunk = create_chunk(node, *size);
|
||||
if (chunk == NULL) {
|
||||
debug_print(ERROR, "Could not allocate a shm_chunk_t");
|
||||
spin_unlock(&bsl);
|
||||
spin_unlock(bsl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -287,14 +288,14 @@ void * shm_obtain (char * path, size_t * size) {
|
||||
void * vshm_start = map_in(chunk, proc);
|
||||
*size = chunk_size(chunk);
|
||||
|
||||
spin_unlock(&bsl);
|
||||
spin_unlock(bsl);
|
||||
invalidate_page_tables();
|
||||
|
||||
return vshm_start;
|
||||
}
|
||||
|
||||
int shm_release (char * path) {
|
||||
spin_lock(&bsl);
|
||||
spin_lock(bsl);
|
||||
process_t * proc = (process_t *)current_process;
|
||||
|
||||
if (proc->group != 0) {
|
||||
@ -304,7 +305,7 @@ int shm_release (char * path) {
|
||||
/* First, find the right chunk */
|
||||
shm_node_t * _node = get_node(path, 0);
|
||||
if (!_node) {
|
||||
spin_unlock(&bsl);
|
||||
spin_unlock(bsl);
|
||||
return 1;
|
||||
}
|
||||
shm_chunk_t * chunk = _node->chunk;
|
||||
@ -319,7 +320,7 @@ int shm_release (char * path) {
|
||||
}
|
||||
}
|
||||
if (node == NULL) {
|
||||
spin_unlock(&bsl);
|
||||
spin_unlock(bsl);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -340,14 +341,14 @@ int shm_release (char * path) {
|
||||
free(node);
|
||||
free(mapping);
|
||||
|
||||
spin_unlock(&bsl);
|
||||
spin_unlock(bsl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function should only be called if the process's address space
|
||||
* is about to be destroyed -- chunks will not be unmounted therefrom ! */
|
||||
void shm_release_all (process_t * proc) {
|
||||
spin_lock(&bsl);
|
||||
spin_lock(bsl);
|
||||
|
||||
node_t * node;
|
||||
while ((node = list_pop(proc->shm_mappings)) != NULL) {
|
||||
@ -362,7 +363,7 @@ void shm_release_all (process_t * proc) {
|
||||
proc->shm_mappings->head = proc->shm_mappings->tail = NULL;
|
||||
proc->shm_mappings->length = 0;
|
||||
|
||||
spin_unlock(&bsl);
|
||||
spin_unlock(bsl);
|
||||
}
|
||||
|
||||
|
||||
|
57
kernel/spin.c
Normal file
57
kernel/spin.c
Normal file
@ -0,0 +1,57 @@
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* This file is part of ToaruOS and is released under the terms
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
* Copyright (C) 2015 Dale Weiler
|
||||
*
|
||||
* Spin locks with waiters
|
||||
*
|
||||
*/
|
||||
#include <system.h>
|
||||
|
||||
static inline int arch_atomic_swap(volatile int * x, int v) {
|
||||
asm("xchg %0, %1" : "=r"(v), "=m"(*x) : "0"(v) : "memory");
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline void arch_atomic_store(volatile int * p, int x) {
|
||||
asm("movl %1, %0" : "=m"(*p) : "r"(x) : "memory");
|
||||
}
|
||||
|
||||
static inline void arch_atomic_inc(volatile int * x) {
|
||||
asm("lock; incl %0" : "=m"(*x) : "m"(*x) : "memory");
|
||||
}
|
||||
|
||||
static inline void arch_atomic_dec(volatile int * x) {
|
||||
asm("lock; decl %0" : "=m"(*x) : "m"(*x) : "memory");
|
||||
}
|
||||
|
||||
void spin_wait(volatile int * addr, volatile int * waiters) {
|
||||
if (waiters) {
|
||||
arch_atomic_inc(waiters);
|
||||
}
|
||||
while (*addr) {
|
||||
switch_task(1);
|
||||
}
|
||||
if (waiters) {
|
||||
arch_atomic_dec(waiters);
|
||||
}
|
||||
}
|
||||
|
||||
void spin_lock(spin_lock_t lock) {
|
||||
while (arch_atomic_swap(lock, 1)) {
|
||||
spin_wait(lock, lock+1);
|
||||
}
|
||||
}
|
||||
|
||||
void spin_init(spin_lock_t lock) {
|
||||
lock[0] = 0;
|
||||
lock[1] = 0;
|
||||
}
|
||||
|
||||
void spin_unlock(spin_lock_t lock) {
|
||||
if (lock[0]) {
|
||||
arch_atomic_store(lock, 0);
|
||||
if (lock[1])
|
||||
switch_task(1);
|
||||
}
|
||||
}
|
@ -16,13 +16,30 @@
|
||||
static hashmap_t * symboltable = NULL;
|
||||
static hashmap_t * modules = NULL;
|
||||
|
||||
extern char kernel_symbols_start[];
|
||||
extern char kernel_symbols_end[];
|
||||
|
||||
typedef struct {
|
||||
uintptr_t addr;
|
||||
char name[];
|
||||
} kernel_symbol_t;
|
||||
|
||||
extern char kernel_symbols_start[];
|
||||
extern char kernel_symbols_end[];
|
||||
/* Cannot use symboltable here because symbol_find is used during initialization
|
||||
* of IRQs and ISRs.
|
||||
*/
|
||||
void (* symbol_find(const char * name))(void) {
|
||||
kernel_symbol_t * k = (kernel_symbol_t *)&kernel_symbols_start;
|
||||
|
||||
while ((uintptr_t)k < (uintptr_t)&kernel_symbols_end) {
|
||||
if (strcmp(k->name, name)) {
|
||||
k = (kernel_symbol_t *)((uintptr_t)k + sizeof *k + strlen(k->name) + 1);
|
||||
continue;
|
||||
}
|
||||
return (void (*)(void))k->addr;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int module_quickcheck(void * blob) {
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
* Copyright (C) 2011-2014 Kevin Lange
|
||||
* Copyright (C) 2012 Markus Schober
|
||||
* Copyright (C) 2015 Dale Weiler
|
||||
*
|
||||
* Processes
|
||||
*
|
||||
@ -13,6 +14,7 @@
|
||||
#include <process.h>
|
||||
#include <tree.h>
|
||||
#include <list.h>
|
||||
#include <bitset.h>
|
||||
#include <logging.h>
|
||||
#include <shm.h>
|
||||
#include <printf.h>
|
||||
@ -24,10 +26,12 @@ list_t * sleep_queue;
|
||||
volatile process_t * current_process = NULL;
|
||||
process_t * kernel_idle_task = NULL;
|
||||
|
||||
static uint8_t volatile tree_lock = 0;
|
||||
static uint8_t volatile process_queue_lock = 0;
|
||||
static uint8_t volatile wait_lock_tmp = 0;
|
||||
static uint8_t volatile sleep_lock = 0;
|
||||
static spin_lock_t tree_lock = { 0 };
|
||||
static spin_lock_t process_queue_lock = { 0 };
|
||||
static spin_lock_t wait_lock_tmp = { 0 };
|
||||
static spin_lock_t sleep_lock = { 0 };
|
||||
|
||||
static bitset_t pid_set;
|
||||
|
||||
/* Default process name string */
|
||||
char * default_name = "[unnamed]";
|
||||
@ -40,6 +44,12 @@ void initialize_process_tree(void) {
|
||||
process_list = list_create();
|
||||
process_queue = list_create();
|
||||
sleep_queue = list_create();
|
||||
|
||||
/* Start off with enough bits for 64 processes */
|
||||
bitset_init(&pid_set, 64 / 8);
|
||||
/* First two bits are set by default */
|
||||
bitset_set(&pid_set, 0);
|
||||
bitset_set(&pid_set, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -112,9 +122,9 @@ void make_process_ready(process_t * proc) {
|
||||
/* XXX can't wake from timed sleep */
|
||||
if (proc->timed_sleep_node) {
|
||||
IRQ_OFF;
|
||||
spin_lock(&sleep_lock);
|
||||
spin_lock(sleep_lock);
|
||||
list_delete(sleep_queue, proc->timed_sleep_node);
|
||||
spin_unlock(&sleep_lock);
|
||||
spin_unlock(sleep_lock);
|
||||
IRQ_RES;
|
||||
proc->sleep_node.owner = NULL;
|
||||
free(proc->timed_sleep_node->value);
|
||||
@ -122,14 +132,14 @@ void make_process_ready(process_t * proc) {
|
||||
/* Else: I have no idea what happened. */
|
||||
} else {
|
||||
proc->sleep_interrupted = 1;
|
||||
spin_lock(&wait_lock_tmp);
|
||||
spin_lock(wait_lock_tmp);
|
||||
list_delete((list_t*)proc->sleep_node.owner, &proc->sleep_node);
|
||||
spin_unlock(&wait_lock_tmp);
|
||||
spin_unlock(wait_lock_tmp);
|
||||
}
|
||||
}
|
||||
spin_lock(&process_queue_lock);
|
||||
spin_lock(process_queue_lock);
|
||||
list_append(process_queue, &proc->sched_node);
|
||||
spin_unlock(&process_queue_lock);
|
||||
spin_unlock(process_queue_lock);
|
||||
}
|
||||
|
||||
|
||||
@ -155,11 +165,13 @@ void delete_process(process_t * proc) {
|
||||
}
|
||||
|
||||
/* Remove the entry. */
|
||||
spin_lock(&tree_lock);
|
||||
spin_lock(tree_lock);
|
||||
/* Reparent everyone below me to init */
|
||||
tree_remove_reparent_root(process_tree, entry);
|
||||
list_delete(process_list, list_find(process_list, proc));
|
||||
spin_unlock(&tree_lock);
|
||||
spin_unlock(tree_lock);
|
||||
|
||||
bitset_clear(&pid_set, proc->id);
|
||||
|
||||
/* Uh... */
|
||||
free(proc);
|
||||
@ -239,7 +251,8 @@ process_t * spawn_init(void) {
|
||||
init->image.user_stack = 0;
|
||||
init->image.size = 0;
|
||||
init->image.shm_heap = SHM_START; /* Yeah, a bit of a hack. */
|
||||
init->image.lock = 0;
|
||||
|
||||
spin_init(init->image.lock);
|
||||
|
||||
/* Process is not finished */
|
||||
init->finished = 0;
|
||||
@ -277,9 +290,14 @@ process_t * spawn_init(void) {
|
||||
* @return A usable PID for a new process.
|
||||
*/
|
||||
pid_t get_next_pid(void) {
|
||||
/* Terribly naïve, I know, but it works for now */
|
||||
static pid_t next = 2;
|
||||
return (next++);
|
||||
int index = bitset_ffub(&pid_set);
|
||||
if (index == -1) {
|
||||
int next = pid_set.size * 8;
|
||||
bitset_set(&pid_set, next);
|
||||
return next;
|
||||
}
|
||||
bitset_set(&pid_set, index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -291,11 +309,11 @@ void process_disown(process_t * proc) {
|
||||
/* Find the process in the tree */
|
||||
tree_node_t * entry = proc->tree_entry;
|
||||
/* Break it of from its current parent */
|
||||
spin_lock(&tree_lock);
|
||||
spin_lock(tree_lock);
|
||||
tree_break_off(process_tree, entry);
|
||||
/* And insert it back elsewhere */
|
||||
tree_node_insert_child_node(process_tree, process_tree->root, entry);
|
||||
spin_unlock(&tree_lock);
|
||||
spin_unlock(tree_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -340,7 +358,8 @@ process_t * spawn_process(volatile process_t * parent) {
|
||||
debug_print(INFO," }");
|
||||
proc->image.user_stack = parent->image.user_stack;
|
||||
proc->image.shm_heap = SHM_START; /* Yeah, a bit of a hack. */
|
||||
proc->image.lock = 0;
|
||||
|
||||
spin_init(proc->image.lock);
|
||||
|
||||
assert(proc->image.stack && "Failed to allocate kernel stack for new process.");
|
||||
|
||||
@ -390,10 +409,10 @@ process_t * spawn_process(volatile process_t * parent) {
|
||||
tree_node_t * entry = tree_node_create(proc);
|
||||
assert(entry && "Failed to allocate a process tree node for new process.");
|
||||
proc->tree_entry = entry;
|
||||
spin_lock(&tree_lock);
|
||||
spin_lock(tree_lock);
|
||||
tree_node_insert_child_node(process_tree, parent->tree_entry, entry);
|
||||
list_insert(process_list, (void *)proc);
|
||||
spin_unlock(&tree_lock);
|
||||
spin_unlock(tree_lock);
|
||||
|
||||
/* Return the new process */
|
||||
return proc;
|
||||
@ -409,9 +428,9 @@ uint8_t process_compare(void * proc_v, void * pid_v) {
|
||||
process_t * process_from_pid(pid_t pid) {
|
||||
if (pid < 0) return NULL;
|
||||
|
||||
spin_lock(&tree_lock);
|
||||
spin_lock(tree_lock);
|
||||
tree_node_t * entry = tree_find(process_tree,&pid,process_compare);
|
||||
spin_unlock(&tree_lock);
|
||||
spin_unlock(tree_lock);
|
||||
if (entry) {
|
||||
return (process_t *)entry->value;
|
||||
}
|
||||
@ -420,7 +439,7 @@ process_t * process_from_pid(pid_t pid) {
|
||||
|
||||
process_t * process_get_parent(process_t * process) {
|
||||
process_t * result = NULL;
|
||||
spin_lock(&tree_lock);
|
||||
spin_lock(tree_lock);
|
||||
|
||||
tree_node_t * entry = process->tree_entry;
|
||||
|
||||
@ -428,7 +447,7 @@ process_t * process_get_parent(process_t * process) {
|
||||
result = entry->parent->value;
|
||||
}
|
||||
|
||||
spin_unlock(&tree_lock);
|
||||
spin_unlock(tree_lock);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -539,9 +558,9 @@ uint32_t process_move_fd(process_t * proc, int src, int dest) {
|
||||
int wakeup_queue(list_t * queue) {
|
||||
int awoken_processes = 0;
|
||||
while (queue->length > 0) {
|
||||
spin_lock(&wait_lock_tmp);
|
||||
spin_lock(wait_lock_tmp);
|
||||
node_t * node = list_pop(queue);
|
||||
spin_unlock(&wait_lock_tmp);
|
||||
spin_unlock(wait_lock_tmp);
|
||||
if (!((process_t *)node->value)->finished) {
|
||||
make_process_ready(node->value);
|
||||
}
|
||||
@ -553,9 +572,9 @@ int wakeup_queue(list_t * queue) {
|
||||
int wakeup_queue_interrupted(list_t * queue) {
|
||||
int awoken_processes = 0;
|
||||
while (queue->length > 0) {
|
||||
spin_lock(&wait_lock_tmp);
|
||||
spin_lock(wait_lock_tmp);
|
||||
node_t * node = list_pop(queue);
|
||||
spin_unlock(&wait_lock_tmp);
|
||||
spin_unlock(wait_lock_tmp);
|
||||
if (!((process_t *)node->value)->finished) {
|
||||
process_t * proc = node->value;
|
||||
proc->sleep_interrupted = 1;
|
||||
@ -574,9 +593,9 @@ int sleep_on(list_t * queue) {
|
||||
return 0;
|
||||
}
|
||||
current_process->sleep_interrupted = 0;
|
||||
spin_lock(&wait_lock_tmp);
|
||||
spin_lock(wait_lock_tmp);
|
||||
list_append(queue, (node_t *)¤t_process->sleep_node);
|
||||
spin_unlock(&wait_lock_tmp);
|
||||
spin_unlock(wait_lock_tmp);
|
||||
switch_task(0);
|
||||
return current_process->sleep_interrupted;
|
||||
}
|
||||
@ -588,7 +607,7 @@ int process_is_ready(process_t * proc) {
|
||||
|
||||
void wakeup_sleepers(unsigned long seconds, unsigned long subseconds) {
|
||||
IRQ_OFF;
|
||||
spin_lock(&sleep_lock);
|
||||
spin_lock(sleep_lock);
|
||||
if (sleep_queue->length) {
|
||||
sleeper_t * proc = ((sleeper_t *)sleep_queue->head->value);
|
||||
while (proc && (proc->end_tick < seconds || (proc->end_tick == seconds && proc->end_subtick <= subseconds))) {
|
||||
@ -607,7 +626,7 @@ void wakeup_sleepers(unsigned long seconds, unsigned long subseconds) {
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock(&sleep_lock);
|
||||
spin_unlock(sleep_lock);
|
||||
IRQ_RES;
|
||||
}
|
||||
|
||||
@ -619,7 +638,7 @@ void sleep_until(process_t * process, unsigned long seconds, unsigned long subse
|
||||
process->sleep_node.owner = sleep_queue;
|
||||
|
||||
IRQ_OFF;
|
||||
spin_lock(&sleep_lock);
|
||||
spin_lock(sleep_lock);
|
||||
node_t * before = NULL;
|
||||
foreach(node, sleep_queue) {
|
||||
sleeper_t * candidate = ((sleeper_t *)node->value);
|
||||
@ -633,7 +652,7 @@ void sleep_until(process_t * process, unsigned long seconds, unsigned long subse
|
||||
proc->end_tick = seconds;
|
||||
proc->end_subtick = subseconds;
|
||||
process->timed_sleep_node = list_insert_after(sleep_queue, before, proc);
|
||||
spin_unlock(&sleep_lock);
|
||||
spin_unlock(sleep_lock);
|
||||
IRQ_RES;
|
||||
}
|
||||
|
||||
|
@ -36,8 +36,8 @@ void enter_signal_handler(uintptr_t location, int signum, uintptr_t stack) {
|
||||
debug_print(CRITICAL, "Failed to jump to signal handler!");
|
||||
}
|
||||
|
||||
static uint8_t volatile sig_lock;
|
||||
static uint8_t volatile sig_lock_b;
|
||||
static spin_lock_t sig_lock;
|
||||
static spin_lock_t sig_lock_b;
|
||||
|
||||
char isdeadly[] = {
|
||||
0, /* 0? */
|
||||
@ -136,9 +136,9 @@ void return_from_signal_handler(void) {
|
||||
rets_from_sig = list_create();
|
||||
}
|
||||
|
||||
spin_lock(&sig_lock);
|
||||
spin_lock(sig_lock);
|
||||
list_insert(rets_from_sig, (process_t *)current_process);
|
||||
spin_unlock(&sig_lock);
|
||||
spin_unlock(sig_lock);
|
||||
|
||||
switch_next();
|
||||
}
|
||||
@ -146,11 +146,11 @@ void return_from_signal_handler(void) {
|
||||
void fix_signal_stacks(void) {
|
||||
uint8_t redo_me = 0;
|
||||
if (rets_from_sig) {
|
||||
spin_lock(&sig_lock_b);
|
||||
spin_lock(sig_lock_b);
|
||||
while (rets_from_sig->head) {
|
||||
spin_lock(&sig_lock);
|
||||
spin_lock(sig_lock);
|
||||
node_t * n = list_dequeue(rets_from_sig);
|
||||
spin_unlock(&sig_lock);
|
||||
spin_unlock(sig_lock);
|
||||
if (!n) {
|
||||
continue;
|
||||
}
|
||||
@ -168,12 +168,12 @@ void fix_signal_stacks(void) {
|
||||
p->signal_kstack = NULL;
|
||||
make_process_ready(p);
|
||||
}
|
||||
spin_unlock(&sig_lock_b);
|
||||
spin_unlock(sig_lock_b);
|
||||
}
|
||||
if (redo_me) {
|
||||
spin_lock(&sig_lock);
|
||||
spin_lock(sig_lock);
|
||||
list_insert(rets_from_sig, (process_t *)current_process);
|
||||
spin_unlock(&sig_lock);
|
||||
spin_unlock(sig_lock);
|
||||
switch_next();
|
||||
}
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ static int sys_sbrk(int size) {
|
||||
if (proc->group != 0) {
|
||||
proc = process_from_pid(proc->group);
|
||||
}
|
||||
spin_lock(&proc->image.lock);
|
||||
spin_lock(proc->image.lock);
|
||||
uintptr_t ret = proc->image.heap;
|
||||
uintptr_t i_ret = ret;
|
||||
while (ret % 0x1000) {
|
||||
@ -164,7 +164,7 @@ static int sys_sbrk(int size) {
|
||||
alloc_frame(get_page(proc->image.heap_actual, 1, current_directory), 0, 1);
|
||||
invalidate_tables_at(proc->image.heap_actual);
|
||||
}
|
||||
spin_unlock(&proc->image.lock);
|
||||
spin_unlock(proc->image.lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -428,7 +428,8 @@ static int sys_chdir(char * newdir) {
|
||||
static int sys_getcwd(char * buf, size_t size) {
|
||||
if (buf) {
|
||||
PTR_VALIDATE(buf);
|
||||
return (int)memcpy(buf, current_process->wd_name, min(size, strlen(current_process->wd_name) + 1));
|
||||
size_t len = strlen(current_process->wd_name) + 1;
|
||||
return (int)memcpy(buf, current_process->wd_name, MIN(size, len));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -8,90 +8,9 @@
|
||||
*/
|
||||
#include <system.h>
|
||||
|
||||
unsigned int __irq_sem = 0;
|
||||
|
||||
void spin_lock(uint8_t volatile * lock) {
|
||||
while(__sync_lock_test_and_set(lock, 0x01)) {
|
||||
switch_task(1);
|
||||
}
|
||||
}
|
||||
|
||||
void spin_unlock(uint8_t volatile * lock) {
|
||||
__sync_lock_release(lock);
|
||||
}
|
||||
|
||||
char * boot_arg = NULL;
|
||||
char * boot_arg_extra = NULL;
|
||||
|
||||
/*
|
||||
* memcpy
|
||||
* Copy from source to destination. Assumes that
|
||||
* source and destination are not overlapping.
|
||||
*/
|
||||
void * memcpy(void * restrict dest, const void * restrict src, size_t count) {
|
||||
asm volatile ("cld; rep movsb" : "+c" (count), "+S" (src), "+D" (dest) :: "memory");
|
||||
return dest;
|
||||
}
|
||||
|
||||
int max(int a, int b) {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
int min(int a, int b) {
|
||||
return (a > b) ? b : a;
|
||||
}
|
||||
|
||||
int abs(int a) {
|
||||
return (a >= 0) ? a : -a;
|
||||
}
|
||||
|
||||
void swap(int *a, int *b) {
|
||||
int t = *a;
|
||||
*a = *b;
|
||||
*b = t;
|
||||
}
|
||||
|
||||
void * memmove(void * restrict dest, const void * restrict src, size_t count) {
|
||||
size_t i;
|
||||
unsigned char *a = dest;
|
||||
const unsigned char *b = src;
|
||||
if (src < dest) {
|
||||
for ( i = count; i > 0; --i) {
|
||||
a[i-1] = b[i-1];
|
||||
}
|
||||
} else {
|
||||
for ( i = 0; i < count; ++i) {
|
||||
a[i] = b[i];
|
||||
}
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
int strcmp(const char * a, const char * b) {
|
||||
uint32_t i = 0;
|
||||
while (1) {
|
||||
if (a[i] < b[i]) {
|
||||
return -1;
|
||||
} else if (a[i] > b[i]) {
|
||||
return 1;
|
||||
} else {
|
||||
if (a[i] == '\0') {
|
||||
return 0;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* memset
|
||||
* Set `count` bytes to `val`.
|
||||
*/
|
||||
void * memset(void * b, int val, size_t count) {
|
||||
asm volatile ("cld; rep stosb" : "+c" (count), "+D" (b) : "a" (val) : "memory");
|
||||
return b;
|
||||
}
|
||||
|
||||
/*
|
||||
* memsetw
|
||||
* Set `count` shorts to `val`.
|
||||
@ -104,31 +23,6 @@ unsigned short * memsetw(unsigned short * dest, unsigned short val, int count) {
|
||||
return dest;
|
||||
}
|
||||
|
||||
/*
|
||||
* strlen
|
||||
* Returns the length of a given `str`.
|
||||
*/
|
||||
uint32_t strlen(const char *str) {
|
||||
int i = 0;
|
||||
while (str[i] != (char)0) {
|
||||
++i;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
char * strdup(const char *str) {
|
||||
int len = strlen(str);
|
||||
char * out = malloc(sizeof(char) * (len+1));
|
||||
memcpy(out, str, len+1);
|
||||
return out;
|
||||
}
|
||||
|
||||
char * strcpy(char * dest, const char * src) {
|
||||
int len = strlen(src);
|
||||
memcpy(dest, src, len+1);
|
||||
return dest;
|
||||
}
|
||||
|
||||
uint32_t __attribute__ ((pure)) krand(void) {
|
||||
static uint32_t x = 123456789;
|
||||
static uint32_t y = 362436069;
|
||||
@ -142,22 +36,6 @@ uint32_t __attribute__ ((pure)) krand(void) {
|
||||
return w = w ^ (w >> 19) ^ t ^ (t >> 8);
|
||||
}
|
||||
|
||||
/*
|
||||
* atoi
|
||||
* Naïve implementation thereof.
|
||||
*/
|
||||
int atoi(const char * str) {
|
||||
uint32_t len = strlen(str);
|
||||
uint32_t out = 0;
|
||||
uint32_t i;
|
||||
uint32_t pow = 1;
|
||||
for (i = len; i > 0; --i) {
|
||||
out += (str[i-1] - 48) * pow;
|
||||
pow *= 10;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
unsigned short inports(unsigned short _port) {
|
||||
unsigned short rv;
|
||||
asm volatile ("inw %1, %0" : "=a" (rv) : "dN" (_port));
|
||||
@ -178,154 +56,33 @@ void outportl(unsigned short _port, unsigned int _data) {
|
||||
asm volatile ("outl %%eax, %%dx" : : "dN" (_port), "a" (_data));
|
||||
}
|
||||
|
||||
/*
|
||||
* inportb
|
||||
* Read from an I/O port.
|
||||
*/
|
||||
unsigned char inportb(unsigned short _port) {
|
||||
unsigned char rv;
|
||||
asm volatile ("inb %1, %0" : "=a" (rv) : "dN" (_port));
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* outportb
|
||||
* Write to an I/O port.
|
||||
*/
|
||||
void outportb(unsigned short _port, unsigned char _data) {
|
||||
asm volatile ("outb %1, %0" : : "dN" (_port), "a" (_data));
|
||||
}
|
||||
|
||||
/*
|
||||
* Output multiple sets of shorts
|
||||
*/
|
||||
void outportsm(unsigned short port, unsigned char * data, unsigned long size) {
|
||||
asm volatile ("rep outsw" : "+S" (data), "+c" (size) : "d" (port));
|
||||
}
|
||||
|
||||
/*
|
||||
* Input multiple sets of shorts
|
||||
*/
|
||||
void inportsm(unsigned short port, unsigned char * data, unsigned long size) {
|
||||
asm volatile ("rep insw" : "+D" (data), "+c" (size) : "d" (port) : "memory");
|
||||
}
|
||||
|
||||
char * strtok_r(char * str, const char * delim, char ** saveptr) {
|
||||
char * token;
|
||||
if (str == NULL) {
|
||||
str = *saveptr;
|
||||
}
|
||||
str += strspn(str, delim);
|
||||
if (*str == '\0') {
|
||||
*saveptr = str;
|
||||
return NULL;
|
||||
}
|
||||
token = str;
|
||||
str = strpbrk(token, delim);
|
||||
if (str == NULL) {
|
||||
*saveptr = (char *)lfind(token, '\0');
|
||||
} else {
|
||||
*str = '\0';
|
||||
*saveptr = str + 1;
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
size_t lfind(const char * str, const char accept) {
|
||||
size_t i = 0;
|
||||
while ( str[i] != accept) {
|
||||
i++;
|
||||
}
|
||||
return (size_t)(str) + i;
|
||||
return (size_t)strchr(str, accept);
|
||||
}
|
||||
|
||||
size_t rfind(const char * str, const char accept) {
|
||||
size_t i = strlen(str) - 1;
|
||||
while (str[i] != accept) {
|
||||
if (i == 0) return UINT32_MAX;
|
||||
i--;
|
||||
}
|
||||
return (size_t)(str) + i;
|
||||
}
|
||||
|
||||
char * strstr(const char * haystack, const char * needle) {
|
||||
const char * out = NULL;
|
||||
const char * ptr;
|
||||
const char * acc;
|
||||
const char * p;
|
||||
size_t s = strlen(needle);
|
||||
for (ptr = haystack; *ptr != '\0'; ++ptr) {
|
||||
size_t accept = 0;
|
||||
out = ptr;
|
||||
p = ptr;
|
||||
for (acc = needle; (*acc != '\0') && (*p != '\0'); ++acc) {
|
||||
if (*p == *acc) {
|
||||
accept++;
|
||||
p++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (accept == s) {
|
||||
return (char *)out;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return (size_t)strrchr(str, accept);
|
||||
}
|
||||
|
||||
uint8_t startswith(const char * str, const char * accept) {
|
||||
size_t s = strlen(accept);
|
||||
for (size_t i = 0; i < s; ++i) {
|
||||
if (*str != *accept) return 0;
|
||||
str++;
|
||||
accept++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t strspn(const char * str, const char * accept) {
|
||||
const char * ptr = str;
|
||||
const char * acc;
|
||||
|
||||
while (*str) {
|
||||
for (acc = accept; *acc; ++acc) {
|
||||
if (*str == *acc) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (*acc == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
str++;
|
||||
}
|
||||
|
||||
return str - ptr;
|
||||
}
|
||||
|
||||
char * strpbrk(const char * str, const char * accept) {
|
||||
const char *acc = accept;
|
||||
|
||||
if (!*str) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (*str) {
|
||||
for (acc = accept; *acc; ++acc) {
|
||||
if (*str == *acc) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (*acc) {
|
||||
break;
|
||||
}
|
||||
++str;
|
||||
}
|
||||
|
||||
if (*acc == '\0') {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (char *)str;
|
||||
return strstr(str, accept) == str;
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,8 @@ struct ata_device {
|
||||
ata_identify_t identity;
|
||||
};
|
||||
|
||||
static volatile uint8_t ata_lock = 0;
|
||||
//static volatile uint8_t ata_lock = 0;
|
||||
static spin_lock_t ata_lock = { 0 };
|
||||
|
||||
/* TODO support other sector sizes */
|
||||
#define ATA_SECTOR_SIZE 512
|
||||
@ -302,7 +303,7 @@ static void ata_device_read_sector(struct ata_device * dev, uint32_t lba, uint8_
|
||||
uint16_t bus = dev->io_base;
|
||||
uint8_t slave = dev->slave;
|
||||
|
||||
spin_lock(&ata_lock);
|
||||
spin_lock(ata_lock);
|
||||
|
||||
int errors = 0;
|
||||
try_again:
|
||||
@ -323,7 +324,7 @@ try_again:
|
||||
errors++;
|
||||
if (errors > 4) {
|
||||
debug_print(WARNING, "-- Too many errors trying to read this block. Bailing.");
|
||||
spin_unlock(&ata_lock);
|
||||
spin_unlock(ata_lock);
|
||||
return;
|
||||
}
|
||||
goto try_again;
|
||||
@ -332,14 +333,14 @@ try_again:
|
||||
int size = 256;
|
||||
inportsm(bus,buf,size);
|
||||
ata_wait(dev, 0);
|
||||
spin_unlock(&ata_lock);
|
||||
spin_unlock(ata_lock);
|
||||
}
|
||||
|
||||
static void ata_device_write_sector(struct ata_device * dev, uint32_t lba, uint8_t * buf) {
|
||||
uint16_t bus = dev->io_base;
|
||||
uint8_t slave = dev->slave;
|
||||
|
||||
spin_lock(&ata_lock);
|
||||
spin_lock(ata_lock);
|
||||
|
||||
outportb(bus + ATA_REG_CONTROL, 0x02);
|
||||
|
||||
@ -358,7 +359,7 @@ static void ata_device_write_sector(struct ata_device * dev, uint32_t lba, uint8
|
||||
outportsm(bus,buf,size);
|
||||
outportb(bus + 0x07, ATA_CMD_CACHE_FLUSH);
|
||||
ata_wait(dev, 0);
|
||||
spin_unlock(&ata_lock);
|
||||
spin_unlock(ata_lock);
|
||||
}
|
||||
|
||||
static int buffer_compare(uint32_t * ptr1, uint32_t * ptr2, size_t size) {
|
||||
|
@ -38,7 +38,7 @@ typedef struct {
|
||||
unsigned int cache_entries; /* Size of ->disk_cache */
|
||||
unsigned int cache_time; /* "timer" that increments with each cache read/write */
|
||||
|
||||
uint8_t volatile lock; /* Synchronization lock point */
|
||||
spin_lock_t lock; /* Synchronization lock point */
|
||||
|
||||
uint8_t bgd_block_span;
|
||||
uint8_t bgd_offset;
|
||||
@ -120,14 +120,14 @@ static int read_block(ext2_fs_t * this, unsigned int block_no, uint8_t * buf) {
|
||||
}
|
||||
|
||||
/* This operation requires the filesystem lock to be obtained */
|
||||
spin_lock(&this->lock);
|
||||
spin_lock(this->lock);
|
||||
|
||||
/* We can make reads without a cache in place. */
|
||||
if (!DC) {
|
||||
/* In such cases, we read directly from the block device */
|
||||
read_fs(this->block_device, block_no * this->block_size, this->block_size, (uint8_t *)buf);
|
||||
/* We are done, release the lock */
|
||||
spin_unlock(&this->lock);
|
||||
spin_unlock(this->lock);
|
||||
/* And return SUCCESS */
|
||||
return E_SUCCESS;
|
||||
}
|
||||
@ -145,7 +145,7 @@ static int read_block(ext2_fs_t * this, unsigned int block_no, uint8_t * buf) {
|
||||
/* Read the block */
|
||||
memcpy(buf, DC[i].block, this->block_size);
|
||||
/* Release the lock */
|
||||
spin_unlock(&this->lock);
|
||||
spin_unlock(this->lock);
|
||||
/* Success! */
|
||||
return E_SUCCESS;
|
||||
}
|
||||
@ -178,7 +178,7 @@ static int read_block(ext2_fs_t * this, unsigned int block_no, uint8_t * buf) {
|
||||
DC[oldest].dirty = 0;
|
||||
|
||||
/* Release the lock */
|
||||
spin_unlock(&this->lock);
|
||||
spin_unlock(this->lock);
|
||||
|
||||
/* And return success */
|
||||
return E_SUCCESS;
|
||||
@ -199,7 +199,7 @@ static int write_block(ext2_fs_t * this, unsigned int block_no, uint8_t *buf) {
|
||||
}
|
||||
|
||||
/* This operation requires the filesystem lock */
|
||||
spin_lock(&this->lock);
|
||||
spin_lock(this->lock);
|
||||
|
||||
/* Find the entry in the cache */
|
||||
int oldest = -1;
|
||||
@ -210,7 +210,7 @@ static int write_block(ext2_fs_t * this, unsigned int block_no, uint8_t *buf) {
|
||||
DC[i].last_use = get_cache_time(this);
|
||||
DC[i].dirty = 1;
|
||||
memcpy(DC[i].block, buf, this->block_size);
|
||||
spin_unlock(&this->lock);
|
||||
spin_unlock(this->lock);
|
||||
return E_SUCCESS;
|
||||
}
|
||||
if (DC[i].last_use < oldest_age) {
|
||||
@ -233,7 +233,7 @@ static int write_block(ext2_fs_t * this, unsigned int block_no, uint8_t *buf) {
|
||||
DC[oldest].dirty = 1;
|
||||
|
||||
/* Release the lock */
|
||||
spin_unlock(&this->lock);
|
||||
spin_unlock(this->lock);
|
||||
|
||||
/* We're done. */
|
||||
return E_SUCCESS;
|
||||
@ -241,7 +241,7 @@ static int write_block(ext2_fs_t * this, unsigned int block_no, uint8_t *buf) {
|
||||
|
||||
static unsigned int ext2_sync(ext2_fs_t * this) {
|
||||
/* This operation requires the filesystem lock */
|
||||
spin_lock(&this->lock);
|
||||
spin_lock(this->lock);
|
||||
|
||||
/* Flush each cache entry. */
|
||||
for (unsigned int i = 0; i < this->cache_entries; ++i) {
|
||||
@ -251,7 +251,7 @@ static unsigned int ext2_sync(ext2_fs_t * this) {
|
||||
}
|
||||
|
||||
/* Release the lock */
|
||||
spin_unlock(&this->lock);
|
||||
spin_unlock(this->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -450,7 +450,7 @@ static int write_inode(ext2_fs_t * this, ext2_inodetable_t *inode, uint32_t inde
|
||||
if (group > BGDS) {
|
||||
return E_BADBLOCK;
|
||||
}
|
||||
|
||||
|
||||
uint32_t inode_table_block = BGD[group].inode_table;
|
||||
index -= group * this->inodes_per_group;
|
||||
uint32_t block_offset = ((index - 1) * this->inode_size) / this->block_size;
|
||||
@ -953,7 +953,7 @@ static ext2_dir_t * direntry_ext2(ext2_fs_t * this, ext2_inodetable_t * inode, u
|
||||
inode_read_block(this, inode, block_nr, block);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free(block);
|
||||
return NULL;
|
||||
}
|
||||
@ -981,7 +981,7 @@ static fs_node_t * finddir_ext2(fs_node_t *node, char *name) {
|
||||
inode_read_block(this, inode, block_nr, block);
|
||||
}
|
||||
ext2_dir_t *d_ent = (ext2_dir_t *)((uintptr_t)block + dir_offset);
|
||||
|
||||
|
||||
if (d_ent->inode == 0 || strlen(name) != d_ent->name_len) {
|
||||
dir_offset += d_ent->rec_len;
|
||||
total_offset += d_ent->rec_len;
|
||||
@ -1043,7 +1043,7 @@ static void unlink_ext2(fs_node_t * node, char * name) {
|
||||
inode_read_block(this, inode, block_nr, block);
|
||||
}
|
||||
ext2_dir_t *d_ent = (ext2_dir_t *)((uintptr_t)block + dir_offset);
|
||||
|
||||
|
||||
if (d_ent->inode == 0 || strlen(name) != d_ent->name_len) {
|
||||
dir_offset += d_ent->rec_len;
|
||||
total_offset += d_ent->rec_len;
|
||||
@ -1439,7 +1439,7 @@ static fs_node_t * mount_ext2(fs_node_t * block_device) {
|
||||
char * bg_buffer = malloc(this->block_size * sizeof(char));
|
||||
for (uint32_t i = 0; i < BGDS; ++i) {
|
||||
debug_print(INFO, "Block Group Descriptor #%d @ %d", i, this->bgd_offset + i * SB->blocks_per_group);
|
||||
debug_print(INFO, "\tBlock Bitmap @ %d", BGD[i].block_bitmap); {
|
||||
debug_print(INFO, "\tBlock Bitmap @ %d", BGD[i].block_bitmap); {
|
||||
debug_print(INFO, "\t\tExamining block bitmap at %d", BGD[i].block_bitmap);
|
||||
read_block(this, BGD[i].block_bitmap, (uint8_t *)bg_buffer);
|
||||
uint32_t j = 0;
|
||||
|
@ -15,13 +15,13 @@
|
||||
typedef struct packet_manager {
|
||||
/* uh, nothing, lol */
|
||||
list_t * exchanges;
|
||||
volatile uint8_t lock;
|
||||
spin_lock_t lock;
|
||||
} pex_t;
|
||||
|
||||
typedef struct packet_exchange {
|
||||
char * name;
|
||||
char fresh;
|
||||
volatile uint8_t lock;
|
||||
spin_lock_t lock;
|
||||
fs_node_t * server_pipe;
|
||||
list_t * clients;
|
||||
} pex_ex_t;
|
||||
@ -130,12 +130,12 @@ static uint32_t write_server(fs_node_t * node, uint32_t offset, uint32_t size, u
|
||||
|
||||
if (head->target == NULL) {
|
||||
/* Brodcast packet */
|
||||
spin_lock(&p->lock);
|
||||
spin_lock(p->lock);
|
||||
foreach(f, p->clients) {
|
||||
debug_print(INFO, "Sending to client 0x%x", f->value);
|
||||
send_to_client(p, (pex_client_t *)f->value, size - sizeof(header_t), head->data);
|
||||
}
|
||||
spin_unlock(&p->lock);
|
||||
spin_unlock(p->lock);
|
||||
debug_print(INFO, "Done broadcasting to clients.");
|
||||
return size;
|
||||
} else if (head->target->parent != p) {
|
||||
@ -221,7 +221,7 @@ static void close_client(fs_node_t * node) {
|
||||
|
||||
debug_print(WARNING, "Closing packetfs client: 0x%x:0x%x", p, c);
|
||||
|
||||
spin_lock(&p->lock);
|
||||
spin_lock(p->lock);
|
||||
|
||||
node_t * n = list_find(p->clients, c);
|
||||
if (n && n->owner == p->clients) {
|
||||
@ -229,7 +229,7 @@ static void close_client(fs_node_t * node) {
|
||||
free(n);
|
||||
}
|
||||
|
||||
spin_unlock(&p->lock);
|
||||
spin_unlock(p->lock);
|
||||
|
||||
char tmp[1];
|
||||
|
||||
@ -301,11 +301,11 @@ static struct dirent * readdir_packetfs(fs_node_t *node, uint32_t index) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
spin_lock(&p->lock);
|
||||
spin_lock(p->lock);
|
||||
|
||||
foreach(f, p->exchanges) {
|
||||
if (i == index) {
|
||||
spin_unlock(&p->lock);
|
||||
spin_unlock(p->lock);
|
||||
pex_ex_t * t = (pex_ex_t *)f->value;
|
||||
struct dirent * out = malloc(sizeof(struct dirent));
|
||||
memset(out, 0x00, sizeof(struct dirent));
|
||||
@ -317,7 +317,7 @@ static struct dirent * readdir_packetfs(fs_node_t *node, uint32_t index) {
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock(&p->lock);
|
||||
spin_unlock(p->lock);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -341,17 +341,17 @@ static fs_node_t * finddir_packetfs(fs_node_t * node, char * name) {
|
||||
|
||||
debug_print(INFO, "[pex] finddir(%s)", name);
|
||||
|
||||
spin_lock(&p->lock);
|
||||
spin_lock(p->lock);
|
||||
|
||||
foreach(f, p->exchanges) {
|
||||
pex_ex_t * t = (pex_ex_t *)f->value;
|
||||
if (!strcmp(name, t->name)) {
|
||||
spin_unlock(&p->lock);
|
||||
spin_unlock(p->lock);
|
||||
return file_from_pex(t);
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock(&p->lock);
|
||||
spin_unlock(p->lock);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -363,12 +363,12 @@ static void create_packetfs(fs_node_t *parent, char *name, uint16_t permission)
|
||||
|
||||
debug_print(NOTICE, "[pex] create(%s)", name);
|
||||
|
||||
spin_lock(&p->lock);
|
||||
spin_lock(p->lock);
|
||||
|
||||
foreach(f, p->exchanges) {
|
||||
pex_ex_t * t = (pex_ex_t *)f->value;
|
||||
if (!strcmp(name, t->name)) {
|
||||
spin_unlock(&p->lock);
|
||||
spin_unlock(p->lock);
|
||||
/* Already exists */
|
||||
return;
|
||||
}
|
||||
@ -379,14 +379,15 @@ static void create_packetfs(fs_node_t *parent, char *name, uint16_t permission)
|
||||
|
||||
new_exchange->name = strdup(name);
|
||||
new_exchange->fresh = 1;
|
||||
new_exchange->lock = 0;
|
||||
new_exchange->clients = list_create();
|
||||
new_exchange->server_pipe = make_pipe(4096);
|
||||
|
||||
spin_init(new_exchange->lock);
|
||||
/* XXX Create exchange server pipe */
|
||||
|
||||
list_insert(p->exchanges, new_exchange);
|
||||
|
||||
spin_unlock(&p->lock);
|
||||
spin_unlock(p->lock);
|
||||
|
||||
}
|
||||
|
||||
@ -403,7 +404,7 @@ static void unlink_packetfs(fs_node_t *parent, char *name) {
|
||||
|
||||
int i = -1, j = 0;
|
||||
|
||||
spin_lock(&p->lock);
|
||||
spin_lock(p->lock);
|
||||
|
||||
foreach(f, p->exchanges) {
|
||||
pex_ex_t * t = (pex_ex_t *)f->value;
|
||||
@ -419,13 +420,15 @@ static void unlink_packetfs(fs_node_t *parent, char *name) {
|
||||
list_remove(p->exchanges, i);
|
||||
}
|
||||
|
||||
spin_unlock(&p->lock);
|
||||
spin_unlock(p->lock);
|
||||
}
|
||||
|
||||
static fs_node_t * packetfs_manager(void) {
|
||||
pex_t * pex = malloc(sizeof(pex_t));
|
||||
pex->exchanges = list_create();
|
||||
pex->lock = 0;
|
||||
|
||||
spin_init(pex->lock);
|
||||
|
||||
fs_node_t * fnode = malloc(sizeof(fs_node_t));
|
||||
memset(fnode, 0x00, sizeof(fs_node_t));
|
||||
fnode->inode = 0;
|
||||
|
@ -41,7 +41,9 @@ static void find_rtl(uint32_t device, uint16_t vendorid, uint16_t deviceid, void
|
||||
|
||||
static void net_handler_enqueue(void * buffer);
|
||||
static list_t * net_queue = NULL;
|
||||
static volatile uint8_t net_queue_lock = 0;
|
||||
//static volatile uint8_t net_queue_lock = 0;
|
||||
|
||||
static spin_lock_t net_queue_lock = { 0 };
|
||||
|
||||
static int rtl_irq = 0;
|
||||
static uint32_t rtl_iobase = 0;
|
||||
@ -65,16 +67,17 @@ static fs_node_t * irc_socket;
|
||||
static uint32_t seq_no = 0xff0000;
|
||||
static uint32_t ack_no = 0x0;
|
||||
|
||||
static volatile uint8_t _lock;
|
||||
//static volatile uint8_t _lock;
|
||||
static spin_lock_t _lock;
|
||||
static int next_tx_buf(void) {
|
||||
int out;
|
||||
spin_lock(&_lock);
|
||||
spin_lock(_lock);
|
||||
out = next_tx;
|
||||
next_tx++;
|
||||
if (next_tx == 4) {
|
||||
next_tx = 0;
|
||||
}
|
||||
spin_unlock(&_lock);
|
||||
spin_unlock(_lock);
|
||||
return out;
|
||||
}
|
||||
|
||||
@ -400,7 +403,9 @@ static char irc_input[400] = {'\0'};
|
||||
static char irc_prompt[100] = {'\0'};
|
||||
static char irc_nick[32] = {'\0'};
|
||||
static char irc_payload[512];
|
||||
static volatile uint8_t irc_tty_lock = 0;
|
||||
|
||||
static spin_lock_t irc_tty_lock = { 0 };
|
||||
//static volatile uint8_t irc_tty_lock = 0;
|
||||
//static struct netif rtl_netif;
|
||||
|
||||
static void irc_send(char * payload) {
|
||||
@ -422,7 +427,7 @@ static void handle_irc_packet(fs_node_t * tty, size_t size, uint8_t * packet) {
|
||||
if ((uintptr_t)e > (uintptr_t)packet + size) {
|
||||
break;
|
||||
}
|
||||
spin_lock(&irc_tty_lock);
|
||||
spin_lock(irc_tty_lock);
|
||||
|
||||
if (!e) {
|
||||
/* XXX */
|
||||
@ -445,7 +450,7 @@ static void handle_irc_packet(fs_node_t * tty, size_t size, uint8_t * packet) {
|
||||
char * command;
|
||||
char * channel;
|
||||
char * message;
|
||||
|
||||
|
||||
user = c;
|
||||
|
||||
command = strstr(user, " ");
|
||||
@ -498,7 +503,7 @@ prompt_:
|
||||
fprintf(tty, "%s", irc_prompt);
|
||||
fprintf(tty, "%s", irc_input);
|
||||
|
||||
spin_unlock(&irc_tty_lock);
|
||||
spin_unlock(irc_tty_lock);
|
||||
|
||||
if (!e) break;
|
||||
|
||||
@ -622,11 +627,11 @@ static struct ethernet_packet * net_receive(void) {
|
||||
while (!net_queue->length) {
|
||||
sleep_on(rx_wait);
|
||||
}
|
||||
spin_lock(&net_queue_lock);
|
||||
spin_lock(net_queue_lock);
|
||||
node_t * n = list_dequeue(net_queue);
|
||||
struct ethernet_packet * eth = (struct ethernet_packet *)n->value;
|
||||
free(n);
|
||||
spin_unlock(&net_queue_lock);
|
||||
spin_unlock(net_queue_lock);
|
||||
|
||||
return eth;
|
||||
}
|
||||
@ -655,11 +660,11 @@ static void net_handler(void * data, char * name) {
|
||||
static void net_handler_enqueue(void * buffer) {
|
||||
/* XXX size? source? */
|
||||
|
||||
spin_lock(&net_queue_lock);
|
||||
spin_lock(net_queue_lock);
|
||||
|
||||
list_insert(net_queue, buffer);
|
||||
|
||||
spin_unlock(&net_queue_lock);
|
||||
spin_unlock(net_queue_lock);
|
||||
}
|
||||
|
||||
static void parse_dns_response(fs_node_t * tty, void * last_packet) {
|
||||
@ -954,11 +959,11 @@ static int tty_readline(fs_node_t * dev, char * linebuf, int max) {
|
||||
debug_print(WARNING, "Read nothing?");
|
||||
continue;
|
||||
}
|
||||
spin_lock(&irc_tty_lock);
|
||||
spin_lock(irc_tty_lock);
|
||||
linebuf[read] = buf[0];
|
||||
if (buf[0] == '\n') {
|
||||
linebuf[read] = 0;
|
||||
spin_unlock(&irc_tty_lock);
|
||||
spin_unlock(irc_tty_lock);
|
||||
break;
|
||||
} else if (buf[0] == 0x08) {
|
||||
if (read > 0) {
|
||||
@ -970,18 +975,18 @@ static int tty_readline(fs_node_t * dev, char * linebuf, int max) {
|
||||
switch (buf[0]) {
|
||||
case 0x0C: /* ^L */
|
||||
/* Should reset display here */
|
||||
spin_unlock(&irc_tty_lock);
|
||||
spin_unlock(irc_tty_lock);
|
||||
break;
|
||||
default:
|
||||
/* do nothing */
|
||||
spin_unlock(&irc_tty_lock);
|
||||
spin_unlock(irc_tty_lock);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
fprintf(dev, "%c", buf[0]);
|
||||
read += r;
|
||||
}
|
||||
spin_unlock(&irc_tty_lock);
|
||||
spin_unlock(irc_tty_lock);
|
||||
}
|
||||
tty_set_buffered(dev);
|
||||
return read;
|
||||
@ -1091,7 +1096,7 @@ DEFINE_SHELL_FUNCTION(irc_join, "irc channel tool") {
|
||||
fprintf(tty, irc_prompt);
|
||||
int c = tty_readline(tty, irc_input, 400);
|
||||
|
||||
spin_lock(&irc_tty_lock);
|
||||
spin_lock(irc_tty_lock);
|
||||
|
||||
irc_input[c] = '\0';
|
||||
|
||||
@ -1099,7 +1104,7 @@ DEFINE_SHELL_FUNCTION(irc_join, "irc channel tool") {
|
||||
fprintf(tty, "\n");
|
||||
sprintf(irc_payload, "PART %s\r\n", channel);
|
||||
irc_send(irc_payload);
|
||||
spin_unlock(&irc_tty_lock);
|
||||
spin_unlock(irc_tty_lock);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1120,7 +1125,7 @@ DEFINE_SHELL_FUNCTION(irc_join, "irc channel tool") {
|
||||
}
|
||||
|
||||
memset(irc_input, 0x00, sizeof(irc_input));
|
||||
spin_unlock(&irc_tty_lock);
|
||||
spin_unlock(irc_tty_lock);
|
||||
}
|
||||
memset(irc_prompt, 0x00, sizeof(irc_prompt));
|
||||
memset(irc_input, 0x00, sizeof(irc_input));
|
||||
@ -1153,7 +1158,7 @@ DEFINE_SHELL_FUNCTION(http, "Open a prompt to send HTTP commands.") {
|
||||
|
||||
/* /posting.php?mode=post&f=7 */
|
||||
|
||||
char * content =
|
||||
char * content =
|
||||
"-----------------------------2611311029845263341299213952\r\n"
|
||||
"Content-Disposition: form-data; name=\"subject\"\r\n"
|
||||
"\r\n"
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include <system.h>
|
||||
|
||||
/* Utility macros */
|
||||
#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
|
||||
#define N_ELEMENTS(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
|
||||
#define SND_BUF_SIZE 0x1000
|
||||
@ -35,8 +34,9 @@ static int snd_mixer_ioctl(fs_node_t * node, int request, void * argp);
|
||||
static void snd_mixer_open(fs_node_t * node, unsigned int flags);
|
||||
static void snd_mixer_close(fs_node_t * node);
|
||||
|
||||
static uint8_t _devices_lock;
|
||||
static list_t _devices;
|
||||
static spin_lock_t _devices_lock;
|
||||
|
||||
static list_t _devices;
|
||||
static fs_node_t _dsp_fnode = {
|
||||
.name = "dsp",
|
||||
.device = &_devices,
|
||||
@ -52,7 +52,7 @@ static fs_node_t _mixer_fnode = {
|
||||
.open = snd_mixer_open,
|
||||
.close = snd_mixer_close,
|
||||
};
|
||||
static uint8_t _buffers_lock;
|
||||
static spin_lock_t _buffers_lock;
|
||||
static list_t _buffers;
|
||||
static uint32_t _next_device_id = SND_DEVICE_MAIN;
|
||||
|
||||
@ -60,7 +60,7 @@ int snd_register(snd_device_t * device) {
|
||||
int rv = 0;
|
||||
|
||||
debug_print(WARNING, "[snd] _devices lock: %d", _devices_lock);
|
||||
spin_lock(&_devices_lock);
|
||||
spin_lock(_devices_lock);
|
||||
device->id = _next_device_id;
|
||||
_next_device_id++;
|
||||
if (list_find(&_devices, device)) {
|
||||
@ -72,7 +72,7 @@ int snd_register(snd_device_t * device) {
|
||||
debug_print(NOTICE, "[snd] %s registered", device->name);
|
||||
|
||||
snd_register_cleanup:
|
||||
spin_unlock(&_devices_lock);
|
||||
spin_unlock(_devices_lock);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -89,7 +89,7 @@ int snd_unregister(snd_device_t * device) {
|
||||
debug_print(NOTICE, "[snd] %s unregistered", device->name);
|
||||
|
||||
snd_unregister_cleanup:
|
||||
spin_unlock(&_devices_lock);
|
||||
spin_unlock(_devices_lock);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -103,25 +103,25 @@ static int snd_dsp_ioctl(fs_node_t * node, int request, void * argp) {
|
||||
}
|
||||
|
||||
static void snd_dsp_open(fs_node_t * node, unsigned int flags) {
|
||||
/*
|
||||
/*
|
||||
* XXX(gerow): A process could take the memory of the entire system by opening
|
||||
* too many of these...
|
||||
*/
|
||||
/* Allocate a buffer for the node and keep a reference for ourselves */
|
||||
node->device = ring_buffer_create(SND_BUF_SIZE);
|
||||
spin_lock(&_buffers_lock);
|
||||
spin_lock(_buffers_lock);
|
||||
list_insert(&_buffers, node->device);
|
||||
spin_unlock(&_buffers_lock);
|
||||
spin_unlock(_buffers_lock);
|
||||
}
|
||||
|
||||
static void snd_dsp_close(fs_node_t * node) {
|
||||
spin_lock(&_buffers_lock);
|
||||
spin_lock(_buffers_lock);
|
||||
list_delete(&_buffers, list_find(&_buffers, node->device));
|
||||
spin_unlock(&_buffers_lock);
|
||||
spin_unlock(_buffers_lock);
|
||||
}
|
||||
|
||||
static snd_device_t * snd_device_by_id(uint32_t device_id) {
|
||||
spin_lock(&_devices_lock);
|
||||
spin_lock(_devices_lock);
|
||||
snd_device_t * out = NULL;
|
||||
snd_device_t * cur = NULL;
|
||||
|
||||
@ -131,7 +131,7 @@ static snd_device_t * snd_device_by_id(uint32_t device_id) {
|
||||
out = cur;
|
||||
}
|
||||
}
|
||||
spin_unlock(&_devices_lock);
|
||||
spin_unlock(_devices_lock);
|
||||
|
||||
return out;
|
||||
}
|
||||
@ -199,7 +199,7 @@ int snd_request_buf(snd_device_t * device, uint32_t size, uint8_t *buffer) {
|
||||
|
||||
memset(buffer, 0, size);
|
||||
|
||||
spin_lock(&_buffers_lock);
|
||||
spin_lock(_buffers_lock);
|
||||
foreach(buf_node, &_buffers) {
|
||||
ring_buffer_t * buf = buf_node->value;
|
||||
/* ~0x3 is to ensure we don't read partial samples or just a single channel */
|
||||
@ -223,19 +223,19 @@ int snd_request_buf(snd_device_t * device, uint32_t size, uint8_t *buffer) {
|
||||
bytes_left -= this_read_size;
|
||||
}
|
||||
}
|
||||
spin_unlock(&_buffers_lock);
|
||||
spin_unlock(_buffers_lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static snd_device_t * snd_main_device() {
|
||||
spin_lock(&_devices_lock);
|
||||
spin_lock(_devices_lock);
|
||||
foreach(node, &_devices) {
|
||||
spin_unlock(&_devices_lock);
|
||||
spin_unlock(_devices_lock);
|
||||
return node->value;
|
||||
}
|
||||
|
||||
spin_unlock(&_devices_lock);
|
||||
spin_unlock(_devices_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
#define TMPFS_TYPE_FILE 1
|
||||
#define TMPFS_TYPE_DIR 2
|
||||
|
||||
uint8_t volatile tmpfs_lock = 0;
|
||||
static spin_lock_t tmpfs_lock = { 0 };
|
||||
|
||||
struct tmpfs_dir * tmpfs_root = NULL;
|
||||
|
||||
@ -26,7 +26,7 @@ static fs_node_t * tmpfs_from_dir(struct tmpfs_dir * d);
|
||||
|
||||
static struct tmpfs_file * tmpfs_file_new(char * name) {
|
||||
|
||||
spin_lock(&tmpfs_lock);
|
||||
spin_lock(tmpfs_lock);
|
||||
|
||||
struct tmpfs_file * t = malloc(sizeof(struct tmpfs_file));
|
||||
t->name = strdup(name);
|
||||
@ -45,12 +45,12 @@ static struct tmpfs_file * tmpfs_file_new(char * name) {
|
||||
t->blocks[i] = NULL;
|
||||
}
|
||||
|
||||
spin_unlock(&tmpfs_lock);
|
||||
spin_unlock(tmpfs_lock);
|
||||
return t;
|
||||
}
|
||||
|
||||
static struct tmpfs_dir * tmpfs_dir_new(char * name, struct tmpfs_dir * parent) {
|
||||
spin_lock(&tmpfs_lock);
|
||||
spin_lock(tmpfs_lock);
|
||||
|
||||
struct tmpfs_dir * d = malloc(sizeof(struct tmpfs_dir));
|
||||
d->name = strdup(name);
|
||||
@ -63,7 +63,7 @@ static struct tmpfs_dir * tmpfs_dir_new(char * name, struct tmpfs_dir * parent)
|
||||
d->ctime = d->atime;
|
||||
d->files = list_create();
|
||||
|
||||
spin_unlock(&tmpfs_lock);
|
||||
spin_unlock(tmpfs_lock);
|
||||
return d;
|
||||
}
|
||||
|
||||
@ -82,7 +82,7 @@ static void tmpfs_file_blocks_embiggen(struct tmpfs_file * t) {
|
||||
static char * tmpfs_file_getset_block(struct tmpfs_file * t, size_t blockid, int create) {
|
||||
debug_print(INFO, "Reading block %d from file %s", blockid, t->name);
|
||||
if (create) {
|
||||
spin_lock(&tmpfs_lock);
|
||||
spin_lock(tmpfs_lock);
|
||||
while (blockid >= t->pointers) {
|
||||
tmpfs_file_blocks_embiggen(t);
|
||||
}
|
||||
@ -91,7 +91,7 @@ static char * tmpfs_file_getset_block(struct tmpfs_file * t, size_t blockid, int
|
||||
t->blocks[t->block_count] = malloc(BLOCKSIZE);
|
||||
t->block_count += 1;
|
||||
}
|
||||
spin_unlock(&tmpfs_lock);
|
||||
spin_unlock(tmpfs_lock);
|
||||
} else {
|
||||
if (blockid >= t->block_count) {
|
||||
debug_print(CRITICAL, "This will probably end badly.");
|
||||
@ -283,22 +283,23 @@ static fs_node_t * finddir_tmpfs(fs_node_t * node, char * name) {
|
||||
|
||||
struct tmpfs_dir * d = (struct tmpfs_dir *)node->device;
|
||||
|
||||
spin_lock(&tmpfs_lock);
|
||||
spin_lock(tmpfs_lock);
|
||||
|
||||
foreach(f, d->files) {
|
||||
struct tmpfs_file * t = (struct tmpfs_file *)f->value;
|
||||
if (!strcmp(name, t->name)) {
|
||||
spin_unlock(&tmpfs_lock);
|
||||
spin_unlock(tmpfs_lock);
|
||||
switch (t->type) {
|
||||
case TMPFS_TYPE_FILE:
|
||||
return tmpfs_from_file(t);
|
||||
case TMPFS_TYPE_DIR:
|
||||
return tmpfs_from_dir((struct tmpfs_dir *)t);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock(&tmpfs_lock);
|
||||
spin_unlock(tmpfs_lock);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -306,7 +307,7 @@ static fs_node_t * finddir_tmpfs(fs_node_t * node, char * name) {
|
||||
static void unlink_tmpfs(fs_node_t * node, char * name) {
|
||||
struct tmpfs_dir * d = (struct tmpfs_dir *)node->device;
|
||||
int i = -1, j = 0;
|
||||
spin_lock(&tmpfs_lock);
|
||||
spin_lock(tmpfs_lock);
|
||||
|
||||
foreach(f, d->files) {
|
||||
struct tmpfs_file * t = (struct tmpfs_file *)f->value;
|
||||
@ -323,7 +324,7 @@ static void unlink_tmpfs(fs_node_t * node, char * name) {
|
||||
list_remove(d->files, i);
|
||||
}
|
||||
|
||||
spin_unlock(&tmpfs_lock);
|
||||
spin_unlock(tmpfs_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -333,16 +334,16 @@ static void create_tmpfs(fs_node_t *parent, char *name, uint16_t permission) {
|
||||
struct tmpfs_dir * d = (struct tmpfs_dir *)parent->device;
|
||||
debug_print(CRITICAL, "Creating TMPFS file %s in %s", name, d->name);
|
||||
|
||||
spin_lock(&tmpfs_lock);
|
||||
spin_lock(tmpfs_lock);
|
||||
foreach(f, d->files) {
|
||||
struct tmpfs_file * t = (struct tmpfs_file *)f->value;
|
||||
if (!strcmp(name, t->name)) {
|
||||
spin_unlock(&tmpfs_lock);
|
||||
spin_unlock(tmpfs_lock);
|
||||
debug_print(WARNING, "... already exists.");
|
||||
return; /* Already exists */
|
||||
}
|
||||
}
|
||||
spin_unlock(&tmpfs_lock);
|
||||
spin_unlock(tmpfs_lock);
|
||||
|
||||
debug_print(NOTICE, "... creating a new file.");
|
||||
struct tmpfs_file * t = tmpfs_file_new(name);
|
||||
@ -350,9 +351,9 @@ static void create_tmpfs(fs_node_t *parent, char *name, uint16_t permission) {
|
||||
t->uid = current_process->user;
|
||||
t->gid = current_process->user;
|
||||
|
||||
spin_lock(&tmpfs_lock);
|
||||
spin_lock(tmpfs_lock);
|
||||
list_insert(d->files, t);
|
||||
spin_unlock(&tmpfs_lock);
|
||||
spin_unlock(tmpfs_lock);
|
||||
}
|
||||
|
||||
static void mkdir_tmpfs(fs_node_t * parent, char * name, uint16_t permission) {
|
||||
@ -361,16 +362,16 @@ static void mkdir_tmpfs(fs_node_t * parent, char * name, uint16_t permission) {
|
||||
struct tmpfs_dir * d = (struct tmpfs_dir *)parent->device;
|
||||
debug_print(CRITICAL, "Creating TMPFS directory %s (in %s)", name, d->name);
|
||||
|
||||
spin_lock(&tmpfs_lock);
|
||||
spin_lock(tmpfs_lock);
|
||||
foreach(f, d->files) {
|
||||
struct tmpfs_file * t = (struct tmpfs_file *)f->value;
|
||||
if (!strcmp(name, t->name)) {
|
||||
spin_unlock(&tmpfs_lock);
|
||||
spin_unlock(tmpfs_lock);
|
||||
debug_print(WARNING, "... already exists.");
|
||||
return; /* Already exists */
|
||||
}
|
||||
}
|
||||
spin_unlock(&tmpfs_lock);
|
||||
spin_unlock(tmpfs_lock);
|
||||
|
||||
debug_print(NOTICE, "... creating a new directory.");
|
||||
struct tmpfs_dir * out = tmpfs_dir_new(name, d);
|
||||
@ -378,9 +379,9 @@ static void mkdir_tmpfs(fs_node_t * parent, char * name, uint16_t permission) {
|
||||
out->uid = current_process->user;
|
||||
out->gid = current_process->user;
|
||||
|
||||
spin_lock(&tmpfs_lock);
|
||||
spin_lock(tmpfs_lock);
|
||||
list_insert(d->files, out);
|
||||
spin_unlock(&tmpfs_lock);
|
||||
spin_unlock(tmpfs_lock);
|
||||
}
|
||||
|
||||
static fs_node_t * tmpfs_from_dir(struct tmpfs_dir * d) {
|
||||
|
Loading…
Reference in New Issue
Block a user