0

Hello I am having trouble with strtol (specifically, that implicit conversion loses integer precision) as well as with sem_open incompatible pointer types passing sem_t

I have tried to use named semaphores instead of unnamed semaphores, use sem_open instead of sem_init, and use sem_close and sem_unlink instead of sem_destroy, but still getting errors.

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <fcntl.h>           /* For O_* constants */
#include <sys/stat.h>        /* For mode constants */
#include <semaphore.h>

// Global mutex and semaphores
pthread_mutex_t lock;
sem_t full;
sem_t empty;

// Global item to be incremented and enqueued
int global_value = 1;

// Queue
int* buffer;
int in_index;
int out_index;

// Producer and consumer arrays for comparing
int* producer_arr;
int* consumer_arr;
int p_idx = 0;
int c_idx = 0;

// Global args
int num_buffers;
int num_producers;
int num_consumers;
int items_produced;
int items_consumed;
int over_consume;
int over_consume_amount;
int p_time;
int c_time;

/*
 * Function to remove item.
 * Item removed is returned
 */
int dequeue_item() {
    int item = buffer[out_index];
    buffer[out_index] = 0;
    out_index = (out_index + 1) % num_buffers;
    return item;
}

/*
 * Function to add item.
 * Item added is returned.
 * It is up to you to determine
 * how to use the ruturn value.
 * If you decide to not use it, then ignore
 * the return value, do not change the
 * return type to void.
 */
int enqueue_item(int item) {
    buffer[in_index] = item;
    in_index = (in_index + 1) % num_buffers;
    return item;
}


void* producer(void* arg) {
    int tid = *((int*) arg);
    int item;

    for (int i = 0; i < items_produced; i++) {
        // Increment global item
        item = global_value++;

        // Lock semaphore and mutex
        sem_wait(&empty);
        pthread_mutex_lock(&lock);

        // Produce item onto queue
        enqueue_item(item);
        producer_arr[p_idx++] = item;
        printf( "%5d was produced by producer->\t%5d\n" , item, tid);

        // Unlock mutex and semaphore
        pthread_mutex_unlock(&lock);
        sem_post(&full);

        // Sleep
        sleep(p_time);
    }

    pthread_exit(0);
}


void* consumer(void* arg) {
    int tid = *((int*) arg);
    int item;

    if (!over_consume) {
        // Either over or not required
        for (int i = 0; i < items_consumed; i++) {
            // Lock semaphore and mutex
            sem_wait(&full);
            pthread_mutex_lock(&lock);

            // Consume item from queue
            item = dequeue_item();
            consumer_arr[c_idx++] = item;
            printf( "%5d was consumed by consumer->\t%5d\n" , item, tid);

            // Unlock mutex and semaphore
            pthread_mutex_unlock(&lock);
            sem_post(&empty);

            // Sleep
            sleep(c_time);
        }
    } else {
        // Over consume if needed at the beginning of the program
        over_consume = 0;
        for (int i = 0; i < items_consumed + over_consume_amount; i++) {
            // Lock semaphore and mutex
            sem_wait(&full);
            pthread_mutex_lock(&lock);

            // Consume item from queue
            item = dequeue_item();
            consumer_arr[c_idx++] = item;
            printf( "%5d was consumed by consumer->\t%5d\n" , item, tid);

            // Unlock mutex and semaphore
            pthread_mutex_unlock(&lock);
            sem_post(&empty);

            // Sleep
            sleep(c_time);
        }
    }

    pthread_exit(0);
}

/*
 * $ ./pandc <N> <P> <C> <X> <Ptime> <Ctime>
 * N = number of buffers to maintain
 * P = number of producer threads
 * C = number of consumer threads
 * X = number of items each producer thread will produce
 * Ptime = how long each producer thread will sleep after producing an item in seconds
 * Ctime = how long each consumer thread will sleep after consuming an item in seconds
 */
