Page 1 of 1

TSS Multitasking with only one TSS!?

Posted: Wed Jul 10, 2002 11:00 pm
by carbonBased
I've just recently added preliminary pre-emptive multitasking to my kernel.  The problem is, though, that I've only got a GDT of 256 entries (and even then, I think its pretty large), which leaves me around 230 entries for tasks... not much.

I could increase the size of my GDT, yes (whats the largest GDT size?  8k * 8?), but that's wasted memory if the system isn't running all those processes.

I've heard of a system that, supposedly, uses only one entry... apparently only one TSS, in fact, and simply copys the registers to and from it.

This sounds promising, but I'd like to read more about it.  Does anybody have any documentation on this approach?  It seems to me that an approach like this would ruin the link field in the TSS, though.  If the task calls a task gate, that task gate stores the callers selector in its TSS... but what if a task switch occurs now?  That same selector is now in use by another task (your only using one TSS, right?)

Anyway, any information on this would be greatly appreciated!

Thanks,
Jeff

PS: Wouldn't you _at least_ need two TSSs?

RE:TSS Multitasking with only one TSS!?

Posted: Thu Jul 11, 2002 11:00 pm
by HARD__MAN
I want ask you is jour system 32 bytes or 16.
if it 16 bytes then you must rewirite system in 32 bytes.

RE:TSS Multitasking with only one TSS!?

Posted: Thu Jul 11, 2002 11:00 pm
by carbonBased
I'm assuming you mean _BITS_ not _BYTES_, and yes, my system is 32 bits.  Like I said, I use TSS multitasking, which isn't supported in 16-bit processors, or any 16-mode (real mode, unreal mode, whatever).

Jeff

RE:TSS Multitasking with only one TSS!?

Posted: Fri Jul 12, 2002 11:00 pm
by TheUbu
When using just one tss you change its addr before doing a call or far jump to it the cpu will save state of current task to the old addr and then load the new addr. If you need an example of how this works you can grab our source the info on how to get it is out our website www.ubixos.com The exact file is schedule.c in src/sys/kernel


-Christopher

RE:TSS Multitasking with only one TSS!?

Posted: Sat Jul 13, 2002 11:00 pm
by anon
I believe Windows does this, although I'm not sure.

Anon

RE:TSS Multitasking with only one TSS!?

Posted: Tue Jul 23, 2002 11:00 pm
by NoLiving
Don't use Task gates.  Only use a TSS for the stack switching function.  Save the register state, FPU state manually in a data structure that you create.  When you're going to the next task, restore the state from your data structure, load up the stack with return values ([ss, esp,] eflags cs, eip) and iret to your next task.

RE:TSS Multitasking with only one TSS!?

Posted: Thu Aug 08, 2002 11:00 pm
by rexlunae
If you are using paging to give each task its own virtual address space, this might work for you.

Designate a linear address for each task to have a tss.  Set up the one gdt entry to reference it.  This tss is only really used to store the pointers to priv 0,1,2 stack.  When you receive an interrupt, you will need to back up any registers you use in your interrupt handler anyway.  Then in order to switch tasks, just load different values into cr3 and the ebp.  As soon as you load the new values, return from your function (restoring esp off the stack automatically), and you will be in the new task, in the interrupt handler at the point when you passed control to another task.  This allows you to switch tasks without dealing with tss's.  To be honest, I don't know if official documentation creates any problems with this method, but I don't think so, and preliminary testing indicates that it works.

RE:TSS Multitasking with only one TSS!?

Posted: Thu Aug 08, 2002 11:00 pm
by rexlunae
Actually, there are 16-bit tsses...and the 286 did support them in protected mode.

RE:TSS Multitasking with only one TSS!?

Posted: Thu Aug 08, 2002 11:00 pm
by carbonBased
This is a very intriging system!  I'm impressed!  No only does it remove the need to alter the "one" tss, to change cs:eip, ss:esp, but it also removes any need to alter the, rather large, io port map!  This was one area I was concerned with, when using "just one" tss... if one application is allowed all ports, while another, none, you'd have a lot of memory writes just to swap tasks.

I just need some confirmation on the process:

For example purposes, we can say the IDT and GDT are mapped to all tasks at 0x0, and the one TSS/per task is mapped just after, at 0x1000, let's say.

Upon entry to the timer interrupt, all registers are saved on the current task's PL0 stack, by convention.

The scheduler decides on the next task, and loads its page directory into CR3, thus altering linear memory, and mapping a new TSS into the position of the previous tasks TSS.

Where does ebp come from, then?  Any pops from the stack will still be poping from the previous tasks ss:esp, at this point, right?

iret - thus, restoring esp?  Again, wouldn't this still be from the original tasks's stack?

Or does your implementation map all PL0 stacks to the same linear address space as well?

Again, this is very intriging.  I like the elegance of this system.  Have you got a working implementation that I might take a look at?

Cheers,
Jeff

RE:TSS Multitasking with only one TSS!?

Posted: Fri Aug 09, 2002 11:00 pm
by rexlunae
"Where does ebp come from, then?  Any pops from the stack will still be poping from the previous tasks ss:esp, at this point, right?"
"iret - thus, restoring esp?  Again, wouldn't this still be from the original tasks's stack?"

This is one of the caveats of this system.  After you load cr3, you must load ebp (in the same function) and return from a function in order to have a consistent stack.  In the mean while, you cannot reference the stack, (parameters, non-static local variables).  You also have to be certain that your optimizer doesn't remove the enters and leaves (or equivalent longhand assembly) from the beginning and end of the funtion.  But when you return from the function, it will leave, restoring esp from ebp.  After that, it will load the return address from the new task's stack.

In some systems you may have to restore ss in order to switch tasks.  If you do, you should be able to restore it any time in the function.  However, in my system, I only allow one value for ss in the kernel, so I can assume that the value in effect will be correct.

An example function might look like this:

void switch_task(struct task newtask)
{
//For SMP kernel, there should be a lock here to prevent two processors from using these statics.  I don't know how badly this would effect performance.

     static u_int32_t newebp, newcr3;

/*
Store current values of ebp and cr3 somewhere so that you can restore them to switch back to them later.  This is too implementation specific to give a good example.
*/

     newebp = newtask.ebp;   //This is necessary to avoid referencing the stack
     newcr3 = newtask.cr3;

     loadcr3(newcr3);     //From here to the end of the function, the stack is indeterminate, so we cannot use it.
     loadebp(newebp);
     return;              //At this point, we switch to the new task at the same point we left off.  The stack will then be fully consistent.
}

"Again, this is very intriging.  I like the elegance of this system.  Have you got a working implementation that I might take a look at?"

At the moment, my code base is broken, particularly the multitasking portion.  I'd rather wait until I get it fixed to send it out.  If you really want to see it though, I could arrange it.  Perhaps you could send me an email address to send it to or something?  Otherwise, I am trying to restore my kernel's multitasking capabilities before the summer is over, so if you want to wait for a working example it should be available pretty soon.