рдореИрдВ рдПрдХ рдЦрд┐рд▓реМрдирд╛ рдУрдПрд╕ рд▓рд┐рдЦ рд░рд╣рд╛ рд╣реВрдВ (рдиреАрдВрдж рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ)


рдПрдХ рдЦрд┐рд▓реМрдирд╛ рдУрдПрд╕ рдкрд░ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдкрд┐рдд рдмреНрд▓реЙрдЧ рдХреЗ рд▓рд┐рдП рдПрдХ рдФрд░ рдкреЛрд╕реНрдЯред рдкрд┐рдЫрд▓реА рдмрд╛рд░ рдореИрдВрдиреЗ рдПрдХ рд╕рд╛рдзрд╛рд░рдг AHCI (SATA) рдбреНрд░рд╛рдЗрд╡рд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд▓рд┐рдЦрд╛ рдерд╛ред рдЗрд╕ рджрд┐рд╢рд╛ рдореЗрдВ рдЖрдЧреЗ рдмрдврд╝рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдореИрдВрдиреЗ рдбреНрд░рд╛рдЗрд╡рд░ рдмреБрдирд┐рдпрд╛рджреА рдврд╛рдВрдЪреЗ рдХреЛ рд░реЗрдЦрд╛рдВрдХрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛: рд╕рд╛рдорд╛рдиреНрдп рдбреНрд░рд╛рдЗрд╡рд░ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ + рдЕрдкрдбреЗрдЯреЗрдб рд╕реНрдЯреЛрд░реЗрдЬ рдбрд┐рд╡рд╛рдЗрд╕ рдбреНрд░рд╛рдЗрд╡рд░ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ред рдЗрди рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЗ рдирд┐рд░реНрдорд╛рдг рд╕реЗ рдПрдХ рд╕рдорд╕реНрдпрд╛ рд╕рд╛рдордиреЗ рдЖрдИ, рдЬрд┐рд╕ рдкрд░ рдореИрдВрдиреЗ рдкрд╣рд▓реЗ рдзреНрдпрд╛рди рдирд╣реАрдВ рджрд┐рдпрд╛ рдерд╛ - рдкреЛрд░реНрдЯреЗрдмрд┐рд▓рд┐рдЯреА рдХреА рд╕рдорд╕реНрдпрд╛ред

рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо-рдЗрдВрдбрд┐рдкреЗрдВрдбреЗрдВрдЯ рдХреЛрдб (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЕрдзрд┐рдХрд╛рдВрд╢ рд╢реЗрдбреНрдпреВрд▓рд░, рд╕рд╣рд╛рдпрдХ рдХреЛрдб рдЬреИрд╕реЗ kprintf, ...) рдХреЛрдб рдХреЗ рд╕рд╛рде рдорд┐рд▓рд╛рддрд╛ рд╣реИ рдЬреЛ рдХреЗрд╡рд▓ x86_64 (рд╕рд┐рд╕реНрдЯрдо рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ рдЯреЗрдмрд▓, APIC, рдЗрдВрдЯрд░рдкреНрдЯ, ...) рдХреЗ рд▓рд┐рдП рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐ рдореБрдЭреЗ рдбреНрд░рд╛рдЗрд╡рд░ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рддреИрдпрд╛рд░ рдХрд░рдиреЗ рд╕реЗ рдХреБрдЫ рднреА рдирд╣реАрдВ рд░реЛрдХ рд░рд╣рд╛ рдерд╛, рдЬреЛ рдХрд┐ x86_64 (рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдкреАрд╕реАрдЖрдИ рдкрддреЗ рдХреЗ рд╕рд╛рде рд╕реНрд╡рддрдВрддреНрд░ рд░реВрдк рд╕реЗ рд╕рдВрдЪрд╛рд▓рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП) рдХреЗ рд▓рд┐рдП рдХрд╕рдХрд░ рдмрд╛рдзреНрдп рдерд╛, рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рд╕реНрдкрд╖реНрдЯ рд╣реЛ рдЧрдпрд╛ рдХрд┐ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдХреЛрдб рдХреЛ рд╕рд╛рдорд╛рдиреНрдп рдкреЛрд░реНрдЯреЗрдмрд▓ рдХреЛрдб рд╕реЗ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рд╕реЗ рдЕрд▓рдЧ рдХрд┐рдП рдмрд┐рдирд╛, рдореИрдВ рдХреЗрд╡рд▓ рд╕реНрдерд┐рддрд┐ рдХреЛ рдмрдврд╝рд╛рдКрдВрдЧрд╛ред рдЗрд╕рд▓рд┐рдП, рдореИрдВрдиреЗ рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ (рд░реВрдЯ src /) рдХреЛрдб рдХреЛ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕реЗ рдЕрд▓рдЧ рдХрд░рдХреЗ, рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдХреЗ рд▓рд┐рдП (src / x86_64 /) рдореЗрдВ рдХреЛрдб рд╕реЗ рд░реВрдЯ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ред рдпрд╣ рдореИрдВ рдкрд┐рдЫрд▓реЗ рджреЛ рд╕рдкреНрддрд╛рд╣ рд╕реЗ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред

