Threads and Processors

General discussion about anything related to Ultibo.
develone
Posts: 308
Joined: Wed Dec 28, 2016 7:40 pm
Location: El Paso Tx USA

Re: Threads and Processors

Postby develone » Tue Nov 07, 2017 8:50 pm

Added TFTP & Remote shell

See the diff between commit 0c31640765844e49d7c82be8dab02aa403eeb06a
& commit b821478e67bc38d8d7fa7711effe9c866d0926d5


https://github.com/develone/Ultibo_DedicatedCPU




Following the build of kernel7.img
For the RPi2B
/home/pi/Ultibo_DedicatedCPU/RPi2
tftp 192.168.1.195 < cmdstftp

Following the build of kernel7.img
For the RPi3B
/home/pi/Ultibo_DedicatedCPU/Ultibo_DedicatedCPU_2nd/RPi3
tftp 192.168.1.185 < cmdstftp

https://github.com/develone/Ultibo_Dedi ... oggles.odp

provides a power point of the effort.

This is now using http://abyz.me.uk/rpi/pigpio/examples.html#Misc_code
with piscope to see the initial toggles by RPi2B.

Still struggling with Asm for RPi3 to detect the toggles of RPi2B.
Any and all help is appreciated.

tftp 192.168.1.185 < cmdstftp


provides a power point of the effort.
Attachments
piscope_on.png
piscope_on.png (26.62 KiB) Viewed 1045 times
develone
Posts: 308
Joined: Wed Dec 28, 2016 7:40 pm
Location: El Paso Tx USA

Re: Threads and Processors

Postby develone » Thu Nov 09, 2017 12:58 am

Added a var GPIO_IN to pass the GPIO read asm to Pascal.
Seeing GPIO_IN 8192 in left window when GPIO_PIN_16 is lo.
Seeing GPIO_IN 8193 in left window when GPIO_PIN_16 is hi.

Now seeing the Counter on RPi3, close to value Counter on RPi2.

Just updated the repository
https://github.com/develone/Ultibo_DedicatedCPU

Which has two projects I for the RPi2B to toggle GPIO_PIN_16.
The 2nd for the RPi3B to count the toggles on GPIO_PIN_16 from the RP2B.
prb
Posts: 45
Joined: Tue Oct 10, 2017 8:53 am

Re: Threads and Processors

Postby prb » Thu Nov 09, 2017 1:57 pm

Develone, what exactly are you trying to accomplish now?
develone
Posts: 308
Joined: Wed Dec 28, 2016 7:40 pm
Location: El Paso Tx USA

Re: Threads and Processors

Postby develone » Thu Nov 09, 2017 5:06 pm

The rates that your method gets, 55MHz RPi Zero,
40 MHz RPi2B, and 60 MHz RPi3B. I assume, that all cpu resources
are working for period that the toggle is counting, to determine
the GPIO performance. Your method exceeds or equals the benchmarks found
http://codeandlife.com/2012/07/03/benchmarking-raspberry-pi-gpio-speed/


I want to demonstrate a constant toggle from cpu 3.
This I am told, is needed to increase the accuracy of the GPS receiver.
Not sure what steps will be needed to interface with my GPS reciever.

Since I do not have a scope, the use of the RPi3B to count the toggles of RPi2B
provided some interesting challenges.
The pigpio & piscope in Linux, was just trying to see if the RPi2B was indeed
toggling gpio pin 16. Leds could not be used at 5.9 MHz that the RPi2B is toggling.

I want to read the UART with GPS attached on Dedicated CPU cpu 2.

https://github.com/develone/ultibo_serial_testing/tree/master/RPi2/RPi_UART_GPS


This will require creating
https://github.com/develone/Ultibo_DedicatedCPU/blob/master/RPi2/ThreadUnit_GPS.pas


The other two processor could then be used to interface with the outside world.

In addition, I was interested in learning asembly language which was a struggle.

This is more of learning effort, which Ultibo provides a great set of tools.
develone
Posts: 308
Joined: Wed Dec 28, 2016 7:40 pm
Location: El Paso Tx USA

Re: Threads and Processors

Postby develone » Thu Nov 16, 2017 4:14 pm

I am trying to start 2 DedicatedCPUs on CPU_2 & CPU_3.

