Apple Developer Connection
Member Login Log In | Not a Member? Contact ADC

< Previous PageNext Page > Hide TOC

Calculating the Intertask Signaling Time

When using Multiprocessing Services tasks, the amount of time used by the task should be much greater than the time taken to pass notifications to the task. This intertask signaling time is generally between 20 and 50 microseconds. If you want to explicitly calculate the signaling time, you can use the code in Listing B-1 to do so.

Listing B-1  Calculating the intertask signaling time

#include <Multiprocessing.h>
 
#include <Types.h>
#include <stdio.h>
#include <stdlib.h>
#include <sioux.h>
#include <math64.h>
#include <DriverServices.h>
 
 
enum  {
    aQueue = 0,
    aSemaphore,
    anEvent
} reflectOP;
 
MPOpaqueID waiterID, postID;
 
 
static OSStatus Reflector ( )
{
    void    *p1,*p2,*p3;
    MPEventFlags events;
 
    while (true)
    {
        switch (reflectOP)
        {
            case aQueue:
                MPWaitOnQueue((MPQueueID) waiterID, &p1, &p2, &p3, kDurationForever);
                break;
 
            case aSemaphore:
                MPWaitOnSemaphore((MPSemaphoreID) waiterID, kDurationForever);
                break;
 
            case anEvent:
                MPWaitForEvent((MPEventID) waiterID, &events, kDurationForever);
                break;
 
            default:
                return -123;
        }
 
        switch (reflectOP)
        {
            case aQueue:
                MPNotifyQueue((MPQueueID) postID, &p1, &p2, &p3);
                break;
 
            case aSemaphore:
                MPSignalSemaphore((MPSemaphoreID) postID);
                break;
 
            case anEvent:
                MPSetEvent((MPEventID) postID, 0x01010101);
                break;
 
            default:
                return -123;
        }
    }
 
    return -123;
}
 
 
static float HowLong(
    AbsoluteTime endTime,
    AbsoluteTime bgnTime
    )
{
    AbsoluteTime absTime;
    Nanoseconds  nanosec;
 
    absTime = SubAbsoluteFromAbsolute(endTime, bgnTime);
    nanosec = AbsoluteToNanoseconds(absTime);
    return (float) UnsignedWideToUInt64( nanosec ) / 1000.0;
}
 
 
void main ( void )
{
    OSStatus            err;
    MPTaskID            task;
    UInt32              i, count;
    void                *p1,*p2,*p3;
    MPEventFlags events;
    AbsoluteTime nowTime, bgnTime;
    float               uSec;
    char                buff[10];
 
 
    /* Set the console window defaults */
    /* (this is a Metrowerks CodeWarrior thing). */
    SIOUXSettings.autocloseonquit    = true;
    SIOUXSettings.asktosaveonclose  = false;
    SIOUXSettings.showstatusline    = false;
    SIOUXSettings.columns           = 100;
    SIOUXSettings.rows              = 20;
    SIOUXSettings.fontsize          = 10;
//  SIOUXSettings.fontid             = monaco;
    SIOUXSettings.standalone         = true;
 
 
//  DebugStr ( "\pStarting" );
 
    /*  Can't get very far without this one. */
    if  (!MPLibraryIsLoaded())
    {
        printf("The MP library did not load.\n");
        return;
    }
 
 
    /*  Find the overhead up UpTime. Perform a bunch of calls to average out */
    /*   cache effects. */
    printf("\n");
 
    bgnTime = UpTime();
    for (i=0; i<16; i++)
    {
        nowTime = UpTime();
    }
 
    uSec  = HowLong(nowTime, bgnTime);
    uSec /=  16.0;
    printf(" UpTime overhead: %.3f usec \n", uSec);
 
    /*  Time intertask communication. */
    printf("\n Queues\n");
 
    reflectOP = aQueue;
    MPCreateQueue((MPQueueID*) &waiterID);
    MPCreateQueue((MPQueueID*) &postID);
 
    bgnTime = UpTime();
    err = MPCreateTask( Reflector,
                  NULL,
                  0,
                  NULL,
                  0,
                  0,
                  kNilOptions,
                  &task );
    nowTime = UpTime();
    uSec  = HowLong(nowTime, bgnTime);
    printf(" MPCreateTask overhead: %.3f usec (may vary significantly) \n", uSec);
    if (err != noErr)
    {
        printf(" Task not created!\n");
        return;
    }
 
    count = 100000;
    bgnTime = UpTime();
    for (i=0; i<count; i++)
    {
        MPNotifyQueue((MPQueueID) waiterID, 0, 0, 0);
        while (true)
        {
            err = MPWaitOnQueue((MPQueueID) postID, &p1, &p2, &p3, kDurationImmediate);
            if (err != kMPTimeoutErr) break;
        }
    }
    nowTime = UpTime();
    uSec  = HowLong(nowTime, bgnTime);
    uSec  /= ((float) count / 2.0); // Two trips.
    printf(" Intertask signaling using queues overhead: %.3f usec \n", uSec);
 
    /*  Time intertask communication.
    */
    MPTerminateTask(task, 123);
    printf("\n Semaphores\n");
 
    reflectOP = aSemaphore;
 
    MPCreateSemaphore(1, 0, (MPSemaphoreID*) &waiterID);
    MPCreateSemaphore(1, 0, (MPSemaphoreID*) &postID);
 
    bgnTime = UpTime();
    err = MPCreateTask( Reflector,
                  NULL,
                  0,
                  NULL,
                  0,
                  0,
                  kNilOptions,
                  &task );
    nowTime = UpTime();
    uSec  = HowLong(nowTime, bgnTime);
    printf(" MPCreateTask overhead: %.3f usec (may vary significantly) \n", uSec);
    if (err != noErr)
    {
        printf(" Task not created!\n");
        return;
    }
 
    count = 100000;
    bgnTime = UpTime();
    for (i=0; i<count; i++)
    {
        MPSignalSemaphore((MPSemaphoreID) waiterID);
        while (true)
        {
            err = MPWaitOnSemaphore((MPSemaphoreID) postID, kDurationImmediate);
            if (err != kMPTimeoutErr) break;
        }
    }
    nowTime = UpTime();
    uSec  = HowLong(nowTime, bgnTime);
    uSec  /= ((float) count / 2.0); // Two trips.
    printf(" Intertask signaling using semaphores overhead: %.3f usec \n", uSec);
 
 
    /*  Time intertask communication. */
    MPTerminateTask(task, 123);
    printf("\n Event Groups\n");
 
    reflectOP = anEvent;
    MPCreateEvent((MPEventID*) &waiterID);
    MPCreateEvent((MPEventID*) &postID);
 
    bgnTime = UpTime();
    err = MPCreateTask( Reflector,
                  NULL,
                  0,
                  NULL,
                  0,
                  0,
                  kNilOptions,
                  &task );
    nowTime = UpTime();
    uSec  = HowLong(nowTime, bgnTime);
    printf(" MPCreateTask overhead: %.3f usec (may vary significantly) \n", uSec);
    if (err != noErr)
    {
        printf(" Task not created!\n");
        return;
    }
 
    count = 100000;
    bgnTime = UpTime();
    for (i=0; i<count; i++)
    {
        MPSetEvent((MPEventID) waiterID, 0x01);
        while (true)
        {
            err = MPWaitForEvent((MPEventID) postID, &events, kDurationImmediate);
            if (err != kMPTimeoutErr) break;
        }
    }
    nowTime = UpTime();
    uSec  = HowLong(nowTime, bgnTime);
    uSec  /= ((float) count / 2.0); // Two trips.
    printf(" Intertask signaling using events overhead: %.3f usec \n", uSec);
 
    gets(buff);
 
}
 


< Previous PageNext Page > Hide TOC


Last updated: 2007-10-31




Did this document help you?
Yes: Tell us what works for you.

It’s good, but: Report typos, inaccuracies, and so forth.

It wasn’t helpful: Tell us what would have helped.
Get information on Apple products.
Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Copyright © 2007 Apple Inc.
All rights reserved. | Terms of use | Privacy Notice