int main(int argc, char** argv) {
    // argv[0] is the program itself ("./pandc")
    if (argc != 7) {
        printf("Enter 6 arguments: \"$ ./pandc <N> <P> <C> <X> <Ptime> <Ctime>\"\n");
        exit(EXIT_FAILURE);
    }

    // Print current time
    time_t start_time = time(0);
    printf( "Current time: %s\n" , ctime(&start_time));

    // Read command-line args
    num_buffers = strtol(argv[1], NULL, 10);
    num_producers = strtol(argv[2], NULL, 10);
    num_consumers = strtol(argv[3], NULL, 10);
    items_produced = strtol(argv[4], NULL, 10);
    items_consumed = (num_producers * items_produced) / num_consumers;
    over_consume = (num_producers * items_produced) % num_consumers > 0 ? 1 : 0;
    over_consume_amount = (num_producers * items_produced) - (num_consumers * items_consumed);
    p_time = strtol(argv[5], NULL, 10);
    c_time = strtol(argv[6], NULL, 10);

    // Print producer-consumer problem information
    printf("\t Number of Buffers : %5d\n", num_buffers);
    printf("\t Number of Producers : %5d\n", num_producers);
    printf("\t Number of Consumers : %5d\n", num_consumers);
    printf("\tNumber of items Produced by each producer : %5d\n", items_produced);
    printf("\tNumber of items Consumed by each consumer : %5d\n", items_consumed);
    printf("\t Over consume on? : %5s\n", (over_consume) ? "yes" : "no");
    printf("\t Over consume amount : %5d\n", over_consume_amount);
    printf("\t Time each Producer Sleeps (seconds) : %5d\n", p_time);
    printf("\t Time each Consumer Sleeps (seconds) : %5d\n", c_time);
    printf("\n");

    // Initialize mutex, semaphore, buffer, arrays
    pthread_mutex_init(&lock, NULL); // mutex lock = 1;
    sem_open( &full, 0, 0); // semaphore full = 0;
    sem_open( &empty, 0, num_buffers); // semaphore empty = N;
    buffer = malloc(sizeof(int*) * num_buffers); // buffer[N];
    producer_arr = malloc(sizeof(int*) * num_producers * items_produced);
    consumer_arr = malloc(sizeof(int*) * num_producers * items_produced);
    // consumer_arr = malloc(sizeof(int*) * num_consumers * items_consumed);
    in_index = 0;
    out_index = 0;

    // New threads
    pthread_t producer_ids[num_producers];
    pthread_t consumer_ids[num_consumers];

    // Create producer and consumer threads
    for (int i = 0; i < num_producers; i++) {
        int id = i + 1;
        pthread_create(&producer_ids[i], NULL, &producer, (void*) &id);
    }
    for (int i = 0; i < num_consumers; i++) {
        int id = i + 1;
        pthread_create(&consumer_ids[i], NULL, &consumer, (void*) &id);
    }

    // Join producer and consumer threads
    for (int i = 0; i < num_producers; i++) {
        pthread_join(producer_ids[i], NULL);
        printf( "Producer thread joined:%5d\n" , i);
    }
    for (int i = 0; i < num_consumers; i++) {
        pthread_join(consumer_ids[i], NULL);
        printf( "Consumer thread joined:%5d\n" , i);
    }

    time_t end_time = time(0);
    printf( "Current time: %s\n" , ctime(&end_time));

    // Compare and match producer and consumer arrays
    int match = 1; // Start out as true
    fprintf(stderr, "Producer Array\t| Consumer Array\n");
    for (int i = 0; i < num_producers * items_produced; i++) {
        fprintf(stderr, "%d\t\t\t\t| %d\n", producer_arr[i], consumer_arr[i]);
        if (producer_arr[i] != consumer_arr[i]) {
            match = 0; // False when mismatch detected
        }
    }

    fprintf(stderr, "\nConsume and Produce Arrays %s!\n", (match) ? "Match" : "DO NOT Match");
    fprintf(stderr, "\nTotal Runtime: %d secs\n", (int) (end_time - start_time));

    // Cleanup
    pthread_mutex_destroy(&lock);
    sem_unlink(&full);
    sem_unlink(&empty);
    free(buffer);

    return 0;
}
akshayk07
  • 2,092
  • 1
  • 20
  • 32
  • Please show your declarations. (And why so many global variables?) – rici Aug 13 '19 at 04:11
  • 2
    `strtol` returns `long`.. what types are you storing the result in? please post a complete code example. – paddy Aug 13 '19 at 04:13
  • please read the [manpage for sem_open](http://man7.org/linux/man-pages/man3/sem_open.3.html), as it appears you are confused about the parameters it takes and its return value. – paddy Aug 13 '19 at 04:15
  • posted whole code – mememlissa Aug 13 '19 at 04:17
  • 2
    For what it's worth, the `l` in `strtol` stands for `long` (as in "[convert] string to long"), which means that the value it returns is a `long`. If you try to store a `long` into an `int` variable, overflow is possible. A `long` can be a value too big to fit into an `int`. That's what the compiler is warning you about. – rici Aug 13 '19 at 04:17
  • should i change my ints to longs to resolve the problem? – mememlissa Aug 13 '19 at 04:19
  • @mememlissa That would be a first step, yes. Never try to store larger items into smaller ones unless your code specifically handles the overflow case. – Carey Gregory Aug 13 '19 at 04:45
  • 1
    you don't post the whole code but create a [mcve]. See also http://sscce.org/ – phuclv Aug 13 '19 at 06:11

0 Answers0