C concurrent array allocation and free - c

I am using array with 2 threads. One is writing to it and another reading. You can assume that reading is slower than writing. The reader and writer are separate pthreads. As far as I know sharing an array as a global variable between those threads is safe.
So overall picture is like:
char ** array;
void writer(void){
for (unsigned long i = 0; i < maxArraySize; i++){
array[i] = malloc(someSize);
array[i] = someCharArray;
}
void reader(void){
for (unsigned long i = 0; i < maxArraySize; i++){
if(array[i] == NULL){ // in case reader is faster
i--;
continue;
}
useData(array[i]);
free(array[i]); // HERE IS MY QUESTION..
}
main(){
array = malloc(maxArraySize);
pthread_t reader, writer;
pthread_create( &reader, NULL, reader, NULL);
pthread_create( &writer, NULL, writer, NULL);
}
My question is related with line where I free i'th element of array. Is it safe to do it? Because when I free i'th element, at the same time, write is writing to array. So can there be a case that writer gets wrong address as it can lose the head pointer?

No it is not safe if you read during a write without a special instruction the result is undefined. You could get any value, though it is unlikely that you will see any other than NULL or the one you had assigned.
As others have mentioned in the comments the un-initialized array may contain anything (it is undefined) though it is likely zeroed before the kernel gave it to you.
If you want safety you need a locking mechanism such as a semaphore (http://man7.org/linux/man-pages/man3/sem_init.3.html).
char ** array;
// Allows access while non zero
sem_t sem;
void writer(void){
for (unsigned long i = 0; i < maxArraySize; i++){
array[i] = malloc(someSize);
array[i] = someCharArray;
// Increment semaphore.
sem_post(&sem);
}
void reader(void){
for (unsigned long i = 0; i < maxArraySize; i++){
// Will return -1 if the semaphore is not at zero
// Will return 0 if semaphore is greater than zero and decrement it.
if(sem_trywait(&sem)){ // in case reader is faster
i--;
continue;
}
useData(array[i]);
free(array[i]); // HERE IS MY QUESTION..
}
main(){
// Initialize semaphore to zero
sem_init(&sem, 0 , 0);
// Initialize array to have maxArraySize elements.
array = malloc(maxArraySize * sizeof(*array));
pthread_t reader, writer;
pthread_create( &reader, NULL, reader, NULL);
pthread_create( &writer, NULL, writer, NULL);
}
This should be fast but will spin your cpu doing a lot of nothing at the sem_trywait. Use sem_wait if you can wait a little longer and do not need the spinning.
I also corrected the bug in your malloc statement because it was not allocating enough space for maxArraySize char * items.

Related

Why does my simple counting program take longer to run with multiple threads? (in C)

Here's my code:
#define COUNT_TO 100000000
#define MAX_CORES 4
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
long long i = 0;
void* start_counting(void *arg){
for(;;){
pthread_mutex_lock(&mutex);
if(i >= COUNT_TO){
pthread_mutex_unlock(&mutex);
return NULL;
}
i++;
pthread_mutex_unlock(&mutex);
//printf("i = %lld\n", i);
}
}
int main(int argc, char* argv[]){
int i = 0;
pthread_t * thread_group = malloc(sizeof(pthread_t) * MAX_CORES);
for(i = 0; i < MAX_CORES; i++){
pthread_create(&thread_group[i], NULL, start_counting, NULL);
}
for(i = 0; i < MAX_CORES; i++){
pthread_join(thread_group[i], NULL);
}
return 0;
}
This is what your threads do:
Read the value of i.
Increment the value we read.
Write back the incremented value of i.
Go to step 1.
Cleary, another thread cannot read the value of i after a different thread has accomplished step 1 but before it has completed step 3. So there can be no overlap between two threads doing steps 1, 2, or 3.
So all your threads are fighting over access to the same resource -- i (or the mutex that protects it). No thread can make useful forward progress without exclusive access to one or both of those. Given that, there is no benefit to using multiple threads since only one of them can accomplish useful work at a time.

Why are my threads I created not printed in order?

I have this program:
void *func(void *arg) {
pthread_mutex_lock(&mutex);
int *id = (int *)arg;
printf("My ID is %d\n" , *id);
pthread_mutex_unlock(&mutex);
}
int main() {
int i;
pthread_t tid[3];
// Let us create three threads
for (i = 0; i < 3; i++) {
pthread_create(&tid[i], NULL, func, (void *)&i);
}
for (i = 0; i < 3; i++) {
pthread_join(tid[i], NULL);
}
pthread_exit(NULL);
return 0;
}
I expected it to output this:
My ID is 0
My ID is 1
My ID is 2
But instead I get random output, such as this:
My ID is 0
My ID is 0
My ID is 2
Since I already added mutex lock, I thought it would solve the problem. What else did I do wrong? Is this related to race condition?
Here id points to the same variable i in main for all the threads.
int *id = (int *)arg;
printf("My ID is %d\n" , *id);
But the variable i is constantly being update by the two for-loops in main behind the threads back. So before the thread reaches the point of printf, the value of i, and therefore also the value of *id, may have changed.
There are a few ways to solve this. The best way depends on the use case:
Wait in main until the thread signals that it has made a copy of *id before modifying i or letting it go out of scope.
Declare and initialize an array, int thread_id[], and create the threads like this:
pthread_create(&tid[i], NULL, func, &thread_id[i]);
malloc some memory and and initialize it with a copy of i:
int *thread_id = malloc(sizeof(*thread_id));
*thread_id = i
pthread_create(&tid[i], NULL, func, thread_id);
Just don't forget to free your memory int the thread when you are finished using it. Or in main if the thread fails to start.
If i fits in a void * can pass its content directly as a parameter to the thread. To make sure it fits, you can declare it as intptr_t rather than int
(We basicly abuse the fact that pointers are nothing more than magic integers) :
void *func(void *arg) {
pthread_mutex_lock(&mutex);
// Here we interpret a pointer value as an integer value
intptr_t id = (intptr_t )arg;
printf("My ID is %d\n" , (int)id);
pthread_mutex_unlock(&mutex);
}
int main() {
intptr_t i;
pthread_t tid[3];
// Let us create three threads
for (i = 0; i < 3; i++) {
// Here we squeeze the integer value of `i` into something that is
// supposed to hold a pointer
pthread_create(&tid[i], NULL, func, (void *)i);
}
for (i = 0; i < 3; i++) {
pthread_join(tid[i], NULL);
}
// This does not belong here !!
// pthread_exit(NULL);
return 0;
}
Nope, no race conditions involved. (my b) There can be a race condition on i because all threads access it. Each thread gets started with a pointer to i. However, the main problem is that there is no guarantee that the thread will start and run the critical section while i holds the value you expect, in an order that you expect.
I'm assuming you declared the variable mutex globally and called pthread_mutex_init() somewhere to initialize it.
Mutexes are great to allow only one thread to access a critical section of code at a time. So the code as you've written creates all three threads to run in parallel, but only lets one thread at a time run the following code.
int *id = (int *)arg;
printf("My ID is %d\n" , *id);

Multithreaded search in c

I'm supposed to have two threads that search for the minimum element in an array: the first one searches the first half, and the second thread searches the other half. However, when I run my code, it seems that it chooses a thread randomly. I'm not sure what I'm doing wrong, but it probably has to do with the "mid" part. I tried dividing an array into two, finding the midpoint and then writing the conditions from there, but I probably went wrong somewhere. I also tried putting array[i] in the conditions, but in that case only thread2 executes.
EDIT: I'm really trying my best here, but I'm not getting anywhere. I edited the code in a way that made sense to me, and I probably typecasted "min" wrong but now it doesn't even execute it just gives me an error, even though it compiles just fine. I'm just a beginner, and while I do understand everything you guys are talking about, I have a hard time implementing the ideas, so really, any help with fixing this is appreciated!
EDIT2: Okay so the previous code made no sense at all, I do apologize but I was exhausted while writing it. Anyway, I came up with something else that works partially! I split the array into two halves, however only the first element is accessible when using the pointer. But would it work if the whole array was being accessed and if so how can I fix that then?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#define size 20
void *smallest(void *arg);
pthread_t th, th2;
int array[size], i, min;
int main(int argc, char *argv[]) {
srand ( time(NULL) );
for(i = 0; i < size; i++)
{
array[i] = (rand() % 100)+1;
printf("%d ", array[i]);
}
int *array1 = malloc(10 * sizeof(int));
int *array2 = malloc(10 * sizeof(int));
memcpy(array1, array, 10 * sizeof(int));
memcpy(array2, array + 10, 10 * sizeof(int));
printf("\nFirst half gives %d \n", *array1);
printf("Second half gives %d \n", *array2);
pthread_create(&th, NULL, smallest, (void*) array1);
pthread_create(&th2, NULL, smallest, (void*) array2);
pthread_join(th, NULL);
pthread_join(th2, NULL);
//printf("\nFirst half gives %d\n", array1);
//printf("Second half gives %d\n", array2);
if (*array1 < *array2) {
printf("\nThread1 finds the number\n");
printf("The smallest element is %i\n", *array1);
}
else {
printf("\nThread2 finds the number\n");
printf("The smallest element is %i\n", *array2);
}
return 0;
}
void *smallest(void* arg){
int *array = (int*)arg;
min = array[0];
for (i = 0; i < size; i++) {
if (array[i] < min) {
min = array[i];
}
}
pthread_exit(NULL);
}
The code you've set up never runs more than one thread. Notice that if you run the first branch of the if statement, you fire off one thread to search half the array, wait for it to finish, then continue onward, and if the else branch executes, the same thing happens in the second half of the array. Fundamentally, you probably want to rethink your strategy here by having the code always launch two threads and join each of them only after both threads have started running.
The condition within your if statement also seems like it's mistaken. You're asking whether the middle element of the array is greater than its index. I assume this isn't what you're trying to do.
Finally, the code you have in each thread always looks at the entire array, not just a half of it. I would recommend rewriting the thread routine so that its argument represents the start and end indices of the range to take the minimum of. You would then update the code in main so that when you fire off the thread, you specify which range to search.
I would structure things like this:
Fire off a thread to find the minimum of the first half of the array.
Fire off a thread to find the minimum of the second half of the array.
Join both threads.
Use the results from each thread to find the minimum.
As one final note, since you'll have two different threads each running at the same time, you'll need to watch for data races as both threads try to read or write the minimum value. Consider having each thread use its exit code to signal where the minimum is and then resolving the true minimum back in main. This eliminates the race condition. Alternatively, have one global minimum value, but guard it with a mutex.
1) You´re redeclaring the global variables in the main function, so there´s actually no point in declaring i, low, high, min:
int array[size], i, low, high, min;
The problem you´re having is with the scope of the variables when you redeclare the variables in the main function, the global ones with the same name become "invisible"
int *low = array;
int *high = array + (size/2);
int mid = (*low + *high) / 2;
So when you run the threads all the values of your variables(low, high, min;
) are 0, this is because they are never actually modified by the main and because they start in 0 default(startup code,etc).
Anyways I wouldn´t really recommend(it´s really frowned upon) using global variables unless it´s a really small proyect for personal use.
2) Another crucial problem is that you´re ignorning the main idea behind threads which is running both simultaneously
if (array[mid] > mid) {
pthread_create(&th, NULL, &smallest, NULL);
pthread_join(th, NULL);
printf("\nThread1 finds the number\n");
}
else if (array[mid] < mid) {
pthread_create(&th2, NULL, &smallest, NULL);
pthread_join(th2, NULL);
printf("\nThread2 finds the number\n");
}
You´re actually only running one thread when executing.
Try something like this:
pthread_create(&th, NULL, &smallest, NULL);
pthread_create(&th2, NULL, &smallest, NULL);
pthread_join(th2, NULL);
pthread_join(th, NULL);
3) You are trying to have two threads access the same variable this can result in undefined behaviour, you MUST use a muthex to avoid a number from not actually being stored.
This guide is pretty complete regarding mutexes but if you need anyhelp please let me know.
This is a single threaded version of what you are asking.
#include <stdio.h>
#include <stdlib.h>
/*
I can not run pthread on my system.
So this is some code that should kind of work the same way
*/
typedef int pthread_t;
typedef int pthread_attr_t;
typedef void*(*threadfunc)(void*);
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg)
{
start_routine(arg);
return 0;
}
int pthread_join(pthread_t thread, void **value_ptr)
{
return 0;
}
struct context
{
int* begin;
int* end;
int* result;
};
//the function has to be castable to the threadfunction type
//that way you do not have to worry about casting the argument.
//be careful though - if something does not match these errors may be hard to track
void * smallest(context * c) //signature needet for start routine
{
c->result = c->begin;
for (int* current = c->begin; current < c->end; ++current)
{
if (*current < *c->result)
{
c->result = current;
}
}
return 0; // not needet with the way the argument is set up.
}
int main(int argc, char *argv[])
{
pthread_t t1, t2;
#define size 20
int array[size];
srand(0);
for (int i = 0; i < size; ++i)
{
array[i] = (rand() % 100) + 1;
printf("%d ", array[i]);
}
//prepare data
//one surefire way of messing up in multithreading is sharing data between threads.
//even a simple approach like storing in a variable who is accessing will not solve the issues
//to properly lock data you would have to dive into the memory model.
//either lock with mutexes or memory barriers or just don' t share data between threads.
context c1;
context c2;
c1.begin = array;
c1.end = array + (size / 2);
c2.begin = c1.end + 1;
c2.end = array + size;
//start threads - here your threads would go
//note the casting - you may wnt to wrap this in its own function
//there is error potential here, especially due to maintainance etc...
pthread_create(&t1, 0, (void*(*)(void*))smallest, &c1); //without typedef
pthread_create(&t2, 0, (threadfunc)smallest, &c2); //without typedef
pthread_join(t1, 0);//instead of zero you could have a return value here
pthread_join(t1, 0);//as far as i read 0 throws the return value away
//return value could be useful for error handling
//evaluate
if (*c1.result < *c2.result)
{
printf("\nThread1 finds the number\n");
printf("The smallest element is %i\n", *c1.result);
}
else
{
printf("\nThread2 finds the number\n");
printf("The smallest element is %i\n", *c2.result);
}
return 0;
}
Edit:
I edited some stubs in to give you an idea of how to use multithreading.
I never used pthread but this should likely work.
I used this source for prototype information.

2D global array without knowing lengths. Best practice?

I need to have buffers that I will use it in multiple different types of threads. So the array needs to be global.
Buffer size and number of buffers are given as input to the program.
As an alternative I could implement linked list maybe.
What is the best way to implement such buffers? Can you provide a sample?
Any help is appreciated!
I don't understand what do you mean by "without knowing length", if you pass size of each buffer and number of buffers as input parameters then you know every required length.
Maybe this is not the best, but that would be my way.
First declare global buffer and threads.
static void ** buffer;
pthread_t tid[2];
Here is described how the threads will work. First buffer will assign with data first two sub-buffers. Second will do the same with the other two.
void *assignBuffer(void *threadid) {
pthread_t id = pthread_self();
if (pthread_equal(id, tid[0])) {
strcpy(buffer[0], "foo");
strcpy(buffer[1], "bar");
} else {
strcpy(buffer[2], "oof");
strcpy(buffer[3], "rab");
}
return NULL;
}
Converting program args from string to integer.
Here we assign buffer with arrays of unknown type.
Here we assign each buffer with his size in bytes.
Finally we create working threads. The important thing is that they
will run simultaneously.
Waiting until all threads done their job.
Simple print buffer contents.
Ok, here is the code.
int main(int argc, char **argv) {
//1
int bufferSize = atoi(argv[1]);
int buffersAmount = atoi(argv[2]);
//2
buffer = malloc(sizeof(void *)*buffersAmount);
//3
int i;
for (i = 0; i < buffersAmount; ++i) {
buffer[i] = malloc(bufferSize);
}
//4
i = 0;
while (i < 2) {
pthread_create(&tid[i], NULL, &assignBuffer, NULL);
++i;
}
//5
for (i = 0; i < 2; i++)
pthread_join(tid[i], NULL);
//6
for (i = 0; i < 4; ++i) {
printf("%d %s\n", i, (char*)buffer[i]);
}
for (i = 0; i < buffersAmount; ++i) {
free(buffer[i]);
}
return 0;
}
Feel free to ask if you don't understand something, also sorry for my english it is not my native language.

Malloc accessibility between two functions

I'm writing a variant of the producer-consumer problem with multi threading. I'm trying to use a queue to store the "produced" items until they get "consumed" later on. My problem is that when the consumer thread runs, it only processes the most recent item added to the queue (rather than the oldest item on the queue). Further, it processes that item repeatedly (up to the number of items on the queue itself).
I think that my problem might be that I need to allocate some memory when I push an item onto the queue (not sure about this, though). But then, I need a way to refer to this memory when that item is about to be consumed.
Anyway, here is a paired down version of my program. I realize that what I am posting here is incomplete (this is an infinite loop), but I'm trying just show the part that is relevant to this issue. The functions queue_push() and and queue_pop() are well tested, so I don't think that the problem lies there. I'll post more if needed.
Can anyone see why my consumer thread only processes the newest queue item? Thank you!
sem_t mutex;
queue q;
FILE* inputFPtr[10];
char host_in[BUFFERSIZE];
char host_out[BUFFERSIZE];
void* p(void* inputFile) {
while (fscanf(inputFile, INPUTFS, host_in) > 0)
{
sem_wait(&mutex);
queue_push(&q, host_in); //this function pushes the hostname onto the back of the queue
fprintf(stdout, "Produced: %d) %s\n", i, host_in);
sem_post(&mutex);
}
fclose (inputFile);
}
void* c() {
while (TRUE)
{
sem_wait(&mutex);
sprintf(hostname_out, "%s", (char *) queue_pop(&q));
printf("%s\n", host_out);
sem_post(&mutex);
}
}
int main (int argc, char* argv[]) {
int i;
pthread_t *th_in[argc-2];
pthread_t *th_out[2];
for (i = 0; i < (argc-2); i++) {
th_in[i] = (pthread_t *) malloc(sizeof(pthread_t));
inputFPtr[i] = fopen(argv[i+1], "r");
pthread_create (th_in[i], NULL, p, inputFPtr[i]);
}
for (i = 0; i < 2; i++) {
th_out[i] = (pthread_t *) malloc(sizeof(pthread_t));
pthread_create (th_out[i], NULL, c, null);
}
for (i = 0; i < (argc - 2); i++) {
pthread_join(*th_in[i], 0);
free(th_in[i]);
}
for (i = 0; i < (2); i++) {
pthread_join(*th_out[i], 0);
free(th_out[i]);
}
return EXIT_SUCCESS;
}
You forgot to post you code. However from your description, it seems like all the queue members point to the same memory block. This is why all your pops result with the same item.
The answer to you question is YES. You need to allocate memory for each one of the items and free it after it was "consumed".
Try to post some code for more specific answers...

Resources