Added to Ultibo_DedicatedCPU/RPi2/InitUnit.pas

Code: Select all

+ {Disable thread allocation for CPU 2}
+ SchedulerAllocationDisable(CPU_ID_2);


Added to Ultibo_DedicatedCPU/RPi2/DedicatedCPU.lpr

Code: Select all

+ //StartDedicatedThread(LeftWindow);
+ StartDedicatedThreadGPS(LeftWindow);
  StartDedicatedThread(LeftWindow);


Only when I get the error message

Error, 1 threads remaining on CPU_ID_2

does DedicatedCPU CPU_ID_3 start.

The repository is the following.

https://github.com/develone/Ultibo_DedicatedCPU


Any and all help is appreciated.
User avatar
Ultibo
Site Admin
Posts: 2255
Joined: Sat Dec 19, 2015 3:49 am
Location: Australia

Re: Threads and Processors

Postby Ultibo » Mon Nov 20, 2017 10:52 am

develone wrote:I am trying to start 2 DedicatedCPUs on CPU_2 & CPU_3.
...
Only when I get the error message

Error, 1 threads remaining on CPU_ID_2

I have now tested running two dedicated CPUs threads (one on CPU2 and one on CPU3) and it all worked correctly in my tests.

Since the example includes the WebStatus unit, can you look at the Thread List page and see which thread is remaining on CPU2 to generate this error.

Remember there will be several (Idle, IRQ, FIQ, SWI) that don't get migrated off as per the comments in the example, what you are looking for is one of the normal threads still showing as CPU2.
Ultibo.org | Make something amazing
https://ultibo.org
develone
Posts: 308
Joined: Wed Dec 28, 2016 7:40 pm
Location: El Paso Tx USA

Re: Threads and Processors

Postby develone » Mon Nov 20, 2017 5:09 pm

This is what I see every few times Ultibo reboots.

Migrated 4 Threads from CPU_ID_2

Error, 1 threads remaining on CPU_ID_2

The TheadUnit_GPS displays

Waiting for a Messagegps from main thread


http://192.168.1.195/status/threadlist

Dedicated CPU Thread GPS THREAD_STATE_RECEIVE THREAD_PRIORITY_NORMAL CPU_ID_2

Idle2 THREAD_STATE_RUNNING THREAD_PRIORITY_IDLE CPU_ID_2

SWI2 THREAD_STATE_READY THREAD_PRIORITY_NONE CPU_ID_2

FIQ2 THREAD_STATE_READY THREAD_PRIORITY_NONE CPU_ID_2

IRQ2 THREAD_STATE_READY THREAD_PRIORITY_NONE CPU_ID_2


I don't see any other threads running on CPU_ID_2.

When I do not get the error

Error, 1 threads remaining on CPU_ID_2

Only TheadUnit_GPS starts.
Brutus
Posts: 32
Joined: Sun Jan 20, 2019 1:24 pm

Re: Threads and Processors

Postby Brutus » Tue Feb 05, 2019 3:52 am

This is an old thread, but this might be useful to somebody:

When the above happens, you'll find out that the name of the remaining (non migrable thread) contains the string "PRIORITY".
From experience (I haven't enough Ultibo knowledge to figure out why), but if you didn't manage to migrate that thread after 1 second, it doesn't really matter because this means it is never used...

So just leave it alone and start your dedicated thread! :)
User avatar
Ultibo
Site Admin
Posts: 2255
Joined: Sat Dec 19, 2015 3:49 am
Location: Australia

Re: Threads and Processors

Postby Ultibo » Tue Feb 05, 2019 11:19 pm

