Call Reentrant Code with No Persistent or Global Data (UNIX Only) - MATLAB & Simulink (original) (raw)
Main Content
This example requires POSIX thread (pthread) libraries and, therefore, runs only on UNIX® platforms. It is a simple multithreaded example that uses no persistent or global data. Two threads call the MATLAB® function matrix_exp
with different sets of input data.
Provide a Main Function
To call the reentrant code, provide a main
function that:
- Includes the header file
matrix_exp.h
. - For each thread, allocates memory for stack data.
- Calls the
matrix_exp_initialize
housekeeping function. For more information, see Deploy Generated Code. - Calls
matrix_exp
. - Calls
matrix_exp_terminate
. - Frees the memory used for stack data.
For this example, main.c
contains:
#include <stdio.h> #include <stdlib.h> #include <pthread.h> #include "matrix_exp.h" #include "matrix_exp_initialize.h" #include "matrix_exp_terminate.h" #include "rtwtypes.h" #define NUMELEMENTS (160*160) typedef struct { real_T in[NUMELEMENTS]; real_T out[NUMELEMENTS]; matrix_expStackData* spillData; } IODATA; /* The thread_function calls the matrix_exp function written in MATLAB */ void *thread_function(void *dummyPtr) { IODATA *myIOData = (IODATA*)dummyPtr; matrix_exp_initialize(); matrix_exp(myIOData->spillData, myIOData->in, myIOData->out); matrix_exp_terminate(); } int main() { pthread_t thread1, thread2; int iret1, iret2; IODATA data1; IODATA data2; int32_T i; /*Initializing data for passing to the 2 threads*/ matrix_expStackData* sd1=(matrix_expStackData*)calloc(1,sizeof(matrix_expStackData)); matrix_expStackData* sd2=(matrix_expStackData*)calloc(1,sizeof(matrix_expStackData)); data1.spillData = sd1; data2.spillData = sd2; for (i=0;i<NUMELEMENTS;i++) { data1.in[i] = 1; data1.out[i] = 0; data2.in[i] = 1.1; data2.out[i] = 0; } /*Initializing the 2 threads and passing required data to the thread functions*/ printf("Starting thread 1...\n"); iret1 = pthread_create(&thread1, NULL, thread_function, (void*) &data1); if (iret1 != 0){ perror( "Thread 1 creation failed."); exit(EXIT_FAILURE); } printf("Starting thread 2...\n"); iret2 = pthread_create(&thread2, NULL, thread_function, (void*) &data2); if (iret2 != 0){ perror( "Thread 2 creation failed."); exit(EXIT_FAILURE); } /*Wait for both the threads to finish execution*/ iret1 = pthread_join(thread1, NULL); if (iret1 != 0){ perror( "Thread 1 join failed."); exit(EXIT_FAILURE); } iret2 = pthread_join(thread2, NULL); if (iret2 != 0){ perror( "Thread 2 join failed."); exit(EXIT_FAILURE); } free(sd1); free(sd2); printf("Finished Execution!\n"); exit(EXIT_SUCCESS); } |
---|
Generate Reentrant C Code
To generate code, run the following script at the MATLAB command prompt.
% This example can only be run on Unix platforms if ~isunix error('This example requires pthread libraries and can only be run on Unix.'); end % Setting the options for the Config object % Create a code gen configuration object cfg = coder.config('exe'); % Enable reentrant code generation cfg.MultiInstanceCode = true; % Set the post code generation command to be the 'setbuildargs' function cfg.PostCodeGenCommand = 'setbuildargs(buildInfo)'; % Compiling codegen -config cfg main.c matrix_exp.m -report -args ones(160,160) |
---|
This script:
- Generates an error message if the example is not running on a UNIX platform.
- Creates a code configuration object for generation of an executable.
- Enables the
MultiInstanceCode
option to generate reusable, reentrant code. - Uses the
PostCodeGenCommand
option to set the post code generation command to be thesetbuildargs
function. This function sets the-lpthread
flag to specify that the build include the pthread library.
function setbuildargs(buildInfo)
% The example being compiled requires pthread support.
% The -lpthread flag requests that the pthread library
% be included in the build
linkFlags = {'-lpthread'};
addLinkFlags(buildInfo, linkFlags);
For more information, see Build Process Customization. - Invokes
codegen
with the following options:-config
to pass in the code generation configuration objectcfg
.main.c
to include this file in the compilation.-report
to create a code generation report.-args
to specify an example input with class, size, and complexity.
Examine the Generated Code
codegen
generates a header file matrix_exp_types.h
, which defines the matrix_expStackData
global structure. This structure contains local variables that are too large to fit on the stack.
/* * matrix_exp_types.h * * Code generation for function 'matrix_exp' * */ #ifndef __MATRIX_EXP_TYPES_H__ #define __MATRIX_EXP_TYPES_H__ /* Include files */ #include "rtwtypes.h" /* Type Definitions */ #ifndef typedef_matrix_expStackData #define typedef_matrix_expStackData typedef struct { struct { double F[25600]; double Y[25600]; double X[25600]; } f0; } matrix_expStackData; #endif /*typedef_matrix_expStackData*/ #endif /* End of code generation (matrix_exp_types.h) */ |
---|
Run the Code
Call the code using the command:
The executable runs and reports completion.
See Also
Control Stack Space Usage | Stack Allocation and Performance