Quickstart: Adaptive Partitioning Thread Scheduler

This chapter provides you with a quick hands-on introduction to the thread scheduler. It assumes that you're running the Photon microGUI on your Neutrino system.

  1. Log in as root.
  2. Go to the directory that contains the buildfile for your system's boot image (e.g. /boot/build).
  3. Create a copy of the buildfile:
    cp qnxbasedma.build apsdma.build
      
  4. Edit the copy (e.g. apsdma.build).
  5. Search for procnto. The line might look like this:
    PATH=/proc/boot:/bin:/usr/bin:/opt/bin \
    LD_LIBRARY_PATH=/proc/boot:/lib:/usr/lib:/lib/dll:/opt/lib \
    procnto-instr
      

    Note: In a real buildfile, you can't use a backslash (\) character to divide a long line into shorter segments; we've only done that here to make the command easier to read.

  6. Add [module=aps] to the beginning of the line:
    [module=aps] PATH=/proc/boot:/bin:/usr/bin:/opt/bin \
    LD_LIBRARY_PATH=/proc/boot:/lib:/usr/lib:/lib/dll:/opt/lib \
    procnto-instr
      

    You can add commands to your buildfile to create partitions and start programs in them, but when you're experimenting with scheduler partitions, it's better to do it at runtime, so that you can easily manke changes as required. For more information, see the Setting Up and Using the Adaptive Partitioning Tread Scheduler chapter.

  7. Save your changes to the buildfile.
  8. Generate a new boot image:
    mkifs apsdma.build apsdma.ifs
      
  9. Put the new image in place. In order to ensure you can still boot your system if an error occurs, we recommend the following:
  10. Reboot your system.
  11. Log in as a typical user.

    Note: You don't have to be root to manipulate the partitions because the security options are initially not set. If you use the thread scheduler, you should choose the level of security that's appropriate. For more information about security for the thread scheduler, see the Security for Scheduler Partitions chapter in this guide, and the documentation for SchedCtl() in the Neutrino Library Reference.

  12. The thread scheduler automatically creates one partition, called System. Use the aps utility to create another partition:
    aps create -b20 partitionA
      

    Note: The new partition's budget is subtracted from its parent partition's budget (the System partition in this case).

  13. Use the aps utility to list the partitions on your system:
    $ aps show -l
                        +---- CPU Time ----+-- Critical Time --
    Partition name   id | Budget |    Used | Budget |      Used
    --------------------+------------------+-------------------
    System            0 |    80% |  14.14% |  100ms |   0.000ms
    partitionA        1 |    20% |   0.00% |    0ms |   0.000ms
    --------------------+------------------+-------------------
    Total               |   100% |  14.14% |
      

    Note: The -l option makes this command loop until you terminate it (e.g. by pressing Ctrl-C). For this example, leave it running, and start another terminal window to work in.

  14. Use the on command to start a process in the partition you just created called partitionA:
    on -Xaps=partitionA rebound &
      

    Note: Because rebound is a graphical application, it makes io-graphics (which runs in the System partition) and uses some CPU time. Don't set rebound to run at its highest speed, otherwise io-graphics will starve the shells that are also running in the System partition.

  15. Create another partition called partitionB and run rebound in that partition using the following commands:
    aps create -b20 partitionB
    on -Xaps=partitionB rebound &
      
  16. To determine which partitions your processes are running in, use the pidin sched command. For scheduler partitions, the ExtSched column displays the partition name.
  17. Create this program and name it greedy.c. It is a program that simply loops forever. Include the following code.
    #include <stdlib.h>
    
    int main( void )
    {
        while (1) {
        }
    
        return EXIT_SUCCESS;
    }
      
  18. Compile it, and then run it in one of the partitions where it will consume as much CPU as possible:
    qcc -o greedy greedy.c
    on -Xaps=partitionB ./greedy &
      

    The instance of rebound that's running in partitionB no longer recieves much (if any) CPU time, but the one in partitionA still does because the thread scheduler guarantees that partition 20% of the CPU time.

  19. Look at the output results from the aps utility. It will look something like this:
                        +---- CPU Time ----+-- Critical Time --
    Partition name   id | Budget |    Used | Budget |      Used
    --------------------+------------------+-------------------
    System            0 |    60% |  11.34% |  100ms |   0.000ms
    partitionA        1 |    20% |   2.12% |    0ms |   0.000ms
    partitionB        2 |    20% |  86.50% |    0ms |   0.000ms
    --------------------+------------------+-------------------
    Total               |   100% |  99.96% |
      

    Note that partitionB is using more than its budget of 20%. This occurs because the other partitions aren't using their budgets. Instead of running an idle thread in the other partitions, the thread scheduler gives unused time to the partitions that need it.

  20. Start another instance of the greedy application in partitionA using this command:
    on -Xaps=partitionA ./greedy &
      

    The instance of rebound in that partition grinds to a halt. The output of aps looks something like this:

                        +---- CPU Time ----+-- Critical Time --
    Partition name   id | Budget |    Used | Budget |      Used
    --------------------+------------------+-------------------
    System            0 |    60% |   1.73% |  100ms |   0.000ms
    partitionA        1 |    20% |  48.91% |    0ms |   0.000ms
    partitionB        2 |    20% |  49.32% |    0ms |   0.000ms
    --------------------+------------------+-------------------
    Total               |   100% |  99.96% |
      

    The System partition's unused time is divided between the other two partitions.

  21. Start another instance of the greedy application in the System partition:
    on -Xaps=System ./greedy &
      

    There's now no free time left in the system, so each partition gets only its minimum guaranteed CPU time. The output of the aps utility looks something like this:

                        +---- CPU Time ----+-- Critical Time --
    Partition name   id | Budget |    Used | Budget |      Used
    --------------------+------------------+-------------------
    System            0 |    60% |  59.99% |  100ms |   0.000ms
    partitionA        1 |    20% |  19.97% |    0ms |   0.000ms
    partitionB        2 |    20% |  19.99% |    0ms |   0.000ms
    --------------------+------------------+-------------------
    Total               |   100% |  99.96% |
      
  22. If you slay the instances of greedy, the instances of rebound come back to life, and the consumption of CPU time drops.

Because you created the partitions at runtime instead of in your OS image, the new partitions will disappear when you restart the system.