CSCI 4100 –Assignment 3InstructionsFor this assignment you will be implementing a blocking bounded queue using locks and condition variables. I have provided structures and prototypes for your queue...

1 answer below »
CSCI 4100 –Assignment 3InstructionsFor this assignment you will be implementing a blocking bounded queue using locks and condition variables. I have provided structures and prototypes for your queue in the file msg_queue.h. You will need to implement the functions I have specified in a file called msg_queue.c.You will also be testing out this queue with multiple sending and receiving threads. Ihave provided structures and prototypes for testing in the file msg_queue_tester.cYou must implement a mainfunction and other specified functions in the same file


files/msg_queue.c /* YOUR NAME HERE * CSCI 4100 Assignment 3 * Source file for message queue implementation */ #include "msg_queue.h" /* Initialize the message queue */ void mq_init(struct msg_queue * mq) { /* YOUR CODE HERE */ } /* Send a message to a message queue */ void mq_send(struct msg_queue * mq, struct mq_msg * message) { /* YOUR CODE HERE */ } /* Receive a message from a message queue */ void mq_receive(struct msg_queue *mq, struct mq_msg * message) { /* YOUR CODE HERE */ } files/msg_queue.h /* YOUR NAME HERE * CSCI 4100 Assignment 3 * Header file for message queue structures and functions */ #ifndef MSG_QUEUE_H #define MSG_QUEUE_H #include #define QUEUE_SIZE 10 /* Structure for a message */ struct mq_msg { int t_id; // sender thread id int m_id; // message id }; /* Structure for a message queue */ struct msg_queue { struct mq_msg messages[QUEUE_SIZE]; unsigned int in; // number of messages sent unsigned int out; // number of messages received pthread_mutex_t lock; pthread_cond_t msg_added; pthread_cond_t msg_removed; }; /* Initialize the message queue */ void mq_init(struct msg_queue * mq); /* Send a message to a message queue */ void mq_send(struct msg_queue * mq, struct mq_msg * message); /* Receive a message from a message queue */ void mq_receive(struct msg_queue * mq, struct mq_msg * message); #endif files/msg_queue_tester.c /* Nicholas Coleman * CSCI 4100 Assignment 3 * This program tests a message queue by creating multiple sending and * receiving threads */ #include #include #include "msg_queue.h" /* Structure to hold thread arguments */ struct thread_args { int t_id; int num_msgs; struct msg_queue * mq; }; /* Function prototypes */ void thread_args_init(struct thread_args *args, int t_id, int num_msgs, struct msg_queue * mq); void * send_msgs(void * args); void * receive_msgs(void * args); /* Main function */ int main(int argc, char *argv[]) { /* YOUR CODE HERE */ } /* Initialize thread_args structure */ void thread_args_init(struct thread_args *args, int t_id, int num_msgs, struct msg_queue * mq) { /* YOUR CODE HERE */ } /* Function for sending thread to execute */ void * send_msgs(void * args) { /* YOUR CODE HERE */ } /* Function for receiving thread to execute */ void * receive_msgs(void * args) { /* YOUR CODE HERE */ } CSCI 4100 – Assignment 3 CSCI 4100 – Assignment 3 Instructions For this assignment you will be implementing a blocking bounded queue using locks and condition variables. I have provided structures and prototypes for your queue in the file msg_queue.h. You will need to implement the functions I have specified in a file called msg_queue.c. You will also be testing out this queue with multiple sending and receiving threads. I have provided structures and prototypes for testing in the file msg_queue_tester.c You must implement a main function and other specified functions in the same file. Structures and Pointers in C To declare a variable of a structure type, the struct keyword and the name of the structure must appear before the variable name: struct mq_msg message; The components of a structure are called fields, and can be accessed using the . operator: message.t_id = 3; message.m_id = 2; printf("thread id: %d\n", message.t_id); printf("message id: %d\n", message.m_id); Structures can be copied using assignment: struct mq_msg message_copy; message_copy = message; Pointers can be defined to point to structures: struct mq_msq * message_ptr; message_ptr = &message; The -> operator can be used to dereference a pointer to a structure and access a field: message_ptr->t_id = 3; message_ptr->m_id = 2; printf("thread id: %d\n", message_ptr->t_id); printf("message id: %d\n", message_ptr->m_id); Pointers can also be defined to point to fields: int * t_id_ptr = &message.t_id; int * m_id_ptr = &message_ptr->m_id; POSIX Threads, Locks, and Condition Variables The standard thread library for UNIX-based systems is POSIX Threads (aka Pthreads.) To use this library you will need the following include statement: #include To create and use a thread you must do the following: 1. Declare a variable of type pthread_t. 2. Write a function whose argument and return value are both of type void * (this means the function can take and return pointers to anything.) 3. Create a structure that can hold all of the information that the thread will need to execute, and create an instance of this structure containing the information for this thread. 4. Start the thread using the following function call: pthread_create(&my_thread, NULL, my_function, &args); where my_thread is the thread variable from step 1, my_function is the name of the function from step 2, and args is the structure from step 3. 5. Wait for the thread to complete using the following function call: pthread_join(my_thread, NULL); To create and use a lock you must do the following: 1. Create a variable of type pthread_mutex_t. pthread_mutex_t my_lock; 2. Initialize this variable using the following function call: pthread_mutex_init(&my_lock, NULL); 3. When the currently running thread needs to acquire the lock, use the following function call: pthread_mutex_lock(&my_lock); 4. When the currently running thread needs to release the lock, use the following function call: pthread_mutex_unlock(&my_lock); To create and use a condition variable you must do the following: 1. Create a variable of type pthread_cond_t. pthread_cond_t my_condition_variable; 2. Initialize this variable using the following function call: pthread_cont_init(&my_condition_variable, NULL); 3. To make the current thread wait on the condition variable use the following function call: pthread_cond_wait(&my_condition_variable, &my_lock) Note that the lock must be acquired before calling this function in order for it to work properly. 4. To make the current thread notify a single thread waiting on the condition, use the following function call: pthread_cond_signal(&my_condition_variable) The Message Queue There are two structures defined for the message queue: • mq_msg is a structure that represents a simple message. It contains the following fields: – t_id represents the id number of the thread that is sending the message. – m_id represents the id number of the message itself. • msg_queue is a structure that represents the queue itself. It contains the following fields: – messages is an array of mq_msg structures of length QUEUE_SIZE used to store the messages in the queue. – in represents the total number of messages added to the queue. – out represents the total number of messages removed from the queue. – lock is a lock used to guard the state of the queue. – msg_added is a condition variable used to make a thread wait until a message has been added to the queue. – msg_removed is a condition variable used to make a thread wait until a message has been removed from the queue. There are three functions having to do the message queue: • mq_init is used to initialize a queue. The in and out variables are initialized to zero. See the section on POSIX Threads, Locks, and Condition Variables for how to initialize the lock and condition variables. • mq_send is used to send a message to the queue. It should do the following: a. Acquire the queue lock. b. While the queue is full, wait on the queue’s msg_removed condition variable. c. Copy the message from the mq_msg structure provided to the correct location in the queue. d. Increment the queue’s in member variable. e. Signal the queue’s msg_added condition variable. f. Release the queue lock. • mq_receive is used to receive a message from the queue. It should do the following: a. Acquire the queue lock. b. While the queue is empty, wait on the queue’s msg_added condition variable c. Copy the message from the correct location in the queue to the mq_msg structure provided. d. Increment the queue’s out member variable. e. Signal the queue’s msg_removed condition variable. f. Release the queue lock. Testing the Message Queue You must also write code to test your queue with multiple sending and receiving threads. This functionality should be implemented in a file called msg_queue_tester.c. I have provided a structure and three prototypes to help you do this. The thread_args structure is used to store all of the arguments that will be required for a sending or receiving thread to get started. It contains the following fields: • t_id is the id number for the thread. • num_msgs is the number of messages for the thread to send or receive. • queue is a pointer to the queue that the thread will use to send or receive messages. A structure of type thread_args can be initialized using the thread_args_init function. This function must set all of the fields of the thread_args structure using the given parameters. The send_msgs function is executed by a sending thread. It must do the following: 1. Cast the void pointer args to a pointer to a thread_args structure using the following statement: struct thread_args * real_args = (struct thread_args *) args; 2. Declare a mq_msg structure. 3. Send the number of messages specified in the thread_args structure by repeatedly doing the following: a. Initialize the mq_msg structure with the appropriate thread id and message id. b. Send the message to the queue in the thread_args structure using mq_send. 4. Return NULL. The receive_msgs function is executed by a receiving thread. It must do the following: 1. Cast the void pointer args to a pointer to a thread_args structure. 2. Declare a mq_msg structure. 3. Receive the number of messages specified in the thread_args structure by repeatedly doing the following: a. Receive the message from the queue in the thread_args structure using mq_receive. b. Display the message along with the receiver thread id from the thread_args structure. 4. Return NULL Your main function should do the following: 1. Declare a pthread_t variable for each of the sending and receiving threads. 2. Declare a msg_queue structure and initialize it using mq_init. 3. Declare a thread_args structure
Answered 3 days AfterOct 01, 2021

