How to create n threads, each one creates n - 1 threads - c

I am working with a large project and I am trying to create a test that does the following thing: first, create 5 threads. Each one of this threads will create 4 threads, which in turn each one creates 3 other threads. All this happens until 0 threads.
I have _ThreadInit() function used to create a thread:
status = _ThreadInit(mainThreadName, ThreadPriorityDefault, &pThread, FALSE);
where the 3rd parameter is the output(the thread created).
What am I trying to do is start from a number of threads that have to be created n = 5, the following way:
for(int i = 0; i < n; i++){
// here call the _ThreadInit method which creates a thread
}
I get stuck here. Please, someone help me understand how it should be done. Thanks^^

Building on Eugene Sh.'s comment, you could create a function that takes a parameter, which is the number of threads to create, that calls itself recursively.
Example using standard C threads:
#include <stdbool.h>
#include <stdio.h>
#include <threads.h>
int MyCoolThread(void *arg) {
int num = *((int*)arg); // cast void* to int* and dereference
printf("got %d\n", num);
if(num > 0) { // should we start any threads at all?
thrd_t pool[num];
int next_num = num - 1; // how many threads the started threads should start
for(int t = 0; t < num; ++t) { // loop and create threads
// Below, MyCoolThread creates a thread that executes MyCoolThread:
if(thrd_create(&pool[t], MyCoolThread, &next_num) != thrd_success) {
// We failed to create a thread, set `num` to the number of
// threads we actually created and break out.
num = t;
break;
}
}
int result;
for(int t = 0; t < num; ++t) { // join all the started threads
thrd_join(pool[t], &result);
}
}
return 0;
}
int main() {
int num = 5;
MyCoolThread(&num); // fire it up
}
Statistics from running:
1 thread got 5
5 threads got 4
20 threads got 3
60 threads got 2
120 threads got 1
120 threads got 0

Related

why is this c code causing a race condition?

