feat: nearly complete POSIX.1-2008 compliant terminal interface implementation
authorMinep <lunaixsky@qq.com>
Sun, 26 Nov 2023 23:17:42 +0000 (23:17 +0000)
committerMinep <lunaixsky@qq.com>
Sun, 26 Nov 2023 23:17:42 +0000 (23:17 +0000)
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

27 files changed:
lunaix-os/.clang-format
lunaix-os/arch/i386/mm/pfault.c
lunaix-os/hal/ahci/io_event.c
lunaix-os/hal/char/serial.c
lunaix-os/hal/char/uart/16550_pmio.c
lunaix-os/hal/term/lcntls/ansi_cntl.c
lunaix-os/hal/term/lcntls/lcntl.c [new file with mode: 0644]
lunaix-os/hal/term/term.c
lunaix-os/hal/term/term_io.c [new file with mode: 0644]
lunaix-os/includes/hal/serial.h
lunaix-os/includes/hal/term.h
lunaix-os/includes/lunaix/compiler.h
lunaix-os/includes/lunaix/device.h
lunaix-os/includes/lunaix/ds/rbuffer.h [new file with mode: 0644]
lunaix-os/includes/lunaix/iopoll.h
lunaix-os/includes/lunaix/types.h
lunaix-os/includes/usr/lunaix/ioctl_defs.h
lunaix-os/includes/usr/lunaix/term.h [new file with mode: 0644]
lunaix-os/kernel/debug/trace.c
lunaix-os/kernel/device/device.c
lunaix-os/kernel/device/poll.c
lunaix-os/kernel/ds/rbuffer.c [new file with mode: 0644]
lunaix-os/kernel/mm/cake.c
lunaix-os/kernel/mm/mmap.c
lunaix-os/kernel/mm/region.c
lunaix-os/kernel/process/sched.c
lunaix-os/kernel/process/signal.c

index a429ba1a42dd8e0391580277aafc416992f3464a..079efc7c598e7f72299c84b514dafe0fe8c38216 100644 (file)
----
-Language:        Cpp
-# BasedOnStyle:  Mozilla
-AccessModifierOffset: -2
-AlignAfterOpenBracket: Align
+---
+# Language: Cpp
+# BasedOnStyle:  Mozilla
+AccessModifierOffset: -2
+AlignAfterOpenBracket: Align
 AlignConsecutiveMacros: false
 AlignConsecutiveAssignments: false
 AlignConsecutiveDeclarations: false
 AlignEscapedNewlines: Right
 AlignConsecutiveMacros: false
 AlignConsecutiveAssignments: false
 AlignConsecutiveDeclarations: false
 AlignEscapedNewlines: Right
-AlignOperands:   true
+AlignOperands: true
 AlignTrailingComments: true
 AlignTrailingComments: true
-AllowAllArgumentsOnNextLine: true
-AllowAllConstructorInitializersOnNextLine: true
-AllowAllParametersOfDeclarationOnNextLine: false
+AllowAllArgumentsOnNextLine: true
+AllowAllConstructorInitializersOnNextLine: true
+AllowAllParametersOfDeclarationOnNextLine: false
 AllowShortBlocksOnASingleLine: Never
 AllowShortBlocksOnASingleLine: Never
-AllowShortCaseLabelsOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
 AllowShortFunctionsOnASingleLine: Inline
 AllowShortFunctionsOnASingleLine: Inline
-AllowShortLambdasOnASingleLine: All
-AllowShortIfStatementsOnASingleLine: Never
-AllowShortLoopsOnASingleLine: false
-AlwaysBreakAfterDefinitionReturnType: TopLevel
+AllowShortLambdasOnASingleLine: All
+AllowShortIfStatementsOnASingleLine: Never
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: TopLevel
 AlwaysBreakAfterReturnType: TopLevel
 AlwaysBreakAfterReturnType: TopLevel
-AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakBeforeMultilineStrings: false
 AlwaysBreakTemplateDeclarations: Yes
 BinPackArguments: false
 BinPackParameters: false
 BraceWrapping:
 AlwaysBreakTemplateDeclarations: Yes
 BinPackArguments: false
 BinPackParameters: false
 BraceWrapping:
-  AfterCaseLabel:  false
-  AfterClass:      true
+  AfterCaseLabel: false
+  AfterClass: true
   AfterControlStatement: false
   AfterControlStatement: false
