I'm trying to run a piece of code with multiple threads. My understanding is, even though threads are sharing process memory, each function calling from the thread has its own stack frame, registers. Therefore, calling the same function from multiple threads should not be a problem (please correct me if I'm wrong).
I have the following code. This code works normally with a single thread. My goal is to run some part of this code concurrently.
#include "rsa/config.h"
#include "rsa/aes.h"
#include "rsa/bignum.h"
#include "rsa/rsa.h"
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/resource.h>
#include <pthread.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define NUM_OF_THREAD 8
void thread_function(void * input){
printf("Test thread\n");
unsigned char private_encrypt[KEY_BUFFER_SIZE];
int total_dec=1000;
unsigned char * buffer = 0;
long length;
unsigned char msg_decrypted[KEY_LEN];
FILE * fp2 = fopen ("msg.enc", "rb");
int size1=KEY_BUFFER_SIZE;
if(fp2){
while(size1>0){
fread(private_encrypt,1,sizeof (private_encrypt),fp2);
size1=size1-1;
}
}
fclose(fp2);
FILE * fp = fopen ("rsa_priv.txt", "rb");
if (fp){
fseek (fp, 0, SEEK_END);
length = ftell (fp);
fseek (fp, 0, SEEK_SET);
buffer = calloc (1,length+1);
if (buffer){
fread (buffer, 1, length, fp);
}
fclose (fp);
}
// initialize rsaContext
rsa_context rsaContext;
rsa_init(&rsaContext,RSA_PKCS_V15, 0);
rsaContext.len=KEY_LEN;
// spliting keys and load into rsa context
const char s[3] = "= ";
char *token;
int k=0, size;
// get the first token
token = strtok(buffer, s);
// walk through other tokens
while( token != NULL ) {
size = strlen(token);
switch (k) {
case 1:
token[size-1]='\0';
mpi_read_string(&rsaContext.N, 16, token);
break;
case 3:
token[size-1]='\0';
mpi_read_string(&rsaContext.E, 16, token);
break;
case 5:
token[size-1]='\0';
mpi_read_string(&rsaContext.D, 16, token);
break;
case 7:
token[size-1]='\0';
mpi_read_string(&rsaContext.P, 16, token);
break;
case 9:
token[size-1]='\0';
mpi_read_string(&rsaContext.Q, 16, token);
break;
case 11:
token[size-1]='\0';
mpi_read_string(&rsaContext.DP, 16, token);
break;
case 13:
token[size-1]='\0';
mpi_read_string(&rsaContext.DQ, 16, token);
break;
case 15:
token[size-1]='\0';
mpi_read_string(&rsaContext.QP, 16, token);
break;
}
k=k+1;
token = strtok(NULL, "= \n");
}
printf("Here\n");
while (total_dec>=0) {
if( rsa_private(&rsaContext,private_encrypt, msg_decrypted) != 0 ) {
printf( "Decryption failed! %d\n", rsa_private(&rsaContext,private_encrypt, msg_decrypted));
}else{
printf("%d Decrypted plaintext-----> %s\n",total_dec, msg_decrypted );
}
total_dec--;
}
}
int main(){
int i;
clock_t t;
// total number of thread
pthread_t ths[NUM_OF_THREAD];
// start time count
t = clock();
for (i = 0; i < NUM_OF_THREAD; i++) {
pthread_create(&ths[i], NULL, thread_function, NULL);
}
for (i = 0; i < NUM_OF_THREAD; i++) {
void* res;
pthread_join(ths[i], &res);
}
// end time count
t = clock() - t;
double time_taken = ((double)t)/CLOCKS_PER_SEC; // in seconds
printf("Took %f seconds to execute \n", time_taken);
printf("Total Cycle %f \n", t);
return 0;
}
When I run the code with a single thread, the code works fine and produces desirable results. If I set NUM_OF_THREAD
to different values, my program starts acting weird. Some times all the thread created and works perfectly, sometimes threads are created but get segmentation fault after that. Sometimes a couple of threads work, a couple of threads don't.
Error type: 1 (set NUM_OF_THREAD 8
), output:
So, I try to run the code with 8 threads. Different attempts give me different results
$./multiThread
Test thread
Test thread
Test thread
Test thread
Test thread
Test thread
Test thread
Here
Here
Here
Here
Segmentation fault (core dumped)
Error type: 2 (set NUM_OF_THREAD 8
), output:
$./multiThread
Test thread
Test thread
Test thread
Test thread
Test thread
Here
Here
Test thread
Here
Here
Here
Decryption failed! -17156
Decryption failed! -17156
Segmentation fault (core dumped)
Error type: 3 (set NUM_OF_THREAD 8
), output:
In this trial, a couple of thread fails but some of them produce the desire results.
$./multiThread
Decryption failed! -17156
Decryption failed! -17156
.
.
.
.
3 Decrypted plaintext-----> xxxxxxxxxxx
2 Decrypted plaintext-----> xxxxxxxxxxx
2 Decrypted plaintext-----> xxxxxxxxxxx
1 Decrypted plaintext-----> xxxxxxxxxxx
1 Decrypted plaintext-----> xxxxxxxxxxx
0 Decrypted plaintext-----> xxxxxxxxxxx
0 Decrypted plaintext-----> xxxxxxxxxxx
Took 174.413690 seconds to execute
Total Cycle 174.413690
My hunch, the problem is coming from rsa_private()
. This is declared in #include "rsa/rsa.h"
. Is this considered a shared resource? If I'm not correct, can someone please tell me what I'm doing wrong here? What Can I do to fix this issue? I do not want to use a lock since it causes my code to slow down.
My CPU :Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz, Quad Core, 2 thread per core.