OSDev.org

The Place to Start for Operating System Developers
It is currently Fri Mar 29, 2024 8:47 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 34 posts ]  Go to page Previous  1, 2, 3
Author Message
 Post subject: Re: Troubles implementing multitasking
PostPosted: Sat Aug 18, 2018 5:12 am 
Offline
Member
Member

Joined: Wed Jul 25, 2018 2:47 pm
Posts: 38
Location: Pizzaland, Southern Europe
@Brendan I'm not sure if this should be addressed here or in the wiki's discussion page, I'll move the post if necessary.
The current issue I'm facing while following your tutorial is this: let's suppose I have a task A, which blocks because it needs to wait for B to finish.

Looking at the code for block_task and unblock_task:
Code:
void block_task(int reason) {
    lock_scheduler();
    current_task_TCB->state = reason;
    schedule();
    unlock_scheduler();
}

void unblock_task(thread_control_block * task) {
    lock_scheduler();
    if(first_ready_to_run_task == NULL) {
        // Only one task was running before, so pre-empt
        switch_to_task(task);
    } else {
        // There's at least one task on the "ready to run" queue already, so don't pre-empt
        last_ready_to_run_task->next = task;
        last_ready_to_run_task = task;
    }
    unlock_scheduler();
}

this happens:
Code:
// A is running, sched_lock_cnt=0:
lock_scheduler(); // sched_lock=1, interrupts disabled
schedule(); // Now B is running
// Something something...
// B ends, unblocks A
lock_scheduler(); // sched_lock_cnt=2
switch_tasks(); // Now A is running
unlock_scheduler(); // sched_lock_cnt=1
// A continues its way, never to be interrupted again...


Top
 Profile  
 
 Post subject: Re: Troubles implementing multitasking
PostPosted: Sat Aug 18, 2018 3:49 pm 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
frabert wrote:
@Brendan I'm not sure if this should be addressed here or in the wiki's discussion page, I'll move the post if necessary.
The current issue I'm facing while following your tutorial is this: let's suppose I have a task A, which blocks because it needs to wait for B to finish.

Looking at the code for block_task and unblock_task:
Code:
void block_task(int reason) {
    lock_scheduler();
    current_task_TCB->state = reason;
    schedule();
    unlock_scheduler();
}

void unblock_task(thread_control_block * task) {
    lock_scheduler();
    if(first_ready_to_run_task == NULL) {
        // Only one task was running before, so pre-empt
        switch_to_task(task);
    } else {
        // There's at least one task on the "ready to run" queue already, so don't pre-empt
        last_ready_to_run_task->next = task;
        last_ready_to_run_task = task;
    }
    unlock_scheduler();
}

this happens:
Code:
// A is running, sched_lock_cnt=0:
lock_scheduler(); // sched_lock=1, interrupts disabled
schedule(); // Now B is running
// Something something...
// B ends, unblocks A
lock_scheduler(); // sched_lock_cnt=2
switch_tasks(); // Now A is running
unlock_scheduler(); // sched_lock_cnt=1
// A continues its way, never to be interrupted again...


There's a paragraph near the end of "Step 5: Race Conditions and Locking Version 1" that tries to explain this:

Note that this can be a little confusing depending on your perspective. From the perspective of one task, it locks the scheduler, does a task switch, and then when it gets CPU time again it unlocks the scheduler; and this is fine (the scheduler is always unlocked after its locked). From the perspective of the CPU, one task locks the scheduler then the scheduler does a task switch and a completely different task unlocks the scheduler; and this is also fine (the scheduler is still unlocked after its locked).

In other words; this happens:
Code:
// A is running, sched_lock_cnt=0:
lock_scheduler(); // sched_lock=1, interrupts disabled
schedule(); // Now B is running
unlock_scheduler(); // B unlocks the scheduler, sched_lock_cnt=0

// Something something...

lock_scheduler(); // B locks the scheduler, sched_lock_cnt=1
switch_tasks(); // Now A is running
unlock_scheduler(); // A unlocks the scheduler, sched_lock_cnt=0

// A continues its way


Note that this is the same issue you were having before you read the tutorial. This makes me wonder if the tutorial is adequate for other people (who don't have pre-existing expectations of a problem), or if the tutorial needs to explain it better (either because people without pre-existing expectations will also think there's a problem or because other people are likely to have pre-existing expectations).


Cheers,

Brendan

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re: Troubles implementing multitasking
PostPosted: Sun Aug 19, 2018 2:30 am 
Offline
Member
Member

Joined: Wed Jul 25, 2018 2:47 pm
Posts: 38
Location: Pizzaland, Southern Europe
That makes sense if B was being resumed from being blocked, so that it was put to sleep by calling schedule, so that when it awakens it returns from schedule and unlocks the scheduler. But what if B was being started for the first time? In that case, B would not start its execution by returning from a schedule call, so no scheduler unlocking would be done, so I presume I need to add a "preamble" to all the tasks to unlock the scheduler when they are first started?


Top
 Profile  
 
 Post subject: Re: Troubles implementing multitasking
PostPosted: Sun Aug 19, 2018 4:37 pm 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
Hi,

frabert wrote:
That makes sense if B was being resumed from being blocked, so that it was put to sleep by calling schedule, so that when it awakens it returns from schedule and unlocks the scheduler. But what if B was being started for the first time? In that case, B would not start its execution by returning from a schedule call, so no scheduler unlocking would be done, so I presume I need to add a "preamble" to all the tasks to unlock the scheduler when they are first started?


Ah - I understand now. Yes; when a task first starts running it'd need to unlock the scheduler as one of the first things it does (and if it doesn't do this the scheduler will remain locked and it'll cause problems).

Also, the kernel might want to pre-initialise some things (e.g. setting any "caller saved" registers that the task switch code doesn't load to known values, possibly including FPU/MMX/SSE/AVX state later on) or do some other housekeeping (I don't know what - maybe change some flag so that people can tell the difference between "not started yet" and "started properly"?). If you want to avoid having "preamble" in the code for every kernel task (and want a nice place to add/change "initialisation for every kernel task"); you can have a generic "new task startup routine" that releases scheduler's lock and does any other housekeeping/preperation before passing control to task specific code. In this case, when creating the new task's kernel stack your "create_kernel_task()" function would set the "return EIP" (used for the first task switch) to the address of the startup routine and then put the caller's "address that the startup function should return to" on the kernel stack too (plus any other parameters - e.g. if your "create_kernel_task()" function has a generic "void * arg" parameter like "pthread_create()" does, then that would be put on the new kernel stack too).

The tutorial doesn't mention any of this - I'll try to fix that a little later today. :)


Thanks,

Brendan

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 34 posts ]  Go to page Previous  1, 2, 3

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot], Ethin, SemrushBot [Bot] and 263 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group