-  AfterEnum:       true
-  AfterFunction:   true
-  AfterNamespace:  false
+  AfterEnum: true
+  AfterFunction: true
+  AfterNamespace: false
   AfterObjCDeclaration: false
   AfterObjCDeclaration: false
-  AfterStruct:     true
-  AfterUnion:      true
+  AfterStruct: true
+  AfterUnion: true
   AfterExternBlock: true
   AfterExternBlock: true
-  BeforeCatch:     false
-  BeforeElse:      false
-  IndentBraces:    false
+  BeforeCatch: false
+  BeforeElse: false
+  IndentBraces: false
   SplitEmptyFunction: true
   SplitEmptyRecord: false
   SplitEmptyNamespace: true
   SplitEmptyFunction: true
   SplitEmptyRecord: false
   SplitEmptyNamespace: true
-BreakBeforeBinaryOperators: None
+BreakBeforeBinaryOperators: None
 BreakBeforeBraces: Mozilla
 BreakBeforeBraces: Mozilla
-BreakBeforeInheritanceComma: false
-BreakInheritanceList: BeforeComma
+BreakBeforeInheritanceComma: false
+BreakInheritanceList: BeforeComma
 BreakBeforeTernaryOperators: true
 BreakBeforeTernaryOperators: true
-BreakConstructorInitializersBeforeComma: false
-BreakConstructorInitializers: BeforeComma
-BreakAfterJavaFieldAnnotations: false
+BreakConstructorInitializersBeforeComma: false
+BreakConstructorInitializers: BeforeComma
+BreakAfterJavaFieldAnnotations: false
 BreakStringLiterals: true
 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
 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
 IndentCaseLabels: true
 IndentGotoLabels: true
 IndentPPDirectives: None
-IndentWidth:     4
-IndentWrappedFunctionNames: false
-JavaScriptQuotes: Leave
-JavaScriptWrapImports: true
+IndentWidth: 4
+IndentWrappedFunctionNames: false
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
 KeepEmptyLinesAtTheStartOfBlocks: true
 KeepEmptyLinesAtTheStartOfBlocks: true
-MacroBlockBegin: ''
-MacroBlockEnd:   ''
+# MacroBlockBegin: ""
+# MacroBlockEnd: ""
 MaxEmptyLinesToKeep: 1
 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
 PointerAlignment: Left
-ReflowComments:  true
-SortIncludes:    true
-SortUsingDeclarations: true
+# ReflowComments: true
+SortIncludes: true
+SortUsingDeclarations: true
 SpaceAfterCStyleCast: false
 SpaceAfterLogicalNot: false
 SpaceAfterTemplateKeyword: false
 SpaceAfterCStyleCast: false
 SpaceAfterLogicalNot: false
 SpaceAfterTemplateKeyword: false
@@ -119,19 +119,19 @@ SpaceBeforeRangeBasedForLoopColon: true
 SpaceInEmptyBlock: false
 SpaceInEmptyParentheses: false
 SpacesBeforeTrailingComments: 1
 SpaceInEmptyBlock: false
 SpaceInEmptyParentheses: false
 SpacesBeforeTrailingComments: 1
-SpacesInAngles:  false
+SpacesInAngles: false
 SpacesInConditionalStatement: false
 SpacesInContainerLiterals: true
 SpacesInCStyleCastParentheses: false
 SpacesInParentheses: false
 SpacesInSquareBrackets: false
 SpaceBeforeSquareBrackets: false
 SpacesInConditionalStatement: false
 SpacesInContainerLiterals: true
 SpacesInCStyleCastParentheses: false
 SpacesInParentheses: false
 SpacesInSquareBrackets: false
 SpaceBeforeSquareBrackets: false
-Standard:        Latest
+Standard: Latest
 StatementMacros:
   - Q_UNUSED
   - QT_REQUIRE_VERSION
 StatementMacros:
   - Q_UNUSED
   - QT_REQUIRE_VERSION
-TabWidth:        8
-UseCRLF:         false
-UseTab:          Never
-...
+# TabWidth: 8
+UseCRLF: false
+UseTab: Never
+# ---
 
 
index 848f215c359f3c75d851c1ae5a29e092bc707fd6..faf7da066d30a3cba019c1775b9af66c4fca2a86 100644 (file)
@@ -92,7 +92,7 @@ intr_routine_page_fault(const isr_param* param)
                 goto oom;
             }
 
                 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;
         }
             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);
         }
 
         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);
 
 
         memset((void*)ptr, 0, PG_SIZE);
 
