mirror of
https://github.com/hermitcore/libhermit.git
synced 2025-03-09 00:00:03 +01:00
enable the support of dynamic ticks
- a dynamic oneshoot timer is used to wakeup the system instead of a periodic timer
This commit is contained in:
parent
088b496baf
commit
cacd070d24
14 changed files with 142 additions and 114 deletions
|
@ -151,6 +151,7 @@ include/hermit/config.inc: include/hermit/config.h
|
|||
@awk '/^#define MAX_CORES/{ print "%define MAX_CORES", $$3 }' include/hermit/config.h >> include/hermit/config.inc
|
||||
@awk '/^#define KERNEL_STACK_SIZE/{ print "%define KERNEL_STACK_SIZE", $$3 }' include/hermit/config.h >> include/hermit/config.inc
|
||||
@awk '/^#define VIDEO_MEM_ADDR/{ print "%define VIDEO_MEM_ADDR", $$3 }' include/hermit/config.h >> include/hermit/config.inc
|
||||
@awk '/^#define DYNAMIC_TICKS/{ print "%define DYNAMIC_TICKS", $$3 }' include/hermit/config.h >> include/hermit/config.inc
|
||||
|
||||
%.o : %.asm include/hermit/config.inc
|
||||
@echo [ASM] $@
|
||||
|
|
|
@ -6,5 +6,4 @@ TODO list
|
|||
* prioririty handling in the Pthread library is still missing
|
||||
* use gs register to accelerate the access to newlib's reentrant structure
|
||||
* revise TLB shoot down
|
||||
* revise and check tickless support (the tickless support is currently not tested)
|
||||
* revise of the mmnif driver
|
||||
|
|
|
@ -55,9 +55,9 @@ extern "C" {
|
|||
/// LVT Timer Register
|
||||
#define APIC_LVT_T 0x0320
|
||||
/// LVT Thermal Sensor Register
|
||||
#define APIC_LVT_TSR 0x0330
|
||||
#define APIC_LVT_TSR 0x0330
|
||||
/// LVT Performance Monitoring Counters Register
|
||||
#define APIC_LVT_PMC 0x0340
|
||||
#define APIC_LVT_PMC 0x0340
|
||||
/// LVT LINT0 Register
|
||||
#define APIC_LINT0 0x0350
|
||||
/// LVT LINT1 Register
|
||||
|
@ -168,29 +168,29 @@ typedef struct {
|
|||
struct {
|
||||
uint32_t vector : 8,
|
||||
delivery_mode : 3, /* 000: FIXED
|
||||
* 001: lowest prio
|
||||
* 111: ExtINT
|
||||
*/
|
||||
* 001: lowest prio
|
||||
* 111: ExtINT
|
||||
*/
|
||||
dest_mode : 1, /* 0: physical, 1: logical */
|
||||
delivery_status : 1,
|
||||
delivery_status : 1,
|
||||
polarity : 1,
|
||||
irr : 1,
|
||||
irr : 1,
|
||||
trigger : 1, /* 0: edge, 1: level */
|
||||
mask : 1, /* 0: enabled, 1: disabled */
|
||||
__reserved_2 : 15;
|
||||
__reserved_2 : 15;
|
||||
} bitfield;
|
||||
uint32_t whole;
|
||||
} lower;
|
||||
union {
|
||||
struct {
|
||||
uint32_t __reserved_1 : 24,
|
||||
physical_dest : 4,
|
||||
__reserved_2 : 4;
|
||||
physical_dest : 4,
|
||||
__reserved_2 : 4;
|
||||
} physical;
|
||||
|
||||
struct {
|
||||
uint32_t __reserved_1 : 24,
|
||||
logical_dest : 8;
|
||||
logical_dest : 8;
|
||||
} logical;
|
||||
uint32_t upper;
|
||||
} dest;
|
||||
|
@ -203,6 +203,7 @@ int apic_calibration(void);
|
|||
int apic_is_enabled(void);
|
||||
int apic_enable_timer(void);
|
||||
int apic_disable_timer(void);
|
||||
int apic_timer_deadline(uint32_t);
|
||||
int apic_send_ipi(uint64_t dest, uint8_t irq);
|
||||
int ioapic_inton(uint8_t irq, uint8_t apicid);
|
||||
int ioapic_intoff(uint8_t irq, uint8_t apicid);
|
||||
|
|
|
@ -73,17 +73,11 @@ int irq_uninstall_handler(unsigned int irq);
|
|||
*/
|
||||
int irq_init(void);
|
||||
|
||||
/** @brief Disable the timer interrupt
|
||||
/** @brief Switch from a fix to a dynamic timer period
|
||||
*
|
||||
* @return 0 on success
|
||||
*/
|
||||
int disable_timer_irq(void);
|
||||
|
||||
/** @brief Enable the timer interrupt
|
||||
*
|
||||
* @return 0 on success
|
||||
*/
|
||||
int enable_timer_irq(void);
|
||||
int enable_dynticks(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -622,11 +622,7 @@ static inline size_t lsb(size_t i)
|
|||
/// The PAUSE instruction provides a hint to the processor that the code sequence is a spin-wait loop.
|
||||
#define PAUSE asm volatile ("pause")
|
||||
/// The HALT instruction stops the processor until the next interrupt arrives
|
||||
#ifndef CONFIG_TICKLESS
|
||||
#define HALT asm volatile ("hlt")
|
||||
#else
|
||||
#define HALT asm volatile("pause")
|
||||
#endif
|
||||
|
||||
/** @brief Init several subsystems
|
||||
*
|
||||
|
|
|
@ -48,9 +48,6 @@
|
|||
*/
|
||||
extern const void kernel_start;
|
||||
|
||||
extern void start_tickless(void);
|
||||
extern void end_tickless(void);
|
||||
|
||||
#define IOAPIC_ADDR ((size_t) &kernel_start - 2*PAGE_SIZE)
|
||||
#define LAPIC_ADDR ((size_t) &kernel_start - 1*PAGE_SIZE)
|
||||
#define MAX_APIC_CORES 256
|
||||
|
@ -221,13 +218,28 @@ static inline uint32_t apic_lvt_entries(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int apic_timer_deadline(uint32_t t)
|
||||
{
|
||||
if (BUILTIN_EXPECT(apic_is_enabled() && icr, 1)) {
|
||||
//kprintf("timer oneshot %ld\n", t);
|
||||
|
||||
// create one shot interrup
|
||||
lapic_write(APIC_DCR, 0xB); // set it to 1 clock increments
|
||||
lapic_write(APIC_LVT_T, 0x7B); // connects the timer to 123 and enables it
|
||||
lapic_write(APIC_ICR, icr*t);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int apic_disable_timer(void)
|
||||
{
|
||||
if (BUILTIN_EXPECT(!apic_is_enabled(), 0))
|
||||
return -EINVAL;
|
||||
|
||||
lapic_write(APIC_LVT_T, 0x10000); // disable timer interrupt
|
||||
start_tickless();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -238,7 +250,6 @@ int apic_enable_timer(void)
|
|||
lapic_write(APIC_DCR, 0xB); // set it to 1 clock increments
|
||||
lapic_write(APIC_LVT_T, 0x2007B); // connects the timer to 123 and enables it
|
||||
lapic_write(APIC_ICR, icr);
|
||||
end_tickless();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -54,7 +54,6 @@ align 4
|
|||
global boot_processor
|
||||
global cpu_online
|
||||
global possible_cpus
|
||||
global timer_ticks
|
||||
global current_boot_id
|
||||
global isle
|
||||
global possible_isles
|
||||
|
@ -71,7 +70,7 @@ align 4
|
|||
boot_processor dd -1
|
||||
cpu_online dd 0
|
||||
possible_cpus dd 0
|
||||
timer_ticks dq 0
|
||||
dq 0 ; reserved for future extensions
|
||||
current_boot_id dd 0
|
||||
isle dd -1
|
||||
image_size dq 0
|
||||
|
@ -362,12 +361,19 @@ apic_svr:
|
|||
push byte 127
|
||||
jmp common_stub
|
||||
|
||||
global wakeup
|
||||
align 16
|
||||
wakeup:
|
||||
push byte 0 ; pseudo error code
|
||||
push byte 121
|
||||
jmp common_stub
|
||||
|
||||
global mmnif_irq
|
||||
align 16
|
||||
mmnif_irq:
|
||||
push byte 0 ; pseudo error code
|
||||
push byte 122
|
||||
jmp common_stub
|
||||
push byte 0 ; pseudo error code
|
||||
push byte 122
|
||||
jmp common_stub
|
||||
|
||||
extern irq_handler
|
||||
extern get_current_stack
|
||||
|
@ -413,8 +419,10 @@ isrsyscall:
|
|||
call [rax*8+syscall_table]
|
||||
push rax ; result, which we have to return
|
||||
|
||||
%ifdef DYNAMIC_TICKS
|
||||
extern check_ticks
|
||||
call check_ticks
|
||||
%endif
|
||||
|
||||
extern check_timers
|
||||
call check_timers
|
||||
|
|
|
@ -43,9 +43,9 @@
|
|||
#include <asm/io.h>
|
||||
#include <asm/apic.h>
|
||||
|
||||
/*
|
||||
/*
|
||||
* These are our own ISRs that point to our special IRQ handler
|
||||
* instead of the regular 'fault_handler' function
|
||||
* instead of the regular 'fault_handler' function
|
||||
*/
|
||||
extern void irq0(void);
|
||||
extern void irq1(void);
|
||||
|
@ -78,6 +78,7 @@ extern void apic_lint0(void);
|
|||
extern void apic_lint1(void);
|
||||
extern void apic_error(void);
|
||||
extern void apic_svr(void);
|
||||
extern void wakeup(void);
|
||||
extern void mmnif_irq(void);
|
||||
|
||||
#define MAX_HANDLERS 256
|
||||
|
@ -120,7 +121,7 @@ int irq_uninstall_handler(unsigned int irq)
|
|||
* actually happening. We send commands to the Programmable
|
||||
* Interrupt Controller (PICs - also called the 8259's) in
|
||||
* order to make IRQ0 to 15 be remapped to IDT entries 32 to
|
||||
* 47
|
||||
* 47
|
||||
*/
|
||||
static int irq_remap(void)
|
||||
{
|
||||
|
@ -138,7 +139,7 @@ static int irq_remap(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int disable_timer_irq(void)
|
||||
int enable_dynticks(void)
|
||||
{
|
||||
if (BUILTIN_EXPECT(apic_is_enabled(), 1))
|
||||
return apic_disable_timer();
|
||||
|
@ -146,6 +147,7 @@ int disable_timer_irq(void)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int enable_timer_irq(void)
|
||||
{
|
||||
if (BUILTIN_EXPECT(apic_is_enabled(), 1))
|
||||
|
@ -153,6 +155,7 @@ int enable_timer_irq(void)
|
|||
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @brief Remap IRQs and install ISRs in IDT
|
||||
*
|
||||
|
@ -218,6 +221,8 @@ static int irq_install(void)
|
|||
idt_set_gate(113, (size_t)irq81, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0);
|
||||
|
||||
idt_set_gate(121, (size_t)wakeup, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0);
|
||||
idt_set_gate(122, (size_t)mmnif_irq, KERNEL_CODE_SELECTOR,
|
||||
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP, 0);
|
||||
|
||||
|
@ -250,10 +255,10 @@ int irq_init(void)
|
|||
* Each of the IRQ ISRs point to this function, rather than
|
||||
* the 'fault_handler' in 'isrs.c'. The IRQ Controllers need
|
||||
* to be told when you are done servicing them, so you need
|
||||
* to send them an "End of Interrupt" command. If we use the PIC
|
||||
* instead of the APIC, we have two 8259 chips: The first one
|
||||
* exists at 0x20, the second one exists at 0xA0. If the second
|
||||
* controller (an IRQ from 8 to 15) gets an interrupt, you need to
|
||||
* to send them an "End of Interrupt" command. If we use the PIC
|
||||
* instead of the APIC, we have two 8259 chips: The first one
|
||||
* exists at 0x20, the second one exists at 0xA0. If the second
|
||||
* controller (an IRQ from 8 to 15) gets an interrupt, you need to
|
||||
* acknowledge the interrupt at BOTH controllers, otherwise, you
|
||||
* only send an EOI command to the first controller. If you don't send
|
||||
* an EOI, it won't raise any more IRQs.
|
||||
|
@ -270,10 +275,10 @@ size_t** irq_handler(struct state *s)
|
|||
|
||||
check_workqueues_in_irqhandler(s->int_no);
|
||||
|
||||
/*
|
||||
/*
|
||||
* Find out if we have a custom handler to run for this
|
||||
* IRQ and then finally, run it
|
||||
*/
|
||||
* IRQ and then finally, run it
|
||||
*/
|
||||
if (BUILTIN_EXPECT(s->int_no < MAX_HANDLERS, 1)) {
|
||||
handler = irq_routines[s->int_no];
|
||||
if (handler)
|
||||
|
|
|
@ -36,55 +36,28 @@
|
|||
#include <asm/irqflags.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
/*
|
||||
/*
|
||||
* This will keep track of how many ticks the system
|
||||
* has been running for
|
||||
* has been running for
|
||||
*/
|
||||
extern volatile uint64_t timer_ticks;
|
||||
DEFINE_PER_CORE(uint64_t, timer_ticks, 0);
|
||||
extern uint32_t cpu_freq;
|
||||
extern int32_t boot_processor;
|
||||
|
||||
static int8_t use_tickless = 0;
|
||||
static uint64_t last_rdtsc = 0;
|
||||
|
||||
#if MAX_CORES > 1
|
||||
static spinlock_irqsave_t ticks_lock = SPINLOCK_IRQSAVE_INIT;
|
||||
#endif
|
||||
|
||||
void start_tickless(void)
|
||||
{
|
||||
use_tickless = 1;
|
||||
if (has_rdtscp())
|
||||
last_rdtsc = rdtscp(NULL);
|
||||
else
|
||||
last_rdtsc = rdtsc();
|
||||
rmb();
|
||||
}
|
||||
|
||||
void end_tickless(void)
|
||||
{
|
||||
use_tickless = 0;
|
||||
last_rdtsc = 0;
|
||||
}
|
||||
#ifdef DYNAMIC_TICKS
|
||||
DEFINE_PER_CORE(uint64_t, last_rdtsc, 0);
|
||||
|
||||
void check_ticks(void)
|
||||
{
|
||||
if (!use_tickless)
|
||||
return;
|
||||
|
||||
#if MAX_CORES > 1
|
||||
spinlock_irqsave_lock(&ticks_lock);
|
||||
#endif
|
||||
|
||||
if (has_rdtscp()){
|
||||
uint64_t curr_rdtsc = rdtscp(NULL);
|
||||
uint64_t diff;
|
||||
|
||||
rmb();
|
||||
diff = ((curr_rdtsc - last_rdtsc) * (uint64_t)TIMER_FREQ) / (1000000ULL*(uint64_t)get_cpu_frequency());
|
||||
diff = ((curr_rdtsc - per_core(last_rdtsc)) * (uint64_t)TIMER_FREQ) / (1000000ULL*(uint64_t)get_cpu_frequency());
|
||||
if (diff > 0) {
|
||||
timer_ticks += diff;
|
||||
last_rdtsc = curr_rdtsc;
|
||||
set_per_core(timer_ticks, per_core(timer_ticks) + diff);
|
||||
set_per_core(last_rdtsc, curr_rdtsc);
|
||||
rmb();
|
||||
}
|
||||
} else {
|
||||
|
@ -92,37 +65,31 @@ void check_ticks(void)
|
|||
uint64_t diff;
|
||||
|
||||
rmb();
|
||||
diff = ((curr_rdtsc - last_rdtsc) * (uint64_t)TIMER_FREQ) / (1000000ULL*(uint64_t)get_cpu_frequency());
|
||||
diff = ((curr_rdtsc - per_core(last_rdtsc)) * (uint64_t)TIMER_FREQ) / (1000000ULL*(uint64_t)get_cpu_frequency());
|
||||
if (diff > 0) {
|
||||
timer_ticks += diff;
|
||||
last_rdtsc = curr_rdtsc;
|
||||
set_per_core(timer_ticks, per_core(timer_ticks) + diff);
|
||||
set_per_core(last_rdtsc, curr_rdtsc);
|
||||
rmb();
|
||||
}
|
||||
}
|
||||
|
||||
#if MAX_CORES > 1
|
||||
spinlock_irqsave_unlock(&ticks_lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
uint64_t get_clock_tick(void)
|
||||
static void wakeup_handler(struct state *s)
|
||||
{
|
||||
return timer_ticks;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* Handles the timer. In this case, it's very simple: We
|
||||
* increment the 'timer_ticks' variable every time the
|
||||
* timer fires.
|
||||
* timer fires.
|
||||
*/
|
||||
static void timer_handler(struct state *s)
|
||||
{
|
||||
#if MAX_CORES > 1
|
||||
if (CORE_ID == boot_processor)
|
||||
#ifndef DYNAMIC_TICKS
|
||||
/* Increment our 'tick counter' */
|
||||
set_per_core(timer_ticks, per_core(timer_ticks)+1);
|
||||
#endif
|
||||
/* Increment our 'tick counter' */
|
||||
timer_ticks++;
|
||||
|
||||
#if 0
|
||||
/*
|
||||
|
@ -138,7 +105,7 @@ static void timer_handler(struct state *s)
|
|||
int timer_wait(unsigned int ticks)
|
||||
{
|
||||
uint64_t eticks = timer_ticks + ticks;
|
||||
|
||||
|
||||
task_t* curr_task = per_core(current_task);
|
||||
|
||||
if (curr_task->status == TASK_IDLE)
|
||||
|
@ -173,18 +140,26 @@ int timer_wait(unsigned int ticks)
|
|||
while(rdtsc() - start < 1000000) ; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
/*
|
||||
* Sets up the system clock by installing the timer handler
|
||||
* into IRQ0
|
||||
* into IRQ0
|
||||
*/
|
||||
int timer_init(void)
|
||||
{
|
||||
/*
|
||||
/*
|
||||
* Installs 'timer_handler' for the PIC and APIC timer,
|
||||
* only one handler will be later used.
|
||||
*/
|
||||
irq_install_handler(32, timer_handler);
|
||||
irq_install_handler(123, timer_handler);
|
||||
irq_install_handler(121, wakeup_handler);
|
||||
|
||||
#ifdef DYNAMIC_TICKS
|
||||
if (has_rdtscp())
|
||||
last_rdtsc = rdtscp(NULL);
|
||||
else
|
||||
last_rdtsc = rdtsc();
|
||||
#endif
|
||||
|
||||
if (cpu_freq) // do we need to configure the timer?
|
||||
return 0;
|
||||
|
|
|
@ -48,12 +48,11 @@ extern "C" {
|
|||
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
|
||||
//#define CONFIG_TICKLESS
|
||||
#define DYNAMIC_TICKS
|
||||
|
||||
#define BUILTIN_EXPECT(exp, b) __builtin_expect((exp), (b))
|
||||
//#define BUILTIN_EXPECT(exp, b) (exp)
|
||||
#define NORETURN __attribute__((noreturn))
|
||||
#define STDCALL __attribute__((stdcall))
|
||||
|
||||
#define HAVE_ARCH_MEMSET
|
||||
#define HAVE_ARCH_MEMCPY
|
||||
|
|
|
@ -230,13 +230,17 @@ void NORETURN leave_kernel_task(void);
|
|||
* */
|
||||
void check_scheduling(void);
|
||||
|
||||
#ifdef DYNAMIC_TICKS
|
||||
/** @brief check, if the tick counter has to be updated
|
||||
* */
|
||||
void check_ticks(void);
|
||||
#endif
|
||||
|
||||
static inline void check_workqueues_in_irqhandler(int irq)
|
||||
{
|
||||
#ifdef DYNAMIC_TICKS
|
||||
check_ticks();
|
||||
#endif
|
||||
check_timers();
|
||||
|
||||
if (irq < 0)
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
/**
|
||||
* @author Stefan Lankes
|
||||
* @file include/hermit/time.h
|
||||
* @brief Time related functions
|
||||
|
@ -34,6 +34,8 @@
|
|||
#ifndef __TIME_H__
|
||||
#define __TIME_H__
|
||||
|
||||
#include <asm/apic.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -47,7 +49,7 @@ struct tms {
|
|||
clock_t tms_cstime;
|
||||
};
|
||||
|
||||
/** @brief Initialize Timer interrupts
|
||||
/** @brief Initialize Timer interrupts
|
||||
*
|
||||
* This procedure installs IRQ handlers for timer interrupts
|
||||
*/
|
||||
|
@ -61,10 +63,15 @@ int timer_init(void);
|
|||
*/
|
||||
int timer_wait(unsigned int ticks);
|
||||
|
||||
DECLARE_PER_CORE(uint64_t, timer_ticks);
|
||||
|
||||
/** @brief Returns the current number of ticks.
|
||||
* @return Current number of ticks
|
||||
*/
|
||||
uint64_t get_clock_tick(void);
|
||||
static inline uint64_t get_clock_tick(void)
|
||||
{
|
||||
return per_core(timer_ticks);
|
||||
}
|
||||
|
||||
/** @brief sleep some seconds
|
||||
*
|
||||
|
@ -74,6 +81,8 @@ uint64_t get_clock_tick(void);
|
|||
*/
|
||||
static inline void sleep(unsigned int sec) { timer_wait(sec*TIMER_FREQ); }
|
||||
|
||||
static inline int timer_deadline(uint32_t t) { return apic_timer_deadline(t); }
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -195,8 +195,8 @@ int smp_main(void)
|
|||
{
|
||||
int32_t cpu = atomic_int32_inc(&cpu_online);
|
||||
|
||||
#ifdef CONFIG_TICKLESS
|
||||
disable_timer_irq();
|
||||
#ifdef DYNAMIC_TICKS
|
||||
enable_dynticks();
|
||||
#endif
|
||||
|
||||
/* wait for the other cpus */
|
||||
|
@ -324,8 +324,8 @@ int main(void)
|
|||
list_fs(fs_root, 1);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TICKLESS
|
||||
disable_timer_irq();
|
||||
#ifdef DYNAMIC_TICKS
|
||||
enable_dynticks();
|
||||
#endif
|
||||
|
||||
/* wait for the other cpus */
|
||||
|
|
|
@ -79,7 +79,11 @@ void check_scheduling(void)
|
|||
|
||||
uint32_t get_highest_priority(void)
|
||||
{
|
||||
return msb(readyqueues[CORE_ID].prio_bitmap);
|
||||
uint32_t prio = msb(readyqueues[CORE_ID].prio_bitmap);
|
||||
|
||||
if (prio > MAX_PRIO)
|
||||
return 0;
|
||||
return prio;
|
||||
}
|
||||
|
||||
int multitasking_init(void)
|
||||
|
@ -350,6 +354,9 @@ out:
|
|||
if (ret)
|
||||
kfree(stack);
|
||||
|
||||
if (core_id != CORE_ID)
|
||||
apic_send_ipi(core_id, 121);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -448,6 +455,9 @@ out:
|
|||
kfree(counter);
|
||||
}
|
||||
|
||||
if (core_id != CORE_ID)
|
||||
apic_send_ipi(core_id, 121);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -527,6 +537,12 @@ int wakeup_task(tid_t id)
|
|||
readyqueues[core_id].queue[prio-1].last = task;
|
||||
}
|
||||
spinlock_irqsave_unlock(&readyqueues[core_id].lock);
|
||||
|
||||
#ifdef DYNAMIC_TICKS
|
||||
// send IPI to be sure that the scheuler recognize the new task
|
||||
if (core_id != CORE_ID)
|
||||
apic_send_ipi(core_id, 121);
|
||||
#endif
|
||||
}
|
||||
|
||||
irq_nested_enable(flags);
|
||||
|
@ -636,6 +652,9 @@ int set_timer(uint64_t deadline)
|
|||
if (!tmp) {
|
||||
readyqueues[core_id].timers.first = readyqueues[core_id].timers.last = curr_task;
|
||||
curr_task->prev = curr_task->next = NULL;
|
||||
#ifdef DYNAMIC_TICKS
|
||||
timer_deadline(deadline-get_clock_tick());
|
||||
#endif
|
||||
} else {
|
||||
while(tmp && (deadline >= tmp->timeout))
|
||||
tmp = tmp->next;
|
||||
|
@ -655,8 +674,12 @@ int set_timer(uint64_t deadline)
|
|||
tmp->prev = curr_task;
|
||||
if (curr_task->prev)
|
||||
curr_task->prev->next = curr_task;
|
||||
if (readyqueues[core_id].timers.first == tmp)
|
||||
if (readyqueues[core_id].timers.first == tmp) {
|
||||
readyqueues[core_id].timers.first = curr_task;
|
||||
#ifdef DYNAMIC_TICKS
|
||||
timer_deadline(deadline-get_clock_tick());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -684,10 +707,13 @@ void check_timers(void)
|
|||
|
||||
// remove timer from queue
|
||||
readyqueues[core_id].timers.first = readyqueues[core_id].timers.first->next;
|
||||
if (readyqueues[core_id].timers.first)
|
||||
if (readyqueues[core_id].timers.first) {
|
||||
readyqueues[core_id].timers.first->prev = NULL;
|
||||
else
|
||||
readyqueues[core_id].timers.last = NULL;
|
||||
#ifdef DYNAMIC_TICKS
|
||||
if (readyqueues[core_id].timers.first->timeout > get_clock_tick())
|
||||
timer_deadline(readyqueues[core_id].timers.first->timeout-current_tick);
|
||||
#endif
|
||||
} else readyqueues[core_id].timers.last = NULL;
|
||||
task->flags &= ~TASK_TIMER;
|
||||
|
||||
// wakeup task
|
||||
|
|
Loading…
Add table
Reference in a new issue