Selecting a random thread in c - c

I need to randomly select two out of three threads, and I've come up with a few ideas but I'm not sure if they would work.
Is it better to have an array of 3 threads and then have another thread choose from there, or to have three independent threads? And in both cases, how would you even write the function that would randomly select them? From what I understand, rand() can't be used because it's only for integers, and other than that I have no clue what to use.
This is kind of a game project, and the winner of the two selected threads plays with the remaining thread. Can the same function be used for both instances then, or does there have to be a new one? I'm guessing the most useful thing would be the same thread using the same function, only with its choices narrowed down?
I know this is probably simple but I'm only just starting out with threads, so excuse my poor skills. Any help is greatly appreciated!
EDIT: Thank you everyone! However, since I'm already confused I really don't want to go into semaphores now. I've written some code based on one of the comments but it's not giving me the wanted output. Here's what I have:
EDIT #2: I somehow managed to write it! The only thing left is for the function to call itself again but the pointers kind of confuse me so I don't know how to call it in the else part, and I don't know how else to stop the randomized values from repeating.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *play (void *myvar);
void *select (void *var);
pthread_t tid[3], th;
int i, ra1, ra2;
int main(int argc, char *argv[]) {
pthread_create(&th, NULL, &select, NULL);
for (i = 0; i < 3; i++) {
pthread_create(&tid[i], NULL, &play, NULL);
}
pthread_join(th, NULL);
for (i = 0; i < 3; i++) {
pthread_join(tid[i], NULL);
}
return 0;
}
void *play (void *myvar) {
printf("Thread%i hits the ball!\n", i);
return NULL;
}
void *select (void *var) {
srand ( time(NULL) );
ra1 = rand() % 3 + 1;
ra2 = rand() % 3 + 1;
if (ra1 != ra2) {
printf("Threads have been chosen! Thread%i and Thread%i will start the game!\n",
ra1, ra2);
}
else //what to do?;
return NULL;
}

I'm assuming that you want 2 of 3 threads to perform some task, and that this selection should be random. I further assume that you want these 3 threads to do the selection "in common", i.e. not requiring a forth thread to do the selection (or to have one of the three doing a special selection procedure).
A possible approach would be to use a counting semaphore to "protect" the task and only allow 2 threads to use it, i.e. initialize the semaphore to 2. You can then have each thread sleep a random (small) delay, and try to acquire the semaphore.
Without much comment, see this example:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
struct data {
sem_t * semaphore;
int random;
char const * name;
};
void task(char const * name) {
printf("WOOOOO %s\n", name);
}
void * operation(void * d) {
struct data * data = d;
usleep(data->random % 1000);
if (sem_trywait(data->semaphore) == 0) {
task(data->name);
} else {
printf("FAILED, such a shame for %s\n", data->name);;
}
return NULL;
}
int main(void) { // NOTE: Demo, thus no error checking
srand(time(NULL));
sem_t * semaphore = malloc(sizeof(*semaphore));
struct data data[3] = {
{semaphore, rand(), "John"},
{semaphore, rand(), "Marry"},
{semaphore, rand(), "Rupert"}
};
pthread_t others[2];
sem_init(semaphore, 0, 2);
pthread_create(&(others[0]), NULL, &operation, &(data[0]));
pthread_create(&(others[1]), NULL, &operation, &(data[1]));
(void)operation(&(data[2]));
pthread_join(others[0], NULL);
pthread_join(others[1], NULL);
sem_destroy(semaphore);
free(semaphore);
return 0;
}
(Live on ideone)
Note that using rand makes this choice here actually pseudo-random. Getting rid of the sleeping part can lead to a real random selection, especially when the threads have been doing different things previously. (Although I can imagine a situation where one would be able to influence the threads from the outside to achieve a particular selection)

Array of thread ID should server your purpose. Use the rand() function to randomly select the index of the array. Whatever thread ID is stored at that index of your array should be your selected thread.

Related

I don't know what the problem is when I implemented the MCS lock in c

