OSDev.org

The Place to Start for Operating System Developers
It is currently Wed May 15, 2024 5:51 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 73 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next
Author Message
 Post subject: Re:tss on stack???
PostPosted: Tue Sep 13, 2005 7:25 pm 
Offline
Member
Member
User avatar

Joined: Tue Oct 17, 2006 6:06 pm
Posts: 1437
Location: Vancouver, BC, Canada
Brendan wrote:
Unless my wits have completely failed me, this tutorial assumes a CPL=3 stack per task, a CPL=0 stack per task and a CPL=0 stack that's shared by all tasks. This is (IMHO) quite unusual, but explains a lot about previous discussion


This is actually exactly what Minix does. It sets up the TSS to point to the current task's TCB so that the registers get saved in there automatically and don't need to be copied off the kernel stack.

_________________
Top three reasons why my OS project died:
  1. Too much overtime at work
  2. Got married
  3. My brain got stuck in an infinite loop while trying to design the memory manager
Don't let this happen to you!


Top
 Profile  
 
 Post subject: Re:tss on stack???
PostPosted: Wed Sep 14, 2005 12:49 am 
Offline
Member
Member

Joined: Wed Oct 18, 2006 11:59 am
Posts: 1600
Location: Vienna/Austria
@brendan: I know it as "If a butterfly takes a crap somewhere in russia, this might cause a tidal wave on the other side of the world". Something I've read in some terry pratchett book. *rofl*

as for the removing-a-task-stuff: In my OS, tasks are currently removed immediately. First general clean up, then the clean up in the kernel - by a dedicated kernel thread. So no worry, we aren't in the stack of the thread to be deleted. *gg*

_________________
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image


Top
 Profile  
 
 Post subject: Re:tss on stack???
PostPosted: Wed Sep 14, 2005 3:05 am 
Offline
Member
Member
User avatar

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

GLneo wrote:
i think your right, i have been looking at very diferent tutorials and tried to put them togheter :P, i would like to use both a CPL=3 stack and a CPL=0 stack per task, how is THAT done?, :)


That's done with the examples I've been posting, sort of. :)

Specifically, the SS0 and ESP0 fields in the TSS must be updated every task switch to point to the new taskl's kernel stack, and the CPU itself handles all stack switching (except for within the task switch code).

If you want to use C for your kernel, I'd also recommend the elegant method of parameter passing posted by Colonel Kernel. Also, I'd still do the thread switch code itself in a seperate routine.

Combining all of this gives something like:

Code:
;IRQ 0 assembly stub. Must be called with interrupts disabled (i.e. use
;    an "interrupt gate" in the IDT and not a "trap gate").

IRQhandler00:
    <push DS, ES, FS, GS if necessary>
    pusha
    <reload DS and ES (and maybe FS, GS) with values the kernel expects, if necessary>

    push esp                     ;Push the only parameter to the C function (the address of CPU state on the stack)
    call _Timer_IRQ_handler      ;Call the C function (which must send the EOI)
    add esp,4                    ;Remove the C function's parameters from the stack

    cmp eax,esp                  ;Did the C function request a task switch?
    je .skipSwitch               ; no
    call do_task_switch          ; yes, call the assembly code that handles task switches
.skipSwitch:

    popa
    <pop DS, ES, FS, GS if necessary>
    iretd

