From 59ecf21e36b2332f6adf2a568ef555283d8c119a Mon Sep 17 00:00:00 2001 From: Minep Date: Sun, 26 Nov 2023 23:17:42 +0000 Subject: [PATCH] feat: nearly complete POSIX.1-2008 compliant terminal interface implementation fix: a corner case in cake allocator fix: remove a double free and add checks to cake allocator for that fix: enforcing the termination condition of stackwalker fix: signal delivery to process group chore: tweak the clang-formatter config chore: clean-up and refactors --- lunaix-os/.clang-format | 168 +++++------ lunaix-os/arch/i386/mm/pfault.c | 4 +- lunaix-os/hal/ahci/io_event.c | 2 +- lunaix-os/hal/char/serial.c | 46 ++- lunaix-os/hal/char/uart/16550_pmio.c | 2 +- lunaix-os/hal/term/lcntls/ansi_cntl.c | 61 ++-- lunaix-os/hal/term/lcntls/lcntl.c | 173 ++++++++++++ lunaix-os/hal/term/term.c | 310 ++++++++++----------- lunaix-os/hal/term/term_io.c | 118 ++++++++ lunaix-os/includes/hal/serial.h | 19 +- lunaix-os/includes/hal/term.h | 78 ++++-- lunaix-os/includes/lunaix/compiler.h | 4 + lunaix-os/includes/lunaix/device.h | 23 +- lunaix-os/includes/lunaix/ds/rbuffer.h | 56 ++++ lunaix-os/includes/lunaix/iopoll.h | 9 +- lunaix-os/includes/lunaix/types.h | 4 + lunaix-os/includes/usr/lunaix/ioctl_defs.h | 4 - lunaix-os/includes/usr/lunaix/term.h | 95 +++++++ lunaix-os/kernel/debug/trace.c | 6 +- lunaix-os/kernel/device/device.c | 11 +- lunaix-os/kernel/device/poll.c | 12 +- lunaix-os/kernel/ds/rbuffer.c | 100 +++++++ lunaix-os/kernel/mm/cake.c | 12 +- lunaix-os/kernel/mm/mmap.c | 3 - lunaix-os/kernel/mm/region.c | 5 +- lunaix-os/kernel/process/sched.c | 8 +- lunaix-os/kernel/process/signal.c | 2 +- 27 files changed, 963 insertions(+), 372 deletions(-) create mode 100644 lunaix-os/hal/term/lcntls/lcntl.c create mode 100644 lunaix-os/hal/term/term_io.c create mode 100644 lunaix-os/includes/lunaix/ds/rbuffer.h create mode 100644 lunaix-os/includes/usr/lunaix/term.h create mode 100644 lunaix-os/kernel/ds/rbuffer.c diff --git a/lunaix-os/.clang-format b/lunaix-os/.clang-format index a429ba1..079efc7 100644 --- a/lunaix-os/.clang-format +++ b/lunaix-os/.clang-format @@ -1,112 +1,112 @@ ---- -Language: Cpp -# BasedOnStyle: Mozilla -AccessModifierOffset: -2 -AlignAfterOpenBracket: Align +# --- +# Language: Cpp +# # BasedOnStyle: Mozilla +# AccessModifierOffset: -2 +# AlignAfterOpenBracket: Align AlignConsecutiveMacros: false AlignConsecutiveAssignments: false AlignConsecutiveDeclarations: false AlignEscapedNewlines: Right -AlignOperands: true +AlignOperands: true AlignTrailingComments: true -AllowAllArgumentsOnNextLine: true -AllowAllConstructorInitializersOnNextLine: true -AllowAllParametersOfDeclarationOnNextLine: false +# AllowAllArgumentsOnNextLine: true +# AllowAllConstructorInitializersOnNextLine: true +# AllowAllParametersOfDeclarationOnNextLine: false AllowShortBlocksOnASingleLine: Never -AllowShortCaseLabelsOnASingleLine: false +# AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: Inline -AllowShortLambdasOnASingleLine: All -AllowShortIfStatementsOnASingleLine: Never -AllowShortLoopsOnASingleLine: false -AlwaysBreakAfterDefinitionReturnType: TopLevel +# AllowShortLambdasOnASingleLine: All +# AllowShortIfStatementsOnASingleLine: Never +# AllowShortLoopsOnASingleLine: false +# AlwaysBreakAfterDefinitionReturnType: TopLevel AlwaysBreakAfterReturnType: TopLevel -AlwaysBreakBeforeMultilineStrings: false +# AlwaysBreakBeforeMultilineStrings: false AlwaysBreakTemplateDeclarations: Yes BinPackArguments: false BinPackParameters: false BraceWrapping: - AfterCaseLabel: false - AfterClass: true + AfterCaseLabel: false + AfterClass: true AfterControlStatement: false - AfterEnum: true - AfterFunction: true - AfterNamespace: false + AfterEnum: true + AfterFunction: true + AfterNamespace: false AfterObjCDeclaration: false - AfterStruct: true - AfterUnion: true + AfterStruct: true + AfterUnion: true AfterExternBlock: true - BeforeCatch: false - BeforeElse: false - IndentBraces: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false SplitEmptyFunction: true SplitEmptyRecord: false SplitEmptyNamespace: true -BreakBeforeBinaryOperators: None +# BreakBeforeBinaryOperators: None BreakBeforeBraces: Mozilla -BreakBeforeInheritanceComma: false -BreakInheritanceList: BeforeComma +# BreakBeforeInheritanceComma: false +# BreakInheritanceList: BeforeComma BreakBeforeTernaryOperators: true -BreakConstructorInitializersBeforeComma: false -BreakConstructorInitializers: BeforeComma -BreakAfterJavaFieldAnnotations: false +# BreakConstructorInitializersBeforeComma: false +# BreakConstructorInitializers: BeforeComma +# BreakAfterJavaFieldAnnotations: false BreakStringLiterals: true -ColumnLimit: 80 -CommentPragmas: '^ IWYU pragma:' -CompactNamespaces: false -ConstructorInitializerAllOnOneLineOrOnePerLine: false -ConstructorInitializerIndentWidth: 2 -ContinuationIndentWidth: 2 -Cpp11BracedListStyle: false -DeriveLineEnding: true -DerivePointerAlignment: false -DisableFormat: false -ExperimentalAutoDetectBinPacking: false -FixNamespaceComments: false +ColumnLimit: 80 +# CommentPragmas: "^ IWYU pragma:" +# CompactNamespaces: false +# ConstructorInitializerAllOnOneLineOrOnePerLine: false +# ConstructorInitializerIndentWidth: 2 +# ContinuationIndentWidth: 2 +# Cpp11BracedListStyle: false +# DeriveLineEnding: true +# DerivePointerAlignment: false +# DisableFormat: false +# ExperimentalAutoDetectBinPacking: false +# FixNamespaceComments: false ForEachMacros: - foreach - Q_FOREACH - BOOST_FOREACH -IncludeBlocks: Preserve -IncludeCategories: - - Regex: '^"(llvm|llvm-c|clang|clang-c)/' - Priority: 2 - SortPriority: 0 - - Regex: '^(<|"(gtest|gmock|isl|json)/)' - Priority: 3 - SortPriority: 0 - - Regex: '.*' - Priority: 1 - SortPriority: 0 -IncludeIsMainRegex: '(Test)?$' -IncludeIsMainSourceRegex: '' +# IncludeBlocks: Preserve +# IncludeCategories: +# - Regex: '^"(llvm|llvm-c|clang|clang-c)/' +# Priority: 2 +# SortPriority: 0 +# - Regex: '^(<|"(gtest|gmock|isl|json)/)' +# Priority: 3 +# SortPriority: 0 +# - Regex: ".*" +# Priority: 1 +# SortPriority: 0 +# IncludeIsMainRegex: "(Test)?$" +# IncludeIsMainSourceRegex: "" IndentCaseLabels: true IndentGotoLabels: true IndentPPDirectives: None -IndentWidth: 4 -IndentWrappedFunctionNames: false -JavaScriptQuotes: Leave -JavaScriptWrapImports: true +IndentWidth: 4 +# IndentWrappedFunctionNames: false +# JavaScriptQuotes: Leave +# JavaScriptWrapImports: true KeepEmptyLinesAtTheStartOfBlocks: true -MacroBlockBegin: '' -MacroBlockEnd: '' +# MacroBlockBegin: "" +# MacroBlockEnd: "" MaxEmptyLinesToKeep: 1 -NamespaceIndentation: None -ObjCBinPackProtocolList: Auto -ObjCBlockIndentWidth: 2 -ObjCSpaceAfterProperty: true -ObjCSpaceBeforeProtocolList: false -PenaltyBreakAssignment: 2 -PenaltyBreakBeforeFirstCallParameter: 19 -PenaltyBreakComment: 300 -PenaltyBreakFirstLessLess: 120 -PenaltyBreakString: 1000 -PenaltyBreakTemplateDeclaration: 10 -PenaltyExcessCharacter: 1000000 -PenaltyReturnTypeOnItsOwnLine: 200 +# NamespaceIndentation: None +# ObjCBinPackProtocolList: Auto +# ObjCBlockIndentWidth: 2 +# ObjCSpaceAfterProperty: true +# ObjCSpaceBeforeProtocolList: false +# PenaltyBreakAssignment: 2 +# PenaltyBreakBeforeFirstCallParameter: 19 +# PenaltyBreakComment: 300 +# PenaltyBreakFirstLessLess: 120 +# PenaltyBreakString: 1000 +# PenaltyBreakTemplateDeclaration: 10 +# PenaltyExcessCharacter: 1000000 +# PenaltyReturnTypeOnItsOwnLine: 200 PointerAlignment: Left -ReflowComments: true -SortIncludes: true -SortUsingDeclarations: true +# ReflowComments: true +SortIncludes: true +# SortUsingDeclarations: true SpaceAfterCStyleCast: false SpaceAfterLogicalNot: false SpaceAfterTemplateKeyword: false @@ -119,19 +119,19 @@ SpaceBeforeRangeBasedForLoopColon: true SpaceInEmptyBlock: false SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 -SpacesInAngles: false +SpacesInAngles: false SpacesInConditionalStatement: false SpacesInContainerLiterals: true SpacesInCStyleCastParentheses: false SpacesInParentheses: false SpacesInSquareBrackets: false SpaceBeforeSquareBrackets: false -Standard: Latest +Standard: Latest StatementMacros: - Q_UNUSED - QT_REQUIRE_VERSION -TabWidth: 8 -UseCRLF: false -UseTab: Never -... +# TabWidth: 8 +UseCRLF: false +UseTab: Never +# --- diff --git a/lunaix-os/arch/i386/mm/pfault.c b/lunaix-os/arch/i386/mm/pfault.c index 848f215..faf7da0 100644 --- a/lunaix-os/arch/i386/mm/pfault.c +++ b/lunaix-os/arch/i386/mm/pfault.c @@ -92,7 +92,7 @@ intr_routine_page_fault(const isr_param* param) goto oom; } - *pte = *pte | pa | get_ptattr(hit_region); + *pte = pa | get_ptattr(hit_region); memset((void*)PG_ALIGN(ptr), 0, PG_SIZE); goto resolved; } @@ -115,7 +115,7 @@ intr_routine_page_fault(const isr_param* param) } cpu_flush_page((ptr_t)pte); - *pte = (*pte & 0xFFF) | pa | get_ptattr(hit_region); + *pte = pa | get_ptattr(hit_region); memset((void*)ptr, 0, PG_SIZE); diff --git a/lunaix-os/hal/ahci/io_event.c b/lunaix-os/hal/ahci/io_event.c index 2ad988a..c843d29 100644 --- a/lunaix-os/hal/ahci/io_event.c +++ b/lunaix-os/hal/ahci/io_event.c @@ -65,7 +65,7 @@ proceed: blkio_schedule(ioreq->io_ctx); blkio_complete(ioreq); - vfree(cmdstate->cmd_table); + vfree_dma(cmdstate->cmd_table); done: hba_clear_reg(port->regs[HBA_RPxIS]); diff --git a/lunaix-os/hal/char/serial.c b/lunaix-os/hal/char/serial.c index ffe9acb..ddcd57f 100644 --- a/lunaix-os/hal/char/serial.c +++ b/lunaix-os/hal/char/serial.c @@ -15,24 +15,28 @@ static int serial_idx = 0; int serial_accept_one(struct serial_dev* sdev, u8_t val) { - return !!fifo_putone(&sdev->rxbuf, val); + return !!rbuffer_put(&sdev->rxbuf, val); } int serial_accept_buffer(struct serial_dev* sdev, void* val, size_t len) { - return !!fifo_write(&sdev->rxbuf, val, len); + return !!rbuffer_puts(&sdev->rxbuf, val, len); } void serial_end_recv(struct serial_dev* sdev) { + mark_device_done_read(sdev->dev); + pwake_one(&sdev->wq_rxdone); } void serial_end_xmit(struct serial_dev* sdev, size_t len) { + mark_device_done_write(sdev->dev); + sdev->wr_len = len; pwake_one(&sdev->wq_txdone); } @@ -42,7 +46,7 @@ serial_readone_nowait(struct serial_dev* sdev, u8_t* val) { device_lock(sdev->dev); - int rd_len = fifo_readone(&sdev->rxbuf, val); + int rd_len = rbuffer_get(&sdev->rxbuf, (char*)val); device_unlock(sdev->dev); @@ -54,7 +58,9 @@ serial_readone(struct serial_dev* sdev, u8_t* val) { device_lock(sdev->dev); - while (!fifo_readone(&sdev->rxbuf, val)) { + mark_device_doing_read(sdev->dev); + + while (!rbuffer_get(&sdev->rxbuf, (char*)val)) { pwait(&sdev->wq_rxdone); } @@ -66,8 +72,10 @@ serial_readbuf(struct serial_dev* sdev, u8_t* buf, size_t len) { device_lock(sdev->dev); + mark_device_doing_read(sdev->dev); + size_t rdlen; - while (!(rdlen = fifo_read(&sdev->rxbuf, buf, len))) { + while (!(rdlen = rbuffer_gets(&sdev->rxbuf, (char*)buf, len))) { pwait(&sdev->wq_rxdone); } @@ -81,7 +89,9 @@ serial_readbuf_nowait(struct serial_dev* sdev, u8_t* buf, size_t len) { device_lock(sdev->dev); - int rdlen = fifo_read(&sdev->rxbuf, buf, len); + mark_device_doing_read(sdev->dev); + + int rdlen = rbuffer_gets(&sdev->rxbuf, (char*)buf, len); device_unlock(sdev->dev); @@ -93,6 +103,8 @@ serial_writebuf(struct serial_dev* sdev, u8_t* buf, size_t len) { device_lock(sdev->dev); + mark_device_doing_write(sdev->dev); + if (sdev->write(sdev, buf, len) == RXTX_DONE) { goto done; } @@ -111,6 +123,8 @@ serial_writebuf_nowait(struct serial_dev* sdev, u8_t* buf, size_t len) { device_lock(sdev->dev); + mark_device_doing_write(sdev->dev); + sdev->write(sdev, buf, len); int rdlen = sdev->wr_len; @@ -155,10 +169,18 @@ __serial_exec_command(struct device* dev, u32_t req, va_list args) return sdev->exec_cmd(sdev, req, args); } +static int +__serial_poll_event(struct device* dev) +{ + struct serial_dev* sdev = serial_device(dev); + + return sdev->dev->poll_evflags; +} + #define RXBUF_SIZE 512 struct serial_dev* -serial_create(struct devclass* class) +serial_create(struct devclass* class, char* if_ident) { struct serial_dev* sdev = valloc(sizeof(struct serial_dev)); struct device* dev = device_allocseq(NULL, sdev); @@ -167,19 +189,21 @@ serial_create(struct devclass* class) dev->ops.write = __serial_write; dev->ops.write_page = __serial_write_page; dev->ops.exec_cmd = __serial_exec_command; + dev->ops.poll = __serial_poll_event; sdev->dev = dev; dev->underlay = sdev; waitq_init(&sdev->wq_rxdone); waitq_init(&sdev->wq_txdone); - fifo_init(&sdev->rxbuf, valloc(RXBUF_SIZE), RXBUF_SIZE, 0); + rbuffer_init(&sdev->rxbuf, valloc(RXBUF_SIZE), RXBUF_SIZE); llist_append(&serial_devs, &sdev->sdev_list); - // llist_init_head(&sdev->cmds); - class->variant++; - device_register(dev, class, "ttyS%d", class->variant); + device_register(dev, class, "port%s%d", if_ident, class->variant); + sdev->at_term = term_create(dev, if_ident); + + class->variant++; return sdev; } diff --git a/lunaix-os/hal/char/uart/16550_pmio.c b/lunaix-os/hal/char/uart/16550_pmio.c index 81d0642..7bd99da 100644 --- a/lunaix-os/hal/char/uart/16550_pmio.c +++ b/lunaix-os/hal/char/uart/16550_pmio.c @@ -77,7 +77,7 @@ upiom_init(struct device_def* def) uart_enable_fifo(uart, UART_FIFO8); llist_append(&com_ports, &uart->local_ports); - struct serial_dev* sdev = serial_create(&def->class); + struct serial_dev* sdev = serial_create(&def->class, "S"); sdev->backend = uart; sdev->write = uart_general_tx; sdev->exec_cmd = uart_general_exec_cmd; diff --git a/lunaix-os/hal/term/lcntls/ansi_cntl.c b/lunaix-os/hal/term/lcntls/ansi_cntl.c index a11781e..0596a7a 100644 --- a/lunaix-os/hal/term/lcntls/ansi_cntl.c +++ b/lunaix-os/hal/term/lcntls/ansi_cntl.c @@ -1,57 +1,34 @@ +/** + * @file ansi_cntl.c + * @author Lunaixsky (lunaxisky@qq.com) + * @brief Line controller slave that handle all non-POSIX control code or ANSI + * escape sequence + * @version 0.1 + * @date 2023-11-25 + * + * @copyright Copyright (c) 2023 + * + */ #include - -#include +#include #define CTRL_MNEMO(chr) (chr - 'A' + 1) -static inline int -__ansi_actcontrol(struct term* termdev, char chr) +static inline size_t +__ansi_actcontrol(struct term* termdev, struct linebuffer* lbuf, char chr) { - struct linebuffer* lbuf = &termdev->line; + struct rbuffer* cooked = lbuf->next; switch (chr) { - case '\0': // EOL - case CTRL_MNEMO('D'): // EOF - return 0; - - case CTRL_MNEMO('C'): // INTR - signal_send(termdev->fggrp, SIGINT); - break; - - case '\r': // CR - termdev->line.ptr = 0; - return 1; - - case '\x08': // ERASE - return line_put_next(lbuf, chr, -1); - - case CTRL_MNEMO('Q'): // QUIT - signal_send(termdev->fggrp, SIGKILL); - return 1; - - case CTRL_MNEMO('Z'): // SUSP - signal_send(termdev->fggrp, SIGSTOP); - return 1; - default: if ((int)chr < 32) { - line_put_next(lbuf, '^', 0); + rbuffer_put(cooked, '^'); chr += 64; } break; } - return line_put_next(lbuf, chr, 0); -} - -static size_t -ansi_lcntl_process(struct term* termdev, char* line, size_t len) -{ - size_t i = 0; - while (i < len && __ansi_actcontrol(termdev, line[i])) { - i++; - } - - return i; + return rbuffer_put(cooked, chr); } -struct term_lcntl ansi_line_controller = { .apply = ansi_lcntl_process }; \ No newline at end of file +struct term_lcntl ansi_line_controller = { .process_and_put = + __ansi_actcontrol }; \ No newline at end of file diff --git a/lunaix-os/hal/term/lcntls/lcntl.c b/lunaix-os/hal/term/lcntls/lcntl.c new file mode 100644 index 0000000..4359830 --- /dev/null +++ b/lunaix-os/hal/term/lcntls/lcntl.c @@ -0,0 +1,173 @@ +/** + * @file lcntl.c + * @author Lunaixsky (lunaxisky@qq.com) + * @brief Line controller master that handle all POSIX-control code + * @version 0.1 + * @date 2023-11-25 + * + * @copyright Copyright (c) 2023 + * + */ +#include +#include + +#include +#include + +static inline void +raise_sig(struct term* at_term, struct linebuffer* lbuf, int sig) +{ + term_sendsig(at_term, SIGINT); + lbuf->sflags |= LSTATE_SIGRAISE; +} + +static inline int +lcntl_invoke_slaves(struct term* tdev, struct linebuffer* lbuf, char c) +{ + int allow_more = 0; + struct term_lcntl *lcntl, *n; + llist_for_each(lcntl, n, &tdev->lcntl_stack, lcntls) + { + allow_more = lcntl->process_and_put(tdev, lbuf, c); + if (!allow_more) { + break; + } + + line_flip(lbuf); + } + + return allow_more; +} + +static inline int optimize("ipa-cp-clone") +lcntl_transform_seq(struct term* tdev, struct linebuffer* lbuf, bool out) +{ + struct rbuffer* raw = lbuf->current; + struct rbuffer* cooked = lbuf->next; + struct rbuffer* output = tdev->line_out.current; + + int i = 0, _if = tdev->iflags & -!out, _of = tdev->oflags & -!!out, + _lf = tdev->lflags; + int allow_more = 1, latest_eol = cooked->ptr; + char c; + bool should_flush = false; + +#define EOL tdev->cc[_VEOL] +#define EOF tdev->cc[_VEOF] +#define ERASE tdev->cc[_VERASE] +#define KILL tdev->cc[_VKILL] +#define INTR tdev->cc[_VINTR] +#define QUIT tdev->cc[_VQUIT] +#define SUSP tdev->cc[_VSUSP] + + if (!out) { + // Keep all cc's (except VMIN & VTIME) up to L2 cache. + for (size_t i = 0; i < _VMIN; i++) { + prefetch_rd(&tdev->cc[i], 2); + } + } + + while (rbuffer_get(raw, &c) && allow_more) { + + if (c == '\r' && ((_if & _ICRNL) || (_of & _OCRNL))) { + c = '\n'; + } else if (c == '\n') { + if ((_if & _INLCR) || (_of & (_ONLRET | _ONLCR))) { + c = '\r'; + } + } + + if (c == '\0') { + if ((_if & _BRKINT)) { + raise_sig(tdev, lbuf, SIGINT); + break; + } + + if ((_if & _IGNBRK)) { + continue; + } + } + + if ('a' <= c && c <= 'z') { + if ((_if & _IUCLC)) { + c = c | 0b100000; + } else if ((_of & _OLCUC)) { + c = c & ~0b100000; + } + } + + if (c == '\n') { + latest_eol = cooked->ptr + 1; + if (!out && (_lf & _ECHONL)) { + rbuffer_put(output, c); + } + should_flush = true; + } + + if (out) { + goto put_char; + } + + // For input procesing + + if (c == '\n' || c == EOL) { + lbuf->sflags |= LSTATE_EOL; + goto keep; + } else if (c == EOF) { + lbuf->sflags |= LSTATE_EOF; + rbuffer_clear(raw); + break; + } else if (c == INTR) { + raise_sig(tdev, lbuf, SIGINT); + } else if (c == QUIT) { + raise_sig(tdev, lbuf, SIGKILL); + break; + } else if (c == SUSP) { + raise_sig(tdev, lbuf, SIGSTOP); + } else if (c == ERASE) { + rbuffer_erase(cooked); + } else { + goto keep; + } + + continue; + + keep: + if ((_lf & _ECHO)) { + rbuffer_put(output, c); + } + if ((_lf & _ECHOE) && c == ERASE) { + rbuffer_erase(output); + } + if ((_lf & _ECHOK) && c == KILL) { + rbuffer_put(output, c); + rbuffer_put(output, '\n'); + } + + put_char: + allow_more = rbuffer_put(cooked, c); + } + + if (out || (_lf & _IEXTEN)) { + line_flip(lbuf); + lcntl_invoke_slaves(tdev, lbuf, c); + } + + if (should_flush && !(_lf & _NOFLSH)) { + term_flush(tdev); + } + + return i; +} + +int +lcntl_transform_inseq(struct term* tdev) +{ + return lcntl_transform_seq(tdev, &tdev->line_in, false); +} + +int +lcntl_transform_outseq(struct term* tdev) +{ + return lcntl_transform_seq(tdev, &tdev->line_in, true); +} \ No newline at end of file diff --git a/lunaix-os/hal/term/term.c b/lunaix-os/hal/term/term.c index 2130105..b566c55 100644 --- a/lunaix-os/hal/term/term.c +++ b/lunaix-os/hal/term/term.c @@ -2,91 +2,119 @@ #include #include #include +#include #include #include #include #define ANSI_LCNTL 0 +#define termdev(dev) ((struct term*)(dev)->underlay) extern struct term_lcntl ansi_line_controller; -static struct term_lcntl* line_controls[] = { [ANSI_LCNTL] = - &ansi_line_controller }; +static struct term_lcntl* line_controls[] = {[ANSI_LCNTL] = + &ansi_line_controller}; #define LCNTL_TABLE_LEN (sizeof(line_controls) / sizeof(struct term_lcntl*)) +static struct devclass termdev = DEVCLASS(DEVIF_NON, DEVFN_TTY, DEV_VTERM); + static int term_exec_cmd(struct device* dev, u32_t req, va_list args) { - struct term* term = (struct term*)dev->underlay; + struct term* term = termdev(dev); int err = 0; device_lock(dev); switch (req) { - case TIOCSPGRP: { - pid_t pgid = va_arg(args, pid_t); - if (pgid < 0) { - err = EINVAL; - goto done; - } - term->fggrp = pgid; - break; + case TIOCSPGRP: { + pid_t pgid = va_arg(args, pid_t); + if (pgid < 0) { + err = EINVAL; + goto done; } - case TIOCGPGRP: - return term->fggrp; - case TIOCPUSH: { - u32_t lcntl_idx = va_arg(args, u32_t); - struct term_lcntl* lcntl = term_get_lcntl(lcntl_idx); - - if (!lcntl) { - err = EINVAL; - goto done; - } + term->fggrp = pgid; + break; + } + case TIOCGPGRP: + return term->fggrp; + case TDEV_TCPUSHLC: { + u32_t lcntl_idx = va_arg(args, u32_t); + struct term_lcntl* lcntl = term_get_lcntl(lcntl_idx); - term_push_lcntl(term, lcntl); - break; + if (!lcntl) { + err = EINVAL; + goto done; } - case TIOCPOP: - term_pop_lcntl(term); - break; - case TIOCSCDEV: { - int fd = va_arg(args, int); - struct v_fd* vfd; - - if (vfs_getfd(fd, &vfd)) { - err = EINVAL; - goto done; - } - struct device* cdev = device_cast(vfd->file->inode->data); - if (!cdev) { - err = ENOTDEV; - goto done; - } - if (cdev->dev_type != DEV_IFSEQ) { - err = EINVAL; - goto done; - } + term_push_lcntl(term, lcntl); + break; + } + case TDEV_TCPOPLC: + term_pop_lcntl(term); + break; + case TDEV_TCSETCHDEV: { + int fd = va_arg(args, int); + struct v_fd* vfd; + + if (vfs_getfd(fd, &vfd)) { + err = EINVAL; + goto done; + } + + struct device* cdev = device_cast(vfd->file->inode->data); + if (!cdev) { + err = ENOTDEV; + goto done; + } + if (cdev->dev_type != DEV_IFSEQ) { + err = EINVAL; + goto done; + } + + term_bind(term, cdev); + break; + } + case TDEV_TCGETCHDEV: { + struct dev_info* devinfo = va_arg(args, struct dev_info*); - term_bind(term, cdev); - break; + if (!term->chdev) { + err = ENODEV; + goto done; } - case TIOCGCDEV: { - struct dev_info* devinfo = va_arg(args, struct dev_info*); - if (!term->chdev) { - err = ENODEV; + if (devinfo) { + device_populate_info(term->chdev, devinfo); + } + break; + } + case TDEV_TCGETATTR: { + struct _termios* tios = va_arg(args, struct _termios*); + *tios = (struct _termios){.c_oflag = term->oflags, + .c_iflag = term->iflags, + .c_lflag = term->lflags}; + memcpy(tios->c_cc, term->cc, _NCCS * sizeof(cc_t)); + tios->c_baud = term->iospeed; + } break; + case TDEV_TCSETATTR: { + struct _termios* tios = va_arg(args, struct _termios*); + term->iflags = tios->c_iflag; + term->oflags = tios->c_oflag; + term->lflags = tios->c_lflag; + memcpy(term->cc, tios->c_cc, _NCCS * sizeof(cc_t)); + + if (tios->c_baud != term->iospeed) { + term->iospeed = tios->c_baud; + if (!term->chdev_ops.set_speed) { goto done; } - if (devinfo) { - device_populate_info(term->chdev, devinfo); - } - break; + term->chdev_ops.set_speed(term->chdev, tios->c_baud); } - default: - err = EINVAL; - goto done; + } break; + default: + err = EINVAL; + goto done; } done: @@ -95,81 +123,73 @@ done: } static int -term_write(struct device* dev, void* buf, size_t offset, size_t len) +tdev_do_write(struct device* dev, void* buf, size_t offset, size_t len) { - struct term* term = (struct term*)dev->underlay; - size_t sz = MIN(len, term->line.sz_hlf); - - if (!term->chdev) { - return ENODEV; - } - - device_lock(term->dev); - - memcpy(term->line.current, &((char*)buf)[offset], sz); - - struct term_lcntl *lcntl, *n; - llist_for_each(lcntl, n, &term->lcntl_stack, lcntls) - { - sz = lcntl->apply(term, term->line.current, sz); - line_flip(&term->line); + struct term* tdev = termdev(dev); + lbuf_ref_t current = ref_current(&tdev->line_out); + size_t wrsz = 0; + while (wrsz < len) { + wrsz += rbuffer_puts(deref(current), &((char*)buf)[offset + wrsz], + len - wrsz); + if (rbuffer_full(deref(current))) { + term_flush(tdev); + } } - int errcode = term_sendline(term, sz); - - device_unlock(term->dev); - - return errcode; + return 0; } static int -term_read(struct device* dev, void* buf, size_t offset, size_t len) +tdev_do_read(struct device* dev, void* buf, size_t offset, size_t len) { - struct term* term = (struct term*)dev->underlay; - size_t sz = MIN(len, term->line.sz_hlf); - - if (!term->chdev) { - return ENODEV; - } - - device_lock(term->dev); - - sz = term_readline(term, sz); - if (!sz) { - device_unlock(term->dev); - return 0; - } + struct term* tdev = termdev(dev); + lbuf_ref_t current = ref_current(&tdev->line_in); + bool cont = true; + size_t rdsz = 0; + while (cont && rdsz < len) { + if (rbuffer_empty(deref(current))) { + tdev->line_in.sflags = 0; + cont = term_read(tdev); + } - struct term_lcntl *pos, *n; - llist_for_each(pos, n, &term->lcntl_stack, lcntls) - { - sz = pos->apply(term, term->line.current, sz); - line_flip(&term->line); + rdsz += rbuffer_gets(deref(current), &((char*)buf)[offset + rdsz], + len - rdsz); } - memcpy(&((char*)buf)[offset], term->line.current, sz); - - device_unlock(term->dev); - - return sz; + return rdsz; } +static cc_t default_cc[_NCCS] = {4, '\n', 8, 3, 1, 24, 22, 0, 0, 1, 1}; + struct term* -term_create() +term_create(struct device* chardev, char* suffix) { - struct term* terminal = valloc(sizeof(struct term)); + struct term* terminal = vzalloc(sizeof(struct term)); if (!terminal) { return NULL; } terminal->dev = device_allocseq(NULL, terminal); + terminal->chdev = chardev; - terminal->dev->ops.read = term_read; - terminal->dev->ops.write = term_write; + terminal->dev->ops.read = tdev_do_read; + terminal->dev->ops.write = tdev_do_write; llist_init_head(&terminal->lcntl_stack); - line_alloc(&terminal->line, 1024); + line_alloc(&terminal->line_in, 1024); + line_alloc(&terminal->line_out, 1024); + + if (chardev) { + int cdev_var = DEV_VAR_FROM(chardev->ident.unique); + device_register(terminal->dev, &termdev, "tty%s%d", suffix, cdev_var); + } else { + device_register(terminal->dev, &termdev, "tty%d", termdev.variant++); + } + + terminal->lflags = _ICANON | _IEXTEN | _ISIG | _ECHO; + terminal->iflags = _ICRNL; + memcpy(terminal->cc, default_cc, _NCCS * sizeof(cc_t)); return terminal; } @@ -200,7 +220,7 @@ term_get_lcntl(u32_t lcntl_index) return NULL; } - lcntl_instance->apply = lcntl_template->apply; + lcntl_instance->process_and_put = lcntl_template->process_and_put; return lcntl_instance; } @@ -227,7 +247,7 @@ term_pop_lcntl(struct term* term) device_lock(term->dev); struct term_lcntl* lcntl = - list_entry(term->lcntl_stack.prev, struct term_lcntl, lcntls); + list_entry(term->lcntl_stack.prev, struct term_lcntl, lcntls); llist_delete(term->lcntl_stack.prev); vfree(lcntl); @@ -237,76 +257,28 @@ term_pop_lcntl(struct term* term) return 1; } -void -line_flip(struct linebuffer* lbf) -{ - char* tmp = lbf->current; - lbf->current = lbf->next; - lbf->next = tmp; -} - void line_alloc(struct linebuffer* lbf, size_t sz_hlf) { char* buffer = valloc(sz_hlf * 2); - lbf->current = buffer; - lbf->next = &buffer[sz_hlf]; + memset(lbf, 0, sizeof(*lbf)); + lbf->current = rbuffer_create(buffer, sz_hlf); + lbf->next = rbuffer_create(&buffer[sz_hlf], sz_hlf); lbf->sz_hlf = sz_hlf; } void line_free(struct linebuffer* lbf, size_t sz_hlf) { - void* ptr = (void*)MIN((ptr_t)lbf->current, (ptr_t)lbf->next); + void* ptr = + (void*)MIN((ptr_t)lbf->current->buffer, (ptr_t)lbf->next->buffer); vfree(ptr); } -int -term_sendline(struct term* tdev, size_t len) -{ - struct device* chdev = tdev->chdev; - - device_lock(chdev); - - int code = chdev->ops.write(chdev, tdev->line.current, 0, len); - - device_unlock(chdev); - - return code; -} - -int -term_readline(struct term* tdev, size_t len) -{ - struct device* chdev = tdev->chdev; - - device_lock(chdev); - - int code = chdev->ops.read(chdev, tdev->line.current, 0, len); - - device_unlock(chdev); - - return code; -} - -int -term_init(struct device_def* devdef) +void +term_sendsig(struct term* tdev, int signal) { - struct term* terminal = term_create(); - struct device* tdev = device_allocseq(NULL, terminal); - tdev->ops.read = term_read; - tdev->ops.write = term_write; - tdev->ops.exec_cmd = term_exec_cmd; - - devdef->class.variant++; - device_register(tdev, &devdef->class, "tty%d", devdef->class.variant); - - return 0; -} - -static struct device_def vterm_def = { - .class = DEVCLASS(DEVIF_NON, DEVFN_TTY, DEV_VTERM), - .name = "virtual terminal", - .init = term_init -}; -EXPORT_DEVICE(vterm, &vterm_def, load_on_demand); \ No newline at end of file + if ((tdev->lflags & _ISIG)) { + proc_setsignal(get_process(tdev->fggrp), signal); + } +} \ No newline at end of file diff --git a/lunaix-os/hal/term/term_io.c b/lunaix-os/hal/term/term_io.c new file mode 100644 index 0000000..94e61d6 --- /dev/null +++ b/lunaix-os/hal/term/term_io.c @@ -0,0 +1,118 @@ +#include + +#include +#include + +#include + +#define ONBREAK (LSTATE_EOF | LSTATE_SIGRAISE) +#define ONSTOP (LSTATE_SIGRAISE | LSTATE_EOL | LSTATE_EOF) + +static int +do_read_raw(struct term* tdev) +{ + struct device* chdev = tdev->chdev; + + struct linebuffer* line_in = &tdev->line_in; + size_t max_lb_sz = line_in->sz_hlf; + + line_flip(line_in); + + char* inbuffer = line_in->current->buffer; + size_t min = tdev->cc[_VMIN] - 1; + size_t sz = chdev->ops.read(chdev, inbuffer, 0, max_lb_sz); + time_t t = clock_systime(), dt = 0; + time_t expr = (tdev->cc[_VTIME] * 100) - 1; + + while (sz <= min && dt <= expr) { + // XXX should we held the device lock while we are waiting? + sched_yieldk(); + dt = clock_systime() - t; + t += dt; + + max_lb_sz -= sz; + + // TODO pass a flags to read to indicate it is non blocking ops + sz += + chdev->ops.read(chdev, inbuffer, sz, max_lb_sz); + } + + rbuffer_puts(line_in->next, inbuffer, sz); + line_flip(line_in); + + return 0; +} + +static int +do_read_raw_canno(struct term* tdev) { + struct device* chdev = tdev->chdev; + struct linebuffer* line_in = &tdev->line_in; + struct rbuffer* current_buf = line_in->current; + int sz = chdev->ops.read(chdev, current_buf->buffer, 0, line_in->sz_hlf); + + current_buf->ptr = sz; + current_buf->len = sz; + + return sz; +} + +static int +term_read_noncano(struct term* tdev) +{ + struct device* chdev = tdev->chdev; + return do_read_raw(tdev);; +} + +static int +term_read_cano(struct term* tdev) +{ + struct device* chdev = tdev->chdev; + struct linebuffer* line_in = &tdev->line_in; + int size = 0; + + while (!(line_in->sflags & ONSTOP)) { + // move all hold-out content to 'next' buffer + line_flip(line_in); + + size += do_read_raw_canno(tdev); + lcntl_transform_inseq(tdev); + } + + return 0; +} + +int +term_read(struct term* tdev) +{ + if ((tdev->lflags & _ICANON)) { + return term_read_cano(tdev); + } + return term_read_noncano(tdev); +} + +int +term_flush(struct term* tdev) +{ + if ((tdev->oflags & _OPOST)) { + lcntl_transform_inseq(tdev); + } + + struct linebuffer* line_out = &tdev->line_out; + size_t xmit_len = line_out->current->len; + void* xmit_buf = line_out->next->buffer; + + rbuffer_gets(line_out->current, xmit_buf, xmit_len); + + off_t off = 0; + int ret = 0; + while (xmit_len && ret >= 0) { + ret = tdev->chdev->ops.write(tdev->chdev, xmit_buf, off, xmit_len); + xmit_len -= ret; + off += ret; + } + + // put back the left over if transmittion went south + rbuffer_puts(line_out->current, xmit_buf, xmit_len); + + return off; +} \ No newline at end of file diff --git a/lunaix-os/includes/hal/serial.h b/lunaix-os/includes/hal/serial.h index 1211ed0..c346c51 100644 --- a/lunaix-os/includes/hal/serial.h +++ b/lunaix-os/includes/hal/serial.h @@ -2,10 +2,12 @@ #define __LUNAIX_SERIAL_H #include -#include #include #include #include +#include + +#include #define SERIAL_RW_RX 0x0 #define SERIAL_RW_TX 0x1 @@ -26,9 +28,10 @@ struct serial_dev struct device* dev; struct waitq wq_rxdone; struct waitq wq_txdone; + struct term* at_term; void* backend; - struct fifo_buf rxbuf; + struct rbuffer rxbuf; int wr_len; /** @@ -41,8 +44,18 @@ struct serial_dev int (*exec_cmd)(struct serial_dev* sdev, u32_t, va_list); }; +/** + * @brief Create a serial device. + * + * + * @param if_ident a string that differentiate the underlying interface of + * serial ports + * @param with_tty whether a `/dev/tty*` will be automatically created and + * attach to it. + * @return struct serial_dev* + */ struct serial_dev* -serial_create(struct devclass* class); +serial_create(struct devclass* class, char* if_ident); void serial_readone(struct serial_dev* sdev, u8_t* val); diff --git a/lunaix-os/includes/hal/term.h b/lunaix-os/includes/hal/term.h index 79f8f67..00fe32b 100644 --- a/lunaix-os/includes/hal/term.h +++ b/lunaix-os/includes/hal/term.h @@ -2,21 +2,34 @@ #define __LUNAIX_TERM_H #include +#include +#include + +#include struct term; -struct term_lcntl +struct linebuffer { - struct llist_header lcntls; - size_t (*apply)(struct term* termdev, char* line, size_t len); + struct rbuffer *next; + struct rbuffer *current; + short sflags; + short sz_hlf; }; +#define LSTATE_EOL (1) +#define LSTATE_EOF (1 << 1) +#define LSTATE_SIGRAISE (1 << 2) -struct linebuffer +typedef struct rbuffer** lbuf_ref_t; +#define ref_current(lbuf) (&(lbuf)->current) +#define ref_next(lbuf) (&(lbuf)->next) +#define deref(bref) (*(bref)) + +struct term_lcntl { - char* current; - char* next; - size_t sz_hlf; - off_t ptr; + struct llist_header lcntls; + struct term* term; + size_t (*process_and_put)(struct term*, struct linebuffer*, char); }; struct term @@ -24,12 +37,25 @@ struct term struct device* dev; struct device* chdev; struct llist_header lcntl_stack; - struct linebuffer line; + struct linebuffer line_out; + struct linebuffer line_in; pid_t fggrp; + + struct + { + int (*set_speed)(struct device*, speed_t); + } chdev_ops; + + /* -- POSIX.1-2008 compliant fields -- */ + tcflag_t iflags; + tcflag_t oflags; + tcflag_t lflags; + cc_t cc[_NCCS]; + speed_t iospeed; }; struct term* -term_create(); +term_create(struct device* chardev, char* suffix); int term_bind(struct term* tdev, struct device* chdev); @@ -43,8 +69,12 @@ term_pop_lcntl(struct term* tdev); struct term_lcntl* term_get_lcntl(u32_t lcntl_index); -void -line_flip(struct linebuffer* lbf); +static inline void +line_flip(struct linebuffer* lbf) { + struct rbuffer* tmp = lbf->current; + lbf->current = lbf->next; + lbf->next = tmp; +} void line_alloc(struct linebuffer* lbf, size_t sz_hlf); @@ -52,23 +82,19 @@ line_alloc(struct linebuffer* lbf, size_t sz_hlf); void line_free(struct linebuffer* lbf, size_t sz_hlf); -static inline int -line_put_next(struct linebuffer* lbf, char val, int delta) -{ - size_t dptr = (size_t)(lbf->ptr + delta); - if (dptr >= lbf->sz_hlf) { - return 0; - } - - lbf->next[dptr] = val; - lbf->ptr++; - return 1; -} +void +term_sendsig(struct term* tdev, int signal); + +int +term_flush(struct term* tdev); + +int +term_read(struct term* tdev); int -term_sendline(struct term* tdev, size_t len); +lcntl_transform_inseq(struct term* tdev); int -term_readline(struct term* tdev, size_t len); +lcntl_transform_outseq(struct term* tdev); #endif /* __LUNAIX_TERM_H */ diff --git a/lunaix-os/includes/lunaix/compiler.h b/lunaix-os/includes/lunaix/compiler.h index f011a0b..137d288 100644 --- a/lunaix-os/includes/lunaix/compiler.h +++ b/lunaix-os/includes/lunaix/compiler.h @@ -7,6 +7,10 @@ #define weak_alias(name) __attribute__((weak, alias(name))) #define weak __attribute__((weak)) #define noret __attribute__((noreturn)) +#define optimize(opt) __attribute__((optimize(opt))) + +#define prefetch_rd(ptr, ll) __builtin_prefetch((ptr), 0, ll) +#define prefetch_wr(ptr, ll) __builtin_prefetch((ptr), 1, ll) #define stringify(v) #v #define stringify__(v) stringify(v) diff --git a/lunaix-os/includes/lunaix/device.h b/lunaix-os/includes/lunaix/device.h index affdb10..a3b6f94 100644 --- a/lunaix-os/includes/lunaix/device.h +++ b/lunaix-os/includes/lunaix/device.h @@ -125,12 +125,14 @@ struct device int (*acquire)(struct device* dev); int (*release)(struct device* dev); - int (*read)(struct device* dev, void* buf, size_t offset, size_t len); - int (*write)(struct device* dev, void* buf, size_t offset, size_t len); - int (*read_page)(struct device* dev, void* buf, size_t offset); - int (*write_page)(struct device* dev, void* buf, size_t offset); - int (*exec_cmd)(struct device* dev, u32_t req, va_list args); - int (*poll)(struct device* dev); + int (*read)(struct device*, void*, off_t, size_t); + int (*write)(struct device*, void*, off_t, size_t); + + int (*read_page)(struct device*, void*, off_t); + int (*write_page)(struct device*, void*, off_t); + + int (*exec_cmd)(struct device*, u32_t, va_list); + int (*poll)(struct device*); } ops; }; @@ -164,6 +166,15 @@ struct device_def int (*free)(struct device_def*, void* instance); }; +#define mark_device_doing_write(dev_ptr) (dev_ptr)->poll_evflags &= ~_POLLOUT +#define mark_device_done_write(dev_ptr) (dev_ptr)->poll_evflags |= _POLLOUT + +#define mark_device_doing_read(dev_ptr) (dev_ptr)->poll_evflags &= ~_POLLIN +#define mark_device_done_read(dev_ptr) (dev_ptr)->poll_evflags |= _POLLIN + +#define mark_device_hanging(dev_ptr) (dev_ptr)->poll_evflags &= ~_POLLHUP +#define mark_device_grounded(dev_ptr) (dev_ptr)->poll_evflags |= _POLLHUP + static inline u32_t device_id_from_class(struct devclass* class) { diff --git a/lunaix-os/includes/lunaix/ds/rbuffer.h b/lunaix-os/includes/lunaix/ds/rbuffer.h new file mode 100644 index 0000000..f3777b6 --- /dev/null +++ b/lunaix-os/includes/lunaix/ds/rbuffer.h @@ -0,0 +1,56 @@ +#ifndef __LUNAIX_RBUFFER_H +#define __LUNAIX_RBUFFER_H + +#include + +struct rbuffer +{ + char* buffer; + size_t maxsz; + off_t ptr; + size_t len; +}; + +static inline void +rbuffer_init(struct rbuffer* rb, char* buf, size_t maxsz) +{ + *rb = (struct rbuffer){ .buffer = buf, .maxsz = maxsz }; +} + +struct rbuffer* +rbuffer_create(char* buf, size_t maxsz); + +static inline void +rbuffer_clear(struct rbuffer* rb) +{ + rb->len = rb->ptr = 0; +} + +static inline bool +rbuffer_empty(struct rbuffer* rb) +{ + return rb->len == 0; +} + +static inline bool +rbuffer_full(struct rbuffer* rb) +{ + return rb->len == rb->maxsz; +} + +int +rbuffer_erase(struct rbuffer* rb); + +int +rbuffer_put(struct rbuffer* rb, char c); + +int +rbuffer_puts(struct rbuffer* rb, char* c, size_t len); + +int +rbuffer_gets(struct rbuffer* rb, char* buf, size_t len); + +int +rbuffer_get(struct rbuffer* rb, char* c); + +#endif /* __LUNAIX_RBUFFER_H */ diff --git a/lunaix-os/includes/lunaix/iopoll.h b/lunaix-os/includes/lunaix/iopoll.h index 027f6fb..cdc6d79 100644 --- a/lunaix-os/includes/lunaix/iopoll.h +++ b/lunaix-os/includes/lunaix/iopoll.h @@ -3,10 +3,11 @@ #include #include -#include #include +struct v_fd; // + typedef struct llist_header poll_evt_q; struct poll_opts @@ -35,6 +36,12 @@ iopoll_listen_on(struct iopoller* listener, poll_evt_q* source) llist_append(source, &listener->evt_listener); } +static inline void +iopoll_init_evt_q(poll_evt_q* source) +{ + llist_init_head(source); +} + void iopoll_wake_pollers(poll_evt_q*); diff --git a/lunaix-os/includes/lunaix/types.h b/lunaix-os/includes/lunaix/types.h index a6af3c1..b679981 100644 --- a/lunaix-os/includes/lunaix/types.h +++ b/lunaix-os/includes/lunaix/types.h @@ -27,6 +27,10 @@ typedef unsigned int cpu_t; typedef u64_t lba_t; +#define true 1 +#define false 0 +typedef int bool; + /** * container_of - cast a member of a structure out to the containing structure * diff --git a/lunaix-os/includes/usr/lunaix/ioctl_defs.h b/lunaix-os/includes/usr/lunaix/ioctl_defs.h index d99e767..dd5709f 100644 --- a/lunaix-os/includes/usr/lunaix/ioctl_defs.h +++ b/lunaix-os/includes/usr/lunaix/ioctl_defs.h @@ -13,10 +13,6 @@ #define TIOCSPGRP IOREQ(1, 1) #define TIOCCLSBUF IOREQ(2, 0) #define TIOCFLUSH IOREQ(3, 0) -#define TIOCPUSH IOREQ(4, 1) -#define TIOCPOP IOREQ(5, 0) -#define TIOCSCDEV IOREQ(6, 1) -#define TIOCGCDEV IOREQ(7, 0) #define RTCIO_IUNMSK IOREQ(1, 0) #define RTCIO_IMSK IOREQ(2, 0) diff --git a/lunaix-os/includes/usr/lunaix/term.h b/lunaix-os/includes/usr/lunaix/term.h new file mode 100644 index 0000000..8866b30 --- /dev/null +++ b/lunaix-os/includes/usr/lunaix/term.h @@ -0,0 +1,95 @@ +#ifndef __LUNAIX_UTERM_H +#define __LUNAIX_UTERM_H + +#define _BRKINT (1) +#define _ICRNL (1 << 1) +#define _IGNBRK (1 << 2) +#define _IGNCR (1 << 3) +#define _IGNPAR (1 << 4) +#define _INLCR (1 << 5) +#define _INPCK (1 << 6) +#define _ISTRIP (1 << 7) +#define _IUCLC (1 << 8) +#define _IXANY (1 << 9) +#define _IXOFF (1 << 10) +#define _IXON (1 << 11) +#define _PARMRK (1 << 12) + +#define _OPOST 1 +#define _OCRNL _ICRNL + +// 2 +// 3 +// 4 + +#define _ONLRET _INLCR +#define _ONLCR (1 << 6) + +// 7 + +#define _OLCUC _IUCLC // 8 + +#define _ECHO (1) +#define _ECHOE (1 << 1) +#define _ECHOK (1 << 2) +#define _ECHONL (1 << 3) +#define _ICANON (1 << 4) +#define _ISIG (1 << 5) +#define _IEXTEN (1 << 6) +#define _NOFLSH (1 << 7) + +#define _VEOF 0 +#define _VEOL 1 +#define _VERASE 2 +#define _VINTR 3 +#define _VKILL 4 +#define _VQUIT 5 +#define _VSUSP 6 +#define _VSTART 7 +#define _VSTOP 8 +#define _VMIN 9 +#define _VTIME 10 +#define _NCCS 11 + +#define _B50 50 +#define _B75 75 +#define _B110 110 +#define _B134 134 +#define _B150 150 +#define _B200 200 +#define _B300 300 +#define _B600 600 +#define _B1200 1200 +#define _B1800 1800 +#define _B2400 2400 +#define _B4800 4800 +#define _B9600 9600 +#define _B19200 19200 +#define _B38400 38400 + +#define _TCSANOW 1 +#define _TCSADRAIN 2 +#define _TCSAFLUSH 3 + +#define TDEV_TCGETATTR 1 +#define TDEV_TCSETATTR 2 +#define TDEV_TCPUSHLC 3 +#define TDEV_TCPOPLC 4 +#define TDEV_TCSETCHDEV 5 +#define TDEV_TCGETCHDEV 6 + +typedef int tcflag_t; +typedef char cc_t; +typedef unsigned int speed_t; + +struct _termios +{ + tcflag_t c_iflag; + tcflag_t c_oflag; + tcflag_t c_cflag; + tcflag_t c_lflag; + cc_t c_cc[_NCCS]; + speed_t c_baud; +}; + +#endif /* __LUNAIX_UTERM_H */ diff --git a/lunaix-os/kernel/debug/trace.c b/lunaix-os/kernel/debug/trace.c index 1cf9ae3..8c5c180 100644 --- a/lunaix-os/kernel/debug/trace.c +++ b/lunaix-os/kernel/debug/trace.c @@ -77,6 +77,10 @@ ksym_getstr(struct ksym_entry* sym) trace_ctx.ksym_table->ksym_label_off + sym->label_off); } +static inline bool valid_fp(ptr_t ptr) { + return KERNEL_STACK < ptr && ptr < KERNEL_EXEC_END; +} + int trace_walkback(struct trace_record* tb_buffer, ptr_t fp, @@ -87,7 +91,7 @@ trace_walkback(struct trace_record* tb_buffer, struct ksym_entry* current = NULL; int i = 0; - while (frame && i < limit) { + while (valid_fp((ptr_t)frame) && i < limit) { ptr_t pc = *(frame + 1); current = trace_sym_lookup(pc); diff --git a/lunaix-os/kernel/device/device.c b/lunaix-os/kernel/device/device.c index 8765755..cce51b1 100644 --- a/lunaix-os/kernel/device/device.c +++ b/lunaix-os/kernel/device/device.c @@ -20,8 +20,7 @@ struct devclass default_devclass = {}; void device_setname_vargs(struct device* dev, char* fmt, va_list args) { - size_t strlen = - ksnprintfv(dev->name_val, fmt, DEVICE_NAME_SIZE, args); + size_t strlen = ksnprintfv(dev->name_val, fmt, DEVICE_NAME_SIZE, args); dev->name = HSTR(dev->name_val, strlen); @@ -70,6 +69,7 @@ device_create(struct device* dev, llist_init_head(&dev->children); mutex_init(&dev->lock); + iopoll_init_evt_q(&dev->pollers); } struct device* @@ -201,6 +201,13 @@ device_cast(void* obj) return NULL; } +void +device_alert_poller(struct device* dev, int poll_evt) +{ + dev->poll_evflags = poll_evt; + iopoll_wake_pollers(&dev->pollers); +} + __DEFINE_LXSYSCALL3(int, ioctl, int, fd, int, req, va_list, args) { int errno = -1; diff --git a/lunaix-os/kernel/device/poll.c b/lunaix-os/kernel/device/poll.c index e7f0f87..bf7edd7 100644 --- a/lunaix-os/kernel/device/poll.c +++ b/lunaix-os/kernel/device/poll.c @@ -149,7 +149,7 @@ __append_pollers(int* ds, int npoller) return nc; } -static int +static void __wait_until_event() { block_current(); @@ -159,7 +159,7 @@ __wait_until_event() void iopoll_init(struct iopoll* ctx) { - ctx->pollers = valloc(sizeof(ptr_t) * MAX_POLLER_COUNT); + ctx->pollers = vzalloc(sizeof(ptr_t) * MAX_POLLER_COUNT); ctx->n_poller = 0; } @@ -173,9 +173,9 @@ iopoll_free(pid_t pid, struct iopoll* ctx) llist_delete(&poller->evt_listener); vfree(poller); } - - vfree(ctx->pollers); } + + vfree(ctx->pollers); } void @@ -257,7 +257,7 @@ __DEFINE_LXSYSCALL2(int, pollctl, int, action, va_list, va) time_t t1 = clock_systime() + timeout; while (!(retcode == __do_poll_round(pinfos, npinfos))) { - if (timeout >= 0 && t1 >= clock_systime()) { + if (timeout >= 0 && t1 < clock_systime()) { break; } __wait_until_event(); @@ -269,7 +269,7 @@ __DEFINE_LXSYSCALL2(int, pollctl, int, action, va_list, va) time_t t1 = clock_systime() + timeout; while (!(retcode == __do_poll_all(pinfo))) { - if (timeout >= 0 && t1 >= clock_systime()) { + if (timeout >= 0 && t1 < clock_systime()) { break; } __wait_until_event(); diff --git a/lunaix-os/kernel/ds/rbuffer.c b/lunaix-os/kernel/ds/rbuffer.c new file mode 100644 index 0000000..bfcc3a5 --- /dev/null +++ b/lunaix-os/kernel/ds/rbuffer.c @@ -0,0 +1,100 @@ +#include +#include +#include + +#include + +struct rbuffer* +rbuffer_create(char* buf, size_t maxsz) +{ + struct rbuffer* rb = valloc(sizeof(struct rbuffer)); + rbuffer_init(rb, buf, maxsz); + + return rb; +} + +int +rbuffer_erase(struct rbuffer* rb) +{ + if (rb->len == 0) { + return 0; + } + rb->ptr = (rb->ptr - 1) % rb->maxsz; + rb->len--; + + return 1; +} + +int +rbuffer_put(struct rbuffer* rb, char c) +{ + rb->buffer[rb->ptr] = c; + rb->ptr = (rb->ptr + 1) % rb->maxsz; + rb->len = MIN(rb->len + 1, rb->maxsz); + + return 1; +} + +int +rbuffer_puts(struct rbuffer* rb, char* buf, size_t len) +{ + if (!len) + return 0; + + size_t ptr = (rb->ptr + len) % rb->maxsz; + size_t nlen = MIN(len, rb->maxsz); + size_t ptr_start = (ptr - nlen) % rb->maxsz; + + buf = &buf[nlen]; + if (ptr_start >= ptr) { + size_t llen = rb->maxsz - ptr_start; + memcpy(&rb->buffer[ptr_start], &buf[-nlen], llen); + memcpy(&rb->buffer[0], &buf[-nlen + llen], ptr + 1); + } else { + memcpy(&rb->buffer[ptr_start], &buf[-nlen], nlen); + } + + rb->ptr = ptr; + rb->len = nlen; + + return nlen; +} + +int +rbuffer_gets(struct rbuffer* rb, char* buf, size_t len) +{ + if (!len) + return 0; + + size_t nlen = MIN(len, rb->len); + size_t ptr_start = (rb->ptr - rb->len) % rb->maxsz; + size_t ptr_end = (ptr_start + nlen) % rb->maxsz; + + buf = &buf[nlen]; + if (ptr_start >= ptr_end) { + size_t llen = rb->maxsz - ptr_start; + memcpy(&buf[-nlen], &rb->buffer[ptr_start], llen); + memcpy(&buf[-nlen + llen], &rb->buffer[0], ptr_end + 1); + } else { + memcpy(&buf[-nlen], &rb->buffer[ptr_start], nlen); + } + + rb->len -= nlen; + + return nlen; +} + +int +rbuffer_get(struct rbuffer* rb, char* c) +{ + if (rb->len == 0) { + return 0; + } + + size_t ptr_start = (rb->ptr - rb->len) % rb->maxsz; + rb->len--; + + *c = rb->buffer[ptr_start]; + + return 1; +} \ No newline at end of file diff --git a/lunaix-os/kernel/mm/cake.c b/lunaix-os/kernel/mm/cake.c index 2a70ab7..e4ceef4 100644 --- a/lunaix-os/kernel/mm/cake.c +++ b/lunaix-os/kernel/mm/cake.c @@ -84,7 +84,7 @@ __init_pile(struct cake_pile* pile, piece_size = ROUNDUP(piece_size, offset); *pile = (struct cake_pile){ .piece_size = piece_size, - .cakes_count = 1, + .cakes_count = 0, .pieces_per_cake = (pg_per_cake * PG_SIZE) / (piece_size + sizeof(piece_index_t)), @@ -149,7 +149,7 @@ cake_grab(struct cake_pile* pile) pile->alloced_pieces++; llist_delete(&pos->cakes); - if (pos->next_free == EO_FREE_PIECE) { + if (pos->free_list[pos->next_free] == EO_FREE_PIECE) { llist_append(&pile->full, &pos->cakes); } else { llist_append(&pile->partial, &pos->cakes); @@ -169,6 +169,7 @@ int cake_release(struct cake_pile* pile, void* area) { piece_index_t piece_index; + size_t dsize = 0; struct cake_s *pos, *n; struct llist_header* hdrs[2] = { &pile->full, &pile->partial }; @@ -178,7 +179,8 @@ cake_release(struct cake_pile* pile, void* area) if (pos->first_piece > area) { continue; } - piece_index = (ptr_t)(area - pos->first_piece) / pile->piece_size; + dsize = (ptr_t)(area - pos->first_piece); + piece_index = dsize / pile->piece_size; if (piece_index < pile->pieces_per_cake) { goto found; } @@ -188,8 +190,12 @@ cake_release(struct cake_pile* pile, void* area) return 0; found: + assert(!(dsize % pile->piece_size)); pos->free_list[piece_index] = pos->next_free; pos->next_free = piece_index; + + assert_msg(pos->free_list[piece_index] != pos->next_free, "double free"); + pos->used_pieces--; pile->alloced_pieces--; diff --git a/lunaix-os/kernel/mm/mmap.c b/lunaix-os/kernel/mm/mmap.c index d39269c..fa71016 100644 --- a/lunaix-os/kernel/mm/mmap.c +++ b/lunaix-os/kernel/mm/mmap.c @@ -114,7 +114,6 @@ found: region->mfile = file; region->foff = param->offset; - region->flen = param->flen; region->proc_vms = param->pvms; region_add(vm_regions, region); @@ -277,7 +276,6 @@ __unmap_overlapped_cases(ptr_t mnt, if (region->mfile) { size_t f_shifted = new_start - region->start; region->foff += f_shifted; - region->flen = MAX(region->flen, f_shifted) - f_shifted; } region->start = new_start; llist_insert_after(&vmr->head, ®ion->head); @@ -316,7 +314,6 @@ __unmap_overlapped_cases(ptr_t mnt, region_release(vmr); } else if (vmr->mfile) { vmr->foff += displ; - vmr->flen = MAX(vmr->flen, displ) - displ; } *addr = umps_start + umps_len; diff --git a/lunaix-os/kernel/mm/region.c b/lunaix-os/kernel/mm/region.c index f47baa7..2c6c6fe 100644 --- a/lunaix-os/kernel/mm/region.c +++ b/lunaix-os/kernel/mm/region.c @@ -52,8 +52,7 @@ region_add(vm_regions_t* lead, struct mm_region* vmregion) return; } - struct mm_region *pos = (struct mm_region*)lead->next, - *n = list_entry(pos->head.next, struct mm_region, head); + struct mm_region *pos, *n; ptr_t cur_end = 0; llist_for_each(pos, n, lead, head) @@ -117,7 +116,7 @@ region_copy_mm(struct proc_mm* src, struct proc_mm* dest) dup->region_copied(dup); } - region_add(&dest->regions, dup); + llist_append(&dest->regions, &dup->head); } } diff --git a/lunaix-os/kernel/process/sched.c b/lunaix-os/kernel/process/sched.c index 4056021..bec2fae 100644 --- a/lunaix-os/kernel/process/sched.c +++ b/lunaix-os/kernel/process/sched.c @@ -42,9 +42,8 @@ sched_init() proc_pile = cake_new_pile("proc", sizeof(struct proc_info), 1, 0); cake_set_constructor(proc_pile, cake_ctor_zeroing); - sched_ctx = (struct scheduler){ ._procs = vzalloc(PROC_TABLE_SIZE), - .ptable_len = 0, - .procs_index = 0 }; + sched_ctx = (struct scheduler){ + ._procs = vzalloc(PROC_TABLE_SIZE), .ptable_len = 0, .procs_index = 0}; // TODO initialize dummy_proc sched_init_dummy(); @@ -96,6 +95,9 @@ can_schedule(struct proc_info* proc) if ((proc->state & PS_PAUSED)) { return !!(sh->sig_pending & ~1); } + if ((proc->state & PS_BLOCKED)) { + return sigset_test(sh->sig_pending, _SIGINT); + } if (sigset_test(sh->sig_pending, _SIGCONT)) { sigset_clear(sh->sig_pending, _SIGSTOP); diff --git a/lunaix-os/kernel/process/signal.c b/lunaix-os/kernel/process/signal.c index c4e1662..9989425 100644 --- a/lunaix-os/kernel/process/signal.c +++ b/lunaix-os/kernel/process/signal.c @@ -111,7 +111,7 @@ signal_send(pid_t pid, int signum) } else if (!pid) { proc = __current; goto send_grp; - } else if (pid < -1) { + } else if (pid < 0) { proc = get_process(-pid); goto send_grp; } else { -- 2.27.0