Practice Problem Set

1. Given a large array of integers, write a program to calculate the sum of all elements in the array using multiple
threads. Each thread should compute the sum of a specific segment of the array, and the main thread should
gather the partial sums from each thread to calculate the final total.
2. Write a program that creates three separate processes (P1, P2, and P3) from a parent process (P0) to handle
each dimension of a 3D array, with each dimension having a size of at least 224×224.
Process Responsibilities:

a. Each process (P1, P2, and P3) will work on one dimension of the array.
b. Within each process, concurrent dot products are computed on 3×3 submatrices of its
assigned dimension using multiple threads.

Results Collection:

c. Each process (P1, P2, and P3) will store its computed dot products in result matrices R1, R2,
and R3 respectively.
Data Communication:

d. Once the dot product calculations are completed, each process sends its result matrix (R1, R2,
or R3) back to the parent process (P0).

Final Aggregation:

e. The parent process (P0) receives the matrices R1, R2, and R3 from the child processes.
f. It then performs a position-wise sum of these matrices (R1+R2+R3) to produce the final result
matrix.

Output: You can see the below diagram to understand more on the problem.

g. The parent process (P0) prints the final result matrix after all position-wise sums are
completed.

You can follow the below diagram to understand the problem in a more comprehensive manner.

3. Write a program to implement simple inter-process communicaƟon (IPC) system to simulate data
exchange between processes in C. Implement a program that achieves the following:
a. Creates a unidirecƟonal pipe between a parent process and its child process.
b. The parent process should:
 Open and read data from a file named input.txt.
 Send the read data through the pipe to the child process.
c. The child process should:
 Receive data from the pipe.
 Write the received data to a new file named output.txt.
Hints:
Use appropriate system calls for file handling (open(), read(), write()).
Use system calls for creaƟng and managing the pipe (pipe(), fork()).
4. Design a C program that sets up bidirecƟonal communicaƟon between a parent process and two
child processes to perform a data transformaƟon task with mulƟple steps. This program should:
a. Setup BidirecƟonal Pipes:
o Create two bidirecƟonal pipes: one between the parent and child process C1, and
another between the parent and child process C2.

b. File Reading and Data TransformaƟon:
o The parent process reads data from an input.txt file and sends it to child process C1.
o Child process C1 receives the data, performs a transformaƟon (e.g., converts text to
uppercase), and sends the transformed data back to the parent.
o The parent then forwards this transformed data to child process C2 via the second
pipe.
o Child process C2 further processes the data (e.g., reverses the text) and sends it back
to the parent.
c. Final Data Output:
o The parent process writes the fully transformed data from C2 to an output file named
output.txt.

Hints:
 Use appropriate system calls for file handling (open(), read(), write()).
 Use system calls to create and manage pipes (pipe(), fork()), and to manage the bidirecƟonal
communicaƟon.
 Ensure that each process closes unused ends of the pipes to prevent deadlocks and ensure
proper resource management.
5. Write a C program to create two threads, `t1` and `t2`, which call the funcƟons inc () and dec (),
respecƟvely. Both funcƟons operate on a shared counter iniƟally set to 0. The inc () funcƟon
increments the counter, while dec () decrements it. Implement code that demonstrates a race
condiƟon, where the final value of the counter may become 0 or 2 due to unsynchronized access.

6. Write a program in C that demonstrates thread synchronizaƟon with a shared counter variable.
a. IniƟalizaƟon: Define a global counter variable.
b. Thread CreaƟon: Spawn 10 threads in the program, with each thread incremenƟng the
counter 1000 Ɵmes in a loop.
c. Output: AŌer all threads have finished, print the final value of the counter. The expected result
is 10000.

InstrucƟons:
 Without Locks: Run the program iniƟally without any locking mechanism. Observe and explain
how race condiƟons cause the final counter value to be incorrect (typically less than 10000).
 With Locks: Modify the program to use a locking mechanism (e.g., pthread_mutex) to
synchronize access to the counter. Run the program again and verify that the counter is now
updated correctly to 10000.
7. Write a C program to detect a deadlock in a system using a Resource AllocaƟon Graph (RAG).
a. Graph Setup:
o Represent the system's resources and processes as nodes in a graph.
o The program should take input for:
 The number of processes and resources.
 The allocaƟon and request of resources by each process.
o Use an adjacency matrix or adjacency list to store the RAG, where:
 An edge from a process Pi to a resource Rj represents a request.
 An edge from a resource Rj to a process Pi represents an allocaƟon.

b. Deadlock DetecƟon:
o Implement a cycle detecƟon algorithm (e.g., Depth-First Search) to idenƟfy if there is
a cycle in the graph, indicaƟng a deadlock.
o If a cycle exists, output the processes involved in the deadlock; otherwise, report that
no deadlock exists.
c. Input and Output:
o Input: Prompt the user to enter the number of processes, resources, and connecƟons
(allocaƟons and requests).
o Output: Display the detected cycle (if any), showing the processes involved in the
deadlock.

For simplicity, you can consider that each resource type has only one instance.
#include <stdio.h>
#include <unistd.h> 
#include <pthread.h>

//inputs to take
int num1, num2, sum;

//this is the thread function
void* summ(void* arg) 
{
    printf("Entering thread T1\n");
    
    //This is just the example sir took in class
    //running thread for a while
    for(int i= 0; i< 3; i++) 
    {
        printf("Thread T1 is computing...\n");
        sleep(1); //sleep
    }
    
    //compute the sum
    sum= num1+ num2;
    printf("Thread T1 has computed the sum: %d + %d = %d\n", num1, num2, sum);
    


    pthread_exit(NULL); //thread is over
}

int main() 
{
    pthread_t t1;
    int thread;

    printf("Entering main thread\n");

    // Input from user
    printf("Enter num1: ");
    scanf("%d", &num1);

    printf("Enter num2: ");
    scanf("%d", &num2);

    // Create thread T1 to compute the sum
    thread = pthread_create(&t1, NULL, summ, NULL);
    //wait for thread to finish
    thread= pthread_join(t1, NULL); //if this wasn't there here, main and current thread would alternate between tasks.

    printf("Main thread is performing its own tasks\n");

    //main thread performing its own tasks. again, this is the example sir took
    for(int j= 0; j < 5; j++) {
        printf("Main thread: Task %d\n", j + 1);
        sleep(1); 
    }

   
    //thread over. main finishes now
    printf("Main thread: The sum of %d and %d is: %d\n", num1, num2, sum);
    printf("Main thread exiting.\n");
    return 0;
}
pls use this format as reference so that i dont get plag. dont overcomplicate it