Call Reentrant Code with No Persistent or Global Data (UNIX Only)
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:
system('./matrix_exp')
See Also
Control Stack Space Usage | Stack Allocation and Performance