When I implemented MCS lock, understanding "The Art of Multiprocessor Programming" book.
The program gets stuck.
This is my source code.
The problem is I don't know what's wrong with my code.
I think my logic is the same as the code of the book.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdatomic.h>
#define THREADS 2
pthread_t thread_t[THREADS];
struct Lock
{
struct Lock* next;
bool locked;
};
_Atomic(struct Lock*) tail;
_Thread_local struct Lock* my_lock;
void lock_()
{
struct Lock* lock = (struct Lock*)malloc(sizeof(struct Lock));
struct Lock* pred = atomic_exchange(&tail, lock);
my_lock = lock;
if (pred)
{
lock->locked = true;
pred->next = lock;
__sync_synchronize();
while (lock->locked) {
}
}
}
void unlock_()
{
struct Lock* succ = my_lock->next;
if (succ == NULL)
{
struct Lock* expected = my_lock;
if (atomic_compare_exchange_strong(&tail, &expected, NULL))
{
return;
}
while (succ == NULL) {
succ = my_lock->next;
}
}
succ->locked = false;
}
void* lock_func()
{
int j = 0;
for (int i = 0; i < 10000; ++i)
{
lock_();
j++;
unlock_();
}
}
int main(int argc, char *argv[])
{
int i;
for (i = 0; i < THREADS; ++i)
{
if (pthread_create(&thread_t[i], NULL, lock_func, NULL) < 0)
{
perror("thread create error:");
exit(0);
}
}
for (i = 0; i < THREADS; ++i)
pthread_join(thread_t[i], NULL);
}
I used linux ubuntu to execute it.
My program seems to work well when compiled with an O0 flag without optimization.
The spin loop:
while (lock->locked) {
}
looks very bad. Since lock->locked is not atomic, accessing it concurrently in another thread (as you do) is a data race, causing undefined behavior.
Right there the game is lost, but let's explain why it breaks in the particular way you observe. Since a data race would cause UB, the compiler can assume it is not accessed concurrently from another thread, meaning that it can never change. Since you set it to true previously, the compiler therefore can assume it is true forever, and that while (lock->locked) { } is an infinite loop. Since the loop is guaranteed to be infinite, it is unnecessary to do the test, and the compiler "optimizes" it into an unconditionally infinite loop.
That's also why it happens to appear to work with -O0: then the compiler doesn't do that particular optimization. It is, however, still free to make it misbehave in any way at all; you just seem to have gotten "lucky" that it didn't.
The __sync_synchronize() (which should be considered obsolete for a supposedly C11 program) does nothing to help with this. You can't solve a data race by adding fences like that. And anyway, it is outside the loop.
You can see the infinite loop in the generated assembly on godbolt at lines 27-28:
.L4:
jmp .L4
The _unlock function has exactly the same problem and also gets optimized into an infinite loop.
Frankly, this whole program looks completely wrong. Whoever wrote it doesn't seem to have had any idea of the data race rules. If it's truly from a book, then I don't think you should read that book anymore.

proper way to create multiple forked threads

I'm creating a timer function for a bit of embedded code that will allow me to bypass certain GPIO checks while a certain process is running, i.e., when the timer is running in a non-blocking manner.
This seems to run just fine the first 11 times the operations occur, but every time, on the 11th iteration the system will crash. The likely culprit is something in how the timer thread is being handled. My guess is there's some bit of memory cleanup that I'm not handling properly and that's leading to memory leaks of some kind. But I'm really not sure.
I can see through debug tracing that the thread is exiting after each iteration.
Here is the timer code:
#include <time.h>
#include <semaphore.h>
#include <pthread.h>
#include <msp432e4_timer.h>
extern void TaskSleep(uint32_t delay);
static bool timerActive;
static sem_t timerSem;
pthread_t timerThread;
pthread_attr_t attrs;
struct sched_param priParam;
static void *msp432e4_timer(void *argUnused) {
sem_wait(&timerSem);
timerActive = true;
sem_post(&timerSem);
TaskSleep(40);
sem_wait(&timerSem);
timerActive = false;
sem_post(&timerSem);
return (NULL);
}
void initTimer() {
int retc;
pthread_attr_init(&attrs);
priParam.sched_priority = 1;
retc = pthread_attr_setschedparam(&attrs, &priParam);
retc |= pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
retc |= pthread_attr_setstacksize(&attrs, 1024);
if (retc != 0) {
// failed to set attributes
while (1) {}
}
timerActive = false;
if((sem_init(&timerSem, 0, 0)) != 0) {
while(1);
}
sem_post(&timerSem);
}
/*
* return true on starting a new timer
* false implies timer already active
*/
void timerStart() {
int retc;
retc = pthread_create(&timerThread, &attrs, msp432e4_timer, NULL);
if (retc != 0) {
// pthread_create() failed
while (1) {}
}
}
/* return true if timer active */
bool timerCheck() {
bool retval;
sem_wait(&timerSem);
retval = timerActive;
sem_post(&timerSem);
return(retval);
}
The TaskSleep function is a call to a freeRTOS TaskDelay function. It's used in many points throughout the system and has never been an issue.
Hopefully someone can point me in the right direction.
But you didn't really post enough of your code to determine where the problems might be, but I thought this might be worth mentioning:
A general problem is that the sample code you have is open loop wrt thread creation; that is there is nothing to throttle it, and if your implementation has a particularly slow thread exit handling, you could have many zombie threads lying around that haven't died yet.
In typical embedded / real time systems, you want to move resource allocation out of the main loop, since it is often non deterministic. So, more often you would create a timer thread, and park it until it is needed:
void *TimerThread(void *arg) {
while (sem_wait(&request) == 0) {
msp432e4_timer(void *arg);
}
return 0
}
void TimerStart(void) {
sem_post(&request);
}

