feat: Ability to switch data segment
fix: Mitigated some race conditions
feat: Better way for process to yield current time slice.
16 files changed:
#ifndef __ASM__
#include <hal/cpu.h>
#ifndef __ASM__
#include <hal/cpu.h>
-typedef struct {
- gp_regs registers;
+typedef struct
+{
+ struct
+ {
+ reg32 eax;
+ reg32 ebx;
+ reg32 ecx;
+ reg32 edx;
+ reg32 edi;
+ reg32 ebp;
+ reg32 esi;
+ reg32 ds;
+ reg32 es;
+ reg32 fs;
+ reg32 gs;
+ reg32 esp;
+ } registers;
+
unsigned int vector;
unsigned int err_code;
unsigned int eip;
unsigned int vector;
unsigned int err_code;
unsigned int eip;
void
intr_unsubscribe(const uint8_t vector, int_subscriber);
void
intr_unsubscribe(const uint8_t vector, int_subscriber);
-void
-intr_set_fallback_handler(int_subscriber);
+void intr_set_fallback_handler(int_subscriber);
void
intr_handler(isr_param* param);
void
intr_handler(isr_param* param);
} __attribute__((packed)) sg_reg;
void
} __attribute__((packed)) sg_reg;
void
cpu_rcr0()
{
uintptr_t val;
cpu_rcr0()
{
uintptr_t val;
- asm volatile("movl %%cr0,%0" : "=r" (val));
+ asm volatile("movl %%cr0,%0" : "=r"(val));
cpu_rcr2()
{
uintptr_t val;
cpu_rcr2()
{
uintptr_t val;
- asm volatile("movl %%cr2,%0" : "=r" (val));
+ asm volatile("movl %%cr2,%0" : "=r"(val));
cpu_rcr3()
{
uintptr_t val;
cpu_rcr3()
{
uintptr_t val;
- asm volatile("movl %%cr3,%0" : "=r" (val));
+ asm volatile("movl %%cr3,%0" : "=r"(val));
cpu_reflags()
{
uintptr_t val;
cpu_reflags()
{
uintptr_t val;
- asm volatile(
- "pushf\n"
- "popl %0\n"
- :"=r"(val)::);
+ asm volatile("pushf\n"
+ "popl %0\n"
+ : "=r"(val)::);
return val;
}
#pragma GCC diagnostic pop
return val;
}
#pragma GCC diagnostic pop
__LXSYSCALL1(unsigned int, sleep, unsigned int, seconds)
__LXSYSCALL1(unsigned int, sleep, unsigned int, seconds)
-__LXSYSCALL1(pid_t, wait, int*, status);
-
#endif /* __LUNAIX_UNISTD_H */
#endif /* __LUNAIX_UNISTD_H */
#define __LUNAIX_SYS_H
#include <lunaix/syscall.h>
#define __LUNAIX_SYS_H
#include <lunaix/syscall.h>
+#include <lunaix/types.h>
-__LXSYSCALL(void, yield)
+__LXSYSCALL(void, yield);
+
+__LXSYSCALL1(pid_t, wait, int*, status);
+__LXSYSCALL3(pid_t, waitpid, pid_t, pid, int*, status, int, options);
#endif /* __LUNAIX_SYS_H */
#endif /* __LUNAIX_SYS_H */
#define SCHED_TIME_SLICE 300
#define SCHED_TIME_SLICE 300
struct proc_info* _procs;
int procs_index;
unsigned int ptable_len;
};
struct proc_info* _procs;
int procs_index;
unsigned int ptable_len;
};
-void sched_init();
-void schedule();
+void
+sched_init();
+
+void
+schedule();
+
+void
+sched_yield();
#endif /* __LUNAIX_SCHEDULER_H */
#endif /* __LUNAIX_SCHEDULER_H */
#define __SYSCALL_sleep 7
#define __SYSCALL__exit 8
#define __SYSCALL_wait 9
#define __SYSCALL_sleep 7
#define __SYSCALL__exit 8
#define __SYSCALL_wait 9
+#define __SYSCALL_waitpid 10
#define __SYSCALL_MAX 0x100
#define __SYSCALL_MAX 0x100
asmlinkage rettype __lxsys_##name(__PARAM_MAP2(t1, p1, t2, p2))
#define __DEFINE_LXSYSCALL3(rettype, name, t1, p1, t2, p2, t3, p3) \
asmlinkage rettype __lxsys_##name(__PARAM_MAP2(t1, p1, t2, p2))
#define __DEFINE_LXSYSCALL3(rettype, name, t1, p1, t2, p2, t3, p3) \
- asmlinkage rettype __lxsys_##name(__PARAM_MAP3(t1, p1, t2, p2, t3, p3));
+ asmlinkage rettype __lxsys_##name(__PARAM_MAP3(t1, p1, t2, p2, t3, p3))
#define __DEFINE_LXSYSCALL4(rettype, name, t1, p1, t2, p2, t3, p3, t4, p4) \
asmlinkage rettype __lxsys_##nam( \
#define __DEFINE_LXSYSCALL4(rettype, name, t1, p1, t2, p2, t3, p3, t4, p4) \
asmlinkage rettype __lxsys_##nam( \
#include <lunaix/ds/llist.h>
#include <stdint.h>
#include <lunaix/ds/llist.h>
#include <stdint.h>
-#define SYS_TIMER_FREQUENCY_HZ 2048
+#define SYS_TIMER_FREQUENCY_HZ 2048
-#define TIMER_MODE_PERIODIC 0x1
+#define TIMER_MODE_PERIODIC 0x1
typedef uint32_t ticks_t;
typedef uint32_t ticks_t;
-struct lx_timer_context {
- struct lx_timer *active_timers;
+struct lx_timer_context
+{
+ struct lx_timer* active_timers;
/**
* @brief APIC timer base frequency (ticks per seconds)
/**
* @brief APIC timer base frequency (ticks per seconds)
*/
ticks_t base_frequency;
/**
* @brief Desired system running frequency
*/
ticks_t base_frequency;
/**
* @brief Desired system running frequency
*/
uint32_t running_frequency;
/**
* @brief Ticks per hertz
*/
uint32_t running_frequency;
/**
* @brief Ticks per hertz
struct llist_header link;
ticks_t deadline;
ticks_t counter;
struct llist_header link;
ticks_t deadline;
ticks_t counter;
/**
* @brief Initialize the system timer that runs at specified frequency
/**
* @brief Initialize the system timer that runs at specified frequency
* @param frequency The frequency that timer should run in Hz.
*/
void
timer_init(uint32_t frequency);
struct lx_timer*
* @param frequency The frequency that timer should run in Hz.
*/
void
timer_init(uint32_t frequency);
struct lx_timer*
-timer_run_second(uint32_t second, void (*callback)(void*), void* payload, uint8_t flags);
+timer_run_second(uint32_t second,
+ void (*callback)(void*),
+ void* payload,
+ uint8_t flags);
-timer_run_ms(uint32_t millisecond, void (*callback)(void*), void* payload, uint8_t flags);
+timer_run_ms(uint32_t millisecond,
+ void (*callback)(void*),
+ void* payload,
+ uint8_t flags);
struct lx_timer*
timer_run(ticks_t ticks, void (*callback)(void*), void* payload, uint8_t flags);
struct lx_timer*
timer_run(ticks_t ticks, void (*callback)(void*), void* payload, uint8_t flags);
-struct lx_timer_context*
+struct lx_timer_context*
timer_context();
#endif /* __LUNAIX_TIMER_H */
timer_context();
#endif /* __LUNAIX_TIMER_H */
+#define PROCTERM 0x10000
+#define PROCSTOP 0x20000
+
+#define WNOHANG 1
+#define WUNTRACED 2
+#define WEXITSTATUS(wstatus) ((wstatus & 0xffff))
+#define WIFSTOPPED(wstatus) ((wstatus & PROCSTOP))
+#define WIFEXITED(wstatus) \
+ ((wstatus & PROCTERM) && ((short)WEXITSTATUS(wstatus) >= 0))
+
typedef int32_t pid_t;
#endif /* __LUNAIX_TYPES_H */
typedef int32_t pid_t;
#endif /* __LUNAIX_TYPES_H */
#define __ASM__
#include <arch/x86/interrupts.h>
#define __ASM__
#include <arch/x86/interrupts.h>
+#include <lunaix/common.h>
// #define __ASM_INTR_DIAGNOSIS
.macro isr_template vector, no_error_code=1
// #define __ASM_INTR_DIAGNOSIS
.macro isr_template vector, no_error_code=1
isr_template PC_KBD_IV
interrupt_wrapper:
isr_template PC_KBD_IV
interrupt_wrapper:
+ /*
+ Stack layout
+ msa: [ss]
+ [esp]
+ eflags
+ cs
+ eip
+ err_code
+ vector > offset = 28 + 16 + 4 = 48
+ esp
+ gs
+ fs
+ es
+ ds > offset = 7 * 4 = 28
+ esi
+ ebp
+ edi
+ edx
+ ecx
+ ebx
+ lsa: eax > offset = 0
+
+ las: Least Significant Address
+ msa: Most Significant Address
+ */
+ subl $16, %esp
+ movw %gs, 12(%esp)
+ movw %fs, 8(%esp)
+ movw %es, 4(%esp)
+ movw %ds, (%esp)
+
pushl %esi
pushl %ebp
pushl %edi
pushl %esi
pushl %ebp
pushl %edi
+ movl 60(%esp), %eax /* 取出 %cs */
+ andl $0x3, %eax /* 判断 RPL */
+ jz 1f
+
+ movw $KDATA_SEG, %ax /* 如果从用户模式转来,则切换至内核数据段 */
+ movw %ax, %gs
+ movw %ax, %fs
+ movw %ax, %ds
+ movw %ax, %es
+
+ 1:
movl %esp, %eax
andl $0xfffffff0, %esp
subl $16, %esp
movl %esp, %eax
andl $0xfffffff0, %esp
subl $16, %esp
popl %edi
popl %ebp
popl %esi
popl %edi
popl %ebp
popl %esi
+
+ movw (%esp), %ds
+ movw 4(%esp), %es
+ movw 8(%esp), %fs
+ movw 12(%esp), %gs
+
+ movl 16(%esp), %esp
#include <arch/x86/interrupts.h>
#include <hal/apic.h>
#include <hal/cpu.h>
#include <arch/x86/interrupts.h>
#include <hal/apic.h>
#include <hal/cpu.h>
-#include <lunaix/syslog.h>
-#include <lunaix/tty/tty.h>
-#include <lunaix/process.h>
-#include <lunaix/sched.h>
#include <lunaix/mm/page.h>
#include <lunaix/mm/vmm.h>
#include <lunaix/mm/page.h>
#include <lunaix/mm/vmm.h>
+#include <lunaix/process.h>
+#include <lunaix/sched.h>
+#include <lunaix/syslog.h>
+#include <lunaix/tty/tty.h>
LOG_MODULE("intr")
static int_subscriber subscribers[256];
LOG_MODULE("intr")
static int_subscriber subscribers[256];
-static int_subscriber fallback = (int_subscriber) 0;
+static int_subscriber fallback = (int_subscriber)0;
-intr_subscribe(const uint8_t vector, int_subscriber subscriber) {
+intr_subscribe(const uint8_t vector, int_subscriber subscriber)
+{
subscribers[vector] = subscriber;
}
void
subscribers[vector] = subscriber;
}
void
-intr_unsubscribe(const uint8_t vector, int_subscriber subscriber) {
+intr_unsubscribe(const uint8_t vector, int_subscriber subscriber)
+{
if (subscribers[vector] == subscriber) {
if (subscribers[vector] == subscriber) {
- subscribers[vector] = (int_subscriber) 0;
+ subscribers[vector] = (int_subscriber)0;
-intr_set_fallback_handler(int_subscriber subscribers) {
+intr_set_fallback_handler(int_subscriber subscribers)
+{
fallback = subscribers;
}
fallback = subscribers;
}
intr_handler(isr_param* param)
{
__current->intr_ctx = *param;
intr_handler(isr_param* param)
{
__current->intr_ctx = *param;
#ifdef USE_KERNEL_PT
cpu_lcr3(__kernel_ptd);
vmm_mount_pd(PD_MOUNT_1, __current->page_table);
#endif
#ifdef USE_KERNEL_PT
cpu_lcr3(__kernel_ptd);
vmm_mount_pd(PD_MOUNT_1, __current->page_table);
#endif
- isr_param *lparam = &__current->intr_ctx;
-
+ isr_param* lparam = &__current->intr_ctx;
+
if (lparam->vector <= 255) {
int_subscriber subscriber = subscribers[lparam->vector];
if (subscriber) {
if (lparam->vector <= 255) {
int_subscriber subscriber = subscribers[lparam->vector];
if (subscriber) {
fallback(lparam);
goto done;
}
fallback(lparam);
goto done;
}
kprint_panic("INT %u: (%x) [%p: %p] Unknown",
kprint_panic("INT %u: (%x) [%p: %p] Unknown",
- lparam->vector,
- lparam->err_code,
- lparam->cs,
- lparam->eip);
+ lparam->vector,
+ lparam->err_code,
+ lparam->cs,
+ lparam->eip);
done:
// for all external interrupts except the spurious interrupt
// this is required by Intel Manual Vol.3A, section 10.8.1 & 10.8.5
done:
// for all external interrupts except the spurious interrupt
// this is required by Intel Manual Vol.3A, section 10.8.1 & 10.8.5
- if (lparam->vector >= EX_INTERRUPT_BEGIN && lparam->vector != APIC_SPIV_IV) {
+ if (lparam->vector >= EX_INTERRUPT_BEGIN &&
+ lparam->vector != APIC_SPIV_IV) {
.long __lxsys_getppid
.long __lxsys_sleep
.long __lxsys_exit
.long __lxsys_getppid
.long __lxsys_sleep
.long __lxsys_exit
- .long __lxsys_wait /* 9 */
+ .long __lxsys_wait
+ .long __lxsys_waitpid /* 10 */
2:
.rept __SYSCALL_MAX - (2b - 1b)/4
.long 0
2:
.rept __SYSCALL_MAX - (2b - 1b)/4
.long 0
* 2. 将_kernel_post_init搬进proc0进程
* (_kernel_post_init已经更名为init_platform)
*
* 2. 将_kernel_post_init搬进proc0进程
* (_kernel_post_init已经更名为init_platform)
*
- proc0.intr_ctx = (isr_param){ .registers.esp = KSTACK_TOP - 20,
+ proc0.intr_ctx = (isr_param){ .registers = { .ds = KDATA_SEG,
+ .es = KDATA_SEG,
+ .fs = KDATA_SEG,
+ .gs = KDATA_SEG },
.cs = KCODE_SEG,
.eip = (void*)__proc0,
.ss = KDATA_SEG,
.eflags = cpu_reflags() };
.cs = KCODE_SEG,
.eip = (void*)__proc0,
.ss = KDATA_SEG,
.eflags = cpu_reflags() };
- // 必须在读取eflags之后禁用。否则当进程被调度时,中断依然是关闭的!
- cpu_disable_interrupt();
+ // 方案1:必须在读取eflags之后禁用。否则当进程被调度时,中断依然是关闭的!
+ // cpu_disable_interrupt();
+
setup_proc_mem(&proc0, PD_REFERENCED);
// Ok... 首先fork进我们的零号进程,而后由那里,我们fork进init进程。
setup_proc_mem(&proc0, PD_REFERENCED);
// Ok... 首先fork进我们的零号进程,而后由那里,我们fork进init进程。
*/
asm volatile("movl %%cr3, %%eax\n"
"movl %%esp, %%ebx\n"
*/
asm volatile("movl %%cr3, %%eax\n"
"movl %%esp, %%ebx\n"
- "movl %0, %%cr3\n"
- "movl %1, %%esp\n"
+ "movl %1, %%cr3\n"
+ "movl %2, %%esp\n"
"pushl $0\n"
"pushl $0\n"
"pushl $0\n"
"pushl $0\n"
- "movl %%ebx, %%esp\n" ::"r"(proc0.page_table),
- "i"(KSTACK_TOP),
- "i"(KCODE_SEG),
- "r"(proc0.intr_ctx.eip)
+ "movl %%ebx, %%esp\n"
+ : "=m"(proc0.intr_ctx.registers.esp)
+ : "r"(proc0.page_table),
+ "i"(KSTACK_TOP),
+ "i"(KCODE_SEG),
+ "r"(proc0.intr_ctx.eip)
: "%eax", "%ebx", "memory");
// 向调度器注册进程。
: "%eax", "%ebx", "memory");
// 向调度器注册进程。
#ifdef WAIT_DEMO
// 测试wait
kprintf("I am parent, going to fork my child and wait.\n");
#ifdef WAIT_DEMO
// 测试wait
kprintf("I am parent, going to fork my child and wait.\n");
kprintf("I am child, I am about to terminated\n");
_exit(1);
}
kprintf("I am child, I am about to terminated\n");
_exit(1);
}
pid_t child = wait(&status);
pid_t child = wait(&status);
- kprintf(
- "I am parent, my child (%d) terminated with code: %d.\n", child, status);
+ kprintf("I am parent, my child (%d) terminated normally with code: %d.\n",
+ child,
+ WEXITSTATUS(status));
+ pid_t p = 0;
+
+ if (!(p = fork())) {
+ kprintf("Test no hang!");
+ sleep(1);
+ _exit(0);
+ }
+
+ waitpid(-1, &status, 0);
+ // FIXME: WNOHANG还有点问题……
+ // waitpid(-1, &status, WNOHANG);
+
+ sleep(2);
// 这里是就是LunaixOS的第一个进程了!
for (size_t i = 0; i < 10; i++) {
// 这里是就是LunaixOS的第一个进程了!
for (size_t i = 0; i < 10; i++) {
kprintf(KINFO "Forked %d\n", pid);
}
kprintf(KINFO "Forked %d\n", pid);
}
+ while ((p = wait(&status)) >= 0) {
+ short code = WEXITSTATUS(status);
+ if (WIFEXITED(status)) {
+ kprintf(KINFO "Process %d exited with code %d\n", p, code);
+ } else {
+ kprintf(KWARN "Process %d aborted with code %d\n", p, code);
+ }
+ }
+
char buf[64];
kprintf(KINFO "Hello processes!\n");
char buf[64];
kprintf(KINFO "Hello processes!\n");
#include <lunaix/lunistd.h>
#include <lunaix/mm/vmm.h>
#include <lunaix/peripheral/ps2kbd.h>
#include <lunaix/lunistd.h>
#include <lunaix/mm/vmm.h>
#include <lunaix/peripheral/ps2kbd.h>
+#include <lunaix/proc.h>
#include <lunaix/spike.h>
#include <lunaix/syscall.h>
#include <lunaix/syslog.h>
#include <lunaix/spike.h>
#include <lunaix/syscall.h>
#include <lunaix/syslog.h>
asm("jmp _lxinit_main");
}
asm("jmp _lxinit_main");
}
+ while (1) {
+ yield();
+ }
}
extern uint8_t __kernel_start; /* link/linker.ld */
}
extern uint8_t __kernel_start; /* link/linker.ld */
sched_ctx.procs_index = ptr;
sched_ctx.procs_index = ptr;
+ // 上下文切换相当的敏感!我们不希望任何的中断打乱栈的顺序……
+ cpu_disable_interrupt();
__DEFINE_LXSYSCALL(void, yield)
{
__DEFINE_LXSYSCALL(void, yield)
{
+pid_t
+_wait(pid_t wpid, int* status, int options);
+
__DEFINE_LXSYSCALL1(pid_t, wait, int*, status)
__DEFINE_LXSYSCALL1(pid_t, wait, int*, status)
+{
+ return _wait(-1, status, 0);
+}
+
+__DEFINE_LXSYSCALL3(pid_t, waitpid, pid_t, pid, int*, status, int, options)
+{
+ return _wait(pid, status, options);
+}
+
+pid_t
+_wait(pid_t wpid, int* status, int options)
{
pid_t cur = __current->pid;
{
pid_t cur = __current->pid;
struct proc_info *proc, *n;
if (llist_empty(&__current->children)) {
return -1;
struct proc_info *proc, *n;
if (llist_empty(&__current->children)) {
return -1;
repeat:
llist_for_each(proc, n, &__current->children, siblings)
{
repeat:
llist_for_each(proc, n, &__current->children, siblings)
{
- if (proc->state == PROC_TERMNAT) {
- goto done;
+ if (!~wpid || proc->pid == wpid) {
+ if (proc->state == PROC_TERMNAT && !options) {
+ status_flags |= PROCTERM;
+ goto done;
+ }
+ if (proc->state == PROC_STOPPED && (options & WUNTRACED)) {
+ status_flags |= PROCSTOP;
+ goto done;
+ }
- // FIXME: 除了循环,也许有更高效的办法……
- // (在这里进行schedule,需要重写context switch!)
+ if ((options & WNOHANG)) {
+ return 0;
+ }
+ // 放弃当前的运行机会
+ sched_yield();
- *status = proc->exit_code;
+ *status = (proc->exit_code & 0xffff) | status_flags;
return destroy_process(proc->pid);
}
return destroy_process(proc->pid);
}
/**
* @file timer.c
* @author Lunaixsky
/**
* @file timer.c
* @author Lunaixsky
- * @brief A simple timer implementation based on APIC with adjustable frequency and subscribable "timerlets"
+ * @brief A simple timer implementation based on APIC with adjustable frequency
+ * and subscribable "timerlets"
* @version 0.1
* @date 2022-03-12
* @version 0.1
* @date 2022-03-12
* @copyright Copyright (c) 2022
* @copyright Copyright (c) 2022
*/
#include <arch/x86/interrupts.h>
#include <hal/apic.h>
#include <hal/rtc.h>
#include <lunaix/mm/kalloc.h>
*/
#include <arch/x86/interrupts.h>
#include <hal/apic.h>
#include <hal/rtc.h>
#include <lunaix/mm/kalloc.h>
+#include <lunaix/sched.h>
#include <lunaix/spike.h>
#include <lunaix/syslog.h>
#include <lunaix/timer.h>
#include <lunaix/spike.h>
#include <lunaix/syslog.h>
#include <lunaix/timer.h>
-#include <lunaix/sched.h>
#define LVT_ENTRY_TIMER(vector, mode) (LVT_DELIVERY_FIXED | mode | vector)
#define LVT_ENTRY_TIMER(vector, mode) (LVT_DELIVERY_FIXED | mode | vector)
LOG_MODULE("TIMER");
static void
LOG_MODULE("TIMER");
static void
timer_ctx->active_timers =
(struct lx_timer*)lxmalloc(sizeof(struct lx_timer));
llist_init_head(timer_ctx->active_timers);
timer_ctx->active_timers =
(struct lx_timer*)lxmalloc(sizeof(struct lx_timer));
llist_init_head(timer_ctx->active_timers);
Timer calibration process - measure the APIC timer base frequency
step 1: setup a temporary isr for RTC timer which trigger at each tick
Timer calibration process - measure the APIC timer base frequency
step 1: setup a temporary isr for RTC timer which trigger at each tick
- (1024Hz)
- step 2: setup a temporary isr for #APIC_TIMER_IV
- step 3: setup the divider, APIC_TIMER_DCR
- step 4: Startup RTC timer
- step 5: Write a large value, v, to APIC_TIMER_ICR to start APIC timer (this must be
- followed immediately after step 4)
- step 6: issue a write to EOI and clean up.
+ (1024Hz)
+ step 2: setup a temporary isr for #APIC_TIMER_IV
+ step 3: setup the divider, APIC_TIMER_DCR
+ step 4: Startup RTC timer
+ step 5: Write a large value, v, to APIC_TIMER_ICR to start APIC timer
+ (this must be followed immediately after step 4) step 6: issue a write to
+ EOI and clean up.
When the APIC ICR counting down to 0 #APIC_TIMER_IV triggered, save the
rtc timer's counter, k, and disable RTC timer immediately (although the
When the APIC ICR counting down to 0 #APIC_TIMER_IV triggered, save the
rtc timer's counter, k, and disable RTC timer immediately (although the
- #ifdef __LUNAIXOS_DEBUG__
+#ifdef __LUNAIXOS_DEBUG__
if (frequency < 1000) {
kprintf(KWARN "Frequency too low. Millisecond timer might be dodgy.");
}
if (frequency < 1000) {
kprintf(KWARN "Frequency too low. Millisecond timer might be dodgy.");
}
timer_ctx->base_frequency = 0;
rtc_counter = 0;
timer_ctx->base_frequency = 0;
rtc_counter = 0;
wait_until(apic_timer_done);
wait_until(apic_timer_done);
assert_msg(timer_ctx->base_frequency, "Fail to initialize timer (NOFREQ)");
kprintf(KINFO "Base frequency: %u Hz\n", timer_ctx->base_frequency);
assert_msg(timer_ctx->base_frequency, "Fail to initialize timer (NOFREQ)");
kprintf(KINFO "Base frequency: %u Hz\n", timer_ctx->base_frequency);
-timer_run_second(uint32_t second, void (*callback)(void*), void* payload, uint8_t flags)
+timer_run_second(uint32_t second,
+ void (*callback)(void*),
+ void* payload,
+ uint8_t flags)
- return timer_run(second * timer_ctx->running_frequency, callback, payload, flags);
+ return timer_run(
+ second * timer_ctx->running_frequency, callback, payload, flags);
-timer_run_ms(uint32_t millisecond, void (*callback)(void*), void* payload, uint8_t flags)
+timer_run_ms(uint32_t millisecond,
+ void (*callback)(void*),
+ void* payload,
+ uint8_t flags)
- return timer_run(timer_ctx->running_frequency / 1000 * millisecond, callback, payload, flags);
+ return timer_run(timer_ctx->running_frequency / 1000 * millisecond,
+ callback,
+ payload,
+ flags);
}
struct lx_timer*
timer_run(ticks_t ticks, void (*callback)(void*), void* payload, uint8_t flags)
{
}
struct lx_timer*
timer_run(ticks_t ticks, void (*callback)(void*), void* payload, uint8_t flags)
{
- struct lx_timer* timer = (struct lx_timer*)lxmalloc(sizeof(struct lx_timer));
+ struct lx_timer* timer =
+ (struct lx_timer*)lxmalloc(sizeof(struct lx_timer));
- if (!timer) return NULL;
+ if (!timer)
+ return NULL;
timer->callback = callback;
timer->counter = ticks;
timer->callback = callback;
timer->counter = ticks;
llist_for_each(pos, n, &timer_list_head->link, link)
{
llist_for_each(pos, n, &timer_list_head->link, link)
{
- if (!pos->counter) {
- llist_delete(&pos->link);
- lxfree(pos);
- continue;
- }
-
if (--(pos->counter)) {
continue;
}
if (--(pos->counter)) {
continue;
}
if ((pos->flags & TIMER_MODE_PERIODIC)) {
pos->counter = pos->deadline;
if ((pos->flags & TIMER_MODE_PERIODIC)) {
pos->counter = pos->deadline;
+ } else {
+ llist_delete(&pos->link);
+ lxfree(pos);
sched_ticks_counter++;
if (sched_ticks_counter >= sched_ticks) {
sched_ticks_counter++;
if (sched_ticks_counter >= sched_ticks) {
+void
+sched_yield()
+{
+ sched_ticks_counter = sched_ticks;
+}
+
static void
temp_intr_routine_rtc_tick(const isr_param* param)
{
static void
temp_intr_routine_rtc_tick(const isr_param* param)
{
-struct lx_timer_context*
-timer_context() {
+struct lx_timer_context*
+timer_context()
+{
return timer_ctx;
}
\ No newline at end of file
return timer_ctx;
}
\ No newline at end of file