How to use a semaphore and struct for multi threads - c

I am trying to have a multithread program that work with struct and semaphore.
I am not sure how to pass those values. Therefore I decided to pass my struct by reference and put my semaphore as a global variable.
What I am trying to do is to make two threads count to 20
(where one would be t1 = 0, 2 , 4 ,6 ... 20 and t2 = 1, 3 , ... , 19)
Here is what I have so far:
#include <fcntl.h>
#include <semaphore.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#define SEM_sem;
#define MaxVal 20;
typedef struct {
int startVal;
int maxVal;
} countStruct;
sem_t *sem;
void *t1(void *param) {
countStruct *counting;
counting = (countStruct *) param;
int i = counting->startVal;
while(i <= counting->maxVal) {
printf("%d\n",i);
i = i + 2;
sem_post(sem);
sem_wait(sem);
}
pthread_exit(0);
}
void *t2(void *param) {
countStruct *counting;
counting = (countStruct *) param;
int i = counting->startVal;
while(i <= counting->maxVal) {
printf("%d\n",i);
i = i + 2;
sem_post(sem);
sem_wait(sem);
}
pthread_exit(0);
}
int main() {
sem = sem_open(SEM_sem, O_CREAT | O_EXCL, 0666, 0);
if (sem == SEM_FAILED) {
printf("sem_open() failed\n");
sem_unlink(SEM_mpoulinl);
return(8);
}
pthread_attr_t attr;
pthread_t tid1, tid2
countStruct array_struct[3];
int i = 0;
for(i ; i < 2 ; i++) {
array_struct[i].startVal = i;
array_struct[i].maxVal = MaxVal;
}
pthread_create(&tid1, NULL, t1, (void*)&array_struct[0]);
sleep(1);
pthread_create(&tid2, NULL, t=2, (void*)&array_struct[1]);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
sem_close(sem);
sem_unlink(SEM_mpoulinl);
return(0);
}
Unfortunately my code print t1 then t2.
Why is it not working?
is it because my semaphore is global?
I tested taking out sem_post(sem) sem_wait(sem) and the code still work, therefore those two things does not seem to work or am I not using it appropriately?
Thank you!

Related

In C, I want to access one array in two separate processes [duplicate]

