so im trying to get this program with semaphores to work.
finally got rid of all of the errors, and now its giving me a core dump issue?
trying to figure out what im doing wrong, been working this all morning and cant seem to find the issue.
#include <pthread.h>
#include <stdio.h>
#include <semaphore.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#define BUFF_SIZE 20
char buffer[BUFF_SIZE];
int nextIn = 0;
int nextOut = 0;
//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;
typedef struct {
char buffer[BUFF_SIZE];
int nextIn;
int nextOut;
} shared_data;
void Put(char item){
sem_wait(empty_slots);
sem_wait(mutex);
buffer[nextIn] = item;
nextIn = (nextIn + 1) % BUFF_SIZE;
sem_post(mutex);
printf("Producing %c ...\n", item);
sem_post(full_slots);
}
void * Producer(){
int i;
for(i = 0; i < 15; i++){
sleep(rand()%6);
Put((char)('A'+ i % 26));
}
}
void Get(char item){
sem_wait(full_slots);
sem_wait(mutex);
item= buffer[nextOut];
nextOut = (nextOut + 1) % BUFF_SIZE;
sem_post(mutex);
printf("Consuming %c ...\n", item);
sem_post(empty_slots);
}
void * Consumer(){
int i;
char item;
for(i = 0; i < 15; i++){
sleep(rand()%6);
Get(item);
}
}
void main(){
sem_init(empty_slots, 0, 1);
sem_init(full_slots, 0, BUFF_SIZE);
sem_init(mutex, 0, 1);
/* Initialize semaphores */
pthread_t pid, cid;
pthread_create(&pid, NULL, Producer, NULL);
pthread_create(&cid, NULL, Consumer, NULL);
// create more consumer & producer threads.
pthread_join(pid, NULL);
pthread_join(cid, NULL);
}
when i use gdb i get the error
(gdb)
Id Target Id Frame
* 1 Thread 0xb7de8700 (LWP 3567) "labp2" __new_sem_init (sem=0x0, pshared=0, value=1)
at sem_init.c:60
(gdb)
Related
I tried to solve the Sleeping Barber problem using the pthread functions.
code:
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
#include <unistd.h>
#define NR_CUSTOMERS 20
#define NR_CHAIRS 3 //chairs in the waiting room + barber chair
sem_t lock;
sem_t customer;
sem_t barber;
int waitingCustomers = 0;
int barberChair = 0;
void *th_customer(void *arg)
{
int myId = (int)(size_t)arg;
int tooBusy = 0;
usleep(1000 * (rand() % 20));
printf("[C%02d] Entering the barber shop\n", myId);
sem_wait(&lock);
if (waitingCustomers < NR_CHAIRS) //if there are still empty seats, the client waits
{
++waitingCustomers;
printf("[C%02d] %d customer(s) waiting\n", myId, waitingCustomers);
}
else
{
tooBusy = 1; //if not the client leaves because it is too crowded
}
sem_post(&lock);
if (tooBusy)
{
printf("[C%02d] Too busy, will come back another day.\n", myId);
}
else //one of the waiting customers is served
{
sem_wait(&customer);
sem_wait(&lock);
--waitingCustomers;
sem_post(&lock);
barberChair = myId;
sem_post(&barber);
printf("[C%02d] being served\n", myId);
usleep(1000);
}
return NULL;
}
void *th_barber()
{
for (;;)
{
sem_post(&customer);
sem_wait(&barber);
printf("[B ] Serving customer %d\n", barberChair);
usleep(1000);
}
return NULL;
}
int main()
{
int i;
pthread_t tidC[NR_CUSTOMERS], tidB;
srand(time(NULL));
sem_init(&lock, 0, 1);
sem_init(&customer, 0, 0);
sem_init(&barber, 0, 0);
pthread_create(&tidB, NULL, th_barber, NULL);
for (i = 0; i < NR_CUSTOMERS; i++)
{
pthread_create(&tidC[i], NULL, th_customer, (void *)(size_t)(i + 1));
}
for (i = 0; i < NR_CUSTOMERS; i++)
{
pthread_join(tidC[i], NULL);
}
pthread_cancel(tidB);
pthread_join(tidB, NULL);
sem_destroy(&lock);
sem_destroy(&customer);
sem_destroy(&barber);
return 0;
}
The problem: I'm worried about possible concurrence, not the data, that's correct, but in terms of not using available resources: a customer may not receive a haircut due to the maximum number of customers, but one is already on his way to the barber chair, but does he who enters just not notice that his place has just been vacated?
What other problems can be hidden?
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <wait.h>
#include <pthread.h>
int item_to_produce, curr_buf_size;
int total_items, max_buf_size, num_workers, num_masters;
int consumed_items;
int *buffer;
pthread_mutex_t mutex;
pthread_cond_t has_data;
pthread_cond_t has_space;
void print_produced(int num, int master) {
printf("Produced %d by master %d\n", num, master);
}
void print_consumed(int num, int worker) {
printf("Consumed %d by worker %d\n", num, worker);
}
//consume items in buffer
void *consume_requests_loop(void *data)
{
int thread_id = *((int *)data);
while(1)
{
pthread_mutex_lock(&mutex); // mutex lock for consume
if(consumed_items == total_items) {
pthread_mutex_unlock(&mutex);
break;
}
while(curr_buf_size == 0) {
pthread_cond_wait(&has_data, &mutex);
}
print_consumed(buffer[(curr_buf_size--)-1], thread_id);
consumed_items++;
pthread_cond_signal(&has_space);
pthread_mutex_unlock(&mutex);
}
return 0;
}
//produce items and place in buffer
//modify code below to synchronize correctly
void *generate_requests_loop(void *data)
{
int thread_id = *((int *)data);
while(1) {
pthread_mutex_lock(&mutex); // mutex lock for consume
//all of items are produced
//master threads need to join
if(item_to_produce == total_items) {
pthread_mutex_unlock(&mutex);
break;
}
//there is no item to read
while (curr_buf_size == max_buf_size) {
pthread_cond_wait(&has_space, &mutex);
}
buffer[curr_buf_size++] = item_to_produce;
print_produced(item_to_produce, thread_id);
item_to_produce++;
pthread_cond_signal(&has_data);
pthread_mutex_unlock(&mutex); // mutex_produce unlock
}
return 0;
}
//write function to be run by worker threads
//ensure that the workers call the function print_consumed when they consume an item
int main(int argc, char *argv[])
{
int *master_thread_id; // array of master_thread_id
int *worker_thread_id; // array of worker_thread_id
pthread_t *master_thread; // array of master_thread
pthread_t *worker_thread; // array of worker_thread
item_to_produce = 0; // item will be produced by master_thread at next time
curr_buf_size = 0; // index of item will be saved in
consumed_items = 0;
int i;
if (argc < 5) {
printf("./master-worker #total_items #max_buf_size #num_workers #masters e.g. ./exe 10000 1000 4 3\n");
exit(1);
}
else {
num_masters = atoi(argv[4]);
num_workers = atoi(argv[3]);
total_items = atoi(argv[1]);
max_buf_size = atoi(argv[2]);
}
buffer = (int *)malloc (sizeof(int) * max_buf_size);
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&has_space, NULL);
pthread_cond_init(&has_data, NULL);
//create master producer threads
master_thread_id = (int *)malloc(sizeof(int) * num_masters);
master_thread = (pthread_t *)malloc(sizeof(pthread_t) * num_masters);
for (i = 0; i < num_masters; i++)
master_thread_id[i] = i;
for (i = 0; i < num_masters; i++)
pthread_create(&master_thread[i], NULL, generate_requests_loop, (void *)&master_thread_id[i]);
//create worker consumer threads
worker_thread_id = (int *)malloc(sizeof(int) * num_workers);
worker_thread = (pthread_t *)malloc(sizeof(pthread_t) * num_workers);
for (i = 0; i < num_workers; i++)
worker_thread_id[i] = i;
for (i = 0 ; i < num_workers; i++)
pthread_create(&worker_thread[i], NULL, consume_requests_loop, (void *)&worker_thread_id[i]);
//wait for all threads to complete
for (i = 0; i < num_masters; i++)
{
pthread_join(master_thread[i], NULL);
printf("master %d joined\n", i);
}
for (i = 0; i < num_workers; i++)
{
pthread_join(worker_thread[i], NULL);
printf("worker %d joined\n", i);
}
/*----Deallocating Buffers---------------------*/
free(buffer);
free(master_thread_id);
free(master_thread);
free(worker_thread_id);
free(worker_thread);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&has_data);
pthread_cond_destroy(&has_space);
return 0;
}
This code produces a number in the range of given numbers through the argument and consumes it.
But producer produces a number outside the range and doesn't join if it matches the condition. The consumer is too.
e.g when I give range of number like 0~39(total_item = 500), buff size 30(max_buf_size), num_workers 5, num_master 3, it doesn't produce and consume number only 0~39.
It produces and consumes numbers over 40.
In that way the thread is in a loop. To put the thread in sleep you can use, for example, the condition variables. (You can read this for more info https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_wait.html)
I've created a table of mq file descriptors and I'm trying to pass numbers from stdin by one of them.
I'm using notification using threads and when a number occures in one of the queues it should print for example "Number: 1 from queue: 3".
Here's my code:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <mqueue.h>
#define MAX_LENGTH 20
#define ERR(source) (\
fprintf(stderr, "%s:%d\n", __FILE__, __LINE__),\
perror(source),\
kill(0, SIGKILL),\
exit(EXIT_FAILURE)\
)
static void not_func(union sigval sv) {
mqd_t queue;
uint8_t number;
unsigned msg_prio;
queue = *((mqd_t*)sv.sival_ptr);
static struct sigevent not;
not.sigev_notify = SIGEV_THREAD;
not.sigev_notify_function = not_func;
not.sigev_value.sival_ptr = &queue;
if(mq_notify(queue, ¬)<0) ERR("mq_notify");
for(;;) {
if(mq_receive(queue, (char*)&number, 1, &msg_prio)<1) {
if(errno == EAGAIN) break;
else ERR("mq_receive");
printf("Number: %d from queue: %d", number, msg_prio);
}
}
}
void get_queue_name(int nr, char *str) {
snprintf(str, MAX_LENGTH, "/queue%d", nr);
}
mqd_t create_message_queue(int nr) {
mqd_t queue;
char name[MAX_LENGTH] = "";
get_queue_name(nr, name);
struct mq_attr attr;
attr.mq_maxmsg = 10;
attr.mq_msgsize = 1;
if((queue = TEMP_FAILURE_RETRY(mq_open(name, O_RDWR|O_NONBLOCK|O_CREAT, 0600, &attr))) == (mqd_t)-1) ERR("mq open in");
static struct sigevent not;
not.sigev_notify = SIGEV_THREAD;
not.sigev_notify_function = not_func;
not.sigev_value.sival_ptr = &queue;
if(mq_notify(queue, ¬)<0) ERR("mq_notify");
return queue;
}
void delete_message_queue(mqd_t queue, int nr) {
char name[MAX_LENGTH] = "";
get_queue_name(nr, name);
mq_close(queue);
if(mq_unlink(name)) ERR("mq_unlink");
}
void usage(void) {
fprintf(stderr, "USAGE: mqueue n\n");
fprintf(stderr, "100 > n > 0 - number of children\n");
exit(EXIT_FAILURE);
}
int main(int argc, char **argv) {
int n, i;
char strnumber[MAX_LENGTH];
int number;
mqd_t *queues;
srand(time(NULL));
if(argc != 2) usage();
n = atoi(argv[1]);
if(n<=0 || n>=100) usage();
queues = (mqd_t*)malloc(sizeof(mqd_t) * n);
if(queues == NULL) ERR("malloc");
for(i = 0; i < n; i++) {
queues[i] = create_message_queue(i+1);
}
while(fgets(strnumber, MAX_LENGTH, stdin)!=NULL) {
number = (uint8_t)atoi(strnumber);
if(number<=0) continue;
int randomQueue = rand()%n;
if(TEMP_FAILURE_RETRY(mq_send(queues[randomQueue], (const char *)&number, 1, (unsigned)randomQueue))) ERR("mq_send");
}
for(i = 0; i < n; i++) {
delete_message_queue(queues[i], i+1);
}
free(queues);
return EXIT_SUCCESS;
}
When I execute my code nothing happens:
or I have such an error:
You pass a pointer to queue (which is a local variable) to the thread (via not.sigev_value.sival_ptr) which runs after that variable goes out of scope. So it gets a dangling pointer.
Either pass the descriptor by value (if it fits in sigval; it should), or store it on the heap (with new/malloc) and pass that pointer.
Trying to use a bounded buffer from a separate file that I've coded and it seems like that's where the code goes all crazy. Fairly new to C, and I was wondering if I am using the buffer the right way. The concept of instantiation isn't here, so if I just call one of the functions such as bbuff_blocking_insert will the array get initialized? How do I make the appropriate calls in order to get this working?
candy.c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include "bbuff.h"
#include <stdbool.h>
#include <time.h>
_Bool stop_thread = false;
typedef struct {
int source_thread;
double time_stamp_in_ms;
} candy_t;
double current_time_in_ms (void) {
struct timespec now;
clock_gettime(CLOCK_REALTIME, &now);
return now.tv_sec * 1000.0 + now.tv_nsec/1000000.0;
}
void* createCandy(void* arg) {
int r;
int factoryNumber = *(int*)arg;
while(!stop_thread) {
r = rand() % 4;
printf("Random Number: %d\n", r);
printf("\tFactory %d ship candy & wait %ds\n", factoryNumber, r);
candy_t *candy = (candy_t*)malloc(sizeof(candy_t));
candy->source_thread = factoryNumber;
candy->time_stamp_in_ms = current_time_in_ms();
bbuff_blocking_insert((void *)candy);
sleep(r);
}
printf("Candy-factory %d done\n", factoryNumber);
return 0;
}
void* extractCandy(void* arg) {
int r;
candy_t* candy;
while(true) {
candy = (candy_t*)bbuff_blocking_extract();
printf("Candy Source Thread: %d\n", candy->source_thread);
r = rand() % 2;
sleep(r);
}
return 0;
}
int main(int argc, char* argv[]) {
//Extract Arguments
if (argc <= 1) {
printf("Insufficient Arguments\n");
exit(-1);
}
int NO_FACTORIES = atoi(argv[1]);
int NO_KIDS = atoi(argv[2]);
int NO_SECONDS = atoi(argv[3]);
bbuff_init();
//Spawn Factory Threads
pthread_t ftids[NO_FACTORIES];
int factoryNumber[NO_FACTORIES];
for (int i = 0; i < NO_FACTORIES; i++) {
factoryNumber[i] = i;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&ftids[i], &attr, createCandy, &factoryNumber[i]);
}
//Spawn Kid Threads
pthread_t ktids [NO_KIDS];
for (int i = 0; i < NO_KIDS; i++) {
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&ktids[i], &attr, extractCandy, NULL);
}
//Wait for Requested Time
for (int i = 0; i < NO_SECONDS; i++) {
sleep(1);
printf("Time %ds\n", i+1);
}
//Stop Factory Threads
stop_thread = true;
for (int i = 0; i < NO_FACTORIES; i++) {
pthread_join(ftids[i], NULL);
}
//Wait until no more candy
while(bbuff_is_data_available()) {
printf("Waiting for all candy to be consumed");
sleep(1);
}
//Stop kid Threads
for (int i = 0; i < NO_KIDS; i++) {
pthread_cancel(ktids[i]);
pthread_join(ktids[i], NULL);
}
//Print Statistics
//Clean up any allocated memory
return 0;
}
bbuff.h
#ifndef BBUFF_H
#define BBUFF_H
#define QUEUE_SIZE 10
void bbuff_init(void);
void bbuff_blocking_insert(void* item);
void* bbuff_blocking_extract(void);
_Bool bbuff_is_data_available(void);
#endif
bbuff.c
#include "bbuff.h"
pthread_mutex_t mutex;
sem_t empty;
sem_t full;
int in = 0;
int out = 0;
int counter = 0;
void* buffer[QUEUE_SIZE];
void bbuff_init(void){
pthread_mutex_init(&mutex, NULL);
sem_init( &empty, 0, QUEUE_SIZE);
sem_init( &full, 0, 0);
}
void bbuff_blocking_insert(void* item) {
sem_wait(&empty);
pthread_mutex_lock(&mutex);
counter++;
buffer[in] = item;
in = (in+1) % QUEUE_SIZE;
pthread_mutex_unlock(&mutex);
sem_post(&full);
}
void* bbuff_blocking_extract(void) {
void* extractedItem;
sem_wait(&full);
pthread_mutex_lock(&mutex);
counter--;
extractedItem = buffer[out];
buffer[out] = NULL;
out = out % QUEUE_SIZE;
pthread_mutex_unlock(&mutex);
sem_post(&empty);
return extractedItem;
}
Output
$ ./candykids 1 1 10
Random Number: 3
Factory 0 ship candy & wait 3s
Candy Source Thread: 0
Time 1s
Time 2s
Random Number: 1
Factory 0 ship candy & wait 1s
Time 3s
Segmentation fault (core dumped)
In bbuff_blocking_extract(),
out = out % QUEUE_SIZE;
Should be:
out = (out+1) % QUEUE_SIZE;
I am trying to solve the producer consumer problem using pthreads and semaphores. At the moment, neither of the threads seem to execute and even main isn't printing out a printf, it seems like the process is waiting for input. (so all that happens is, blinking cursor, then I press ctrl+c to end the process because nothing is happening). I have tested get_rand_num and that works. I am compiling with clang -Wall -std=c99 -lpthread -o randnumgen randnumgen.c
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <stdint.h>
#include "sema.c"
typedef struct buffer {
uint64_t *buffer;
int max_size;
int min_fill_lvl;
uint64_t *first;
uint64_t *last;
int size;
semaphore produce;
semaphore consume;
} buffer;
void *producer();
void *consumer();
uint64_t get_rand_num();
void init_buffer();
void cleanup_buffer();
void put_buffer();
uint64_t get_buffer();
int exit1=0;
buffer buf;
int main(){
initialize(&buf.produce, 0);
initialize(&buf.consume, 0);
pthread_t producerThread;
pthread_t consumerThread;
printf("test");
pthread_create(&producerThread, NULL, producer, (void *) &buf);
pthread_create(&consumerThread, NULL, consumer, (void *) &buf);
vacate(&buf.produce);
pthread_join(producerThread, NULL);
pthread_join(consumerThread, NULL);
return 1;
}
void *producer(buffer *buf){
printf("in producer");
init_buffer(&buf, 2, 1);
while (1){
procure(&buf->produce);
uint64_t ret = get_rand_num();
put_buffer(&buf, ret);
vacate(&buf->consume);
}
cleanup_buffer(&buf);
pthread_exit(NULL);
}
void *consumer(buffer *buf){
printf("in consumer");
while (1){
procure(&buf->consume);
uint64_t ret = get_buffer(&buf);
printf("%i", (int) ret);
vacate(&buf->produce);
}
pthread_exit(NULL);
}
uint64_t get_rand_num(){
FILE *rand = NULL;
rand = fopen("/dev/random", "r");
uint64_t num;
//static const size_t size = sizeof(uint64_t);
fread(&num, sizeof(num), 1, rand); //returns -1 if fails i believe
//printf("%i\n", (int) num);
return num;
}
void init_buffer(buffer *buf, int max, int min){
buf->buffer = malloc(sizeof(uint64_t) * max);
buf->size = 0;
buf->min_fill_lvl = min;
buf->max_size = max;
}
void cleanup_buffer(buffer *buf){
free(&buf->buffer);
}
void put_buffer(buffer *buf, uint64_t *num){
if (buf->size < buf->max_size){
*(buf->last++) = *num;
buf->size++;
}
printf("successfully placed num in buffer");
}
uint64_t get_buffer(buffer *buf){
if ((buf->size - 1) <= buf->min_fill_lvl){
buf->size--;
int ret = *buf->first;
buf->first++;
return ret;
}
return 0;
}
This is my semaphore code:
// semaphore setup
void initialize(semaphore *sp, int startVal){
pthread_mutex_init(&sp->lock, NULL);
sp->vacancy = startVal; //starting value for semaphore
pthread_cond_init(&sp->condition, NULL);
}
//destroys semaphore
void destruct(semaphore *sp){
pthread_mutex_destroy(&sp->lock);
pthread_cond_destroy(&sp->condition);
}
//waits until semaphore is available
void procure(semaphore *sp){
pthread_mutex_lock(&sp->lock);
while(sp->vacancy <= 0){
pthread_cond_wait(&sp->condition, &sp->lock);
}
sp->vacancy--;
pthread_mutex_unlock(&sp->lock);
}
//increments vacancy value signalling that a position has been freed
void vacate(semaphore *sp){
pthread_mutex_lock(&sp->lock);
sp->vacancy++;
pthread_cond_signal(&sp->condition);
pthread_mutex_unlock(&sp->lock);
}