рдореИрдВ рдПрдХ рдЕрдиреБрд╕реВрдЪрдХ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреЛрдб рдкреГрдердХреНрдХрд░рдг рдХреЗ рддрдВрддреНрд░ рдХрд╛ рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ рд╡рд░реНрдгрди рдХрд░реВрдВрдЧрд╛ред Src / Schedule.h рдЕрдиреБрд╕реВрдЪрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдореЗрдВ (#include) рдПрдХ рд╡рд┐рд╢реЗрд╖ src / x86_64 / schedule.inc рдлрд╝рд╛рдЗрд▓ рд╢рд╛рдорд┐рд▓ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо-рдирд┐рд░реНрднрд░ рд╕реНрдерд┐рд░ рдЗрдирд▓рд╛рдЗрди рдлрд╝рдВрдХреНрд╢рдВрд╕ (рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдФрд░ рдЖрдВрддрд░рд┐рдХ рджреЛрдиреЛрдВ) рд╢рд╛рдорд┐рд▓ рд╣реИрдВред рд╕рднреА рдЖрдВрддрд░рд┐рдХ рд╡рд░реНрдг (рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдирд╣реАрдВ, рд▓реЗрдХрд┐рди рд╕реНрдерд┐рд░ рдирд╣реАрдВ рд╣реИрдВ) "__" рдЙрдкрд╕рд░реНрдЧ рдХреЗ рд╕рд╛рде рдЙрдкрд╕рд░реНрдЧ рдХрд┐рдП рдЧрдП рд╣реИрдВред рдореБрдЦреНрдп рдЕрдиреБрд╕реВрдЪрдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди src / Schedule.c рдореЗрдВ рд╣реИ, рдЕрд▓рдЧ рдЖрдВрддрд░рд┐рдХ рдХрд╛рд░реНрдп рдФрд░ рдХреЛрдбрд╛рдВрддрд░рдХ рдХреЛрдб src / x86_64 / schedule.c рдореЗрдВ рд╣реИрдВред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╢реЗрдбреНрдпреВрд▓рд░ рдХреЛрдб "рд╕реНрдкреНрд░реАрдб" рджреЛ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛рдУрдВ рдореЗрдВ рд╣реИред рдмреЗрд╢рдХ, рдпрд╣ рдЬрдЯрд┐рд▓рддрд╛ рдХреЗрд╡рд▓ рд╕рд╛рдорд╛рдиреНрдп рдорд╛рдорд▓реЗ рдХреЗ рд▓рд┐рдП рд╣реИ, рдЬрдмрдХрд┐ рдХрдИ рдореЙрдбреНрдпреВрд▓ рдПрдХ рд╕рд░рд▓реАрдХреГрдд рдпреЛрдЬрдирд╛ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдмрдирд╛рдП рдЧрдП рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, cpu_info (рддрд╛рд░реНрдХрд┐рдХ рдкреНрд░реЛрд╕реЗрд╕рд░ рдЬрд╛рдирдХрд╛рд░реА) рдХреЗ рд▓рд┐рдП, рд╣реЗрдбрд░ src / рдореЗрдВ рд╕реНрдерд┐рдд рд╣реИ, рдФрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди src / x86_64 / рдореЗрдВ рд╕реНрдерд┐рдд рд╣реИред рдпрд╛ рдПрдХ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо-рд╡рд┐рд╢рд┐рд╖реНрдЯ APIC рдкреВрд░реА рддрд░рд╣ рд╕реЗ src / x86_64 / рдореЗрдВ рд░рдЦрд╛ рдЧрдпрд╛ рд╣реИред

рдЕрдм рд╡рд╛рджрд╛ рдХрд┐рдпрд╛ рдиреАрдВрдж рд╕рдорд╛рд░реЛрд╣ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВред рдореНрдпреВрдЯреЗрдХреНрд╕ рдХреЗ рд╡рд┐рдкрд░реАрдд, рдиреАрдВрдж рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдЕрдиреБрд╕реВрдЪрдХ (рдпрджреНрдпрдкрд┐ рдиреНрдпреВрдирддрдо) рдХреЗ рдХреБрдЫ рд╕рдВрд╢реЛрдзрди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдереАред рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рднрд╛рдЧ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рднрд╛рдЧ ( src / schedule.h ) рдореЗрдВ рдЬреЛрдбрд╝реЗ рдЧрдП рдереЗ:

typedef void (*timer_proc)(uint64_t ticks); uint64_t get_ticks(void); timer_proc get_timer_proc(void); uint64_t get_timer_ticks(void); // is zeroed after triggering void set_timer_proc(timer_proc proc); // called within a timer interrupt void set_timer_ticks(uint64_t ticks); // not thread-safe 

рдпрд╛рдиреА рдЕрдм рд╢реЗрдбреНрдпреВрд▓рд░ рднреА рдПрдХ рдЯрд╛рдЗрдорд░ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИ: рдпрд╣ рдЯрд┐рдХ рдХрд╛рдЙрдВрдЯрд░ (рдЖрдВрддрд░рд┐рдХ рдЯрд╛рдЗрдорд░ рдЗрдВрдЯрд░рдкреНрдЯ) рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЬреИрд╕реЗ рд╣реА рдЯрд┐рдХрд░ рдХреА рд╕рдВрдЦреНрдпрд╛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╕рдВрдЦреНрдпрд╛ рддрдХ рдкрд╣реБрдВрдЪрддреА рд╣реИ, рд╣реИрдВрдбрд▓рд░ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рднреА рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рддрдВрддреНрд░ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ ( src / Schedule.c )ред

 static inline void handle_timer(int cpu) { if (cpu == get_bsp_cpu()) ticks++; if (timer_ticks[cpu] && timer_ticks[cpu] <= ticks) { uint64_t prev_ticks = timer_ticks[cpu]; timer_ticks[cpu] = 0; set_outer_spinlock(true); timer_proc_(prev_ticks); set_outer_spinlock(false); } } 

рдкреНрд░рддреНрдпреЗрдХ рдЯрд╛рдЗрдорд░ рд░реБрдХрд╛рд╡рдЯ рдкрд░ handle_timer рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕ рддрдереНрдп рдХреЗ рдмрд╛рд╡рдЬреВрдж рдХрд┐ рдЯрд┐рдХ рдХрд╛рдЙрдВрдЯрд░ рдХреЗрд╡рд▓ рдмреВрдЯрд╕реНрдЯреНрд░реИрдк рдкреНрд░реЛрд╕реЗрд╕рд░ рдХреЗ рд▓рд┐рдП рдмрдврд╝рд╛ рд╣реБрдЖ рд╣реИ, рдЯрд╛рдЗрдорд░ рдкреНрд░рддреНрдпреЗрдХ рддрд╛рд░реНрдХрд┐рдХ рдкреНрд░реЛрд╕реЗрд╕рд░ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рддрдВрддреНрд░ рд░реВрдк рд╕реЗ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред Set_outer_spinlock рдореЗрдВ рд╣реИрдВрдбрд▓рд░ рдХреЙрд▓ рдХреЛ рд▓рдкреЗрдЯрдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рддрд╛рдХрд┐ рд╣реИрдВрдбрд▓рд░ рдХреЗ рдЕрдВрджрд░ release_spinlock рдХреЙрд▓ рдЧрд▓рддреА рд╕реЗ STI рдирд┐рд░реНрджреЗрд╢ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рди рдХрд░реЗрдВ (рдпрд╣ рдордд рднреВрд▓реЛ рдХрд┐ рд╣рдо рдПрдХ рд░реБрдХрд╛рд╡рдЯ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рд╣реИрдВ)ред

рдЕрдм, рд╢реЗрдбреНрдпреВрд▓рд░ рдХреА рдЗрд╕ рдЙрдиреНрдирдд рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ, рд╣рдо рдиреАрдВрдж ( src / Sync.c ) рдХреЛ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

 struct sleep_node { struct sleep_node *next; thread_id thread; uint64_t ticks; }; static struct sleep_data { struct sleep_node *tail; struct mem_pool pool; struct spinlock lock; } sleeping[CONFIG_CPUS_MAX]; static void sleep_timer_proc(UNUSED uint64_t ticks) { struct sleep_data *slp = &sleeping[get_cpu()]; if (slp->tail) { struct sleep_node *node = slp->tail; slp->tail = slp->tail->next; if (slp->tail) set_timer_ticks(slp->tail->ticks); resume_thread(node->thread); free_block(&slp->pool, node); } } err_code sleep(uint64_t period) { struct sleep_data *slp = &sleeping[get_cpu()]; err_code err = ERR_NONE; acquire_spinlock(&slp->lock, 0); struct sleep_node *node = alloc_block(&slp->pool); if (node) { node->thread = get_thread(); node->ticks = get_ticks() + period / CONFIG_SCHEDULER_TICK_INTERVAL; if (!slp->tail || slp->tail->ticks > node->ticks) { // is first to wake up node->next = slp->tail, slp->tail = node; set_timer_ticks(node->ticks); } else { struct sleep_node *prev = slp->tail; while (prev->next && prev->next->ticks <= node->ticks) prev = prev->next; node->next = prev->next, prev->next = node; } pause_this_thread(&slp->lock); } else err = ERR_OUT_OF_MEMORY; if (err) release_spinlock(&slp->lock); return err; } 

рдЙрдкрд░реЛрдХреНрдд рдХреЛрдб рдХреЛ рдХреБрдЫ рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:

1. рд╕реНрд▓реАрдк_рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рддрд╛рд░реНрдХрд┐рдХ рдкреНрд░реЛрд╕реЗрд╕рд░ рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИред Sleep_node рдХреЗ рд▓рд┐рдП рдкреВрд▓ рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░реЛрд╕реЗрд╕рд░ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рддрдВрддреНрд░ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ mem_pool рдереНрд░реЗрдб рд╕реБрд░рдХреНрд╖рд┐рдд рдирд╣реАрдВ рд╣реИред

рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ рдореБрдЭреЗ рдореНрдпреВрдЯреЗрдХреНрд╕ рдХреЛрдб рдореЗрдВ рдЫрд┐рдкрд╛рдиреЗ рдХреА рдПрдХ рдЧрдВрднреАрд░ рдЧрд▓рддреА рд╣реИ: рд╕рднреА рдореНрдпреВрдЯреЗрдХреНрд╕ рдХреЗ рд▓рд┐рдП, рдореНрдпреВрдЯреЗрдХреНрд╕_рдиреЛрдб рдХреЗ рд▓рд┐рдП рдПрдХ рдПрдХрд▓ рдкреВрд▓ рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдореНрдпреВрдЯреЗрдХреНрд╕ рдХрд╛ рдЕрдкрдирд╛ рдкреВрд▓ рд╣реЛред рдореИрдВ рдирд┐рдХрдЯ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдЗрд╕реЗ рдареАрдХ рдХрд░рдиреЗ рдХреА рдпреЛрдЬрдирд╛ рдмрдирд╛ рд░рд╣рд╛ рд╣реВрдВред

2. рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдХреЛрдб рд╕реЗ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрдм рд╕реВрдЪреА рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдзрд╛рд░рд╛рдУрдВ рдХреЛ рдЙрд╕ рд╕рдордп рддрдХ рд░реИрдВрдХ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрдм рд╡реЗ рдЬрд╛рдЧрддреЗ рд╣реИрдВ (рдЯрд┐рдХреНрд╕ рдореЗрдВ)ред

3. Sleep_timer_proc рдлрд╝рдВрдХреНрд╢рди рд╣реИрдВрдбрд▓рд░ рд╣реИ рдЬрд┐рд╕реЗ рдЯрд╛рдЗрдорд░ рд░реБрдХрд╛рд╡рдЯ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдЕрдиреБрд╕реВрдЪрдХ рджреНрд╡рд╛рд░рд╛ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЙрд╕рдХрд╛ рдХрд╛рдо рд╡рд╛рдВрдЫрд┐рдд рдкреНрд░рд╡рд╛рд╣ рдХреЛ рдЬрдЧрд╛рдирд╛ рд╣реИред

рдмрд╛рдХреА рдХрд╛рдлреА рдкрд╛рд░рджрд░реНрд╢реА рд▓рдЧрддрд╛ рд╣реИред

Source: https://habr.com/ru/post/In181870/


All Articles