C in printing function mutex does not work properly - c

I am trying to give an id to threads and then I want to print each threads id that I have given, but there is a situation about mutex I guess, I think I am handling the critical section but it seems I could not.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
struct info{
int id;
int flag;
};
void *print_info(void* arg){
struct info *arg_struct = (struct info*) arg;
pthread_mutex_lock(&m);
printf("%d ", arg_struct->id);
pthread_mutex_unlock(&m);
pthread_exit(0);
}
int main(int argc, char *argv[])
{
int number = 10;
pthread_t tid[number];
for (int i = 0; i < number; ++i) {
int info[2];
info[0] = i;
info[1] = 0;
pthread_create(&tid[i], NULL, print_info, &info);
}
for (int i = 0; i < number; ++i) {
pthread_join(tid[i], NULL);
}
return 0;
}
Here is the output:
1 2 3 4 5 6 7 8 9 9
Each time I execute it differ but more or less the concept is the same is does not print some values and it prints some more than once.
But the expected output is this:
0 1 2 3 4 5 6 7 8 9
[or something not in order but each value is exactly printed once I guess]
Thanks

Giving each thread its own control data
As written, your code cannot guarantee the sequence of the output numbers — the order in which the threads execute depends on the o/s and the hardware. You can easily make sure that each ID is printed just once, by making sure that each thread has its own struct info to work with. Your existing code (a) type-puns an array with a structure, which is a bad idea (alk's comment), and (b) reuses the same space on the main program's stack so that by the time the threads are at work, it is feasible for the main loop to have changed the values stored.
This is what #rafix07 said in a comment. You claimed to have tried the fix without success. I have to conclude that your amended code didn't do what was necessary.
You need to use code more like this (which also prints a newline at the end of each run):
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
struct info
{
int id;
int flag;
};
static void *print_info(void *arg)
{
struct info *arg_struct = (struct info *)arg;
pthread_mutex_lock(&m);
printf("%d ", arg_struct->id);
pthread_mutex_unlock(&m);
pthread_exit(0);
}
int main(void)
{
int number = 10;
pthread_t tid[number];
struct info info[number];
for (int i = 0; i < number; ++i)
{
info[i].id = i;
info[i].flag = 0;
pthread_create(&tid[i], NULL, print_info, &info[i]);
}
for (int i = 0; i < number; ++i)
{
pthread_join(tid[i], NULL);
}
putchar('\n');
return 0;
}
When I ran it 10 times in a row, I got the outputs:
0 7 2 8 3 1 4 9 5 6
1 8 0 9 2 3 6 5 4 7
0 4 5 2 3 6 7 1 8 9
0 1 2 3 4 5 6 7 8 9
2 7 0 3 5 6 4 8 1 9
2 0 7 6 3 5 4 8 9 1
0 9 1 3 5 6 7 2 8 4
0 7 1 8 4 3 9 2 5 6
0 7 1 8 3 5 4 2 9 6
0 3 4 5 6 1 2 8 7 9
As you can see, each of the numbers 0..9 appears once in each line of output, but the sequence in which the threads execute is anything but determinate.
I'm not convinced that the mutex is buying you anything. All I/O functions such as printf() must behave as if they use flockfile() on entry and funlockfile() on return.
Tested on a MacBook Pro running macOS Mojave 10.14.6 (don't ask!) with GCC 9.2.0.
Guaranteeing sequence
A simple modification ensures the sequence — the main thread locks the mutex before launching a thread, and the thread unlocks it before exiting. However, this means there is no meaningful concurrency — you might as well write:
for (int i = 0; i < 10; i++)
printf("%d ", i);
putchar('\n');
This would avoid all the overhead of starting, running, and cleaning up after the threads.
The revised code simply moves one line from the print_info() function into main():
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
struct info
{
int id;
int flag;
};
static void *print_info(void *arg)
{
struct info *arg_struct = (struct info *)arg;
printf("%d ", arg_struct->id);
pthread_mutex_unlock(&m);
pthread_exit(0);
}
int main(void)
{
int number = 10;
pthread_t tid[number];
struct info info[number];
for (int i = 0; i < number; ++i)
{
info[i].id = i;
info[i].flag = 0;
pthread_mutex_lock(&m);
pthread_create(&tid[i], NULL, print_info, &info[i]);
}
for (int i = 0; i < number; ++i)
{
pthread_join(tid[i], NULL);
}
putchar('\n');
return 0;
}
And the output:
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9

It fails because you keep passing a pointer to what is effectively the same vector to the child threads, and promptly overwriting the contents in the main thread while the child threads are running.
You could equally well get an output of all 9s given a loaded system. Or even the numbers in reverse (only because I don't remmember there being a guarantee anywhere that threads will be scheduled in the same order as you create them). Or a very very strange number because if the child threads don't start running till the main thread starts the join, whatever 'arg' points to will be in the middle of the pthread_join call stack.
All the mutex protects you from is the threads outputting to stdout at the same time.
In passing, casting an array of ints to a struct of 2 ints is undefined behaviour, which is a whole other can of worms.

Related

Why does this code create the correct pattern?

I've recently started to learn the C programming language and therefore started tackling problems on Hackerrank. One of the problems is as follows:
In this problem, you need to print the pattern of the following form containing the numbers from 1 to n.
4 4 4 4 4 4 4
4 3 3 3 3 3 4
4 3 2 2 2 3 4
4 3 2 1 2 3 4
4 3 2 2 2 3 4
4 3 3 3 3 3 4
4 4 4 4 4 4 4
I saw a programmer on YouTube. He wrote a very short program to solve it:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#define max(x,y) ((x)>(y)?x:y)
int main()
{
int n;
scanf("%d", &n);
int len = n*2 - 1;
for (int i = 0; i < len; i++){
for(int j = 0; j < len; j++){
printf("%d ",max( abs(n -i-1) + 1, abs(n-j-1) +1 ));
}
printf("\n");
}
return 0;
}
I already listed all the indexing of the 2n-1 x 2n-1 matrix and tried to observe the relationship. But I can't formulate the relation of max( abs(n -i-1) + 1, abs(n-j-1) +1 ).
I just don't get the idea of max( abs(n -i-1) + 1, abs(n-j-1) +1 ), why does this line of code get the correct the value of each element in the matrix?

Why 2 is not smaller than 10 on Codeblocks?

I just worked to my final exam with simple codes; when I try to sorting strings, I face annoying error. Why 2 is not smaller than 10 on my CodeBlocks IDE but is smaller than 10 on real and onlinegdb.com?
This is the annoying code:
#include <string.h>
#include <stdio.h>
#define STR_SIZ 20
int main()
{
char strArr[][STR_SIZ] = {"abc", "hdas", "sdfasf", "kakldf", "caksl", "casd", "keam", "cznjcx", "mnxzv", "jkalkds"};
char minStr[STR_SIZ];
strcpy(minStr, strArr[0]);
int N = sizeof(strArr)/sizeof(minStr);
// int N = 10;
for(int x = 0; x < N-1; x++)
{
printf("%d", x);
strcpy(minStr,strArr[x]);
int j;
for(j=1+x; j < 10; j++)
{
printf("%4d\n", j);
int cmp = strcmp(strArr[j], minStr);
if(cmp < 0)
strcpy(minStr,strArr[j]);
}
char temp[STR_SIZ];
strcpy(temp,strArr[x]);
strcpy(strArr[x], minStr);
strcpy(strArr[j], temp);
}
return 0;
}
Output on onlinegdb.com:
0 1
2
3
4
5
6
7
8
9
1 2
3
4
5
6
7
8
9
2 3
4
5
6
7
8
9
3 4
5
6
7
8
9
4 5
6
7
8
9
5 6
7
8
9
6 7
8
9
7 8
9
8 9
Output on CodeBlocks:
0 1
2
3
4
5
6
7
8
9
1 2
3
4
5
6
7
8
9
2
PS: I just have used Codeblock in the morning and it was okey with executing.
strArr has 10 elements. At the end of your loop, you call strcpy(strArr[j], temp);. This will write to strArr[10], which is out of bounds and will overwrite some unknown memory. Anything can happen after that.
You should save the j value when you copy a string into minStr.
FYI, your code above prints this as your final string order with onlinegdb:
abc
caksl
caksl
caksl
caksl
casd
cznjcx
cznjcx
jkalkds
jkalkds
So I think you have other problems as well.
try this
#include <string.h>
#include <stdio.h>
#define STR_SIZ 20
int main()
{
char strArr[][STR_SIZ] = {"abc", "hdas", "sdfasf", "kakldf", "caksl", "casd", "keam", "cznjcx", "mnxzv", "jkalkds"};
strcpy(minStr, strArr[0]);
// Calculate the number of elements this way.
const int N = sizeof(strArr)/sizeof(strArr[0]);
// int N = 10;
for(int x = 0; x < N-1; x++)
{
printf("%d", x);
int j;
for(j=1+x; j < N; j++) // Use N here too!
{
printf("%4d\n", j);
int cmp = strcmp(strArr[j], strArr[x]);
if(cmp < 0)
{
// Do the swaps only when needed.
char temp[STR_SIZ];
strcpy(temp,strArr[x]);
strcpy(strArr[x], strArr[j]);
strcpy(strArr[j], temp);
}
}
}
// Verify result
for(int x = 0; x < N; x++) printf("%s\n", strArr[x]);
return 0;
}
I moved your swap into your if check and got rid of your minStr as it was not needed. Notice how I calculate the N size too. Honestly, you were close, but you needed to verify your output.

C programming: Replacing if statements

Hello a beginner here who needs some of your help. My C program is good and does what it is supposed to do only that it is not supposed to use any kind of if statements. I wrote it that way as I saw it would be easier so that I can then replace the if statements. I have been trying to replace the if statements but am now stuck. What can I use instead of the if statement to still produce the same output.
The program is supposed to generate a sequence of thirty random integers between 0 and 9 and then print out the sequence both forward and backwards. Then print out a count of how many times each number between 0 and 9 appeared in the sequence.
This is the output
Here is a sequence of 30 random numbers between 0 and 9:
3 6 7 5 3 5 6 2 9 1 2 7 0 9 3 6 0 6 2 6 1 8 7 9 2 0 2 3 7 5
Printing them backwards, that's:
5 7 3 2 0 2 9 7 8 1 6 2 6 0 6 3 9 0 7 2 1 9 2 6 5 3 5 7 6 3
There were 3 0's
There were 2 1's
There were 5 2's
There were 4 3's
There were no 4's
There were 3 5's
There were 5 6's
There were 4 7's
There was only 1 8
There were 3 9's
This is my C program
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i, j, array[30]={0}, count=0,check;
srand(time(NULL));
for(i=0;i<30;i++)
array[i]=rand()%10;
for(i=0;i<30;i++)
printf("%d ",array[i]);
printf("\n\n");
for(i=29;i>=0;i--)
printf("%d ",array[i]);
printf("\n\n");
for(i=0;i<30;i++){
check=array[i];
if(array[i]!=-1)
array[i]=-1;
if(check == -1)
continue;
count =1;
for(j=0;j<30;j++){
if((i==j) || (array[j]==-1))
continue;
if(check==array[j]){
count++;
array[j]=-1;
}
}
printf("There were %d %d's\n",count,check);
}
return 0;
}
You'll understand the algorithm from comments:
#include <stdio.h>
#include <stdlib.h>
//time.h is needed for time()
#include <time.h>
int main()
{
int i, array[30] = {0};
srand(time(NULL));
//generate and print 30 random numbers
for(i = 0; i < 30; i++){
array[i] = rand() % 10;
printf("%d ", array[i]);
}
puts("\n\n");
//print these numbers backwards
for(i = 29; i >= 0; i--)
printf("%d ",array[i]);
puts("\n\n");
// print out a count of how many times each number
// between 0 and 9 appeared in the sequence.
int count[10] = {0};
for(i = 0; i < 30; i++)
count[array[i]]++;
//output the count for each number
for(i = 0; i < 10; i++)
printf("There were %d %d's\n",count[i], i);
return 0;
}
Output:
9 2 3 9 8 4 3 8 1 3 6 4 3 2 5 3 2 3 0 1 9 0 3 5 1 3 3 8 2 0
0 2 8 3 3 1 5 3 0 9 1 0 3 2 3 5 2 3 4 6 3 1 8 3 4 8 9 3 2 9
There were 3 0's
There were 3 1's
There were 4 2's
There were 9 3's
There were 2 4's
There were 2 5's
There were 1 6's
There were 0 7's
There were 3 8's
There were 3 9's
The following is a simplification of your original source while removing the if statements. There are implied if statements in several places where a logical expression is used as part of a source code statement.
For instance for(j = 0; j < 30 && match >= 0; j++) has several logical expressions but no if appears in this statement. The logical expressions are j < 30 and match >= 0 and the complete expression of j < 30 && match >= 0.
This example uses a logical expression and the evaluation short circuit behavior of the C compiler (see Short-circuit evaluation in Wikipedia) in the statement array[j] == match && ++count && (array[j] = -1); so that if the logical expression array[j] == match evaluates to false then the rest of the statement will not be executed.
We also depend on the preincrement operator with the ++count to increment count and then take the resulting value to check if it is false (zero) or true (non-zero). Since the variable count is initialized to zero and when incremented will always be non-zero then the next logical expression in the statement is evaluated the (array[j] = -1). We put the assignment statement within parenthesis to enforce the order of evaluation. We want the variable array[j] to be assigned the value of -1 and for the result to then be used in the logical statement. Since this is the last logical expression of the entire logical statement, whether it evaluates to false (zero) or true (non-zero) doesn't matter as what we want is the side effect of assigning the value of -1 to the array element.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
int i, array[30] = {0};
srand(time(NULL));
for(i = 0; i < 30; i++)
array[i] = rand() % 10;
for(i = 0; i < 30; i++)
printf("%d ", array[i]);
printf("\n\n");
for(i = 29; i >= 0; i--)
printf("%d ",array[i]);
printf("\n\n");
for(i = 0; i < 30; i++){
int j;
int count = 0;
int match = array[i];
for(j = 0; j < 30 && match >= 0; j++){
array[j] == match && ++count && (array[j] = -1);
// replaces the following if as value of count is
// tested after it is incremented so will always be nonzero.
// if (array[j] == match) {
// count++; array[j] = -1;
// }
}
// if this is a valid array element value we are trying to match
// then print the count and the value being matched. printf()
// is a function that returns an int indicating number of character written.
match >= 0 && printf("There were %d %d's\n", count, match);
}
return 0;
}
An example output.
8 2 4 0 8 0 8 1 1 4 6 9 3 9 7 6 3 9 0 1 0 7 1 2 4 0 3 0 2 3
3 2 0 3 0 4 2 1 7 0 1 0 9 3 6 7 9 3 9 6 4 1 1 8 0 8 0 4 2 8
There were 3 8's
There were 3 2's
There were 3 4's
There were 6 0's
There were 4 1's
There were 2 6's
There were 3 9's
There were 4 3's
There were 2 7's

how to use recursion to count down after counting up

I am trying to get my program to count down after counting up to ten. I have tried to alter the code from counting up to make it count down to no avail.
#include <stdio.h>
void count(int k)
{
if (k > 0) {
count(-k + 1);
printf("%d", k);
}
else {
if (k == 0)
{
printf("%d,", k);
}
else {
count(k + 1);
printf("%d,", -k);
}
}
}
int main(int argc, char ** argv)
{
count(10);
getchar();
return 0;
}
Here is a simple example of the recursion which does this, illustrating Eugene's comment:
#include <stdio.h>
void count(int n) {
if (n > 10) {
printf("\n");
return;
}
printf("%d ", n);
count(n+1);
printf("%d ", n);
}
int main() {
count(0);
printf("\n");
return 0;
}
it counts up on the way into recursion and counts down while it exits it. Actually on the way down it only re-prints the state which it was before diving into the next level:
0 1 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1 0
The function can be easy implemented if to use a static local variable inside it. For example.
#include <stdio.h>
void count(unsigned int n)
{
static unsigned int m;
printf("%u ", m);
if (n != m)
{
++m;
count(n);
--m;
printf("%u ", m);
}
}
int main( void )
{
const unsigned int N = 10;
unsigned int i = 0;
do
{
count(i);
putchar('\n');
} while (i++ != N);
return 0;
}
The program output is
0
0 1 0
0 1 2 1 0
0 1 2 3 2 1 0
0 1 2 3 4 3 2 1 0
0 1 2 3 4 5 4 3 2 1 0
0 1 2 3 4 5 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9 10 9 8 7 6 5 4 3 2 1 0
Within the function the static variable m behaves as an index in a for loop (or there will be more suitable a do-while loop).
At first it is initialized implicitly by zero (as any static variable)
static unsigned int m;
You can use the initializer explicitly if you want
static unsigned int m = 0;
then it is changed from 0 to n and afterward backward from n again to 0.
++m; // changing from 0 to n
count(n);
--m; // changing from n to 0

Scheduling algorithms in C Shortest Remain Time Next

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.

Resources