I'm trying to count the number of prime numbers up to 10 million and I have to do it using multiple threads using Posix threads(so, that each thread computes a subset of 10 million). However, my code is not checking for the condition IsPrime. I'm thinking this is due to a race condition. If it is what can I do to ameliorate this issue?
I've tried using a global integer array with k elements but since k is not defined it won't let me declare that at the file scope.
I'm running my code using gcc -pthread:
/*
Program that spawns off "k" threads
k is read in at command line each thread will compute
a subset of the problem domain(check if the number is prime)
to compile: gcc -pthread lab5_part2.c -o lab5_part2
*/
#include <math.h>
#include <stdio.h>
#include <time.h>
#include <pthread.h>
#include <stdlib.h>
typedef int bool;
#define FALSE 0
#define TRUE 1
#define N 10000000 // 10 Million
int k; // global variable k willl hold the number of threads
int primeCount = 0; //it will hold the number of primes.
//returns whether num is prime
bool isPrime(long num) {
long limit = sqrt(num);
for(long i=2; i<=limit; i++) {
if(num % i == 0) {
return FALSE;
}
}
return TRUE;
}
//function to use with threads
void* getPrime(void* input){
//get the thread id
long id = (long) input;
printf("The thread id is: %ld \n", id);
//how many iterations each thread will have to do
int numOfIterations = N/k;
//check the last thread. to make sure is a whole number.
if(id == k-1){
numOfIterations = N - (numOfIterations * id);
}
long startingPoint = (id * numOfIterations);
long endPoint = (id + 1) * numOfIterations;
for(long i = startingPoint; i < endPoint; i +=2){
if(isPrime(i)){
primeCount ++;
}
}
//terminate calling thread.
pthread_exit(NULL);
}
int main(int argc, char** args) {
//get the num of threads from command line
k = atoi(args[1]);
//make sure is working
printf("Number of threads is: %d\n",k );
struct timespec start,end;
//start clock
clock_gettime(CLOCK_REALTIME,&start);
//create an array of threads to run
pthread_t* threads = malloc(k * sizeof(pthread_t));
for(int i = 0; i < k; i++){
pthread_create(&threads[i],NULL,getPrime,(void*)(long)i);
}
//wait for each thread to finish
int retval;
for(int i=0; i < k; i++){
int * result = NULL;
retval = pthread_join(threads[i],(void**)(&result));
}
//get the time time_spent
clock_gettime(CLOCK_REALTIME,&end);
double time_spent = (end.tv_sec - start.tv_sec) +
(end.tv_nsec - start.tv_nsec)/1000000000.0f;
printf("Time tasken: %f seconds\n", time_spent);
printf("%d primes found.\n", primeCount);
}
the current output I am getting: (using the 2 threads)
Number of threads is: 2
Time tasken: 0.038641 seconds
2 primes found.
The counter primeCount is modified by multiple threads, and therefore must be atomic. To fix this using the standard library (which is now supported by POSIX as well), you should #include <stdatomic.h>, declare primeCount as an atomic_int, and increment it with an atomic_fetch_add() or atomic_fetch_add_explicit().
Better yet, if you don’t care about the result until the end, each thread can store its own count in a separate variable, and the main thread can add all the counts together once the threads finish. You will need to create, in the main thread, an atomic counter per thread (so that updates don’t clobber other data in the same cache line), pass each thread a pointer to its output parameter, and then return the partial tally to the main thread through that pointer.
This looks like an exercise that you want to solve yourself, so I won’t write the code for you, but the approach to use would be to declare an array of counters like the array of thread IDs, and pass &counters[i] as the arg parameter of pthread_create() similarly to how you pass &threads[i]. Each thread would need its own counter. At the end of the thread procedure, you would write something like, atomic_store_explicit( (atomic_int*)arg, localTally, memory_order_relaxed );. This should be completely wait-free on all modern architectures.
You might also decide that it’s not worth going to that trouble to avoid a single atomic update per thread, declare primeCount as an atomic_int, and then atomic_fetch_add_explicit( &primeCount, localTally, memory_order_relaxed ); once before the thread procedure terminates.

Synchronization of p_threads using globals

