Which code is right for Peterson's algorithm? - operating-system

Recently I have started learning Inter process communication.
To implement peterson's algorithn I have found two codes:
1.#define N 2
2. #define TRUE 1
3. #define FALSE 0
4. int INTERESTED[N] = FALSE
5. int TURN;
6. void Entry_Section(int process)
7. {
8. int other;
9. other = 1 – process;
10. INTERESTED[process] = TRUE;
11. TURN = process;
12. while(INTERESTED[other] == TRUE && TURN = process)
13. }
14. void Exit_Section(int process)
15. {
16. INTERESTED[process] = FALSE;
17. }
And
1.do
2. {
3.flag[i]=True;
4. turn=j;
5. while (flag[j] && turn==j); // critical. 6.section flag[i]=False; // remainder. 7.section
8. } while (True);
So I want to know which one is true.
I think the second one is correct.
Because:
(1st code)
When, context switch occurs after setting flag value 'turn = process' (process means its pointing itself) and next process comes in enter_regin() function. Both of the values of 'intrested[2]' array will be true. And the while loop after it (which acts as trap) will be true and non of the process can get out of it.
I just want to know am I right or wrong.

Related

How to change quantum in xv6? [duplicate]

Right now it seems that on every click tick, the running process is preempted and forced to yield the processor, I have thoroughly investigated the code-base and the only relevant part of the code to process preemption is below (in trap.c):
// Force process to give up CPU on clock tick.
// If interrupts were on while locks held, would need to check nlock.
if(myproc() && myproc() -> state == RUNNING && tf -> trapno == T_IRQ0 + IRQ_TIMER)
yield();
I guess that timing is specified in T_IRQ0 + IRQ_TIMER, but I can't figure out how these two can be modified, these two are specified in trap.h:
#define T_IRQ0 32 // IRQ 0 corresponds to int T_IRQ
#define IRQ_TIMER 0
I wonder how I can change the default RR scheduling time-slice (which is right now 1 clock tick, fir example make it 10 clock-tick)?
If you want a process to be executed more time than the others, you can allow it more timeslices, *without` changing the timeslice duration.
To do so, you can add some extra_slice and current_slice in struct proc and modify the TIMER trap handler this way:
if(myproc() && myproc()->state == RUNNING &&
tf->trapno == T_IRQ0+IRQ_TIMER)
{
int current = myproc()->current_slice;
if ( current )
myproc()->current_slice = current - 1;
else
yield();
}
Then you just have to create a syscall to set extra_slice and modify the scheduler function to reset current_slice to extra_slice at process wakeup:
// Switch to chosen process. It is the process's job
// to release ptable.lock and then reacquire it
// before jumping back to us.
c->proc = p;
switchuvm(p);
p->state = RUNNING;
p->current_slice = p->extra_slice
You can read lapic.c file:
lapicinit(void)
{
....
// The timer repeatedly counts down at bus frequency
// from lapic[TICR] and then issues an interrupt.
// If xv6 cared more about precise timekeeping,
// TICR would be calibrated using an external time source.
lapicw(TDCR, X1);
lapicw(TIMER, PERIODIC | (T_IRQ0 + IRQ_TIMER));
lapicw(TICR, 10000000);
So, if you want the timer interrupt to be more spaced, change the TICR value:
lapicw(TICR, 10000000); //10 000 000
can become
lapicw(TICR, 100000000); //100 000 000
Warning, TICR references a 32bits unsigned counter, do not go over 4 294 967 295 (0xFFFFFFFF)

Does GPIO.IN need to be linked to GPIO.OUT in RPi.GPIO in order for it to work properly?

I was writing code on an raspbian emulator with GPIO. I am able to get it to work, but for some reason when I change the order of GPIO.HIGH and the print statement in the conditionals, it does not run properly and stops after the first click. Anyone know if this is an issue with the emulator or just a property of raspberry pi and hooking it up to hardware? It also does not work at all if I do not link the GPIO.IN with a GPIO.OUT.
this gif shows what happens when I change order or remove - It turns on the first time, but it does not turn off or on again after that. It for some reason breaks it out of the while loop.
Here is the code I am using:
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
import time
#initialise a previous input variable to 0 (assume button not pressed last)
prev_input = 0
prev_input1 = 0
inputs = [11, 13, 15]
outputs = [3, 5, 7]
GPIO.setup(inputs, GPIO.IN)
GPIO.setup(outputs, GPIO.OUT)
secs = 0
def main():
while True:
button_press(15, 7)
timer = add_secs(11, 5, 2)
#print(timer)
def button_press(button1, button2):
#take a reading
global prev_input
inputa = GPIO.input(button1)
#if the last reading was low and this one high, print
if ((not prev_input) and inputa):
print("Light on")
GPIO.output(button2, GPIO.HIGH) #code does not work if I remove/reorder this statement
if((not inputa) and prev_input):
print("Light off")
GPIO.output(button2, GPIO.LOW) #code does not work if I remove/reorder this statement
#update previous input
prev_input = inputa
#slight pause to debounce
time.sleep(0.05)
def add_secs(button1, button2, num):
global prev_input1
secs = 0
inputa = GPIO.input(button1)
if((not prev_input1) and inputa):
secs = num
print(secs)
GPIO.output(button2, GPIO.LOW) #code does not work if I remove/reorder this statement
prev_input1 = inputa
time.sleep(0.05)
return secs
main()
I contacted the developer of the emulator and he let me know there was an issue with the emulator that is now resolved.
The code runs properly after clearing the browsing data in chrome and re-running the program.

How to modify process preemption policies (like RR time-slices) in XV6?

Right now it seems that on every click tick, the running process is preempted and forced to yield the processor, I have thoroughly investigated the code-base and the only relevant part of the code to process preemption is below (in trap.c):
// Force process to give up CPU on clock tick.
// If interrupts were on while locks held, would need to check nlock.
if(myproc() && myproc() -> state == RUNNING && tf -> trapno == T_IRQ0 + IRQ_TIMER)
yield();
I guess that timing is specified in T_IRQ0 + IRQ_TIMER, but I can't figure out how these two can be modified, these two are specified in trap.h:
#define T_IRQ0 32 // IRQ 0 corresponds to int T_IRQ
#define IRQ_TIMER 0
I wonder how I can change the default RR scheduling time-slice (which is right now 1 clock tick, fir example make it 10 clock-tick)?
If you want a process to be executed more time than the others, you can allow it more timeslices, *without` changing the timeslice duration.
To do so, you can add some extra_slice and current_slice in struct proc and modify the TIMER trap handler this way:
if(myproc() && myproc()->state == RUNNING &&
tf->trapno == T_IRQ0+IRQ_TIMER)
{
int current = myproc()->current_slice;
if ( current )
myproc()->current_slice = current - 1;
else
yield();
}
Then you just have to create a syscall to set extra_slice and modify the scheduler function to reset current_slice to extra_slice at process wakeup:
// Switch to chosen process. It is the process's job
// to release ptable.lock and then reacquire it
// before jumping back to us.
c->proc = p;
switchuvm(p);
p->state = RUNNING;
p->current_slice = p->extra_slice
You can read lapic.c file:
lapicinit(void)
{
....
// The timer repeatedly counts down at bus frequency
// from lapic[TICR] and then issues an interrupt.
// If xv6 cared more about precise timekeeping,
// TICR would be calibrated using an external time source.
lapicw(TDCR, X1);
lapicw(TIMER, PERIODIC | (T_IRQ0 + IRQ_TIMER));
lapicw(TICR, 10000000);
So, if you want the timer interrupt to be more spaced, change the TICR value:
lapicw(TICR, 10000000); //10 000 000
can become
lapicw(TICR, 100000000); //100 000 000
Warning, TICR references a 32bits unsigned counter, do not go over 4 294 967 295 (0xFFFFFFFF)

set default priority for ktimersoftd in linux with RT patch

Is there a way to set the default priority for ktimersoftd/x so that it starts up with lets say a rt prio of -50 instead of doing chrt -p 49 pid of ktimersoftd/0 manually afterwards?
Thanx
Andy
That's set in the kernel, in the following function in kernel/softirq.c:
static inline void ktimer_softirqd_set_sched_params(unsigned int cpu)
{
struct sched_param param = { .sched_priority = 1 };
sched_setscheduler(current, SCHED_FIFO, &param);
/* Take over timer pending softirqs when starting */
local_irq_disable();
current->softirqs_raised = local_softirq_pending() & TIMER_SOFTIRQS;
local_irq_enable();
}
So the only way is to patch the kernel and change 1 with something else. I'll be honest, I don't know the consequences of such a change. There's probably a reason why it's 1 and not 50.
NB: This function is only present in the kernel with PREEMPT_RT patch applied.

How to save SystemC variables during vcs simulation and restore back based on stimulus change

My tests are in SystemC env and for all my tests i run a common routine(basically its my init sequence which doesn't vary much based on seed). This common routine is followed by my actual test.
It looks something like this:
Test_MAIN
init_seq();
my_test();;
Here init_seq() is that common routine and my_test() is my actual test that have actual test sequence which initiate multiple SC threads, for initiating various kind of traffic.
Now, my problem is that i want a way to avoid init_seq() for every run. The entire test should run for one time and the next time i should have a mechanism to directly run from my_test()(which is basically skipping/preloading init_seq() part to the simulator).
VCS save and restore can't be used directly as in this case we also will have to restore the SystemC variables.
Could you please direct me on this..!!
Thanks
ByreddyNaresh
I tried with a SystemC test with init() and run() routine, and use VCS save/restart to restore the test. It seems OK to me that a member variable 'cnt' in test is restored successfully.
This is my test:
// test.h
#ifndef TEST_H
#define TEST_H
#include <systemc.h>
class test: public sc_module{
public:
sc_in<bool> init_start;
sc_in<bool> run_start;
void init();
void run();
int cnt;
SC_CTOR(test){
SC_THREAD(init);
sensitive_pos << init_start;
dont_initialize();
SC_THREAD(run);
sensitive_pos << run_start;
dont_initialize();
}
};
#endif
and
// test.cpp
#include "test.h"
void test::init(){
printf("test init:\n");
while(1){
cnt = 10;
printf("init cnt to %d\n", cnt);
wait();
}
}
void test::run(){
printf("test run:\n");
while(1){
cnt++;
printf("cnt = %d\n", cnt);
wait();
}
}
and the top:
// tb.v
module tb;
reg init_start;
reg run_start;
initial begin
init_start = 0;
run_start = 0;
#100
init_start = 1;
#100
$save("save.chk");
#100
run_start = 1;
#100
$finish;
end
test u_test(
.init_start(init_start),
.run_start(run_start)
);
endmodule
After 'save.chk' is generated, I run it directly and the output is:
$ save.chk
Chronologic VCS simulator copyright 1991-2012
Contains Synopsys proprietary information.
Compiler version G-2012.09; Runtime version G-2012.09; Mar 5 18:01 2014
test run:
cnt = 11
$finish called from file "tb.v", line 17.
$finish at simulation time 1300
V C S S i m u l a t i o n R e p o r t
Time: 1300 ps
CPU Time: 0.260 seconds; Data structure size: 0.0Mb
Wed Mar 5 18:01:08 2014
It seems variable 'cnt' is restored from '10', as is done in init() routine.
Don't know if this is the case you met?