This question already has answers here:
How to use shared memory with Linux in C
(5 answers)
Closed 4 years ago.
This is essentially what I want to do, but the outputs are junk data. What are some of the different options I have for making the child's array visible from inside the parent process?
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
int foo[3]; //initialize array
pid_t pid;
pid = fork(); //create child thread
if (pid == 0) { //child:
foo[0] = 0; foo[1] = 1; foo[2] = 2; //populate array
}
else { //parent:
wait(NULL); //wait for child to finish
printf("%d %d %d", foo[0], foo[1], foo[2]); //print contents of array
}
return 0;
}
Using mmap you can create a shared memory block in your parent process. This is a basic example removing error checking for brevity.
You want to sure the proper protections and flags are set for your needs. Then hand off the address returned by mmap to your child process.
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <unistd.h>
#define LIMIT_MAP 5
void child_worker(void *map)
{
int map_value = -1;
int idx = 0;
while (map_value != LIMIT_MAP) {
map_value = *((int *) map + (idx * sizeof(int)));
printf("Map value: %d\n", map_value);
idx++;
sleep(2);
}
}
int main(int argc, char *argv[])
{
printf("Starting Parent Process...\n");
long page_size = sysconf(_SC_PAGESIZE);
void *memory_map = mmap(0, page_size, PROT_WRITE | PROT_READ,
MAP_SHARED | MAP_ANONYMOUS, 0, 0);
printf("Memory map created: <%p>\n", memory_map);
pid_t pid = fork();
if (pid == 0) {
sleep(1);
printf("Starting child process\n");
child_worker(memory_map);
printf("Exiting child process...\n");
return 0;
} else {
printf("Continuing in parent process\n");
int set_values[5] = { 1, 2, 3, 4, 5 };
for (int i=0; i < 5; i++) {
printf("Setting value: %d\n", set_values[i]);
*((int *) memory_map + (sizeof(int) * i)) = set_values[i];
sleep(1);
}
waitpid(pid, NULL, 0);
printf("Child process is finished!\n");
}
return 0;
}
If fork isn't a requirement and your platform allows for it, pthread is one option. Depending on how your array is being operated on, create a thread pool passing each worker thread a copy of your array.
This is a contrived example but maybe you can pull something from it:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include <pthread.h>
#define THREAD_COUNT 3
#define ITER_LIMIT 7
struct worker_params {
int idx;
int max;
bool done;
double *data;
double condition;
};
void *worker(void *arg)
{
struct worker_params *wp = (struct worker_params *) arg;
int count = 0;
while ( 1 ) {
wp->data[wp->idx] = drand48();
if (wp->max == count)
wp->done = true;
sleep(1);
count++;
}
return NULL;
}
int main(int argc, char *argv[])
{
double data[THREAD_COUNT] = { 0.0 };
pthread_t worker_1, worker_2, worker_3;
pthread_t worker_threads[] = { worker_1, worker_2, worker_3 };
struct worker_params wps[] = {
{ .idx=0, .condition=0.1, .data=data, .done=0 },
{ .idx=1, .condition=0.2, .data=data, .done=0 },
{ .idx=2, .condition=0.3, .data=data, .done=0},
};
for (int i=0; i < THREAD_COUNT; i++) {
wps[i].max = (rand() % ITER_LIMIT) + 2;
pthread_create(&worker_threads[i], NULL, worker, (void *) &wps[i]);
}
// Continue on main execution thread
int running = 1;
while ( running ) {
for (int i=0; i < THREAD_COUNT; i++) {
if (wps[i].done) {
printf("Limit hit in worker <%d>\n", i + 1);
running = 0;
break;
}
printf("Data in worker <%d> :: %g\n", i + 1, wps[i].data[i]);
}
sleep(1);
}
return 0;
}

Using semaphores with shared memory while running multiple processes

I am learning some simple producer/consumer examples involving semaphores, but having a hard time explaining to myself why I am getting a certain result (because I am a noobie to C).
When I run two concurrent processes of the following producer, both processes get hung up and never finish:
#include <stdio.h>
#include <sys/types.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#define BUFF_SIZE 20
typedef struct {
char buffer[BUFF_SIZE];
int nextIn;
int nextOut;
} shared_data;
shared_data *shm, *s;
char sem_name1[] = "mutex";
char sem_name2[] = "empty_slots";
char sem_name3[] = "full_slots";
sem_t *empty_slots;
sem_t *full_slots;
sem_t *mutex;
void Put(char item)
{
sem_wait(empty_slots);
sem_wait(mutex);
s->buffer[s->nextIn] = item;
s->nextIn = (s->nextIn + 1) % BUFF_SIZE;
sem_post(mutex);
printf("Producing %c ... with pid = %d\n", item, getpid());
sem_post(full_slots);
}
void Producer()
{
int i;
for(i = 0; i < 10; i++)
{
sleep(rand()%3);
Put((char)('A'+ i % 26));
}
}
void main()
{
//Create and initialize the semaphores
mutex=sem_open(sem_name1, O_CREAT,0644, 1);
full_slots=sem_open(sem_name3, O_CREAT,0644, 0);
empty_slots=sem_open(sem_name2, O_CREAT,0644, 10);
//Create a key for the segment
key_t key;
key = 1234;
//create the segment
int shmid;
if ((shmid = shmget(key, sizeof(shared_data), IPC_CREAT |0666)) <0)
{
perror("Shmget");
exit(1);
}
//attach to the segment
if ((shm = (shared_data *) shmat(shmid, NULL, 0))==(shared_data *) -1)
{
perror("Shmat");
exit(1);
}
s=shm;
s->nextIn = 0;
Producer();
//detach from the segment
shmdt((void *) shm);
}
The output from the first and second processes, respectively:
Can someone help me understand why this happens (i.e. why do these processes never finish)? Have I created a deadlock? Why or why not? I am completely stumped.
Thanks!