How can I create a function object in C

I would like to create a wrapper for c functions, so that I can convert a function call of the form ret = function(arg1,arg2,arg3); into the form /*void*/ function_wrapper(/*void*/);. That is similar to function objects in C++ and boost bind.
Is this possible? how can I do it?
Update:
To explain in more details what I am looking for:
We start with this function:
int f(int i){
//do stuff
return somevalue;
}
Obvioulsy, it is called like this:
// do stuff
int x = 0;
ret = f(0);
// do more stuff.
I would like to do some magic that will wrap the function into void function(void)
struct function_object fo;
fo.function_pointer = &f;
fo.add_arg(x, int);
fo.set_ret_pointer(&ret);
fo.call();
Note: I saw that there was a vote for closing this question and marking it as unclear. Please do not do that. I have a legitimate need to get this question answered. If you need explanation, ask and I will be glad to elaborate.
I came up with a better code that might allow you to do what you want. First I'll explain how it works, show the code and explain why I still don't think it's a good idea to use it (though the code might open doors for improvements that addresses those issues).
Functionality:
Before you start using the "function objects", you have to call an initialization function (FUNCTIONOBJ_initialize();), which will initialize the mutexes on every data structure used in the library.
After initializing, every time you want to call one of those "function objects", without using the parameters, you will have to set it up first. This is done by creating a FUNCTIONOBJ_handler_t pointer and calling get_function_handler(). This will search for a free FUNCTIONOBJ_handler data structure that can be used at the moment.
If none is found (all FUNCTIONOBJ_handler data structures are busy, being used by some function call) NULL is returned.
If get_function_handler() does find a FUNCTIONOBJ_handler data structure it will try to lock the FUNCTIONOBJ_id_holder data structure, that holds the ID of the FUNCTIONOBJ_handler of the function about to be called.
If FUNCTIONOBJ_id_holder is locked already, get_function_handler() will hang until it's unlocked by the thread using it.
Once FUNCTIONOBJ_id_holder is locked, the ID of the grabbed FUNCTIONOBJ_handler is wrote on it and the FUNCTIONOBJ_handler pointer is returned by get_function_handler.
With the pointer in hand, the user can set the pointer to the arguments and the return variable with set_args_pointer and set_return_pointer, which both take a void * as arguments.
Finally, you can call the function you want. It has to:
1 - Grab the FUNCTIONOBJ_handler ID from the FUNCTIONOBJ_id_holder data structure and use it to get a pointer to the FUNCTIONOBJ_handler itself.
2 - Use the FUNCTIONOBJ_handler to access the arguments.
3 - Return by using one of the return function (on the example we have ret_int, which will return an integer and unlock the FUNCTIONOBJ_handler)
Below is a simplified mind map describing a bit of what is going on:
Finally, the code:
funcobj.h:
#include <stdio.h>
#include <pthread.h>
#define MAX_SIMULTANEOUS_CALLS 1024
typedef struct {
//Current ID about to be called
int current_id;
//Mutex
pthread_mutex_t id_holder_mutex;
} FUNCTIONOBJ_id_holder_t;
typedef struct {
//Attributes
void *arguments;
void *return_pointer;
//Mutex
pthread_mutex_t handler_mutex;
} FUNCTIONOBJ_handler_t;
FUNCTIONOBJ_handler_t FUNCTIONOBJ_handler[MAX_SIMULTANEOUS_CALLS];
FUNCTIONOBJ_id_holder_t FUNCTIONOBJ_id_holder;
void set_return_pointer(FUNCTIONOBJ_handler_t *this, void *pointer);
void set_args_pointer(FUNCTIONOBJ_handler_t *this, void *pointer);
void ret_int(FUNCTIONOBJ_handler_t *this, int return_value);
void FUNCTIONOBJ_initialize(void);
FUNCTIONOBJ_handler_t *get_function_handler(void);
funcobj.c:
#include "funcobj.h"
void set_return_pointer(FUNCTIONOBJ_handler_t *this, void *pointer){
this->return_pointer = pointer;
}
void set_args_pointer(FUNCTIONOBJ_handler_t *this, void *pointer){
this->arguments = pointer;
}
void ret_int(FUNCTIONOBJ_handler_t *this, int return_value){
if(this->return_pointer){
*((int *) (this->return_pointer)) = return_value;
}
pthread_mutex_unlock(&(this->handler_mutex));
}
void FUNCTIONOBJ_initialize(void){
for(int i = 0; i < MAX_SIMULTANEOUS_CALLS; ++i){
pthread_mutex_init(&FUNCTIONOBJ_handler[i].handler_mutex, NULL);
}
pthread_mutex_init(&FUNCTIONOBJ_id_holder.id_holder_mutex, NULL);
}
FUNCTIONOBJ_handler_t *get_function_handler(void){
int i = 0;
while((0 != pthread_mutex_trylock(&FUNCTIONOBJ_handler[i].handler_mutex)) && (i < MAX_SIMULTANEOUS_CALLS)){
++i;
}
if(i >= MAX_SIMULTANEOUS_CALLS){
return NULL;
}
//Sets the ID holder to hold this ID until the function is called
pthread_mutex_lock(&FUNCTIONOBJ_id_holder.id_holder_mutex);
FUNCTIONOBJ_id_holder.current_id = i;
return &FUNCTIONOBJ_handler[i];
}
main.c:
#include "funcobj.h"
#include <string.h>
//Function:
void print(void){
//First the function must grab the handler that contains all its attributes:
//The FUNCTIONOBJ_id_holder is mutex locked, so we can just access its value and
//then free the lock:
FUNCTIONOBJ_handler_t *this = &FUNCTIONOBJ_handler[FUNCTIONOBJ_id_holder.current_id];
//We dont need the id_holder anymore, free it!
pthread_mutex_unlock(&FUNCTIONOBJ_id_holder.id_holder_mutex);
//Do whatever the function has to do
printf("%s\n", (char *) this->arguments);
//Return the value to the pointed variable using the function that returns an int
ret_int(this, 0);
}
void *thread_entry_point(void *data){
int id = (int) data;
char string[100];
snprintf(string, 100, "Thread %u", id);
int return_val;
FUNCTIONOBJ_handler_t *this;
for(int i = 0; i < 200; ++i){
do {
this = get_function_handler();
} while(NULL == this);
set_args_pointer(this, string);
set_return_pointer(this, &return_val);
print();
}
return NULL;
}
int main(int argc, char **argv){
//Initialize global data strucutres (set up mutexes)
FUNCTIONOBJ_initialize();
//testing with 20 threads
pthread_t thread_id[20];
for(int i = 0; i < 20; ++i){
pthread_create(&thread_id[i], NULL, &thread_entry_point, (void *) i);
}
for(int i = 0; i < 20; ++i){
pthread_join(thread_id[i], NULL);
}
return 0;
}
To compile: gcc -o program main.c funcobj.c -lpthread
Reasons to avoid it:
By using this, you are limiting the number of "function objects" that can be running simultaneously. That's because we need to use global data structures to hold the information required by the functions (arguments and return pointer).
You will be seriously slowing down the program when using multiple threads if those use "function objects" frequently: Even though many functions can run at the same time, only a single function object can be set up at a time. So at least for that fraction of time it takes for the program to set up the function and actually call it, all other threads trying to run a function will be hanging waiting the the data structure to be unlocked.
You still have to write some non-intuitive code at the beginning and end of each function you want to work without arguments (grabbing the FUNCTIONOBJ_handler structure, unlocking the FUNCTIONOBJ_id_holder structure, accessing arguments through the pointer you grabbed and returning values with non-built-in functions). This increases the chances of bugs drastically if care is not taken, specially some nasty ones:
Increases the chances of deadlocks. If you forget to unlock one of the data structures in any point of your code, you might end up with a program that works fine at some moments, but randomly freeze completely at others (because all function calls without arguments will be hanging waiting for the lock to be freed). That is a risk that happens on multithreaded programs anyways, but by using this you are increasing the amount of code that requires locks unnecessarily (for style purposes).
Complicates the use of recursive functions: Every time you call the function object you'll have to go through the set up phrase (even when inside another function object). Also, if you call the recursive function enough times to fill all FUNCTIONOBJ_handler structures the program will deadlock.
Amongst other reasons I might not notice at the moment :p

