cmsis rtos demo: mutex

Dependencies:   mbed-rtos mbed

main.cpp

Committer:
cnhzcy14
Date:
2013-01-06
Revision:
1:1308d7d6d53e
Parent:
0:fba50ae123e6

File content as of revision 1:1308d7d6d53e:

/*****************************************************************************
 * DESCRIPTION:
 *   This example program illustrates the use of mutex variables
 *   in a threads program. This version was obtained by modifying the
 *   serial version of the program (dotprod_serial.c) which performs a
 *   dot product. The main data is made available to all threads through
 *   a globally accessible  structure. Each thread works on a different
 *   part of the data. The main thread waits for all the threads to complete
 *   their computations, and then it prints the resulting sum.
 * SOURCE: Vijay Sonnad, IBM
 * MODIFICATOR: (Simon) CHENG Ye
 * LAST REVISED: 06/JAN/2013
 ******************************************************************************/

#include "mbed.h"
#include "cmsis_os.h"

Serial debug(USBTX, USBRX);


/*
 * The following structure contains the necessary information
 * to allow the function "dotprod" to access its input data and
 * place its output into the structure.  This structure is
 * unchanged from the sequential version.
 */
typedef struct
{
    double      *a;
    double      *b;
    double     sum;
    int     veclen;
} DOTDATA;

/* Define globally accessible variables and a mutex */
#define NUMTHRDS 4
#define VECLEN 200  //Use a smaller size vector for limited memeory space on mbed
DOTDATA dotstr;
osMutexId stdio_mutex;
osMutexDef(stdio_mutex);

/*
 * The function dotprod is activated when the thread is created.
 * As before, all input to this routine is obtained from a structure
 * of type DOTDATA and all output from this function is written into
 * this structure. The benefit of this approach is apparent for the
 * multi-threaded program: when a thread is created we pass a single
 * argument to the activated function - typically this argument
 * is a thread number. All  the other information required by the
 * function is accessed from the globally accessible structure.
 */
void dotprod(void const *arg)
{
    /* Define and use local variables for convenience */
    osThreadId id;
    int i, start, end, len ;
    long offset;
    double mysum, *x, *y;
    offset = (long)arg;

    len = dotstr.veclen;
    start = offset*len;
    end   = start + len;
    x = dotstr.a;
    y = dotstr.b;

    /*
     * Perform the dot product and assign result
     * to the appropriate variable in the structure.
     */
    mysum = 0;
    for (i=start; i<end ; i++)
        mysum += (x[i] * y[i]);

    /*
     * Lock a mutex prior to updating the value in the shared
     * structure, and unlock it upon updating.
     */
    osMutexWait(stdio_mutex, osWaitForever);
    dotstr.sum += mysum;
    printf("Thread %ld did %d to %d:  mysum=%f global sum=%f\n",offset,start,end,mysum,dotstr.sum);
    osMutexRelease(stdio_mutex);

    id = osThreadGetId();
    osThreadTerminate(id);
}

void t0(void const *argument) {dotprod(argument);}
osThreadDef(t0, osPriorityNormal, DEFAULT_STACK_SIZE);

void t1(void const *argument) {dotprod(argument);}
osThreadDef(t1, osPriorityNormal, DEFAULT_STACK_SIZE);

void t2(void const *argument) {dotprod(argument);}
osThreadDef(t2, osPriorityNormal, DEFAULT_STACK_SIZE);

void t3(void const *argument) {dotprod(argument);}
osThreadDef(t3, osPriorityNormal, DEFAULT_STACK_SIZE);

/*
 * The main program creates threads which do all the work and then
 * print out result upon completion. Before creating the threads,
 * The input data is created. Since all threads update a shared structure, we
 * need a mutex for mutual exclusion. The main thread needs to wait for
 * all threads to complete, it waits for each one of the threads. We specify
 * a thread attribute value that allow the main thread to join with the
 * threads it creates. Note also that we free up handles  when they are
 * no longer needed.
 */
int main()
{
    debug.baud(57600);

    long i;
    double *a, *b;

    /* Assign storage and initialize values */
    a = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
    b = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));

    for (i=0; i<VECLEN*NUMTHRDS; i++)
    {
        a[i]=1;
        b[i]=a[i];
    }

    dotstr.veclen = VECLEN;
    dotstr.a = a;
    dotstr.b = b;
    dotstr.sum=0;

    stdio_mutex = osMutexCreate(osMutex(stdio_mutex));

    /* Create threads to perform the dotproduct  */
    for(i=0;i<NUMTHRDS;i++)
    {
        /* Each thread works on a different set of data.
         * The offset is specified by 'i'. The size of
         * the data for each thread is indicated by VECLEN.
         */
        if(i==0) osThreadCreate(osThread(t0), (void *)i);
        if(i==1) osThreadCreate(osThread(t1), (void *)i);
        if(i==2) osThreadCreate(osThread(t2), (void *)i);
        if(i==3) osThreadCreate(osThread(t3), (void *)i);
    }

    printf ("Sum =  %f \n", dotstr.sum);
    free (a);
    free (b);
}