Answer To: CSCI 4100 –Assignment 3InstructionsFor this assignment you will be implementing a blocking bounded...

Darshan answered on Oct 04 2021
120 Votes
BrianAssign3/msg_queue.c
/* Brain
* CSCI 4100 Assignment 3
* Source file for message queue implementation
*/
#include
#include "msg_queue.h"
/* Initialize the message queue */
void mq_init(struct msg
_queue * mq)
{
/* YOUR CODE HERE */
    mq->in = 0;
    mq->out = 0;
    pthread_mutex_init(&mq->lock,NULL);
    pthread_cond_init(&mq->msg_added, NULL);
    pthread_cond_init(&mq->msg_removed, NULL);
}
/* Send a message to a message queue */
void mq_send(struct msg_queue * mq, struct mq_msg * message)
{
/* YOUR CODE HERE */
//a. Acquire the queue lock.
    pthread_mutex_lock(&mq->lock);
    
//b. While the queue is full, wait on the queue’s msg_removed condition variable.
    while((mq->in)==QUEUE_SIZE)
    {
        pthread_cond_wait(&mq->msg_removed, &mq->lock);
    }
        
//c. Copy the message from the mq_msg structure provided to the correct location in the queue.
    mq->messages[mq->in].m_id = message->m_id;
//d. Increment the queue’s in member variable.
    mq->in++;
//e. Signal the queue’s msg_added condition variable.
    pthread_cond_signal(&mq->msg_added);
        
//f. Release the queue lock.
    pthread_mutex_unlock(&mq->lock);
}
/* Receive a message from a message queue */
void mq_receive(struct msg_queue *mq, struct mq_msg * message)
{
/* YOUR CODE HERE */
//a. Acquire the queue lock.
    pthread_mutex_lock(&mq->lock);
//b. While the queue is empty, wait on the queue’s msg_added condition variable
    while((mq->in)==0)
    {
        pthread_cond_wait(&mq->msg_added, &mq->lock);
    }
//c. Copy the message from the correct location in the queue to the mq_msg structure provided.
    message->m_id=mq->messages[mq->out].m_id;
//d. Increment the queue’s out member variable.
    mq->out++;
    mq->in--;
//e. Signal the queue’s msg_removed condition variable.
        pthread_cond_signal(&mq->msg_removed);
        
//f. Release the queue lock.
    pthread_mutex_unlock(&mq->lock);
}
BrianAssign3/msg_queue.h
/* Brain
* CSCI 4100 Assignment 3
* Header file for message queue structures and functions
*/
#ifndef MSG_QUEUE_H
#define MSG_QUEUE_H
#include
#define QUEUE_SIZE 10
/* Structure for a message */
struct mq_msg {
int t_id; // sender thread id
...
SOLUTION.PDF

Answer To This Question Is Available To Download

Related Questions & Answers

More Questions »

Submit New Assignment

Copy and Paste Your Assignment Here