Code:
;Kernel API assembly stub. Must be called with interrupts enabled (which is
;    what you'd expect when CPL=3 code was running anyway).

kernelAPIentry:
    <push DS, ES, FS, GS if necessary>
    pusha
    <reload DS and ES (and maybe FS, GS) with values the kernel expects, if necessary>

    push esp                     ;Push the only parameter to the C function (the address of CPU state on the stack)
    call _kernel_API_entry_point ;Call the C function
    add esp,4                    ;Remove the C function's parameters from the stack

    cmp eax,esp                  ;Did the C function request a task switch?
    je .skipSwitch               ; no, skip the task switch

    cli                          ;Disable interrupts for the task switch code
    call do_task_switch          ;Call the assembly code that handles task switches
    sti                          ;Restore interrupts

.skipSwitch:

    popa
    <pop DS, ES, FS, GS if necessary>
    iretd

Code:
;Do a task switch. This code must be called with interrupts disabled.
;All general registers trashed (shouldn't matter as they're always saved
;before calling this code, and restored after this code runs.
;
;Input
; eax   Must contain the top of stack for the task being switched to

do_task_switch:
    mov ebx,[currentTaskStructure]
    mov [ebx+TASK_STRUCT.currentESP],esp

    <work out how much CPU time the last task used and update "[ebx + TASK_STRUCT.timeUsed]">

    <convert EAX into address of task structure and put it in ESI>

    mov ebx,[esi+TASK_STRUCT.kernelStackTop]
    mov [address_of_system_TSS + TSS.ESP0], ebx

    mov ebx,[esi+TASK_STRUCT.pageDirectory]
    mov ecx,cr3
    cmp ecx,ebx                    ;Does address space need to be changed?
    je .skipCR3                    ; no, skip it
    mov cr3,ebx                    ; yes, update CR3

    <do something about FPU/MMX/SSE/SSE2 state saving here>

    mov esp,eax                    ;Switch stacks
    ret


[continued]

_________________
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:tss on stack???
PostPosted: Wed Sep 14, 2005 3:10 am 
Offline
Member
Member
User avatar

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

Then you'd have the C code:

Code:
unsigned int SystemTimerTick = 0;

STACK_DATA *_Timer_IRQ_handler(STACK_DATA *callerRegs) {
    SystemTimerTick++;

    outportb(0x20, 0x20);             //Send the EOI

    if( did_this_task's_time_run_out() == YES) {
        return find_a_new_task_to_run(callerRegs);
    } else {
        return callerRegs;
    }
}

Code:
STACK_DATA *_kernel_API_entry_point(STACK_DATA *callerRegs) {
    switch(callerRegs->EAX) {
        case API_FUNCTION_A:
            return function_A(callerRegs);    // Might cause task switch
        case API_FUNCTION_B:
            return function_B(callerRegs);    // Might cause task switch
        case API_FUNCTION_C:
            function_C(callerRegs);           // Never causes task switch
            return callerRegs;
        default:
            callerRegs->EAX = ERROR_UNDEFINED_FUNCTION;
            return callerRegs;
    }
}

Code:
STACK_DATA *function_A(STACK_DATA *callerRegs) {
   <this is an example kernel API function>
   return callerRegs;
}

STACK_DATA *function_B(STACK_DATA *callerRegs) {
   <this is an example kernel API function>
   return callerRegs;
}

void function_C(STACK_DATA *callerRegs) {
   <this is an example kernel API function>
}

Some notes:

I haven't tested any of this, but you should be able to cut & paste it, then fix all the (lots and lots) of errors caused by missing stuff and it should (hopefully) work. I strongly recommend that you do not do this - instead read it, understand it then implement your own version.

Inside the "do_task_switch" routine there's a line that says "<convert EAX into address of task structure and put it in ESI>". This part depends on how you're keeping track of tasks. I like to have a "Task Control Block" (or structure) that contains things like the task's name, how many messages are in it's queue, which options it's using, etc. If this structure is 8 KB and includes the task's kernel stack, and if the structure is also aligned on an 8 KB boundary, then you could replace the "<convert EAX into address of task structure and put it in ESI>" with something like:

Code:
    mov esi,eax
    and esi,0xFFFF8000

How you do this depends on how you keep track of the rest of the task's data...

All of the code in the "STACK_DATA *_kernel_API_entry_point(STACK_DATA *callerRegs)" function is an example only. I'm not sure how well the compiler will optimize the "switch/case/case" stuff and I'd probably recommend using a call table instead (to avoid a pile of conditional branches).

You must create the "STACK_DATA *" structure/data type so that it matches the data pushed on the stack at the start of "IRQhandler00", "kernelAPIentry" and any other kernel entry points.

I'm not sure if you'll be treating the data segment registers (DS, ES, FS and GS) as constants or allowing them to be changed - you should be able to make allowances either way.


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:tss on stack???
PostPosted: Wed Sep 14, 2005 7:10 am 
Offline
Member
Member
User avatar

Joined: Tue Oct 17, 2006 6:06 pm
Posts: 1437
Location: Vancouver, BC, Canada
Looks pretty good to me. A few things, though:

function_C must have a return value. Otherwise you can't really rely on the value of eax in the assembly stub. If a kernel API function wants to switch to another task, it would call the scheduler and return a pointer to the chosen task's STACK_DATA (or TCB, or whatever...).

Also, while it should be OK to allow interrupts between calling the scheduler in C-land and calling do_task_switch in asm, you should not allow pre-emption. The reason is that when the kernel finally returns to user-mode, it should be returning to the task chosen most recently. If you allow the kernel to be preempted after choosing a task but before switching to it, the kernel will eventually switch to that task later, even if this is no longer the right thing to do (e.g. -- if a higher-priority thread has become ready since the pre-emption and subsequent resumption of the kernel). Sorry if this is confusing... I'm working on a better way to explain this when I have time. :)

Also...

Brendan wrote:
All of the code in the "STACK_DATA *_kernel_API_entry_point(STACK_DATA *callerRegs)" function is an example only. I'm not sure how well the compiler will optimize the "switch/case/case" stuff and I'd probably recommend using a call table instead (to avoid a pile of conditional branches).


Yeah, definitely use a call table. Most compilers I know of do a poor job of optimizing switch/case.

_________________
Top three reasons why my OS project died:
  1. Too much overtime at work
  2. Got married
  3. My brain got stuck in an infinite loop while trying to design the memory manager
Don't let this happen to you!


Top
 Profile  
 
 Post subject: Re:tss on stack???
PostPosted: Wed Sep 14, 2005 9:57 am 
Offline
Member
Member
User avatar

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

Colonel Kernel wrote:
function_C must have a return value. Otherwise you can't really rely on the value of eax in the assembly stub. If a kernel API function wants to switch to another task, it would call the scheduler and return a pointer to the chosen task's STACK_DATA (or TCB, or whatever...).


The return value for "function C" doesn't matter:

Code:
       case API_FUNCTION_C:
            function_C(callerRegs);          // Never causes task switch
            return callerRegs;


Although if a call table was used it'd be a problem - function C would need to match the other functions.

Colonel Kernel wrote:
Also, while it should be OK to allow interrupts between calling the scheduler in C-land and calling do_task_switch in asm, you should not allow pre-emption. The reason is that when the kernel finally returns to user-mode, it should be returning to the task chosen most recently. If you allow the kernel to be preempted after choosing a task but before switching to it, the kernel will eventually switch to that task later, even if this is no longer the right thing to do (e.g. -- if a higher-priority thread has become ready since the pre-emption and subsequent resumption of the kernel). Sorry if this is confusing... I'm working on a better way to explain this when I have time. :)


For this it'd be possible for any code that causes a task switch to disable interrupts and leave them disabled until the task switch occurs. I didn't want to have interrupts disabled for all kernel API functions...

Of course I'd recommend using a different method of preventing task switches, like a "prevent task switches" flag - disabling interrupts for too long isn't a good idea.


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:tss on stack???
PostPosted: Wed Sep 14, 2005 2:47 pm 
doesn't gcc return values on the stack???, how do you get gcc to return in eax, or should i use inline asm to load eax???


Top
  
 
 Post subject: Re:tss on stack???
PostPosted: Wed Sep 14, 2005 2:52 pm 
GLneo wrote:
doesn't gcc return values on the stack???, how do you get gcc to return in eax, or should i use inline asm to load eax???


gcc always puts the return value in eax, unless I'm mistaken.


Top
  
 
 Post subject: Re:tss on stack???
PostPosted: Wed Sep 14, 2005 5:31 pm 
Offline
Member
Member
User avatar

Joined: Tue Oct 17, 2006 6:06 pm
Posts: 1437
Location: Vancouver, BC, Canada
gcc puts return values in eax as long as they're not floats, doubles, structs, or unions. Otherwise, IIRC it copies the return value to some reserved space in the caller's stack frame and returns its address in eax.

<edit>Actually, it might return floats in eax too... I've never tried it.</edit>

_________________
Top three reasons why my OS project died:
  1. Too much overtime at work
  2. Got married
  3. My brain got stuck in an infinite loop while trying to design the memory manager
Don't let this happen to you!


Top
 Profile  
 
 Post subject: Re:tss on stack???
PostPosted: Sun Sep 18, 2005 8:04 am 
ok, i've been working on it but now i'm very confused ??? here is my code:
Code:
_task_timer:
    pushad
    push ds
    push es
    push fs
    push gs
    push esp
    mov eax, _timer_handler
    call eax
    add esp,4
    cmp eax,esp
    je skipSwitch
    call do_task_switch
skipSwitch:
    pop gs
    pop fs
    pop es
    pop ds
    popad
    iretd

do_task_switch:
    mov esp,eax
    ret

and then in c:
Code:
#define QUE_SIZE 128

void task0()
{
    while(1)
        puts("a");
}

void task1()
{
    while(1)
        puts("b");
}

unsigned int curtask = 0;

struct stack_data
{
    unsigned int gs;
    unsigned int fs;
    unsigned int es;
    unsigned int ds;
    unsigned int eax;
    unsigned int ebx;
    unsigned int ecx;
    unsigned int edx;
    unsigned int edi;
    unsigned int esi;
    unsigned int cs;
    unsigned int eflags;
    unsigned int eip;
    unsigned int esp;
};

struct task_data
{
    char name[33];
    struct stack_data esp;
    unsigned int ss;
    unsigned int kstack;
    unsigned int ustack;
    unsigned int time;
    unsigned int priority;
   
};

int front = 0;
int end = 0;
struct task_data rrq[QUE_SIZE];

stack_data schedule(struct stack_data *regs)
{
    cur_task_time_equ(get_pri_time(cur_task_pri()));
    front_to_end();
    return rrq[front].esp;
}

stack_data timer_handler(struct stack_data *regs)
{
    clock();
    outport(0x20, 0x20);
    if(cur_task_time() > 0)
    {
        dec_cur_task_time();
        return regs;
    }
    if(cur_task_time() < 1)
        return schedule(regs);
}

void make_task(int pri, char *name, void (*entry)())
{
     unsigned int *stack;
     stack = (unsigned int *)malloc(64);
     *stack--;
     *stack-- = 0x0202;
     *stack-- = 0x08;
     *stack-- = (unsigned int)entry;
     *stack-- = 0;    //ebp
     *stack-- = 0;    //esp
     *stack-- = 0;    //edi
     *stack-- = 0;    //esi
     *stack-- = 0;    //edx
     *stack-- = 0;    //ecx
     *stack-- = 0;    //ebx
     *stack-- = 0;    //eax
     *stack-- = 0x8;  //ds
     *stack-- = 0x8;  //es
     *stack-- = 0x8;  //fs
     *stack = 0x8;    //gs

     strncpy(rrq[end].name, name, 32);
     rrq[end].esp = (struct stack_data)stack;
     rrq[end].ss = 0x8;
     rrq[end].priority = pri;
     rrq[end].time = get_pri_time(pri);
     end++;
}

void start_sys()
{
     make_task(3, "task0", task0);
     make_task(3, "task1", task1);
     set_a_idt(32, (unsigned)task_timer, 0x08, 0x8E);
}

i dont know if i'm handling return types right or in make_task()what do i need to put in the struct stack_data type ESP???, help, thx ;D


Top
  
 
 Post subject: Re:tss on stack???
PostPosted: Sun Sep 18, 2005 10:03 am 
Offline
Member
Member
User avatar

Joined: Tue Oct 17, 2006 6:06 pm
Posts: 1437
Location: Vancouver, BC, Canada
There are a few problems with this code. First, your task_data should contain a pointer to the task's stack_data, rather than just containing the stack_data itself. stack_data is actually the bottom of the kernel stack for that task, which means that if you keep it in the task_data, you'll be overwriting the task's name and whatever comes before it in memory as the task's kernel stack grows. That's not good. When you create a task, you need to allocate a kernel stack for it. You will have to decide how much you need to allocate -- it depends on the complexity of your kernel. At the bottom of the new stack, you will need to set up your stack_data fields, and also a ring 3 SS and ESP if you intend for the task to run in ring 3 (these will be popped by the CPU if it sees that the CS in your stack_data refers to a ring 3 code segment). After this is all set up, put a pointer to the stack_data struct in the task_data.

The next problem is that you're returning stack_data by value instead of by pointer. That creates a copy of the stack_data, which is not what you want. This will just corrupt the stack since the calling code (your ISR stub) is not prepared to deal with a struct being returned by value. It expects a pointer to a kernel stack to be returned, which is what your C code should be returning.

The next problem is the definition of your stack_data structure. Many of the fields are in the wrong order. The segment registers are ok, but the ones after it are not. Here's how it should look:

Code:
struct stack_data
{
   unsigned int gs;
   unsigned int fs;
   unsigned int es;
   unsigned int ds;
   unsigned int edi;
   unsigned int esi;
   unsigned int ebp;
   unsigned int esp;
   unsigned int ebx;
   unsigned int edx;
   unsigned int ecx;
   unsigned int eax;
   unsigned int eip;
   unsigned int cs;
   unsigned int eflags;
};


Hope this helps.

_________________
Top three reasons why my OS project died:
  1. Too much overtime at work
  2. Got married
  3. My brain got stuck in an infinite loop while trying to design the memory manager
Don't let this happen to you!


Top
 Profile  
 
 Post subject: Re:tss on stack???
PostPosted: Sun Sep 18, 2005 10:09 am 
Offline
Member
Member
User avatar

Joined: Tue Oct 17, 2006 6:06 pm
Posts: 1437
Location: Vancouver, BC, Canada
GLneo wrote:
in make_task()what do i need to put in the struct stack_data type ESP???


Sorry, I missed this question on my first read through your post.

According to the way that pusha works (remember, the Intel manuals are your friend), the value of ESP that gets pushed is the value that ESP was before pushing EAX (that is, before the pusha instruction began executing). So, it should point to the eip field of the stack_data struct.

_________________
Top three reasons why my OS project died:
  1. Too much overtime at work
  2. Got married
  3. My brain got stuck in an infinite loop while trying to design the memory manager
Don't let this happen to you!


Top
 Profile  
 
 Post subject: Re:tss on stack???
PostPosted: Mon Sep 19, 2005 7:59 pm 
thx that helped, well at least it compiles :P, what now happends is it starts then does nothing, it does not crash just goes somewhere??? I followed the exicution of my kernel so if the kernel got control back it doesn't hit a CLI, and it dosent, but i did test it and it does get control back, but it sould hit a jmp $ and stop. it does get one interupt and go into my timer handler and returns then never comes back??? heres the code:
Code:
struct stack_data *schedule(struct stack_data *regs)
{
    cur_task_time_equ(get_pri_time(cur_task_pri()));
    front_to_end();
    return rrq[front].stack;
}

struct stack_data *task_timer_c(struct stack_data *regs)
{
    clock();
    outport(0x20, 0x20);
    if(cur_task_time() > 0)
    {
        dec_cur_task_time();
        return regs; //<------------------It gets here only once!!!
    }
    else
        return schedule(regs);
}

void make_task(int pri, char *name, void (*entry)())
{
     unsigned int *stack;
     stack = (unsigned int *)malloc(64);
     *stack--;
     *stack-- = 0x0202;
     *stack-- = 0x08;
     *stack-- = (unsigned int)entry;
     *stack-- = 0;    //ebp
     *stack-- = 0;    //esp
     *stack-- = 0;    //edi
     *stack-- = 0;    //esi
     *stack-- = 0;    //edx
     *stack-- = 0;    //ecx
     *stack-- = 0;    //ebx
     *stack-- = 0;    //eax
     *stack-- = 0x8;  //ds
     *stack-- = 0x8;  //es
     *stack-- = 0x8;  //fs
     *stack = 0x8;    //gs

     strncpy(rrq[end].name, name, 32);
     rrq[end].stack = (struct stack_data *)stack;
     rrq[end].ss = 0x8;
     rrq[end].priority = pri;
     rrq[end].time = get_pri_time(pri);
     end++;
}

void start_sys()
{
     puts("Setting up Task0... ");
     make_task(3, "task0", task0);
     puts("Done.\n");
     puts("Setting up Task1... ");
     make_task(3, "task1", task1);
     puts("Done.\n");
     set_a_idt(32, (unsigned)task_timer_c, 0x08, 0x8E);
}

any ideas???, thx

EDIT: ok with a little bochs work i have found that es ds gs fs and stuff are at 0x10 i know this is where i sould put my user GDT and where a lot of tutorials set them to but i dont remember using 0x10, it must be on the new task stack becouse that would explain why only one switch happpens before the crash, but in my new_task code you can see the all referens 0x08, whats happening???, thx


Top
  
 
 Post subject: Re:tss on stack???
PostPosted: Mon Sep 19, 2005 9:29 pm 
Offline
Member
Member
User avatar

Joined: Tue Oct 17, 2006 6:06 pm
Posts: 1437
Location: Vancouver, BC, Canada
First, a piece of advice. In your make_task() function, use the fields of your stack_data struct instead of just writing blindly to the malloc'd memory. You're less likely to make a mistake that way (and it would be much easier to read).

Problem #1: You still aren't setting up esp correctly. See my last post.

Problem #2: You're assigning the same selector to both CS and DS/SS/ES/etc. This is incorrect -- CS needs to point to a code segment descriptor, while the rest must point to a data segment descriptor. If your tasks are supposed to run in ring 3, then you should be putting the ring 3 code and data segment selectors in CS, DS, etc.

Also, did you remember to set up your ESP0 and SS0 fields in the TSS correctly...?

_________________
Top three reasons why my OS project died:
  1. Too much overtime at work
  2. Got married
  3. My brain got stuck in an infinite loop while trying to design the memory manager
Don't let this happen to you!


Top
 Profile  
 
 Post subject: Re:tss on stack???
PostPosted: Mon Sep 19, 2005 10:13 pm 
Offline
Member
Member
User avatar

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

Code:
void make_task(int pri, char *name, void (*entry)())
{
     unsigned int *stack;
     stack = (unsigned int *)malloc(64);
     *stack--;
     *stack-- = 0x0202;
     *stack-- = 0x08;
     *stack-- = (unsigned int)entry;
     *stack-- = 0;    //ebp
     *stack-- = 0;    //esp
     *stack-- = 0;    //edi
     *stack-- = 0;    //esi
     *stack-- = 0;    //edx
     *stack-- = 0;    //ecx
     *stack-- = 0;    //ebx
     *stack-- = 0;    //eax
     *stack-- = 0x8;  //ds
     *stack-- = 0x8;  //es
     *stack-- = 0x8;  //fs
     *stack = 0x8;    //gs


This won't work - the stack grows from the top down, while your doing it from the bottom down (and probably overwriting unrelated data).

You'd want to do something like:
Code:
#define STACK_SIZE     64       // Size of stack in "unsigned integers"

void make_task(int pri, char *name, void (*entry)())
{
     unsigned int *stack;
     stack = (unsigned int *)malloc(STACK_SIZE * sizeof(unsigned int) );
     stack += STACK_SIZE;       //stack = address of top of stack
     *stack--;
     *stack-- = 0x0202;
     *stack-- = 0x08;
     *stack-- = (unsigned int)entry;
     *stack-- = 0;    //ebp
     *stack-- = 0;    //esp
     *stack-- = 0;    //edi
     *stack-- = 0;    //esi
     *stack-- = 0;    //edx
     *stack-- = 0;    //ecx
     *stack-- = 0;    //ebx
     *stack-- = 0;    //eax
     *stack-- = 0x8;  //ds
     *stack-- = 0x8;  //es
     *stack-- = 0x8;  //fs
     *stack = 0x8;    //gs


Or, even better, something more like:

Code:
#define STACK_SIZE     64*4                       // Size of stack in bytes
#define KERNEL_CODE_SEG  0x0008       // Not sure if this is right
#define KERNEL_STACK_SEG  0x0010      // Not sure if this is right
#define DATA_SEG  0x0018                        // Not sure if this is right

void make_task(int pri, char *name, void (*entry)())
{
     void *stack;
     stack_data *new_stack_data;

     stack = (unsigned int *)malloc(STACK_SIZE);
     stack += STACK_SIZE - sizeof(stack_data) ;       //stack = address for start of stack data structure
     new_stack_data = stack;

     new_stack_data->gs = DATA_SEG;
     new_stack_data->fs = DATA_SEG;
     new_stack_data->es = DATA_SEG;
     new_stack_data->ds = DATA_SEG;
     new_stack_data->edi = 0;
     new_stack_data->esi = 0;
     new_stack_data->ebp = 0;
     new_stack_data->esp = 0;
     new_stack_data->ebx = 0;
     new_stack_data->edx = 0;
     new_stack_data->ecx = 0;
     new_stack_data->eax = 0;
     new_stack_data->eip = (unsigned int)entry;
     new_stack_data->cs = KERNEL_CODE_SEG;
     new_stack_data->eflags = 0x00000202;

    strncpy(rrq[end].name, name, 32);
    rrq[end].stack = new_stack_data;
    rrq[end].ss = KERNEL_STACK_SEG;
    rrq[end].priority = pri;
    rrq[end].time = get_pri_time(pri);
    end++;


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  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 73 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot], Google [Bot], Kaius, Majestic-12 [Bot] and 22 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