Synchronizing the result of threads with incremented shared variable and condition

The title might not appear particularly clear, but the code explains itself:
int shared_variable;
int get_shared_variable() {
int result;
pthread_mutex_lock(&shared_variable_mutex);
result = shared_variable;
pthread_mutex_unlock(&shared_variable_mutex);
return result;
}
void* thread_routine(void *arg) {
while (get_shared_variable() < 5000) {
printf();
printf();
sleep(2);
int i = 0;
while (pthread_mutex_trylock(&foo_mutexes[i]) != 0) {
i++;
pthread_mutex_lock(&foo_count_mutex);
if (i == foo_count) {
pthread_mutex_unlock(&foo_count_mutex);
sleep(1); // wait one second and retry
i = 0;
}
pthread_mutex_unlock(&foo_count_mutex);
}
pthread_mutex_lock(&shared_variable_mutex);
shared_variable += 10;
pthread_mutex_unlock(&shared_variable_mutex);
}
return NULL;
}
I'm passing thread_routine to a pthread_create (pretty standard), but I'm having a problem with the synchronization of the result. Basically, the problem is that the first thread checks the while condition, it passes, and then another thread checks it, it passes too. However, when the first thread finishes and shared_variable reaches 5000, the second thread has not yet finished and it adds up another 10 and the end result becomes 5010 (or NUM_OF_THREADS - 1 * 10 if I run more than two) at the end, while the whole process should end at 5000.
Another issue is that in // do some work I output something on the screen, so the whole thing inside the loop should pretty much work as a transaction in database terms. I can't seem to figure out how to solve this problem, but I suppose there's something simple that I'm missing. Thanks in advance.
This answer may or may not be what you are after. Because as explained in the comments your description of the expected behaviour of the program is incomplete. Without the exact expected behaviour it is difficult to give a full answer. But since you ask, here is a possible structure of the program based on the code shown. The main principle it is illustrating is that the critical section for shared_variable needs to be both minimal and complete.
int shared_variable;
void* thread_routine(void *arg)
{
while (1) {
pthread_mutex_lock(&shared_variable_mutex);
if (shared_variable >= 5000) {
pthread_mutex_unlock(&shared_variable_mutex);
break;
}
shared_variable += 10;
pthread_mutex_unlock(&shared_variable_mutex);
/* Other code that doesn't use shared_variable goes here */
}
return NULL;
}

