Option TargetCPU ZX24e Option TaskStackMargin 2 Option Ramsize 64*1024-Register.RamStart #define TASK_STACK_SIZE 29 #define MAIN_STACK_SIZE 51 #define HEAP_OVERHEAD 2 Sub Main() Dim i as UnsignedInteger, stack as UnsignedInteger, numberTasks as UnsignedInteger Dim counters as UnsignedInteger, counterAddr as UnsignedInteger Dim previousTime as Single, currentTime as Single Dim totalCount as Long ' Calculate number of tasks from available RAM numberTasks = (Register.RAMSIZE - MAIN_STACK_SIZE - HEAP_OVERHEAD) \ (TASK_STACK_SIZE + SIZEOF(Byte) + HEAP_OVERHEAD) ' use one less as seems to cause error with devices with extended RAM numberTasks = numberTasks - 1 ' For extended RAM, need to allocate one less task Debug.Print "Available RAM is "; CStr(Register.RAMSIZE); " so number of tasks is " ; CStr(numberTasks) ' allocate space on heap for task counters ' seems to need one extra byte at the end of the heap so add 1 to be safe counters = System.Alloc(numberTasks * SIZEOF(Byte)) If counters = 0 Then Debug.Print "Failed to allocate RAM for task counters" Exit Sub End If Debug.Print "Creating "; CStr(numberTasks); " tasks:" previousTime = Timer() ' Lock main task while we create the other tasks. ' This prevents too much slowdown during task creation. Call LockTask() For i = 0 to numberTasks-1 ' calculate address of this counter counterAddr = counters + i * SIZEOF(Byte) ' reset the counter for each task Call RAMPoke(0, counterAddr) ' this allocates memory off the heap for each task stack stack = System.Alloc(TASK_STACK_SIZE) If stack <> 0 Then ' create the task and add it to the rubnnable task list but it wont run yet 'Debug.Print "Task "; CStr(i); ": stack at address "; CStr(stack); " and counter at address "; CStr(counterAddr) CallTask Task(CByteArray(counterAddr)), stack, TASK_STACK_SIZE ' print a period and the task number every 100 tasks Debug.Print "."; If ((i+1) Mod 100) = 0 Then Debug.Print CStr(i+1) End If Else Debug.Print "Could not create task "; CStr(i) End If Next Debug.Print ' print how it took to create the tasks currentTime = Timer Debug.Print "Elapsed time is "; CStr(currentTime - previousTime); " seconds" previousTime = currentTime ' We can unlock main at this point. If it's time slice is about to end then another ' task may be able to run Call UnlockTask() ' Loop forever, monitoring the task counters Do ' We need to lock the main task to give it time to print the counter information Call LockTask() currentTime = Timer Debug.Print Debug.Print "***** Elapsed time is "; CStr(currentTime - previousTime); " seconds" previousTime = currentTime totalCount = 0 ' Calculate the sum of all of counters and then print out the mean totalCount = 0 For i = 0 to numberTasks-1 ' calculate address of this counter counterAddr = counters + i * SIZEOF(Byte) ' add on this counter 'Debug.Print CStr(RAMPeek(counterAddr)); " "; totalCount = totalCount + CLng(RAMPeek(counterAddr)) Next Debug.Print "Average count is "; CStr(CSng(totalCount)/CSng(numberTasks)) Call UnlockTask() ' At this point, the next runnable task gets a chance to execute Call Sleep(5.0) Loop End Sub ' This is the simple task that increments a counter. The counter is only a byte ' so it will wrap every 256 counts Public Sub Task(ByRef counterMemory() as Byte) Dim counter as Byte Alias counterMemory Do counter = counter + 1 ' Give some other task a chance after one increment Call Sleep(0) Loop End Sub