I'm pretty new to C, so I'm not sure where even to start digging about my problem.
I'm trying to port python number-crunching algos to C, and since there's no GIL in C (woohoo), I can change whatever I want in memory from threads, for as long as I make sure there are no races.
I did my homework on mutexes, however, I cannot wrap my head around use of mutexes in case of continuously running threads accessing the same array over and over.
I'm using p_threads in order to split the workload on a big array a[N].
Number crunching algorithm on array a[N] is additive, so I'm splitting it using a_diff[N_THREADS][N] array, writing changes to be applied to a[N] array from each thread to a_diff[N_THREADS][N] and then merging them all together after each step.
I need to run the crunching on different versions of array a[N], so I pass them via global pointer p (in the MWE, there's only one a[N])
I'm synchronizing threads using another global array SYNC_THREADS[N_THREADS] and make sure threads quit when I need them to by setting END_THREADS global (I know, I'm using too many globals - I don't care, code is ~200 lines). My question is in regard to this synchronization technique - is it safe to do so and what is cleaner/better/faster way to achieve that?
MWEe:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define N_THREADS 3
#define N 10000000
#define STEPS 3
double a[N]; // main array
double a_diff[N_THREADS][N]; // diffs array
double params[N]; // parameter used for number-crunching
double (*p)[N]; // pointer to array[N]
// structure for bounds for crunching the array
struct bounds {
int lo;
int hi;
int thread_num;
};
struct bounds B[N_THREADS];
int SYNC_THREADS[N_THREADS]; // for syncing threads
int END_THREADS = 0; // signal to terminate threads
static void *crunching(void *arg) {
// multiple threads run number-crunching operations according to assigned low/high bounds
struct bounds *data = (struct bounds *)arg;
int lo = (*data).lo;
int hi = (*data).hi;
int thread_num = (*data).thread_num;
printf("worker %d started for bounds [%d %d] \n", thread_num, lo, hi);
int i;
while (END_THREADS != 1) { // END_THREADS tells threads to terminate
if (SYNC_THREADS[thread_num] == 1) { // SYNC_THREADS allows threads to start number-crunching
printf("worker %d working... \n", thread_num );
for (i = lo; i <= hi; ++i) {
a_diff[thread_num][i] += (*p)[i] * params[i]; // pretend this is an expensive operation...
}
SYNC_THREADS[thread_num] = 0; // thread disables itself until SYNC_THREADS is back to 1
printf("worker %d stopped... \n", thread_num );
}
}
return 0;
}
int i, j, th,s;
double joiner;
int main() {
// pre-fill arrays
for (i = 0; i < N; ++i) {
a[i] = i + 0.5;
params[i] = 0.0;
}
// split workload between workers
int worker_length = N / N_THREADS;
for (i = 0; i < N_THREADS; ++i) {
B[i].thread_num = i;
B[i].lo = i * worker_length;
if (i == N_THREADS - 1) {
B[i].hi = N;
} else {
B[i].hi = i * worker_length + worker_length - 1;
}
}
// pointer to parameters to be passed to worker
struct bounds **data = malloc(N_THREADS * sizeof(struct bounds*));
for (i = 0; i < N_THREADS; i++) {
data[i] = malloc(sizeof(struct bounds));
data[i]->lo = B[i].lo;
data[i]->hi = B[i].hi;
data[i]->thread_num = B[i].thread_num;
}
// create thread objects
pthread_t threads[N_THREADS];
// disallow threads to crunch numbers
for (th = 0; th < N_THREADS; ++th) {
SYNC_THREADS[th] = 0;
}
// launch workers
for(th = 0; th < N_THREADS; th++) {
pthread_create(&threads[th], NULL, crunching, data[th]);
}
// big loop of iterations
for (s = 0; s < STEPS; ++s) {
for (i = 0; i < N; ++i) {
params[i] += 1.0; // adjust parameters
// zero diff array
for (i = 0; i < N; ++i) {
for (th = 0; th < N_THREADS; ++th) {
a_diff[th][i] = 0.0;
}
}
p = &a; // pointer to array a
// allow threads to process numbers and wait for threads to complete
for (th = 0; th < N_THREADS; ++th) { SYNC_THREADS[th] = 1; }
// ...here threads started by pthread_create do calculations...
for (th = 0; th < N_THREADS; th++) { while (SYNC_THREADS[th] != 0) {} }
// join results from threads (number-crunching is additive)
for (i = 0; i < N; ++i) {
joiner = 0.0;
for (th = 0; th < N_THREADS; ++th) {
joiner += a_diff[th][i];
}
a[i] += joiner;
}
}
}
// join workers
END_THREADS = 1;
for(th = 0; th < N_THREADS; th++) {
pthread_join(threads[th], NULL);
}
return 0;
}
I see that workers don't overlap time-wise:
worker 0 started for bounds [0 3333332]
worker 1 started for bounds [3333333 6666665]
worker 2 started for bounds [6666666 10000000]
worker 0 working...
worker 1 working...
worker 2 working...
worker 2 stopped...
worker 0 stopped...
worker 1 stopped...
worker 2 working...
worker 0 working...
worker 1 working...
worker 1 stopped...
worker 0 stopped...
worker 2 stopped...
worker 2 working...
worker 0 working...
worker 1 working...
worker 1 stopped...
worker 2 stopped...
worker 0 stopped...
Process returned 0 (0x0) execution time : 1.505 s
and I make sure worker's don't get into each other workspaces by separating them via a_diff[thead_num][N] sub-arrays, however, I'm not sure that's always the case and that I'm not introducing hidden races somewhere...
I didn't realize what was the question :-)
So, the question is if you're thinking well with your SYNC_THREADS and END_THREADS synchronization mechanism.
Yes!... Almost. The problem is that threads are burning CPU while waiting.
Conditional Variables
To make threads wait for an event you have conditional variables (pthread_cond). These offer a few useful functions like wait(), signal() and broadcast():
wait(&cond, &m) blocks a thread in a given condition variable. [note 2]
signal(&cond) unlocks a thread waiting in a given condition variable.
broadcast(&cond) unlocks all threads waiting in a given condition variable.
Initially you'd have all the threads waiting [note 1]:
while(!start_threads)
pthread_cond_wait(&cond_start);
And, when the main thread is ready:
start_threads = 1;
pthread_cond_broadcast(&cond_start);
Barriers
If you have data dependencies between iterations, you'd want to make sure threads are executing the same iteration at any given moment.
To synchronize threads at the end of each iteration, you'll want to take a look at barriers (pthread_barrier):
pthread_barrier_init(count): initializes a barrier to synchronize count threads.
pthread_barrier_wait(): thread waits here until all count threads reach the barrier.
Extending functionality of barriers
Sometimes you'll want the last thread reaching a barrier to compute something (e.g. to increment the counter of number of iterations, or to compute some global value, or to check if execution should stop). You have two alternatives
Using pthread_barriers
You'll need to essentially have two barriers:
int rc = pthread_barrier_wait(&b);
if(rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD)
if(shouldStop()) stop = 1;
pthread_barrier_wait(&b);
if(stop) return;
Using pthread_conds to implement our own specialized barrier
pthread_mutex_lock(&mutex)
remainingThreads--;
// all threads execute this
executedByAllThreads();
if(remainingThreads == 0) {
// reinitialize barrier
remainingThreads = N;
// only last thread executes this
if(shouldStop()) stop = 1;
pthread_cond_broadcast(&cond);
} else {
while(remainingThreads > 0)
pthread_cond_wait(&cond, &mutex);
}
pthread_mutex_unlock(&mutex);
Note 1: why is pthread_cond_wait() inside a while block? May seem a bit odd. The reason behind it is due to the existence of spurious wakeups. The function may return even if no signal() or broadcast() was issued. So, just to guarantee correctness, it's usual to have an extra variable to guarantee that if a thread suddenly wakes up before it should, it runs back into the pthread_cond_wait().
From the manual:
When using condition variables there is always a Boolean predicate involving shared variables associated with each condition wait that is true if the thread should proceed. Spurious wakeups from the pthread_cond_timedwait() or pthread_cond_wait() functions may occur. Since the return from pthread_cond_timedwait() or pthread_cond_wait() does not imply anything about the value of this predicate, the predicate should be re-evaluated upon such return.
(...)
If a signal is delivered to a thread waiting for a condition variable, upon return from the signal handler the thread resumes waiting for the condition variable as if it was not interrupted, or it shall return zero due to spurious wakeup.
Note 2:
An noted by Michael Burr in the comments, you should hold a companion lock whenever you modify the predicate (start_threads) and pthread_cond_wait(). pthread_cond_wait() will release the mutex when called; and re-acquires it when it returns.
PS: It's a bit late here; sorry if my text is confusing :-)

Looping a Function in C

I have a school project which requires me to simulate first come first serve using these variables:
Users Input:
Number of Process: 3
Process 1 Arrives at 0 time and requires 5 'resources'
3
1,5,0
2,5,4
3,1,8
However, i can't seem to get past the first 5 'resources'. I'm trying to figure out how to increase PID and repeat but keep time increasing for all these resources. I've created this same program but it only allows for this specific input and I'm trying to make it more versatile so i can choose any number of processes and resources(unit) needed.
#include <stdio.h>
main() {
int n;
printf("Enter the Amount of processes: ");
scanf("%d",&n);
//Variables
int process[n], unit[n], at[n];
int i,time,PID = 1;
int awt, atat,sum,counter;
int x = n;
//Takes and stores the users input into process unit and at
for(i=0;i<n;i++)
{
scanf("%d,%d,%d", &process[i], &unit[i], &at[i]);
}
sum = sum_array(unit,n);
printf("%d\n", sum);
printf("FCFS\n");
printf("Time PID");
for(counter = 0; counter < x; counter++, PID++){
FCFS(time,n,unit,PID);
}
}
int sum_array(int at[], int num_elements){
int x, sum = 0;
for(x=0; x<num_elements;x++){
sum = sum + at[x];
}
return(sum);
}
int FCFS(int time,int n,int unit[], int PID){
for(time = 0, n = 0 ; unit[n] >0 ;time++, unit[n]--){
printf("\n%d ", time);
printf("%d", PID);
}
return;
}
Sample Output:
FCFS
TIME PID
0 1
1 1
2 1
3 1
4 1
5 2
6 2
7 2
8 2
9 2
10 3
Your problems are mostly related to the FCFS function and the loop where you call it.
Try the following:
Initialize time = 0 in the main function
Pass counter instead of n to FCFS in the loop
Return the updated time from FCFS
Don't reset the time and n parameter inside FCFS
Call to FCFS inside for loop:
time = FCFS(time, counter, unit, PID);
Updated FCFS code:
int FCFS(int time,int n,int unit[], int PID)
{
for( ; unit[n] >0 ;time++, unit[n]--)
{
printf("\n%d ", time);
printf("%d", PID);
}
return time;
}
Other than that, there are a number of issues with your code, but it wouldn't really fit into this Q/A to mention them all, so I stick with the necessary things to get your code running for valid example input.
Since this is a homework question, I would encourage you to solve it on your own. Since you have put in some effort on solving this, I am posting the answer below as a spoiler (Note indentation does not work in spoilers). However before seeing the answer here are few suggestions to fix your program:
As mentioned above, passing n does absolutely nothing. Please use a different variable inside the FCFS function.
No need to increment and pass the PID. Since you are putting it in an array, try to get the value from the array.
Instead of n pass counter to the function so that you can index the two arrays.
The for loop inside FCFS makes no sense. It should be for(i=0; i<unit[counter]; i++). time can just be incremented inside the loop.
time needs to be returned to increment properly
And my code:
int time = 0;
int cur_index = 0;
while (cur_index < n) {
int pid = -1;
if (at[cur_index] <= time) {
pid = process[cur_index];
} else {
printf("%d %d\n", time, pid);
time++;
continue;
}
if (pid != -1) {
int r = 0;
for (r = 0; r < unit[cur_index]; r++) {
printf("%d %d\n", time, pid);
time++;
}
}
}

How to create thread blocks?

I have two questions.
First:
I need to create thread blocks gradually not more then some max value, for example 20.
For example, first 20 thread go, job is finished, only then 20 second thread go, and so on in a loop.
Total number of jobs could be much larger then total number of threads (in our example 20), but total number of threads should not be bigger then our max value (in our example 20).
Second:
Could threads be added continuously? For example, 20 threads go, one thread job is finished, we see that total number of threads is 19 but our max value is 20, so we can create one more thread, and one more thread go :)
So we don't waste a time waiting another threads job to be done and our total threads number is not bigger then our some max value (20 in our example) - sounds cool.
Conclusion:
For total speed I consider the second variant would be much faster and better, and I would be very graceful if you help me with this, but also tell how to do the first variant.
Here is me code (it's not working properly and the result is strange - some_array elements become wrong after eleven step in a loop, something like this: Thread counter = 32748):
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <math.h>
#define num_threads 5 /* total max number of threads */
#define lines 17 /* total jobs to be done */
/* args for thread start function */
typedef struct {
int *words;
} args_struct;
/* thread start function */
void *thread_create(void *args) {
args_struct *actual_args = args;
printf("Thread counter = %d\n", *actual_args->words);
free(actual_args);
}
/* main function */
int main(int argc, char argv[]) {
float block;
int i = 0;
int j = 0;
int g;
int result_code;
int *ptr[num_threads];
int some_array[lines] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17};
pthread_t threads[num_threads];
/* counting how many block we need */
block = ceilf(lines / (double)num_threads);
printf("blocks= %f\n", block);
/* doing ech thread block continuously */
for (g = 1; g <= block; g++) {
//for (i; i < num_threads; ++i) { i < (num_threads * g),
printf("g = %d\n", g);
for (i; i < lines; ++i) {
printf("i= %d\n", i);
/* locate memory to args */
args_struct *args = malloc(sizeof *args);
args->words = &some_array[i];
if(pthread_create(&threads[i], NULL, thread_create, args)) {
free(args);
/* goto error_handler */
}
}
/* wait for each thread to complete */
for (j; j < lines; ++j) {
printf("j= %d\n", j);
result_code = pthread_join(threads[j], (void**)&(ptr[j]));
assert(0 == result_code);
}
}
return 0;
}

