Ye Cheng / Mbed 2 deprecated cmsis_rtos_demo_mutex

Dependencies:   mbed-rtos mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*****************************************************************************
00002  * DESCRIPTION:
00003  *   This example program illustrates the use of mutex variables
00004  *   in a threads program. This version was obtained by modifying the
00005  *   serial version of the program (dotprod_serial.c) which performs a
00006  *   dot product. The main data is made available to all threads through
00007  *   a globally accessible  structure. Each thread works on a different
00008  *   part of the data. The main thread waits for all the threads to complete
00009  *   their computations, and then it prints the resulting sum.
00010  * SOURCE: Vijay Sonnad, IBM
00011  * MODIFICATOR: (Simon) CHENG Ye
00012  * LAST REVISED: 06/JAN/2013
00013  ******************************************************************************/
00014 
00015 #include "mbed.h"
00016 #include "cmsis_os.h"
00017 
00018 Serial debug(USBTX, USBRX);
00019 
00020 
00021 /*
00022  * The following structure contains the necessary information
00023  * to allow the function "dotprod" to access its input data and
00024  * place its output into the structure.  This structure is
00025  * unchanged from the sequential version.
00026  */
00027 typedef struct
00028 {
00029     double      *a;
00030     double      *b;
00031     double     sum;
00032     int     veclen;
00033 } DOTDATA;
00034 
00035 /* Define globally accessible variables and a mutex */
00036 #define NUMTHRDS 4
00037 #define VECLEN 200  //Use a smaller size vector for limited memeory space on mbed
00038 DOTDATA dotstr;
00039 osMutexId stdio_mutex;
00040 osMutexDef(stdio_mutex);
00041 
00042 /*
00043  * The function dotprod is activated when the thread is created.
00044  * As before, all input to this routine is obtained from a structure
00045  * of type DOTDATA and all output from this function is written into
00046  * this structure. The benefit of this approach is apparent for the
00047  * multi-threaded program: when a thread is created we pass a single
00048  * argument to the activated function - typically this argument
00049  * is a thread number. All  the other information required by the
00050  * function is accessed from the globally accessible structure.
00051  */
00052 void dotprod(void const *arg)
00053 {
00054     /* Define and use local variables for convenience */
00055     osThreadId id;
00056     int i, start, end, len ;
00057     long offset;
00058     double mysum, *x, *y;
00059     offset = (long)arg;
00060 
00061     len = dotstr.veclen;
00062     start = offset*len;
00063     end   = start + len;
00064     x = dotstr.a;
00065     y = dotstr.b;
00066 
00067     /*
00068      * Perform the dot product and assign result
00069      * to the appropriate variable in the structure.
00070      */
00071     mysum = 0;
00072     for (i=start; i<end ; i++)
00073         mysum += (x[i] * y[i]);
00074 
00075     /*
00076      * Lock a mutex prior to updating the value in the shared
00077      * structure, and unlock it upon updating.
00078      */
00079     osMutexWait(stdio_mutex, osWaitForever);
00080     dotstr.sum += mysum;
00081     printf("Thread %ld did %d to %d:  mysum=%f global sum=%f\n",offset,start,end,mysum,dotstr.sum);
00082     osMutexRelease(stdio_mutex);
00083 
00084     id = osThreadGetId();
00085     osThreadTerminate(id);
00086 }
00087 
00088 void t0(void const *argument) {dotprod(argument);}
00089 osThreadDef(t0, osPriorityNormal, DEFAULT_STACK_SIZE);
00090 
00091 void t1(void const *argument) {dotprod(argument);}
00092 osThreadDef(t1, osPriorityNormal, DEFAULT_STACK_SIZE);
00093 
00094 void t2(void const *argument) {dotprod(argument);}
00095 osThreadDef(t2, osPriorityNormal, DEFAULT_STACK_SIZE);
00096 
00097 void t3(void const *argument) {dotprod(argument);}
00098 osThreadDef(t3, osPriorityNormal, DEFAULT_STACK_SIZE);
00099 
00100 /*
00101  * The main program creates threads which do all the work and then
00102  * print out result upon completion. Before creating the threads,
00103  * The input data is created. Since all threads update a shared structure, we
00104  * need a mutex for mutual exclusion. The main thread needs to wait for
00105  * all threads to complete, it waits for each one of the threads. We specify
00106  * a thread attribute value that allow the main thread to join with the
00107  * threads it creates. Note also that we free up handles  when they are
00108  * no longer needed.
00109  */
00110 int main()
00111 {
00112     debug.baud(57600);
00113 
00114     long i;
00115     double *a, *b;
00116 
00117     /* Assign storage and initialize values */
00118     a = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
00119     b = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
00120 
00121     for (i=0; i<VECLEN*NUMTHRDS; i++)
00122     {
00123         a[i]=1;
00124         b[i]=a[i];
00125     }
00126 
00127     dotstr.veclen = VECLEN;
00128     dotstr.a = a;
00129     dotstr.b = b;
00130     dotstr.sum=0;
00131 
00132     stdio_mutex = osMutexCreate(osMutex(stdio_mutex));
00133 
00134     /* Create threads to perform the dotproduct  */
00135     for(i=0;i<NUMTHRDS;i++)
00136     {
00137         /* Each thread works on a different set of data.
00138          * The offset is specified by 'i'. The size of
00139          * the data for each thread is indicated by VECLEN.
00140          */
00141         if(i==0) osThreadCreate(osThread(t0), (void *)i);
00142         if(i==1) osThreadCreate(osThread(t1), (void *)i);
00143         if(i==2) osThreadCreate(osThread(t2), (void *)i);
00144         if(i==3) osThreadCreate(osThread(t3), (void *)i);
00145     }
00146 
00147     printf ("Sum =  %f \n", dotstr.sum);
00148     free (a);
00149     free (b);
00150 }
00151 
00152