Posted: Thu Mar 03, 2005 8:14 pm
Yes i think i got it working ok by copying the used portion of the old stack over the new. Here's an example:
Which gives the output:
The example initially sets the stack to 200 kb then calls an iterative procedure which monitors the free stack space. When it goes below 100 kb it calls a procedure to increase the stack by 1 mb and then it continues iterating. I set it to stop when the stack size reached 2 mb. The decreasing numbers at the end show the stack was preserved correctly so i think it's all working.
Thanks again El Choni!
Code: Select all
Global *NewStack.l, NewStackSize.l, *OldStack.l, *StartStack.l, *OrigStack.l
MOV *NewStack, esp ; Start of stack
NewStackSize = 1024 * 1024 ; Default stack size is 1 mb
*OldStack = 0
*OrigStack = *NewStack ; Store original stack position to return to at code exit
Procedure.l ReallocateStack(StackSize.l) ; Set new stack size (in bytes)
; Get position in current stack
MOV *StartStack, esp
; Calculate stack free
CurrentFree = NewStackSize - *NewStack + *StartStack
; Need a few bytes spare
If CurrentFree < 256
ProcedureReturn 1 ; Not enough (1 = stack free space too small)
EndIf
; Calculate stack used
NewStackSize = *NewStack - *StartStack
; Check new stack size is bigger than current size in use + 1k
If StackSize < NewStackSize + 1024
ProcedureReturn 2 ; No it isn't (2 = new stack size too small)
EndIf
; Allocate space for new stack
*NewStackPos = AllocateMemory(StackSize)
; Could we allocate memory for new stack?
If *NewStackPos = 0
ProcedureReturn 3 ; Nope we couldn't (3 = not enough free memory to allocate new stack)
EndIf
; Calcaulate position in new stack
*NewStack.l = *NewStackPos + StackSize - NewStackSize
; Temporarily shift stack so as not to interfere with CopyMemory
*TempStack = *StartStack - 128
MOV eax, *TempStack
MOV esp, eax
; Copy used stack across to new stack
CopyMemory(*StartStack, *NewStack, NewStackSize)
; Update stack with new position
MOV eax, *NewStack
MOV esp, eax
; Previous stack no longer needed, so free it
If *OldStack
FreeMemory(*OldStack)
EndIf
; Update new stack position and size and old stack position
*NewStack = *NewStackPos + StackSize
NewStackSize = StackSize
*OldStack = *NewStack - NewStackSize
; Phew, we made it to the end (0 = good)
ProcedureReturn 0
EndProcedure
Procedure.l StackFree() ; Return free stack space
*CurrentStack.l
MOV *CurrentStack, esp
ProcedureReturn NewStackSize - *NewStack + *CurrentStack
EndProcedure
Procedure.l StackUsed() ; Return used stack space
*CurrentStack.l
MOV *CurrentStack, esp
ProcedureReturn *NewStack - *CurrentStack
EndProcedure
Procedure.l flop(count.l) ; Iterative example procedure
; Update every 2000 calls
If count % 2000 = 0
Debug("Count: " + Str(count) + " Stack free (kb): " + Str(StackFree() / 1024) + " Stack used (kb): " + Str(StackUsed() / 1024))
Delay(200)
; Check if less than 100 kb stack space
If StackFree() < 1024 * 100
Debug("Less than 100 kb stack space; increasing stack size by 1 mb:")
result = ReallocateStack(StackUsed() + 1024 * 1024) ; Increase stack by 1 mb
Debug("Stack free (kb): " + Str(StackFree() / 1024) + " Stack used (kb): " + Str(StackUsed() / 1024))
Select result
Case 0 : Debug("Stack space allocated successfully")
Case 1 : Debug("Not enough space on stack") : End
Case 2 : Debug("New stack size must be greater than previous amount in use") : End
Case 3 : Debug("Could not allocate memory for new stack") : End
EndSelect
EndIf
EndIf
If StackUsed() < 1024 * 1024 * 2 ; Go up to 2 mb stack size
flop(count + 1)
EndIf
If count % 2000 = 0 ; Check count is decreasing as procedure exits
Debug(count)
EndIf
EndProcedure
; Output initial free and used stack space
Debug("Initial stack details:")
Debug("Stack free (kb): " + Str(StackFree() / 1024) + " Stack used (kb): " + Str(StackUsed() / 1024))
; Set stack size to 200 kb
Debug("Setting stack size to 200 kb:")
result = ReallocateStack(1024 * 200)
Select result
Case 0 : Debug("Stack space allocated successfully")
Case 1 : Debug("Not enough space on stack") : End
Case 2 : Debug("New stack size must be greater than previous amount in use") : End
Case 3 : Debug("Could not allocate memory for new stack") : End
EndSelect
Debug("Stack free (kb): " + Str(StackFree() / 1024) + " Stack used (kb): " + Str(StackUsed() / 1024))
; Call recursive procedure
Debug("Calling iterative procedure:")
flop(0)
; Return to original stack and free previous stack
If *OldStack
MOV eax, *OrigStack
MOV esp, eax
FreeMemory(*OldStack)
EndIf
Debug("Finished")
Code: Select all
Initial stack details:
Stack free (kb): 1023 Stack used (kb): 0
Setting stack size to 200 kb:
Stack space allocated successfully
Stack free (kb): 199 Stack used (kb): 0
Calling iterative procedure:
Count: 0 Stack free (kb): 199 Stack used (kb): 0
Count: 2000 Stack free (kb): 129 Stack used (kb): 70
Count: 4000 Stack free (kb): 59 Stack used (kb): 140
Less than 100 kb stack space; increasing stack size by 1 mb:
Stack free (kb): 1023 Stack used (kb): 140
Stack space allocated successfully
Count: 6000 Stack free (kb): 953 Stack used (kb): 211
Count: 8000 Stack free (kb): 883 Stack used (kb): 281
Count: 10000 Stack free (kb): 813 Stack used (kb): 351
Count: 12000 Stack free (kb): 742 Stack used (kb): 421
Count: 14000 Stack free (kb): 672 Stack used (kb): 492
Count: 16000 Stack free (kb): 602 Stack used (kb): 562
Count: 18000 Stack free (kb): 531 Stack used (kb): 632
Count: 20000 Stack free (kb): 461 Stack used (kb): 703
Count: 22000 Stack free (kb): 391 Stack used (kb): 773
Count: 24000 Stack free (kb): 320 Stack used (kb): 843
Count: 26000 Stack free (kb): 250 Stack used (kb): 914
Count: 28000 Stack free (kb): 180 Stack used (kb): 984
Count: 30000 Stack free (kb): 109 Stack used (kb): 1054
Count: 32000 Stack free (kb): 39 Stack used (kb): 1125
Less than 100 kb stack space; increasing stack size by 1 mb:
Stack free (kb): 1023 Stack used (kb): 1125
Stack space allocated successfully
Count: 34000 Stack free (kb): 953 Stack used (kb): 1195
Count: 36000 Stack free (kb): 883 Stack used (kb): 1265
Count: 38000 Stack free (kb): 813 Stack used (kb): 1336
Count: 40000 Stack free (kb): 742 Stack used (kb): 1406
Count: 42000 Stack free (kb): 672 Stack used (kb): 1476
Count: 44000 Stack free (kb): 602 Stack used (kb): 1546
Count: 46000 Stack free (kb): 531 Stack used (kb): 1617
Count: 48000 Stack free (kb): 461 Stack used (kb): 1687
Count: 50000 Stack free (kb): 391 Stack used (kb): 1757
Count: 52000 Stack free (kb): 320 Stack used (kb): 1828
Count: 54000 Stack free (kb): 250 Stack used (kb): 1898
Count: 56000 Stack free (kb): 180 Stack used (kb): 1968
Count: 58000 Stack free (kb): 109 Stack used (kb): 2039
58000
56000
54000
52000
50000
48000
46000
44000
42000
40000
38000
36000
34000
32000
30000
28000
26000
24000
22000
20000
18000
16000
14000
12000
10000
8000
6000
4000
2000
0
Finished
Thanks again El Choni!
