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);
}
Related
Start two threads with policy SCHED_RR and priority 45.
One thread's affinity is 0x0004, and another is 0x0008.(my computer contains four cpu cores. system is CentOS 7, not a virtual machine.)
The subTask is simple:
spinning trylock in the while.
call printf show the information.
free the lock.
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <sched.h>
#include <pthread.h>
#define CHECK_ERROR(call)\
do{\
int _error = (call);\
if(_error != 0){\
printf("*** Error *** at [%s:%d] error=%d \n", __FILE__, __LINE__, _error);\
}\
}while(0)
int getThreadCores(pthread_t thread, int *cores);
int getThreadPP(pthread_t thread, int *policy, int *priority);
int setThreadAttrCores(pthread_attr_t *attr, int cores);
int setThreadAttrPP(pthread_attr_t *attr, int policy, int priority);
#define SUB_THREAD_NUM (2)
static int threadsId[SUB_THREAD_NUM];
static pthread_t subThreads[SUB_THREAD_NUM];
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
void *subTask(void *data)
{
int id = *(int*)data;
int policy=0, priority=0, cores=0;
CHECK_ERROR(getThreadCores(pthread_self(), &cores));
CHECK_ERROR(getThreadPP(pthread_self(), &policy, &priority));
printf("the sub thread %d, cores 0x%x, policy %d, priority %d\n",
id,cores,policy,priority);
int n = 1024*10;
int i;
for(i=0;i<n;++i)
{
while(pthread_mutex_trylock(&lock)){}
printf("the sub thread %d, out put %d\n",id,i);
CHECK_ERROR(pthread_mutex_unlock(&lock));
}
return NULL;
}
int main(int argc, char *argv[])
{
pthread_attr_t attr;
CHECK_ERROR(pthread_attr_init(&attr));
int i;
for(i=0;i<SUB_THREAD_NUM;++i)
{
threadsId[i] = i;
CHECK_ERROR(setThreadAttrCores(&attr, 0x0004<<i));
CHECK_ERROR(setThreadAttrPP(&attr, SCHED_RR, 1));
CHECK_ERROR(pthread_create(&subThreads[i],&attr,subTask,threadsId+i));
}
CHECK_ERROR(pthread_attr_destroy(&attr));
for(i=0;i<SUB_THREAD_NUM;++i)
{
CHECK_ERROR(pthread_join(subThreads[i],NULL));
}
printf("multiThreadTest success\n");
return 0;
}
int getThreadCores(pthread_t thread, int *cores)
{
int error = 0;
int cpuNum = sysconf(_SC_NPROCESSORS_CONF);
int _cores = 0;
cpu_set_t mask;
CPU_ZERO(&mask);
error = pthread_getaffinity_np(thread, sizeof(cpu_set_t), &mask);
if(error == 0)
{
int i;
for(i=0;i<cpuNum;++i)
{
if(CPU_ISSET(i, &mask))
{
_cores |= (0x1 << i);
}
}
}
*cores = _cores;
return error;
}
int getThreadPP(pthread_t thread, int *policy, int *priority)
{
int error = 0;
struct sched_param sp;
error = pthread_getschedparam(thread,policy,&sp);
*priority = sp.sched_priority;
return error;
}
static void setCpuSetMask(cpu_set_t *mask, int cores)
{
int cpuNum = sysconf(_SC_NPROCESSORS_CONF);
CPU_ZERO(mask);
int i;
for(i=0;i<cpuNum;++i)
{
if(((cores>>i)&0x1) == 1)
{
CPU_SET(i, mask);
}
}
}
int setThreadAttrCores(pthread_attr_t *attr, int cores)
{
cpu_set_t mask;
if(cores<0)cores=0xFFFFFFFF;
setCpuSetMask(&mask,cores);
return pthread_attr_setaffinity_np(attr, sizeof(cpu_set_t), &mask);
}
int setThreadAttrPriority(pthread_attr_t *attr, int priority)
{
struct sched_param sp;
sp.sched_priority = priority;
return pthread_attr_setschedparam(attr,&sp);
}
int setThreadAttrPP(pthread_attr_t *attr, int policy, int priority)
{
int error = 0;
//firstly, set the inherit to PTHREAD_EXPLICIT_SCHED
error |= pthread_attr_setinheritsched(attr,PTHREAD_EXPLICIT_SCHED);
error |= pthread_attr_setschedpolicy(attr,policy);
error |= setThreadAttrPriority(attr,priority);
return error;
}
compile: gcc -Wall -O3 -lpthread multiThreadTest.c -o multiThreadTest
My question is: the program blocked, one thread blocked in printf and another blocked in spinning trylock, why?
If I change the policy to SCHED_OTHER and the priority to 0, the program unblocked.
If I change the while(pthread_mutex_trylock(&lock)){} to CHECK_ERROR(pthread_mutex_lock(&lock)); the program unblocked.
If I change the while(pthread_mutex_trylock(&lock)){} to while(pthread_mutex_trylock(&lock)){usleep(1);} the program unblocked.
And if I change the printf to fprintf, the program unblocked.
And if I run the same program on Ubuntu system, it is unblocked.
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.
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)
I paste only model, which shows the problem. In function:
int get_random_prime(mpz_t number) I've got: sem_wait(&prime_count); and it doesn't work properrly.It waits and waits and waits even if semaphore is greater that 0.
#include<gmp.h>
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
#include<errno.h>
#include<string.h>
#include<stdlib.h>
#include<fcntl.h>
size_t number_of_cores=2;
pthread_mutex_t mutex_queue;
sem_t prime_count;
sem_t threads_count;
size_t last_length=0;
size_t prime_got=0;
char manager_on=0;
mpz_t prime;
get_random_odd(mpz_t output,size_t length){
size_t i;
size_t dev_random;
int randomFile= open("/dev/urandom", O_RDONLY);
read(randomFile,&dev_random,8);
mpz_set_ui(output,dev_random);
for(i=1;i<(length/64);i++){
read(randomFile,&dev_random,8);
mpz_mul_2exp (output,output, 64);
mpz_add_ui(output,output,dev_random);
}
close(randomFile);
mpz_setbit(output,length-1);
mpz_setbit(output,0);
}
void* get_random_prime_thread(void* ptr_length){
size_t result = 0;
size_t i;
size_t length = *((size_t*)ptr_length);
mpz_t number;
mpz_init(number);
//do{
get_random_odd(number, length);
i=0;
/* do{
result=miller_rabin_test(number);
i++;
}while(result==1 && i<prime_precision);*/
//}while(result==0);
pthread_mutex_lock(&mutex_queue);
mpz_set(prime,number);
pthread_mutex_unlock(&mutex_queue);
sem_post(&prime_count);
mpz_clear(number);
pthread_exit(NULL);
};
void* get_random_prime_manager_start(void* length){
size_t i;
size_t size=32;
pthread_t *threads=malloc(sizeof(pthread_t)*size);
manager_on =1;
pthread_t rc;
pthread_mutex_init(&mutex_queue,NULL);
sem_init(&threads_count,0,number_of_cores);
sem_init(&prime_count,0,0);
i=-1;
do{
sem_wait(&threads_count);
i++;
printf("PROCES:%d\n",i);
if(i>=size){
threads=realloc(threads,size*2);
}
rc=pthread_create(&threads[i],NULL,get_random_prime_thread,length);
if(rc){
printf("%s\n",strerror(errno));
pthread_exit((void*)-1);
}
}while(manager_on);
for(i;i>0;i--){
pthread_cancel(threads[i]);
}
free(threads);
pthread_mutex_destroy(&mutex_queue);
sem_destroy(&threads_count);
sem_destroy(&prime_count);
pthread_exit(NULL);
}
void* get_random_prime_manager_stop(){
manager_on=0;
}
int get_random_prime(mpz_t number){
sem_wait(&prime_count);
printf("GET\n");
pthread_mutex_lock(&mutex_queue);
mpz_set(number,prime);
pthread_mutex_unlock(&mutex_queue);
sem_post(&threads_count);
return 0;
};
int main(){
mpz_init(prime);
size_t rc;
size_t length=1024;
pthread_t thread;
mpz_t p,q,n;
mpz_init(p);
mpz_init(q);
mpz_init(n);
size_t half_length=length/2;
rc=pthread_create(&thread,NULL,get_random_prime_manager_start,(void*)&half_length);
if(rc){
printf("%s\n",strerror(errno));
return -1;
}
do{
get_random_prime(p);
get_random_prime(q);
mpz_mul(n,p,q);
}while( mpz_sizeinbase(n,2)==length);
get_random_prime_manager_stop();
mpz_clear(p);
mpz_clear(q);
mpz_clear(n);
}
Is it possible that thread wait on semaphore that hasn't been initiated yet?
You need to make sure the sem_init calls complete before you try to use any of the semaphores. The best way to do this is to call get_random_prime_manager_start normally and let it initialize the semaphores, start a thread, and then return. That way, you are assured that the manager is sufficiently started for it to be safe to use it when the function returns.
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;