index 2ad988a4239936f1279127daea516f55d5c34c35..c843d29661553e4a2fabfefeb683e720a0732e89 100644 (file)
@@ -65,7 +65,7 @@ proceed:
 
     blkio_schedule(ioreq->io_ctx);
     blkio_complete(ioreq);
 
     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]);
 
 done:
     hba_clear_reg(port->regs[HBA_RPxIS]);
index ffe9acb5460581f92e75403e272425eeeda65a88..ddcd57f97ee4412c3e1392225c0bc595eb8ccc08 100644 (file)
@@ -15,24 +15,28 @@ static int serial_idx = 0;
 int
 serial_accept_one(struct serial_dev* sdev, u8_t val)
 {
 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)
 {
 }
 
 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)
 {
 }
 
 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)
 {
     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);
 }
     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);
 
 {
     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);
 
 
     device_unlock(sdev->dev);
 
@@ -54,7 +58,9 @@ serial_readone(struct serial_dev* sdev, u8_t* val)
 {
     device_lock(sdev->dev);
 
 {
     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);
     }
 
         pwait(&sdev->wq_rxdone);
     }
 
@@ -66,8 +72,10 @@ serial_readbuf(struct serial_dev* sdev, u8_t* buf, size_t len)
 {
     device_lock(sdev->dev);
 
 {
     device_lock(sdev->dev);
 
+    mark_device_doing_read(sdev->dev);
+
     size_t rdlen;
     size_t rdlen;
-    while (!(rdlen = fifo_read(&sdev->rxbuf, buf, len))) {
+    while (!(rdlen = rbuffer_gets(&sdev->rxbuf, (char*)buf, len))) {
         pwait(&sdev->wq_rxdone);
     }
 
         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);
 
 {
     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);
 
 
     device_unlock(sdev->dev);
 
@@ -93,6 +103,8 @@ serial_writebuf(struct serial_dev* sdev, u8_t* buf, size_t len)
 {
     device_lock(sdev->dev);
 
 {
     device_lock(sdev->dev);
 
+    mark_device_doing_write(sdev->dev);
+
     if (sdev->write(sdev, buf, len) == RXTX_DONE) {
         goto done;
     }
     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);
 
 {
     device_lock(sdev->dev);
 
+    mark_device_doing_write(sdev->dev);
+
     sdev->write(sdev, buf, len);
     int rdlen = sdev->wr_len;
 
     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);
 }
 
     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*
 #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);
 {
     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.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);
 
     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_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;
 }
 
     return sdev;
 }
 
index 81d06422e910b5570df022e8fdd388c4d996d15a..7bd99da8d36dce4c5a8b491487391cde36a856ce 100644 (file)
@@ -77,7 +77,7 @@ upiom_init(struct device_def* def)
         uart_enable_fifo(uart, UART_FIFO8);
         llist_append(&com_ports, &uart->local_ports);
 
         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;
         sdev->backend = uart;
         sdev->write = uart_general_tx;
         sdev->exec_cmd = uart_general_exec_cmd;
index a11781eb6e969fde088c54df4266d60760c5a604..0596a7a64af40a6a26d8f5f02d080ae9216b5bf0 100644 (file)
@@ -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 <hal/term.h>
 #include <hal/term.h>
-
-#include <lunaix/process.h>
+#include <usr/lunaix/term.h>
 
 #define CTRL_MNEMO(chr) (chr - 'A' + 1)
 
 
 #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) {
     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) {
         default:
             if ((int)chr < 32) {
-                line_put_next(lbuf, '^', 0);
+                rbuffer_put(cooked, '^');
                 chr += 64;
             }
             break;
     }
 
                 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 (file)
index 0000000..4359830
--- /dev/null
@@ -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 <hal/term.h>
+#include <usr/lunaix/term.h>
+
+#include <lunaix/process.h>
+#include <lunaix/spike.h>
+
+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
index 21301059eaaa61e003f858edf5ed79c77e6b2bf3..b566c555a1ca4c5a53d2beb9a8a94e4c1642eddd 100644 (file)
 #include <klibc/string.h>
 #include <lunaix/fs.h>
 #include <lunaix/mm/valloc.h>
 #include <klibc/string.h>
 #include <lunaix/fs.h>
 #include <lunaix/mm/valloc.h>
+#include <lunaix/process.h>
 #include <lunaix/spike.h>
 #include <lunaix/status.h>
 
 #include <usr/lunaix/ioctl_defs.h>
 
 #define ANSI_LCNTL 0
 #include <lunaix/spike.h>
 #include <lunaix/status.h>
 
 #include <usr/lunaix/ioctl_defs.h>
 
 #define ANSI_LCNTL 0
