----
-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
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
+# ---
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;
}
}
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);
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]);
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);
}
{
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_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);
}
{
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);
}
{
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_lock(sdev->dev);
+ mark_device_doing_write(sdev->dev);
+
if (sdev->write(sdev, buf, len) == RXTX_DONE) {
goto done;
}
{
device_lock(sdev->dev);
+ mark_device_doing_write(sdev->dev);
+
sdev->write(sdev, buf, len);
int rdlen = sdev->wr_len;
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);
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;
}
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;
+/**
+ * @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 <lunaix/process.h>
+#include <usr/lunaix/term.h>
#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
--- /dev/null
+/**
+ * @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
#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
+#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:
}
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;
}
return NULL;
}
- lcntl_instance->apply = lcntl_template->apply;
+ lcntl_instance->process_and_put = lcntl_template->process_and_put;
return lcntl_instance;
}
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);
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
--- /dev/null
+#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
#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/rbuffer.h>
+
+#include <hal/term.h>
#define SERIAL_RW_RX 0x0
#define SERIAL_RW_TX 0x1
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;
/**
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);
#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_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 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);
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_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 */
#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)
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;
};
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)
{
--- /dev/null
+#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 */
#include <lunaix/device.h>
#include <lunaix/ds/llist.h>
-#include <lunaix/fs.h>
#include <usr/lunaix/poll.h>
+struct v_fd; // <lunaix/fs.h>
+
typedef struct llist_header poll_evt_q;
struct poll_opts
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*);
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
*
#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)
--- /dev/null
+#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 */
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,
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);
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);
llist_init_head(&dev->children);
mutex_init(&dev->lock);
+ iopoll_init_evt_q(&dev->pollers);
}
struct device*
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;
return nc;
}
-static int
+static void
__wait_until_event()
{
block_current();
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;
}
llist_delete(&poller->evt_listener);
vfree(poller);
}
-
- vfree(ctx->pollers);
}
+
+ vfree(ctx->pollers);
}
void
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();
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();
--- /dev/null
+#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
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)),
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);
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 };
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;
}
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--;
region->mfile = file;
region->foff = param->offset;
- region->flen = param->flen;
region->proc_vms = param->pvms;
region_add(vm_regions, region);
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);
region_release(vmr);
} else if (vmr->mfile) {
vmr->foff += displ;
- vmr->flen = MAX(vmr->flen, displ) - displ;
}
*addr = umps_start + umps_len;
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)
dup->region_copied(dup);
}
- region_add(&dest->regions, dup);
+ llist_append(&dest->regions, &dup->head);
}
}
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();
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);
} else if (!pid) {
proc = __current;
goto send_grp;
- } else if (pid < -1) {
+ } else if (pid < 0) {
proc = get_process(-pid);
goto send_grp;
} else {