lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <CAFf+5zgoWzHA87nQ+N1L1qaghAKNQsBLuGxV3eeVi0eg_fSvgw@mail.gmail.com>
Date: Mon, 16 Jun 2025 08:44:09 +0530
From: Amit <amitchoudhary0523@...il.com>
To: linux-kernel@...r.kernel.org
Subject: pthread producer consumer program (Two files: pthread_producer_consumer_program.c
 and ReadMe.txt).

pthread producer consumer program (Two files:
pthread_producer_consumer_program.c and ReadMe.txt).

------------------------------------------------------
pthread_producer_consumer_program.c
------------------------------------------------------

/*
 * License:
 *
 * This file has been released under "unlicense" license
 * (https://unlicense.org).
 *
 * This is free and unencumbered software released into the public domain.
 *
 * Anyone is free to copy, modify, publish, use, compile, sell, or distribute
 * this software, either in source code form or as a compiled binary, for any
 * purpose, commercial or non-commercial, and by any means.
 *
 * For more information about this license, please visit - https://unlicense.org
 */

/*
 * Author: Amit Choudhary
 * Email: amitchoudhary0523 AT gmail DOT com
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sched.h>
#include <errno.h>
#include <pthread.h>

#define NUM_ITEMS 10

#define PTHREAD_MUTEX_LOCK pthread_mutex_lock
#define PTHREAD_MUTEX_UNLOCK pthread_mutex_unlock

#define PTHREAD_COND_WAIT pthread_cond_wait
#define PTHREAD_COND_BROADCAST pthread_cond_broadcast

struct common_vars {
    pthread_mutex_t *mutex;
    pthread_cond_t *cond_var;
    int items_queue[NUM_ITEMS];
    int current_num_items_in_queue;
};

static void check_retval_and_exit_on_error(int retval, const char *msg);
static void *producer(void *arg);
static void *consumer(void *arg);

static void check_retval_and_exit_on_error(int retval, const char *msg)
{

    if (retval != 0) {
        printf("\nError: %s. The error number is: %d. Now, there is no point in"
               " running this program. This program is now exiting..\n\n",
               ((msg != NULL) ? msg : ""), retval);
        exit(1);
    }

    return;

} // end of function check_retval_and_exit_on_error()

static void *producer(void *arg)
{

    struct common_vars *cv_ptr = arg;
    int current_index_in_queue = 0;
    int num = 0;
    int to_yield = 0;
    int retval = -1;

    if (arg == NULL) {
        printf("\nError: 'arg' argument is NULL in producer thread. Now, there"
               " is no point in running this program. This program is now"
               " exiting..\n\n");
        exit(1);
    }

    srand((unsigned int)(time(NULL)));

    while (1) {

        num = rand();

        retval = PTHREAD_MUTEX_LOCK(cv_ptr->mutex);

        check_retval_and_exit_on_error(retval, "pthread_mutex_lock() failed in"
                                               " producer thread");

        while (cv_ptr->current_num_items_in_queue == NUM_ITEMS) {

            printf("\nProducer is going to sleep because the queue is full.."
                   "\n\n");
            retval = PTHREAD_COND_WAIT(cv_ptr->cond_var, cv_ptr->mutex);
            check_retval_and_exit_on_error(retval, "pthread_cond_wait() failed"
                                                   " in producer thread");
        }

        cv_ptr->items_queue[current_index_in_queue] = num;
        current_index_in_queue = (current_index_in_queue + 1) % NUM_ITEMS;
        cv_ptr->current_num_items_in_queue++;

        printf("Producer added number %d to the queue. Current number of items"
               " in the queue = %d\n", num, cv_ptr->current_num_items_in_queue);

        retval = PTHREAD_MUTEX_UNLOCK(cv_ptr->mutex);

        check_retval_and_exit_on_error(retval, "pthread_mutex_unlock() failed"
                                               " in producer thread");

        retval = PTHREAD_COND_BROADCAST(cv_ptr->cond_var);

        check_retval_and_exit_on_error(retval, "pthread_cond_broadcast() failed"
                                               " in producer thread");

        // To introduce some randomness, we will do sched_yield() here in some
        // cases.
        to_yield = rand();
        to_yield = to_yield % 100;
        if (to_yield > 25) {
            retval = sched_yield();
        }
        if (retval != 0) {
            printf("\nError: sched_yield() failed in producer thread. The error"
                   " number is: %d\n\n", errno);
        }

    } // end of while (1) loop

    return NULL;

} // end of function producer()

static void *consumer(void *arg)
{

    struct common_vars *cv_ptr = arg;
    int current_index_in_queue = 0;
    int num = 0;
    int to_yield = 0;
    int retval = -1;

    if (arg == NULL) {
        printf("\nError: 'arg' argument is NULL in consumer thread. Now, there"
               " is no point in running this program. This program is now"
               " exiting..\n\n");
        exit(1);
    }

    while (1) {

        retval = PTHREAD_MUTEX_LOCK(cv_ptr->mutex);

        check_retval_and_exit_on_error(retval, "pthread_mutex_lock() failed in"
                                               " consumer thread");

        while (cv_ptr->current_num_items_in_queue == 0) {

            printf("\nConsumer is going to sleep because the queue is empty.."
                   "\n\n");
            retval = PTHREAD_COND_WAIT(cv_ptr->cond_var, cv_ptr->mutex);
            check_retval_and_exit_on_error(retval, "pthread_cond_wait() failed"
                                                   " in consumer thread");
        }

        num = cv_ptr->items_queue[current_index_in_queue];
        current_index_in_queue = (current_index_in_queue + 1) % NUM_ITEMS;
        cv_ptr->current_num_items_in_queue--;

        printf("Consumer removed number %d from the queue. Number of items"
               " remaining in the queue = %d\n", num,
               cv_ptr->current_num_items_in_queue);

        retval = PTHREAD_MUTEX_UNLOCK(cv_ptr->mutex);

        check_retval_and_exit_on_error(retval, "pthread_mutex_unlock() failed"
                                               " in consumer thread");

        retval = PTHREAD_COND_BROADCAST(cv_ptr->cond_var);

        check_retval_and_exit_on_error(retval, "pthread_cond_broadcast() failed"
                                               " in consumer thread");

        // To introduce some randomness, we will do sched_yield() here in some
        // cases.
        to_yield = rand();
        to_yield = to_yield % 100;
        if (to_yield > 25) {
            retval = sched_yield();
        }
        if (retval != 0) {
            printf("\nError: sched_yield() failed in consumer thread. The error"
                   " number is: %d\n\n", errno);
        }

    } // end of while (1) loop

    return NULL;

} // end of function consumer()

int main(void)
{

    struct common_vars cv;
    pthread_t ptid = 0; // producer thread id
    pthread_t ctid = 0; // consumer thread id
    int retval = -1;

    memset(&cv, 0, sizeof(cv));

    cv.mutex = calloc(1, sizeof(*(cv.mutex)));

    if (cv.mutex == NULL) {
        printf("\nError: No memory available. Exiting..\n\n");
        exit(1);
    }

    cv.cond_var = calloc(1, sizeof(*(cv.cond_var)));

    if (cv.cond_var == NULL) {
        free(cv.mutex);
        printf("\nError: No memory available. Exiting..\n\n");
        exit(1);
    }

    retval = pthread_create(&ptid, NULL, producer, &cv);

    if (retval != 0) {
        free(cv.mutex);
        free(cv.cond_var);
        printf("\nError: Could not create producer thread. Exiting..\n\n");
        exit(1);
    }

    retval = pthread_create(&ctid, NULL, consumer, &cv);

    if (retval != 0) {
        free(cv.mutex);
        free(cv.cond_var);
        printf("\nError: Could not create consumer thread. Exiting..\n\n");
        exit(1);
    }

    retval = pthread_join(ptid, NULL);

    if (retval != 0) {
        printf("\nError: Joining on producer thread returned error. Error"
               " number is: %d\n\n", retval);
    }

    retval = pthread_join(ctid, NULL);

    if (retval != 0) {
        printf("\nError: Joining on consumer thread returned error. Error"
               " number is: %d\n\n", retval);
    }

    free(cv.mutex);
    free(cv.cond_var);

    return 0;

} // end of function main()

----------------
ReadMe.txt
----------------

File "pthread_producer_consumer_program.c" uses pthread library to implement a
producer thread and a consumer thread. The producer thread puts items in the
items queue and the consumer thread consumes items from the items queue.

Since the items queue is used by both the producer thread and the consumer
thread, a mutex (from pthread library) is used for synchronization between these
two threads.

A condition variable (from pthread library) is also used for the following two
purposes:

    * If the items queue is full then the producer thread waits on the condition
      variable for the signal from the consumer thread signifying that the items
      queue is no more full because the consumer thread had consumed at least
      one item from the items queue and now the producer thread can again start
      putting item(s) in the items queue.

    * If the items queue is empty then the consumer thread waits on the
      condition variable for the signal from the producer thread signifying that
      the items queue is no more empty because the producer thread had put at
      least one item in the items queue and now the consumer thread can again
      start consuming item(s) from the items queue.

This program should link with the pthread library, so the option -lpthread
should be passed to gcc for compiling this program.

---- End of ReadMe ----

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