+#define termdev(dev) ((struct term*)(dev)->underlay)
 
 extern struct term_lcntl ansi_line_controller;
 
 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*))
 
 #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)
 {
 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) {
     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;
             }
 
                 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:
     }
 
 done:
@@ -95,81 +123,73 @@ done:
 }
 
 static int
 }
 
 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
 }
 
 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*
 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);
 
     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);
 
     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;
 }
 
     return terminal;
 }
@@ -200,7 +220,7 @@ term_get_lcntl(u32_t lcntl_index)
         return NULL;
     }
 
         return NULL;
     }
 
-    lcntl_instance->apply = lcntl_template->apply;
+    lcntl_instance->process_and_put = lcntl_template->process_and_put;
 
     return lcntl_instance;
 }
 
     return lcntl_instance;
 }
@@ -227,7 +247,7 @@ term_pop_lcntl(struct term* term)
     device_lock(term->dev);
 
     struct term_lcntl* lcntl =
     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);
     llist_delete(term->lcntl_stack.prev);
 
     vfree(lcntl);
@@ -237,76 +257,28 @@ term_pop_lcntl(struct term* term)
     return 1;
 }
 
     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);
 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)
 {
     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);
 }
 
     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 (file)
index 0000000..94e61d6
--- /dev/null
@@ -0,0 +1,118 @@
+#include <hal/term.h>
+
+#include <lunaix/clock.h>
+#include <lunaix/sched.h>
+
+#include <usr/lunaix/term.h>
+
+#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
index 1211ed04cb0793018d6f5a8799b48d637f1e5789..c346c51cc2068fd2e0ea716b562d266847263b33 100644 (file)
@@ -2,10 +2,12 @@
 #define __LUNAIX_SERIAL_H
 
 #include <lunaix/device.h>
 #define __LUNAIX_SERIAL_H
 
 #include <lunaix/device.h>
-#include <lunaix/ds/fifo.h>
 #include <lunaix/ds/llist.h>
 #include <lunaix/ds/mutex.h>
 #include <lunaix/ds/waitq.h>
 #include <lunaix/ds/llist.h>
 #include <lunaix/ds/mutex.h>
 #include <lunaix/ds/waitq.h>
+#include <lunaix/ds/rbuffer.h>
+
+#include <hal/term.h>
 
 #define SERIAL_RW_RX 0x0
 #define SERIAL_RW_TX 0x1
 
 #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 device* dev;
     struct waitq wq_rxdone;
     struct waitq wq_txdone;
+    struct term* at_term;
     void* backend;
 
     void* backend;
 
-    struct fifo_buf rxbuf;
+    struct rbuffer rxbuf;
     int wr_len;
 
     /**
     int wr_len;
 
     /**
@@ -41,8 +44,18 @@ struct serial_dev
     int (*exec_cmd)(struct serial_dev* sdev, u32_t, va_list);
 };
 
     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*
 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);
 
 void
 serial_readone(struct serial_dev* sdev, u8_t* val);
index 79f8f67ad1b18fe9831b46bc5667c0551220c0e3..00fe32b04a074ebd40a236a11ee26367b3fcd913 100644 (file)
@@ -2,21 +2,34 @@
 #define __LUNAIX_TERM_H
 
 #include <lunaix/device.h>
 #define __LUNAIX_TERM_H
 
 #include <lunaix/device.h>
+#include <lunaix/ds/rbuffer.h>
+#include <lunaix/signal_defs.h>
+
+#include <usr/lunaix/term.h>
 
 struct term;
 
 
 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
 };
 
 struct term
@@ -24,12 +37,25 @@ struct term
     struct device* dev;
     struct device* chdev;
     struct llist_header lcntl_stack;
     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;
     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*
 };
 
 struct term*
-term_create();
+term_create(struct device* chardev, char* suffix);
 
 int
 term_bind(struct term* tdev, struct device* chdev);
 
 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);
 
 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);
 
 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);
 
 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
 
 int
-term_sendline(struct term* tdev, size_t len);
+lcntl_transform_inseq(struct term* tdev);
 
 int
 
 int
-term_readline(struct term* tdev, size_t len);
+lcntl_transform_outseq(struct term* tdev);
 
 #endif /* __LUNAIX_TERM_H */
 
 #endif /* __LUNAIX_TERM_H */
