]> git.corax.cc Git - corax/commitdiff
Add task_move_stack() function, which moves the current stack and updates ESP and EBP
authorMatthias Kruk <m@m10k.eu>
Thu, 14 Nov 2019 07:46:53 +0000 (16:46 +0900)
committerMatthias Kruk <m@m10k.eu>
Thu, 14 Nov 2019 07:46:53 +0000 (16:46 +0900)
kernel/arch/task.S
kernel/include/arch.h

index c7e5e3257eda87aceba3ca670c3a838130efbdcf..1897a6dad94d8d955f977fd9f743c8cd63b13d04 100644 (file)
@@ -29,6 +29,7 @@
 .global task_switch
 .global task_get_current
 .global task_set_current
+.global task_move_stack
 
 task_prepare:
        /*
@@ -397,3 +398,89 @@ task_set_current:
 1:     movl    4(%esp), %ecx
        movl    %ecx, OFFSET_CPU_CTASK(%eax)
        ret
+
+task_move_stack:
+       /*
+        * void task_move_stack(void *dst, void *src, u32_t size)
+        *
+        *  dst  =  4(%esp)
+        *  src  =  8(%esp)
+        *  size = 12(%esp)
+        */
+
+       /*
+        * For the sake of performance, don't copy the entire stack
+        * but just the portion that was actually used, i.e. the
+        * following:
+        *
+        * +-----+ <- src + size
+        * |     |
+        * |     |
+        * +-----+ <- ESP
+        * |     |
+        * |     |
+        * +-----+ <- src
+        */
+
+       /* compute the offset into the new stack */
+       movl    %esp, %edi
+       subl    8(%esp), %edi /* ESP - src = offset  */
+       addl    4(%esp), %edi /* offset + dst = nESP */
+
+       /* put ESP into ESI so we can copy from ESI to EDI */
+       movl    %esp, %esi
+
+       /* calculate the upper limit for EDI and put it into EDX */
+       movl    4(%esp), %edx
+       addl    12(%esp), %edx
+
+       /*
+        * Update the stack pointers now, since we won't need the
+        * stack anymore afterwards. To update EBP, we need to subtract
+        * the old base and add the new one, so do that before updating
+        * ESP.
+        */
+       subl    8(%esp), %ebp
+       addl    4(%esp), %ebp
+       movl    %edi, %esp
+
+       /*
+        * To copy the stack, keep copying from %(esi) to (%edi),
+        * increasing the two pointers, until %edi reaches %edx
+       */
+
+0:     cmpl    %edx, %edi
+       jge             1f
+
+       movl    (%esi), %eax
+       movl    %eax, (%edi)
+       addl    $4, %esi
+       addl    $4, %edi
+       jmp             0b
+
+       /* iterate over the new stack, adjusting pointers */
+1:     movl    %esp, %edi
+       movl    %edx, %esi
+       movl    8(%esp), %ecx /* lower bound */
+       movl    %ecx, %edx
+       addl    12(%esp), %edx /* upper bound */
+
+2:     cmpl    %esi, %edi
+       jge             4f
+
+       movl    (%edi), %eax
+       cmpl    %ecx, %eax
+       jl              3f
+       cmpl    %edx, %eax
+       jge             3f
+
+       /* adjust the pointer */
+       subl    %ecx, %eax
+       addl    4(%esp), %eax
+       /* store it on the stack */
+       movl    %eax, (%edi)
+3:     addl    $4, %edi
+       jmp             2b
+
+       /* Stacks have been copied and stack pointers updated. We're done. */
+4:     ret
index 10536e58e2d51b82ed7513a58abbf4083b7f572c..ed9b2b9c5cacc874424f7fc358a9cdba96401f59 100644 (file)
@@ -82,6 +82,7 @@ int     task_switch(struct task*);
 
 task_t* task_get_current(void);
 void    task_set_current(task_t*);
+void    task_move_stack(void*, void*, u32_t);
 
 /*
  * Definitions, types, and prototypes related to paging