Thread execution issue

I'm approaching C programming with threads and I can't get this program to work properly. Basically there's a vector with k elements, n threads and each thread has to calculate the max on its k/n elements.
My code is (please note it's not the whole code):
// Struct code used later
struct maxStruct
{
double *vettore;
int dimensione;
};
// Gathering data input from user
[ . . . ]
vector = (double *) malloc (dimensione * sizeof(double));
pid_thread = (int *) malloc (numero_thread * sizeof(int));
thread = (pthread_t *) malloc (numero_thread * sizeof(pthread_t));
// Generating the vector
[ . . . ]
for (i = 0; i < numero_thread; i++)
{
e = generaStruct(i, vettore, dimensione, numero_thread);
if (status = pthread_create(&thread[i], NULL, calcolaMassimo, (void *) e))
{
pthread_perror("pthread_join", status);
exit(1);
}
}
//Note that the function doesn't calculate the max, I've coded it in this way
//in order to see whether it was being called by each thread and apparently it is not.
void *calcolaMassimo(void * e)
{
printf("Sono chiamata!!\n");
struct maxStruct *sottoVettore = e;
printf("Dimensione: %d\n", ((*sottoVettore).dimensione));
}
Apparently this function is not being called by each thread and I can't figure out why. Will you please help me solve this issue?
Firstly, a minor nit pick, the idiomatic way to write (*sottoVettore).dimensione) is sottoVettore->dimensione.
The process containing all of threads will exit when main() exits. I know you said you're joining in you're actual code so that should not be an issue but if you're not joining in the test code then that could be an issue.
It is also possible that the issue is not that the code in each thread isn't executing, but that the statements aren't actually reaching stdout. You might want to try a fflush(stdout) at the end of calcolaMassimo and see if that changes things.

Resources