Writing barrier with shared memory in C

I need to write barrier for process synchronisation. I did and it was working until I put struct barrier in shared memory. My code is as follows:
#include <pthread.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <sys/time.h>
#include <semaphore.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
void nanosleep2(long t)
{
struct timespec a;
a.tv_sec = 0;
a.tv_nsec = t;
nanosleep(&a, NULL);
}
struct barrier
{
int n; // number of processes
sem_t mutex;
int count;
sem_t bar;
};
void init(struct barrier * b, int n)
{
b->n = n;
b->count = 0;
sem_init(&b->mutex, 0, 1);
sem_init(&b->bar, 0, 0);
}
void destroy(struct barrier * b)
{
sem_destroy(&b->mutex);
sem_destroy(&b->bar);
}
void wait(struct barrier * b)
{
sem_wait(&b->mutex); // It seems that some processes never get acces to mutex, but isn't it impossible?
++(b->count);
printf("Horse is there!, %d/%d\n", b->count, b->n);
if (b->count == b->n)
{
printf("the barierr is open!\n");
sem_post(&b->bar);
}
sem_post(&b->mutex);
sem_wait(&b->bar);
sem_post(&b->bar);
}
struct barrier * barr_open(const char * name)
{
int fd = shm_open(name, O_RDWR | O_CREAT, 0666);
ftruncate(fd, sizeof(struct barrier));
struct barrier * res = mmap(NULL, sizeof(struct barrier), PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
close(fd);
return res;
}
void barr_close(struct barrier * barr, const char * name) // if name is not NULL, it also unlinks
{
munmap(barr, sizeof(struct barrier));
if (name != NULL)
shm_unlink(name);
}
const int N = 5; // number of horses
void * horse(void * _)
{
struct barrier * barr = barr_open("/barieraa");
nanosleep2((rand()%200)+10);
wait(barr);
barr_close(barr, NULL);
return NULL;
}
int main()
{
srand(time(NULL));
struct barrier * barr = barr_open("/barieraa");
init(barr, N);
sleep(1);
int i;
for (i = 0; i < N; i++)
{
pthread_t t;
pthread_create(&t, NULL, horse, NULL);
pthread_detach(t);
nanosleep2(rand()%200);
}
sleep(1);
destroy(barr);
barr_close(barr, "/barieraa");
return 0;
}
So, the first printf in wait() only three or four horses are able to reach. Probably something grabs mutex and doesn't return, but is it possible? Why barrier itself works, shared memory itself works, but they both together don't want?

UNIX Pthreads & mutex; program locks up

Following scenario:
We are supposed to make x Threads maximum. Our main-function is supposed to make a single new thread with a pointer to the function 'makeThreads'. This function is supposed to make up to 2 threads, depending on how many threads are already there. Race conditions are to avoid.
I'm stuck. I'm not exactly sure how to solve the problem I'm running into, partly because I don't can't identify the problem itself.
Suggestions are greatly appreciated!
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#define MAX_THR 20
pthread_mutex_t mutex;
int threadCount = 0;
int randomNbr(){
int number = (rand() % 10) + 1;
return number;
}
void *makeThreads(void* number){
int rndnmb = *((int *) number);
pthread_mutex_lock(&mutex);
sleep(rndnmb);
pthread_t threadDummy;
int thread1, i, threadID, rndnbr;
threadID = threadCount;
printf("Hello from Thread %d!\n", threadID);
for(i = 0; i < 2; i++){
if(threadCount < MAX_THR){
rndnbr = randomNbr();
int *rnd = &rndnbr;
threadCount++;
thread1 = pthread_create(&threadDummy, NULL, *makeThreads, (void *) rnd);
pthread_join(threadDummy, NULL);
}
}
pthread_mutex_unlock(&mutex);
printf("Goodbye from Thread %d!\n", threadID);
}
int main(){
int t1, rndnbr;
pthread_t threadOne;
pthread_mutex_init(&mutex, NULL);
srand(time(NULL));
rndnbr = randomNbr();
int *rnd = &rndnbr;
threadCount++;
t1 = pthread_create(&threadOne, NULL, *makeThreads, (void *) rnd);
pthread_join(threadOne, NULL);
}

Segmentation fault in C multithreaded consumer-producer program

I'm currently being introduced to the concept of threading programs, and have been given an assignment to simulate a stockmarket using threads and semaphores. Here is the code:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <semaphore.h>
#include <pthread.h>
#define NUM_WRITERS 5
#define NUM_READERS 5
#define STOCKLIST_SIZE 10
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
sem_t stop_writers;
typedef struct
{ int readers;
int slots[STOCKLIST_SIZE];
} mem_structure;
int id[NUM_READERS + NUM_WRITERS];
mem_structure *stocklist;
pthread_t thr[NUM_WRITERS + NUM_READERS];
void init(){
sem_init(&stop_writers, 0, 1);
}
void cleanup(int signo) // clean up resources by pressing Ctrl-C
{ sem_destroy(&stop_writers);
printf("Closing...\n");
exit(0);
}
void write_stock(int n_writer)
{
int stock = (int)(rand()%STOCKLIST_SIZE);
int stock_value = 1 + (int)(100.0 * rand()/(RAND_MAX + 1.0));
stocklist->slots[stock] = stock_value;
fprintf(stderr, "Stock %d updated by BROKER %d to %d\n", stock, n_writer, stock_value);
}
void* writer(void* id){
int my_id = *((int*) id);
int i = my_id;
while (1)
{
pthread_mutex_lock(&mutex);
sem_wait(&stop_writers);
write_stock(i);
pthread_mutex_unlock(&mutex);
sem_post(&stop_writers);
sleep(1);
++i;
}
}
void read_stock(int pos, int n_reader){
fprintf(stderr, "Stock %d read by client %d = %d.\n", pos, n_reader, stocklist->slots[pos]);
}
void* reader(void* id){
int my_id = *((int*) id);
int i = my_id;
while (1)
{ sem_wait(&stop_writers);
read_stock((int)(rand()%STOCKLIST_SIZE), i);
sem_post(&stop_writers);
sleep(1 + (int) (3.0 * rand() / (RAND_MAX + 1.0)));
++i;
}
}
void monitor() // main process monitors the reception of Ctrl-C
{
struct sigaction act;
act.sa_handler = cleanup;
act.sa_flags = 0;
if ((sigemptyset(&act.sa_mask) == -1) ||
(sigaction(SIGINT, &act, NULL) == -1))
perror("Failed to set SIGINT to handle Ctrl-C");
while(1){
sleep(5);
printf("Still working...\n");
}
exit(0);
}
int main(void)
{ int i, j;
init();
for (i = 0; i < NUM_WRITERS; ++i){
id[i] = i;
pthread_create(&thr[i], NULL, writer, &id[i]);}
for (j = i; j < NUM_READERS; ++j){
id[j] = j;
pthread_create(&thr[j], NULL, reader, &id[j]);}
stocklist->readers = 0;
pthread_exit(NULL);
monitor();
return 0;
}
This is giving me a segmentation fault pretty much as soon as main() begins, with the creation of a thread... Since it's not code that I've created from root, I'm having trouble backtracing the error and fixing it - it would be great if there was someone who could take a look and maybe give me some hints
Thank you!
EDIT
Fixed the problem, thanks to your help :)
I initialized stocklist on init(),
void init(){
sem_init(&stop_writers, 0, 1);
stocklist = (mem_structure*)malloc(sizeof(mem_structure));
}
And changed the second cicle in main(),
for (j = i; j < NUM_READERS+NUM_WRITERS; ++j){
id[j] = j;
pthread_create(&thr[j], NULL, reader, &id[j]);}
Thanks
Here's what I did to track down the problem:
gcc -g program.c -lpthread
gdb a.out
run
Output:
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb7feeb70 (LWP 23060)]
0x08048834 in write_stock (n_writer=0) at program.c:44
44 stocklist->slots[stock] = stock_value;
Looks like the problem is here:
stocklist->slots[stock] = stock_value;

Resources