Simulating round robin with pthreads

The task is to have 5 threads present at the same time, and the user assigns each a burst time. Then a round robin algorithm with a quantum of 2 is used to schedule the threads. For example, if I run the program with
$ ./m 1 2 3 4 5
The output should be
A 1
B 2
C 2
D 2
E 2
C 1
D 2
E 2
E 1
But for now my output shows only
A 1
B 2
C 2
Since the program errs where one thread does not end for the time being, I think the problem is that this thread cannot unlock to let the next thread grab the lock. My sleep() does not work, either. But I have no idea how to modify my code in order to fix them. My code is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
double times[5];
char process[] = {'A', 'B', 'C', 'D', 'E'};
int turn = 0;
void StartNext(int tid) //choose the next thread to run
{
int i;
for(i = (tid + 1) % 5; times[i] == 0; i = (i + 1) % 5)
if(i == tid) //if every thread has finished
return;
turn = i;
}
void *Run(void *tid) //the thread function
{
int i = (int)tid;
while(times[i] != 0)
{
while(turn != i); //busy waiting till it is its turn
if(times[i] > 2)
{
printf("%c 2\n", process[i]);
sleep(2); //sleep is to simulate the actual running time
times[i] -= 2;
}
else if(times[i] > 0 && times[i] <= 2) //this thread will have finished after this turn
{
printf("%c %lf\n", process[i], times[i]);
sleep(times[i]);
times[i] = 0;
}
StartNext(i); //choose the next thread to run
}
pthread_exit(0);
}
int main(int argc, char **argv)
{
pthread_t threads[5];
int i, status;
if(argc == 6)
{
for(i = 0; i < 5; i++)
times[i] = atof(argv[i + 1]); //input the burst time of each thread
for(i = 0; i < 5; i++)
{
status = pthread_create(&threads[i], NULL, Run, (void *)i); //Create threads
if(status != 0)
{
printf("While creating thread %d, pthread_create returned error code %d\n", i, status);
exit(-1);
}
pthread_join(threads[i], 0); //Join threads
}
}
return 0;
}
The program is directly runnable. Could anyone help me figure it out? Thanks!
Some things I've figured out reading your code:
1. At the beginning of the Run function, you convert tid (which is a pointer to void) directly to int. Shouldn't you dereference it?
It is better to make int turn volatile, so that the compiler won't make any assumptions about its value not changing.
When you call the function sleep the second time, you pass a parameter that has type double (times[i]), and you should pass an unsigned int parameter. A direct cast like (unsigned int) times[i] should solve that.
You're doing the pthread_join before creating the other threads. When you create thread 3, and it enters its busy waiting state, the other threads won't be created. Try putting the joins after the for block.

Resources