index f011a0b9df07cd865c81ba2c7e741ee87c5598ca..137d288c5619029b86f66e5fae7b6828ba926ffe 100644 (file)
@@ -7,6 +7,10 @@
 #define weak_alias(name) __attribute__((weak, alias(name)))
 #define weak __attribute__((weak))
 #define noret __attribute__((noreturn))
 #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)
 
 #define stringify(v) #v
 #define stringify__(v) stringify(v)
index affdb10200a91f23b690ddb20fdc2d6f13f0569d..a3b6f9403db071c1403215557245a35dad290242 100644 (file)
@@ -125,12 +125,14 @@ struct device
         int (*acquire)(struct device* dev);
         int (*release)(struct device* dev);
 
         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;
 };
 
     } ops;
 };
 
@@ -164,6 +166,15 @@ struct device_def
     int (*free)(struct device_def*, void* instance);
 };
 
     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)
 {
 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 (file)
index 0000000..f3777b6
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef __LUNAIX_RBUFFER_H
+#define __LUNAIX_RBUFFER_H
+
+#include <lunaix/types.h>
+
+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 */
index 027f6fb23f9197f985e25b0c5a61823b02b141fe..cdc6d79e6b241eb90f152dcaabdfb1418eb4edb8 100644 (file)
@@ -3,10 +3,11 @@
 
 #include <lunaix/device.h>
 #include <lunaix/ds/llist.h>
 
 #include <lunaix/device.h>
 #include <lunaix/ds/llist.h>
-#include <lunaix/fs.h>
 
 #include <usr/lunaix/poll.h>
 
 
 #include <usr/lunaix/poll.h>
 
+struct v_fd; // <lunaix/fs.h>
+
 typedef struct llist_header poll_evt_q;
 
 struct poll_opts
 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);
 }
 
     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*);
 
 void
 iopoll_wake_pollers(poll_evt_q*);
 
index a6af3c10b99ffa7577af409457409c03cdeed999..b6799813d3b4102e66a8c5aeb3e2420ae63e1fd2 100644 (file)
@@ -27,6 +27,10 @@ typedef unsigned int cpu_t;
 
 typedef u64_t lba_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
  *
 /**
  * container_of - cast a member of a structure out to the containing structure
  *
index d99e7674a1ce73fe65c8abaf1ab2b304bab74bb4..dd5709f6ca99c9559e923062129fdd83dce6389c 100644 (file)
 #define TIOCSPGRP IOREQ(1, 1)
 #define TIOCCLSBUF IOREQ(2, 0)
 #define TIOCFLUSH IOREQ(3, 0)
 #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)
 
 #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 (file)
index 0000000..8866b30
--- /dev/null
@@ -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 */
index 1cf9ae34d37295a7251058d80813c978c7e84e12..8c5c1800fd6676ab9ec65d959eea2dc17cbf7706 100644 (file)
@@ -77,6 +77,10 @@ ksym_getstr(struct ksym_entry* sym)
                    trace_ctx.ksym_table->ksym_label_off + sym->label_off);
 }
 
                    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,
 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;
 
     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);
         ptr_t pc = *(frame + 1);
 
         current = trace_sym_lookup(pc);
index 87657551eb50a0e5a3ac42a257d712ad8e011344..cce51b19dbec4aaf9c3bbc9b94a0e8bddc18b018 100644 (file)
@@ -20,8 +20,7 @@ struct devclass default_devclass = {};
 void
 device_setname_vargs(struct device* dev, char* fmt, va_list args)
 {
 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);
 
 
     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);
 
     llist_init_head(&dev->children);
     mutex_init(&dev->lock);
+    iopoll_init_evt_q(&dev->pollers);
 }
 
 struct device*
 }
 
 struct device*
@@ -201,6 +201,13 @@ device_cast(void* obj)
     return NULL;
 }
 
     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;
 __DEFINE_LXSYSCALL3(int, ioctl, int, fd, int, req, va_list, args)
 {
     int errno = -1;
index e7f0f876a909ee602b17ce32d51b2067030f7bd2..bf7edd7c645eb760263c8947bd3992fdfa8feda7 100644 (file)
@@ -149,7 +149,7 @@ __append_pollers(int* ds, int npoller)
     return nc;
 }
 
     return nc;
 }
 
