I am having trouble trying to implement semaphores with pthreads. The scenario that I am trying to program are rats in a maze. Where rats are threads and the maze consists of rooms connected to each other. The rats have to traverse through each room with each room having a different capacity and wait time before a rat can move on. I was able to implement it with a while loop and let the threads sit and spin while waiting for a spot to free up but I need to achieve the objective with semaphores. Here's what I have:
sem_t psem, csem;
void EnterRoom(int iRat, int iRoom) {
time_t currentTime;
currentTime = time(NULL);
RoomVB[iRoom][iRat].tEntry = currentTime - startTime;
RoomVB[iRoom][iRat].iRat = iRat;
VisitorCount[iRoom]++;
sleep(roomArray[iRoom].delay);
}
void LeaveRoom(int iRat, int iRoom) {
time_t currentTime;
currentTime = time(NULL);
VisitorCount[iRoom]--;
RoomVB[iRoom][iRat].tDep = currentTime - startTime;
}
void *rat(void *ratID) {
if (sem_init(&csem, 0, 0) < 0) {
perror("sem_init");
exit(1);
}
int id;
id = (int)ratID;
int i;
for (i = 0; i < numOfRooms; i++) {
/*while (VisitorCount[i] >= roomArray[i].capacity) {
}*/
if (sem_init(&psem, 0, roomArray[i].capacity) < 0) {
perror("sem_init");
exit(1);
}
sem_wait(&psem);
EnterRoom(id, i);
sem_post(&csem);
sem_wait(&csem);
LeaveRoom(id, i);
sem_post(&psem);
}
return NULL;
}
As you can see I commented out the while loop. I had to incorporate additional information like the time it it takes for a rat to travel through rooms in a 2D array.
Error result:
Rat 0 completed maze in 5 seconds.
Rat 1 completed maze in 5 seconds.
Rat 2 completed maze in 5 seconds.
Room 0 [3 1]: 0 0 1; 1 0 1; 2 0 1;
Room 1 [2 2]: 0 1 3; 1 1 3; 2 1 3;
Room 2 [1 2]: 0 3 5; 1 3 5; 2 3 5;
Total traversal time: 15 seconds, compared to ideal time: 15 seconds.
Correct result (achieved with loop):
Rat 0 completed maze in 7 seconds.
Rat 1 completed maze in 5 seconds.
Rat 2 completed maze in 9 seconds.
Room 0 [3 1]: 0 0 1; 1 0 1; 2 0 1;
Room 1 [2 2]: 0 1 3; 1 1 3; 2 3 5;
Room 2 [1 2]: 0 5 7; 1 3 5; 2 7 9;
Total traversal time: 21 seconds, compared to ideal time: 15 seconds.
I assume I need two semaphores with the producer semaphore being initially set to n - which is the capacity of each room. Any ideas how I fix it so it works as it should?
You can't have each thread re-initialise the same two shared semaphores simultaneously. The semaphores all need to be initialised up-front, before your rats start running.
The easiest way to solve this will be to have one semaphore for each room, initialised to the capacity of that room (store the sempahore in the roomArray element for that room). Then, just have the rat wait on the semaphore when it enters the room, and post the semaphore when it exits the room.
Related
So, I tried to modify this code from Samfoundry of a FCFS Scheduler. I removed the things pertaining to the turnaround time as I don't really need it and modified it so it can process elements already inside of an array instead of a user input. I think the logic is correct, but the formatting is not, and I don't really know why even when it's almost identical with the source code.
int main()
{
int pid[5] = {1, 2, 3, 4, 5};
int bt[5] = {5, 3, 1, 2, 3};
int n = 5;
int i, wt[n];
wt[0]=0;
//for calculating waiting time of each process
for(i=1; i<n; i++)
{
wt[i]= bt[i-1]+ wt[i-1];
}
printf("Process ID Burst Time Waiting Time\n");
float twt=0.0;
for(i=0; i<n; i++)
{
printf("%d\t\t", pid[i]);
printf("%d\t\t", bt[i]);
printf("%d\t\t", wt[i]);
//for calculating total waiting time
twt += wt[i];
}
float awt;
//for calculating average waiting time
awt = twt/n;
printf("\nAvg. waiting time= %f\n",awt);
}
Expected output:
ProcessID BurstTime WaitingTime
1 5 0
2 3 5
3 1 8
4 2 9
5 1 11
Actual output:
ProcessID BurstTime WaitingTime
1 5 0 2 3 5 3 1 8 4 2 9 5
3 11
Everything works fine in code you just need to add some extra tab spaces and new line character inside the for loop change
printf("%d\t\t\t\t", pid[i]); //add two more tab spaces
printf("%d\t\t\t\t", bt[i]); //same as here add two tab spaces
printf("%d\t\t\n", wt[i]); // add a \n i.e new line
void makeMove(int player, int move) {
int i, stones, nextPit;
// Get the number of stones in the selected pit
stones = board[player * 6 + move];
board[player * 6 + move] = 0; // Clear the pit
// Distribute the stones
nextPit = player * 6 + move + 1; // Start at the next pit
for (i = 0; i < stones; i++) {
// Skip the opponent's mancala
if (nextPit == (player ^ 1) * 6 + 6) {
nextPit++;
}
// Place a stone in the pit
board[nextPit]++;
nextPit++; // Move to the next pit
// Wrap around to to the beginning of the board
if (nextPit == BOARD_SIZE) {
nextPit = 0;
}
}
so this function takes all the stones from the chosen pit and puts the stones one by one on to the next pits
example : 4 4 4 4 4 if you choose the first pit it goes like 0 5 5 5 5 but i want it to be 1 5 5 5 4
i want this function to take all the stones from the chosen pit and put one back to the chosen pit and then start to put next pits
i am a 2 month computer engineering student im new to this i didnt try much if you can explain this code to me it would mean the world
I'm working on a problem dealing with iteration. I'm supposed to pass in two ints into a function, which represent a number of N objects and M values that I must find all permutations of. I am also given a sample of what the output is supposed to look like
void perm_iter(int N, int nr_values)
and the output this is supposed to print is :
Called : perm_iter(3, 2);
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
I understand the concept of recursion by using a swap function to change the orders of strings to find all permutations of a string, but I'm unsure of how to use iteration to get the same, or similar result. Is this a case where I need to use the stack and push/pop iteratively to get my answer? I was thinking I could use something like a set of nested loops to take the place of recursion and get something like this output but I'm unsure how to set the loops up to go through every permutation and not just iterate, missing some of the possible permutations.
Any help would be appreciated, and thank you for your time.
You just need to count up each "digit" until the max is reached, then reset and increment the next.
Imagine nr_values is 10 (with n=2):
0 0
0 1
0 2
0 3
0 4
0 5
0 6
0 7
0 8
0 9
1 0
1 1
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
Looks familiar because it's just "regular" counting in this case.
Implement this just like you count up: In each step, increment the leftmost value. If max is reached, reset and increment the next value etc.
void perm_iter(int n, int nr_values) {
int[] counter = new int[n];
int i;
// Clear all values
for (i = 0; i < n; i++) {
counter[i] = 0;
}
do {
// Print the current set of values
for (i = 0; i < n; i++) {
printf("%n ", counter[i]);
}
printf("\n");
// Keep incrementing while the values overflow,
// starting at the rightmost counter
i = n - 1;
while (i >= 0) {
counter[i]++;
if (counter[i] < nr_values) {
break;
}
counter[i] = 0;
i--;
}
// We are done when the first value overflows
} while (i >= 0);
}
I am working on Shortest Remaining Time Next Scheduling, where I must check every 1 time unit to see if there is another job that has a shorter time remaining left, if equal keep the current process. For the input I use:
PID ArrivalTime Burst/ExecutionTime
1 0 6
2 3 2
3 5 1
4 9 7
5 10 5
6 12 3
7 14 4
8 16 5
9 17 7
10 19 2
and my output: (on the left is what I am getting, the right is what it should be):
PID WAIT TURNAROUND PID WAIT TURNAROUND
1 0 9 1 0 9
2 0 2 2 0 2
3 0 1 3 0 1
4 0 26 4 0 26
5 0 14 5 0 5
6 0 3 6 3 6
7 1 5 7 4 10
8 8 13 8 8 13
9 18 25 9 18 25
10 0 2 10 0 2
Average Wait: 2.7 Ave Turnaround 10.0 Average Wait: 3.3 Average Turnaround 9.9
I have not been able to narrow down where the problem is in the srtn function, All but 3 of my outputs are correct, which is even more confusing! Any help would be appreciated!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <termios.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/types.h>
#define LINELEN 512
#define MAX_PROCESS 100
#define TIME_QUANTUM 1
typedef struct process
{
int ID;
int arrival_time;
int time_to_completion;
double wait_time;
double turn_around;
double time_wait;
int active;
}process;
void fcfs(struct process[MAX_PROCESS], int);
void sjf (struct process[MAX_PROCESS], int);
void srtn(struct process[MAX_PROCESS], int);
void rr (struct process[MAX_PROCESS], int);
void rrc(struct process[MAX_PROCESS], int);
void print_info(struct process[MAX_PROCESS], int);
void sort_by_time(struct process array[MAX_PROCESS], int num_valid_pid);
int main(int ac,char *av[])
{
int counter=0;
int p1=0, p2=0, p3=0;
process array[MAX_PROCESS];
while ( scanf("%d %d %d", &p1, &p2, &p3) != EOF ){//Get all the info available and put it in array of structs
array[counter].ID = p1;
array[counter].arrival_time = p2;
array[counter].time_to_completion = p3;
array[counter].active = 0;
counter++;
}
//fcfs(array, counter);
//sjf (array, counter);
srtn(array, counter);
/*rr (array, counter);
rrc(array, counter);*/
return 0;
}
void srtn(struct process array[MAX_PROCESS], int num_pid){
printf("Shortest Remaining Time Next\n");//for the output so we know what algorithm
//create an array of pids that are valid to search.
int num_valid_processes = 0, current_time=0, i,j, next_process, counter = 0, fin_pid = 0, keep_going=0;//declarations
process to_sort[MAX_PROCESS];
//we want to do this next loop for as many processes as we have, or num_pid
while(keep_going!=1){
//adds all the available processes to the to sort array to be sorted
//available means that it has arrived, which means it is <= current_time
//after it gets all the processes, it breaks out of the for loop
for(i=counter; i<num_pid; i++){
if(array[i].arrival_time<=current_time){
to_sort[num_valid_processes]=array[i];
num_valid_processes++;
counter++;
}
else
break;
}
//sort the to_sort array by the time_to_completion
sort_by_time(to_sort,num_valid_processes);
//set the wait time and turnaround time for the next process
next_process = to_sort[0].ID-1;
if(array[next_process].active==0){//the id hasn't had the wait time calculated yet
array[next_process].wait_time = current_time-array[next_process].arrival_time;
array[next_process].active=1;
array[next_process].time_wait = current_time;
}
if(array[next_process].time_to_completion <= TIME_QUANTUM){
array[next_process].turn_around = array[next_process].wait_time + (current_time-array[next_process].time_wait)+array[next_process].time_to_completion;
fin_pid++;
//delete the process we just worked on so we don't get duplicates.
num_valid_processes--;
for(i=0;i<num_valid_processes;i++){
to_sort[i]=to_sort[i+1];
}
}
else{
array[next_process].time_to_completion = array[next_process].time_to_completion - TIME_QUANTUM;
//to_sort[0].time_to_completion = to_sort[next_process].time_to_completion - TIME_QUANTUM;
}
current_time = current_time+TIME_QUANTUM;
if(fin_pid==num_pid)
keep_going=1;
}
print_info(array, num_pid);
}
void print_info(struct process array[MAX_PROCESS], int num_pid){
int i;
double tot_wait=0, tot_turn = 0;
printf("\x1b[04mPID\tWAIT\tTURNAROUND\n\x1b[24m");
for(i=0; i<num_pid; i++){
printf("%d\t%.0f\t%.0f\n", array[i].ID, array[i].wait_time, array[i].turn_around);
tot_wait=tot_wait+array[i].wait_time;
tot_turn = tot_turn +array[i].turn_around;
}
printf("Average Wait: %.1f Average Turnaround %.1f\n", tot_wait/num_pid, tot_turn/num_pid);
}
void sort_by_time(struct process array[MAX_PROCESS], int num_valid_pid)
{
int i,j;
for (i = 0; i < num_valid_pid; i++)
{
int min = i;
for (j = i+1; j < num_valid_pid; j++){
if (array[j].time_to_completion < array[min].time_to_completion)
min = j;
if (array[j].time_to_completion == array[min].time_to_completion){
if(array[j].ID<array[min].ID)
min = j;
}
}
process temp = array[i];
array[i] = array[min];
array[min] = temp;
}
}
The problem occurs at time 12 -- pid 6 shows up needing 3 seconds and pid 5 is running with 3 seconds left. How do you resolve the tie between processes that need the same remaining time? In favor of pid 6 gives you the result on the left and in favor of pid 5 gives you the result on the right. Given your weak problem definition, either could be correct.
I'm writing a program that is to take a number between 1-10 and display all possible ways of arranging the numbers.
Ex
input: 3
output:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
Whenever I input 9 or 10, the program gives a segmentation fault and dumps the core. I believe the issue is my recursive algorithm is being called too many times. Could someone help point out how I could limit the amount of recursive calls necessary? Here is my current code:
void rearange(int numbers[11], int index, int num, int fact) {
int temp = numbers[index];
numbers[index] = numbers[index-1];
numbers[index-1] = temp;
int i;
for (i = 1; i <= num; ++i) // print the current sequence
{
printf("%d ", numbers[i]);
}
printf("\n");
fact--; // decrement how many sequences remain
index--; // decrement our index in the array
if (index == 1) // if we're at the beginning of the array
index = num; // reset index to end of the array
if (fact > 0) // If we have more sequences remaining
rearange(numbers, index, num, fact); // Do it all again! :D
}
int main() {
int num, i; // our number and a counter
printf("Enter a number less than 10: ");
scanf("%d", &num); // get the number from the user
int numbers[11]; // create an array of appropriate size
// fill array
for (i = 1; i <= num; i++) { // fill the array from 1 to num
numbers[i] = i;
}
int fact = 1; // calculate the factorial to determine
for (i = 1; i <= num; ++i) // how many possible sequences
{
fact = fact * i;
}
rearange(numbers, num, num, fact); // begin rearranging by recursion
return 0;
}
9! (362880) and 10! (3628800) are huge numbers that overflow the call stack when you do as many recursive calls. Because all the local variables and formal parameters have to be stored. You either you have to increase the stack size or convert the recursion into iteration.
On linux, you can do:
ulimit -s unlimited
to set the stack size to unlimited. The default is usually 8MB.
Calculating permutations can be done iteratively, but even if you do it recursively there is no need to have a gigantic stack (like answers suggesting to increase your system stack say). In fact you only need a tiny amount of your stack. Consider this:
0 1 <- this needs **2** stackframes
1 0 and an for-loop of size 2 in each stackframe
0 1 2 <- this needs **3** stackframes
0 2 1 and an for-loop of size 3 in each stackframe
1 0 2
1 2 0
2 1 0
2 0 1
Permuting 9 elements takes 9 stackframes and a for-loop through 9 elements in each stackframe.
EDIT: I have taken the liberty to add a recursion-counter to your rearrange-function, it now prints like this:
Enter a number less than 10: 4
depth 1 1 2 4 3
depth 2 1 4 2 3
depth 3 4 1 2 3
depth 4 4 1 3 2
depth 5 4 3 1 2
depth 6 3 4 1 2
depth 7 3 4 2 1
depth 8 3 2 4 1
depth 9 2 3 4 1
depth 10 2 3 1 4
depth 11 2 1 3 4
depth 12 1 2 3 4
depth 13 1 2 4 3
depth 14 1 4 2 3
depth 15 4 1 2 3
depth 16 4 1 3 2 which is obviously wrong even if you do it recursively.
depth 17 4 3 1 2
depth 18 3 4 1 2
depth 19 3 4 2 1
depth 20 3 2 4 1
depth 21 2 3 4 1
depth 22 2 3 1 4
depth 23 2 1 3 4
depth 24 1 2 3 4
....
The recursion-leafs should be the only ones which output so the depth should be constant and small (equal to the number you enter).
EDIT 2:
Ok, wrote the code. Try it out:
#include "stdio.h"
void betterRecursion(int depth, int elems, int* temp) {
if(depth==elems) {
int j=0;for(;j<elems;++j){
printf("%i ", temp[j]);
}
printf(" (at recursion depth %u)\n", depth);
} else {
int i=0;for(;i<elems;++i){
temp[depth] = i;
betterRecursion(depth+1, elems, temp);
}
}
}
int main() {
int temp[100];
betterRecursion(0, 11, temp); // arrange the 11 elements 0...10
return 0;
}
I'd make your rearange function iterative - do while added, and recursive call removed:
void rearange(int numbers[11], int index, int num, int fact) {
int temp;
do
{
temp = numbers[index];
numbers[index] = numbers[index-1];
numbers[index-1] = temp;
int i;
for (i = 1; i <= num; ++i) // print the current sequence
{
printf("%d ", numbers[i]);
}
printf("\n");
fact--; // decrement how many sequences remain
index--; // decrement our index in the array
if (index == 1) // if we're at the beginning of the array
index = num; // reset index to end of the array
} while (fact > 0);
}
This is not a task for a deep recursion.
Try to invent some more stack-friendly algorithm.
Following code has rather troubles with speed than with stack size...
It's a bit slow e.g. for n=1000 but it works.
#include <stdio.h>
void print_arrangement(int n, int* x)
{
int i;
for(i = 0; i < n; i++)
{
printf("%s%d", i ? " " : "", x[i]);
}
printf("\n");
}
void generate_arrangements(int n, int k, int* x)
{
int i;
int j;
int found;
if (n == k)
{
print_arrangement(n, x);
}
else
{
for(i = 1; i <= n; i++)
{
found = 0;
for(j = 0; j < k; j++)
{
if (x[j] == i)
{
found = 1;
}
}
if (!found)
{
x[k] = i;
generate_arrangements(n, k + 1, x);
}
}
}
}
int main(int argc, char **argv)
{
int x[50];
generate_arrangements(50, 0, x);
}
Your program is using too many recursions unnecessarily. It is using n! recursions when actually n would be enough.
To use only n recursions, consider this logic for the recursive function:
It receives an array nums[] of n unique numbers to arrange
The arrangements can have n different first number in them, as there are n different numbers in the array
(key step) Loop over the elements of nums[], and in each iteration create a new array but with the current element removed, and recurse into the same function passing this shorter array as parameter
As you recurse deeper, the parameter array will be smaller and smaller
When there is only one element left, that's the end of the recursion
Using this algorithm, your recursion will not be deeper than n and you will not get segmentation fault. The key is in the key step, where you build a new array of numbers that is always 1 item shorter than the input array.
As a side note, make sure to check the output of your program before you submit, for example run it through | sort | uniq | wc -l to make sure you are getting the correct number of combinations, and check that there are no duplicates with | sort | uniq -d (the output should be empty if no dups).
Spoiler alert: here's my implementation in C++ using a variation of the above algorithm:
https://gist.github.com/janosgyerik/5063197