Brutus wrote:When the above happens, you'll find out that the name of the remaining (non migrable thread) contains the string "PRIORITY".
From experience (I haven't enough Ultibo knowledge to figure out why), but if you didn't manage to migrate that thread after 1 second, it doesn't really matter because this means it is never used...

So just leave it alone and start your dedicated thread!

If you have threads remaining that include the string Priority in their name they are most likely either "Priority Timer" or "Priority Worker" threads and neither of them should be ignored, the priority timers are used for critical tasks like the TCP timer and the priority workers are used by high throughput drivers like the LAN78XX and SMSC95XX.

The reason these threads still appear on the dedicated CPU in spite of the call to SchedulerAllocationDisable() is because they are allocated during the boot process which runs before the initialization.

You can easily trigger these priority timer and worker (or any timer and worker) threads to run (and therefore migrate to a new CPU) by submitting either a timer or worker request to be performed.

To submit a timer request which will be executed by the "Timer" threads call TimerCreateEx(), to have the request execute on a "Priority Timer" thread pass the flag TIMER_FLAG_PRIORITY. The actual function that the request calls can do nothing and simply return immediately, it is the act of passing through the scheduler that causes a thread to migrate when requested so simply waking them up is all that is needed.

To submit a worker request which will execute on a "Worker" thread call WorkerScheduleEx() and to use a "Priority Worker" thread pass the flag WORKER_FLAG_PRIORITY, again the called function can do nothing.

There are a configurable number of both timer and worker threads, controlled by variables in GlobalConfig (see TIMER_THREAD_COUNT, WORKER_THREAD_COUNT etc) so you may have to repeat the timer or worker request multiple times in order to force each thread to run but the whole process should only take a few hundred milliseconds at most.

It is important to remember that Ultibo implements true zero overhead waiting for threads, so a thread can be in a wait state for multiple seconds, minutes or hours (even days, weeks or months) and never consume a single CPU cycle until it is woken and made ready to run.
Ultibo.org | Make something amazing
https://ultibo.org
Brutus
Posts: 32
Joined: Sun Jan 20, 2019 1:24 pm

Re: Threads and Processors

Postby Brutus » Wed Feb 06, 2019 4:41 am

Ultibo wrote:If you have threads remaining that include the string Priority in their name they are most likely either "Priority Timer" or "Priority Worker" threads and neither of them should be ignored, the priority timers are used for critical tasks like the TCP timer and the priority workers are used by high throughput drivers like the LAN78XX and SMSC95XX.


Thanks, I don't use any network in my current application so this is the reason why I didn't manage to migrate and wasn't bothered with these threads.

Ultibo wrote:To submit a timer request which will be executed by the "Timer" threads call TimerCreateEx(), to have the request execute on a "Priority Timer" thread pass the flag TIMER_FLAG_PRIORITY. The actual function that the request calls can do nothing and simply return immediately, it is the act of passing through the scheduler that causes a thread to migrate when requested so simply waking them up is all that is needed.

To submit a worker request which will execute on a "Worker" thread call WorkerScheduleEx() and to use a "Priority Worker" thread pass the flag WORKER_FLAG_PRIORITY, again the called function can do nothing.


Great, now I understand and can make my code cleaner...

Ultibo wrote:There are a configurable number of both timer and worker threads, controlled by variables in GlobalConfig (see TIMER_THREAD_COUNT, WORKER_THREAD_COUNT etc) so you may have to repeat the timer or worker request multiple times in order to force each thread to run but the whole process should only take a few hundred milliseconds at most.


OK, I will try something like this:

Code: Select all

      Debug('Migration',9, 'Migrating thread "' + ThreadGetName(ThreadCurrent^.Handle) + '" to ' + CPUIDToString(TARGETCPU) + ' ');
      CountLimit := 0;
      while (ThreadGetCPU(ThreadCurrent^.Handle) <> CPU_ID_0) and (CountLimit < 5) do
       begin
        Sleep(500);
        Debug ('Migration',9, '#');
        Inc(CountLimit);
        if pos('PRIORITY_WORKER', ThreadGetName(ThreadCurrent^.Handle)) = 0 then
          WorkerScheduleEx(0,WORKER_FLAG_PRIORITY,TWorkerTask(ThreadCurrent^.Handle),nil,nil);
        if pos('PRIORITY_TIMER', ThreadGetName(ThreadCurrent^.Handle)) = 0 then
          TimerCreateEx(0,TIMER_STATE_DISABLED,TIMER_FLAG_PRIORITY, nil, nil);
       end;
      DebugNL ('Migration',9, ' ');
      if CountLimit = 5 then
      begin
        DebugNl('Migration',9, 'Failed to migrate thread "' + ThreadGetName(ThreadCurrent^.Handle) + '"');
      end;

Return to “Discussion”

Who is online

Users browsing this forum: dieselnutjob and 1 guest