-static int
+static void
 __wait_until_event()
 {
     block_current();
 __wait_until_event()
 {
     block_current();
@@ -159,7 +159,7 @@ __wait_until_event()
 void
 iopoll_init(struct iopoll* ctx)
 {
 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;
 }
 
     ctx->n_poller = 0;
 }
 
@@ -173,9 +173,9 @@ iopoll_free(pid_t pid, struct iopoll* ctx)
             llist_delete(&poller->evt_listener);
             vfree(poller);
         }
             llist_delete(&poller->evt_listener);
             vfree(poller);
         }
-
-        vfree(ctx->pollers);
     }
     }
+    
+    vfree(ctx->pollers);
 }
 
 void
 }
 
 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))) {
 
             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();
                     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))) {
 
             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();
                     break;
                 }
                 __wait_until_event();
diff --git a/lunaix-os/kernel/ds/rbuffer.c b/lunaix-os/kernel/ds/rbuffer.c
new file mode 100644 (file)
index 0000000..bfcc3a5
--- /dev/null
@@ -0,0 +1,100 @@
+#include <lunaix/ds/rbuffer.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/spike.h>
+
+#include <klibc/string.h>
+
+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
index 2a70ab76d823f7d09d6d62cbc08bc6e70f70372b..e4ceef404121457f67e3cf679f11c81980aac86f 100644 (file)
@@ -84,7 +84,7 @@ __init_pile(struct cake_pile* pile,
 
     piece_size = ROUNDUP(piece_size, offset);
     *pile = (struct cake_pile){ .piece_size = piece_size,
 
     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)),
                                 .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);
     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);
         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;
 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 };
 
     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;
             }
             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;
             }
             if (piece_index < pile->pieces_per_cake) {
                 goto found;
             }
@@ -188,8 +190,12 @@ cake_release(struct cake_pile* pile, void* area)
     return 0;
 
 found:
     return 0;
 
 found:
+    assert(!(dsize % pile->piece_size));
     pos->free_list[piece_index] = pos->next_free;
     pos->next_free = piece_index;
     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--;
 
     pos->used_pieces--;
     pile->alloced_pieces--;
 
index d39269cc77f6ec00d77ad2cc1e2c1d92c02fdcd4..fa71016adc828e4792e47c5bf69796bb6f5a10cd 100644 (file)
@@ -114,7 +114,6 @@ found:
 
     region->mfile = file;
     region->foff = param->offset;
 
     region->mfile = file;
     region->foff = param->offset;
-    region->flen = param->flen;
     region->proc_vms = param->pvms;
 
     region_add(vm_regions, region);
     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;
             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, &region->head);
             }
             region->start = new_start;
             llist_insert_after(&vmr->head, &region->head);
@@ -316,7 +314,6 @@ __unmap_overlapped_cases(ptr_t mnt,
         region_release(vmr);
     } else if (vmr->mfile) {
         vmr->foff += displ;
         region_release(vmr);
     } else if (vmr->mfile) {
         vmr->foff += displ;
-        vmr->flen = MAX(vmr->flen, displ) - displ;
     }
 
     *addr = umps_start + umps_len;
     }
 
     *addr = umps_start + umps_len;
index f47baa749efd493fd560a9c1154200c75ff13306..2c6c6fe05b2bb8cd476651d6d2ccbdbd4e05e1a4 100644 (file)
@@ -52,8 +52,7 @@ region_add(vm_regions_t* lead, struct mm_region* vmregion)
         return;
     }
 
         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)
     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);
         }
 
             dup->region_copied(dup);
         }
 
-        region_add(&dest->regions, dup);
+        llist_append(&dest->regions, &dup->head);
     }
 }
 
     }
 }
 
index 405602199291d2c9f27548ac2cd6b8394b5b1856..bec2faef33af8cc4591949602359bc89d7bd0335 100644 (file)
@@ -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);
 
     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();
 
     // 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_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);
 
     if (sigset_test(sh->sig_pending, _SIGCONT)) {
         sigset_clear(sh->sig_pending, _SIGSTOP);
index c4e1662c1a89aa4ec78f3405c71fa8e93245e481..9989425dc1f42fabee8e1ddb6681c843454e43c0 100644 (file)
@@ -111,7 +111,7 @@ signal_send(pid_t pid, int signum)
     } else if (!pid) {
         proc = __current;
         goto send_grp;
     } else if (!pid) {
         proc = __current;
         goto send_grp;
-    } else if (pid < -1) {
+    } else if (pid < 0) {
         proc = get_process(-pid);
         goto send_grp;
     } else {
         proc = get_process(-pid);
         goto send_grp;
     } else {