Dekker's algorithm for 3 processes - algorithm

As my asignment I have to verify something on Dekker's algorithm - but with 3 processes -
I can only find original version for 2 processes.
The goal is not the algorithm but it's implementation and verification in SMV System
http://www.cs.cmu.edu/~modelcheck/smv.html

You should probably ask the course staff, but you can use two Dekker mutexes to achieve three-process mutex. Processes 0 and 1 compete to acquire mutex A; the holder of mutex A and process 2 compete to acquire mutex B, whose holder is allowed to run a critical section.

// Dekkers algorithm version3
system:
boolean t1WantsToEnter=false;
boolean t2WantsToEnter=false;
startThreads;//initialize and launch all threads
Thread T1;
void main();{
while(!done);
{
t1WantsToEnter=true;
while(t2WantsToEnter); //wait
//critical section cokde
t1WantsToEnter=false;
//code outside critical section
Thread T2;
void main();{
while(!done);
{
t2WantsToEnter=true;
while(t1WantsToEter);//wait
//critical section code
t2WantsToEnter=false;
//code outside critical section
// if u want to know how this code is executed using RAM diagram,

// Dekkers algorithm version3
system:
boolean t1WantsToEnter = false;
boolean t2WantsToEnter = false;
startThreads; // initialize and launch all threads
// Thread T1
void main() {
while(!done);
{
t1WantsToEnter = true;
while(t2WantsToEnter) { // wait
// critical section cokde
t1WantsToEnter = false;
}
// code outside critical section
} // end outer while
} // end Thread T1
// Thread T2
void main() {
while(!done);
{
t2WantsToEnter = true;
while (t1WantsToEter) { //wait
// critical section code
t2WantsToEnter =false;
}
// code outside critical section
} // end outer while
} // end Thread T2

Related

FASTLED.show() stops working when working in core 1 FREERTOS (after deleting the task running a pattern and creating a new one)

I have a couple of pattern functions and one task (Task1) which runs on core 1. I receive data (pattern no.) from BLE in core 0. Depending on the data, I create the task above with the task function as the chosen pattern.
Problem comes when I want to switch patterns. What I do is delete the already running task handle (Task1) and recreate the same Task1 handle with the new pattern function. Sometimes the switch between patterns is flawless. But most times, the switch happens but the leds don't get updated. In the background I can see the new task has been created and the pattern looping as expected but the leds just don't get updated. They are stuck on the colors from the previous deleted task.
The switch of patterns:
`
TaskHandle_t Task1;
// if a new pattern no. has been read
if (command.startsWith("p"))
{
if (Task1 != NULL)
{
vTaskDelete(Task1);
}
xTaskCreatePinnedToCore(
switchPattern(command.substring(1).toInt()), /* Returns a task function. */
"Task1", /* name of task. */
20000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task1, /* Task handle to keep track of created task */
1); /* pin task to core 1 */
mode = 1; // switch to patterns mode
preferences.putInt("mode", mode);
}
**Example pattern function:**
void BPM(void *)
{
while (1)
{
// colored stripes pulsing at a defined Beats-Per-Minute (BPM)
uint8_t BeatsPerMinute = 62;
CRGBPalette16 palette = PartyColors_p;
uint8_t beat = beatsin8(BeatsPerMinute, 64, 255);
for (int i = 0; i < NUM_LEDS; i++)
{ // 9948
led[i] = ColorFromPalette(palette, (i * 2), beat + (i * 10));
}
FastLED.show();
}
}
`
If you know the fault or know a better way to do this, throw it at me.
Any help is appreciated!
I really can't find similar questions online so I haven't tried much.
I have tried not deleting the task at all, but that just adds more tasks to the core 1 hence showing multiple patterns at once, though FASTLED continues working normally. But this is not the expected result of course.
I expect the changing of patterns to be smooth. Maybe I'm missing something.
Creating a new task for a simple control flow branch is a nuclear overkill :) I suspect you don't need to create any threads whatsoever, as FastLED doesn't seem to require it in any way (didn't look too deep).
Assuming you have a LED blinking task, just signal to it which option you want. It can be done quite simply.
typedef enum {
LED_PATTERN_BPM,
LED_PATTERN_Y,
LED_PATTERN_Z
} led_pattern_t;
// "volatile" keyword required for any variable accessed in different threads
volatile led_pattern_t _led_pattern = LED_PATTERN_BPM;
// Single iteration of a flash pattern, no while(1) loop
void flash_pattern_BPM()
{
// colored stripes pulsing at a defined Beats-Per-Minute (BPM)
uint8_t BeatsPerMinute = 62;
CRGBPalette16 palette = PartyColors_p;
uint8_t beat = beatsin8(BeatsPerMinute, 64, 255);
for (int i = 0; i < NUM_LEDS; i++)
{ // 9948
led[i] = ColorFromPalette(palette, (i * 2), beat + (i * 10));
}
FastLED.show();
}
void flash_pattern_Z_interruptible() {
while (_led_pattern == LED_PATTERN_Z) {
// Fill the pattern, show it
}
}
// Task code for flashing the LEDs
void led_task(void* param) {
while (true) {
switch(_led_pattern) {
case LED_PATTERN_BPM:
flash_pattern_BPM();
break;
case LED_PATTERN_Y:
// Flash pattern Y
break;
case LED_PATTERN_Z:
flash_pattern_Z_interruptible();
break;
}
}
}
xTaskCreatePinnedToCore(led_task, "LED task", 20000, NULL, 1, &Task1, 1);
...
// Somewhere in your code where a new pattern is required
_led_pattern = LED_PATTERN_Z;

Detect "suspended" Windows 8/10 process

UWP (or "Metro") apps in Windows 8/10 can be suspended when they are not in the foreground. Apps in this state continue to exist but no longer consume CPU time. It looks like this change was introduced to improve performance on low-power/storage devices like tablets and phones.
What is the most elegant and simple method to detect a process in this state?
I can see 2 possible solutions at the moment:
Call NtQuerySystemInformation() and the enumerate each process and each thread. A process is "suspended" if all threads are in the suspended state. This approach will require a lot of code and critically NtQuerySystemInformation() is only semi-documented and could be removed in a future OS. NtQueryInformationProcess() may also offer a similar solution with the same problem.
Call GetProcessTimes() and record the counters for each process. Wait some longish time (minutes) and check again. If the process counters haven't changed then assume the process is suspended. I admit this is a hack but maybe could work if the time period is long enough.
Is there a more elegant way?
for this exist PROCESS_EXTENDED_BASIC_INFORMATION - meaning of flags in it described in this answer. you are need IsFrozen flag. so you need open process with PROCESS_QUERY_LIMITED_INFORMATION access (for do this for all processes, you will be need have SE_DEBUG_PRIVILEGE enabled in token). and call NtQuerySystemInformation with ProcessBasicInformation and PROCESS_EXTENDED_BASIC_INFORMATION as input. for enumerate all processes we can use NtQuerySystemInformation with SystemProcessInformation. of course possible and use CreateToolhelp32Snapshot + Process32First + Process32Next but this api very not efficient, compare direct call to NtQuerySystemInformation
also possible enumerate all threads in process and check it state and if state wait - wait reason. this is very easy, because all this information already returned by single call to NtQuerySystemInformation with SystemProcessInformation. with this we not need open processes. usually both this ways give the same result (for suspended/frozen) processes, but however use IsFrozen is most correct solution.
void PrintSuspended()
{
BOOLEAN b;
RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, &b);
ULONG cb = 0x1000;
NTSTATUS status;
do
{
status = STATUS_INSUFFICIENT_RESOURCES;
if (PBYTE buf = new BYTE[cb])
{
if (0 <= (status = NtQuerySystemInformation(SystemProcessInformation, buf, cb, &cb)))
{
union {
PBYTE pb;
SYSTEM_PROCESS_INFORMATION* spi;
};
pb = buf;
ULONG NextEntryOffset = 0;
do
{
pb += NextEntryOffset;
if (!spi->UniqueProcessId)
{
continue;
}
if (HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE,
(ULONG)(ULONG_PTR)spi->UniqueProcessId))
{
PROCESS_EXTENDED_BASIC_INFORMATION pebi;
if (0 <= NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pebi, sizeof(pebi), 0) &&
pebi.Size >= sizeof(pebi))
{
if (pebi.IsFrozen)
{
DbgPrint("f:%x %wZ\n", spi->UniqueProcessId, spi->ImageName);
}
}
CloseHandle(hProcess);
}
if (ULONG NumberOfThreads = spi->NumberOfThreads)
{
SYSTEM_THREAD_INFORMATION* TH = spi->TH;
do
{
if (TH->ThreadState != StateWait || TH->WaitReason != Suspended)
{
break;
}
} while (TH++, --NumberOfThreads);
if (!NumberOfThreads)
{
DbgPrint("s:%x %wZ\n", spi->UniqueProcessId, spi->ImageName);
}
}
} while (NextEntryOffset = spi->NextEntryOffset);
}
delete [] buf;
}
} while (status == STATUS_INFO_LENGTH_MISMATCH);
}

in which condition will queue_work() not wake up the work queue in linux?

i am learning linux kernel, and i meet a problem.
in linux kernel, i use "mod_delayed_work(bdi_wq, &wb->dwork, 0)" to queue a work_struct to a work queue, i assume the work function of the queued work_struct will soon be executed. but work function is not executed until 300 seconds later.
and i find a watchdog thread happens meanwhile.
does this a normal case? or is it because of the watchdog thread that make the work queue sleep although there is a work(my queued work_truct) pending here.
added:
the followings are my condition. i use the linux kernel 4.9.13 codes and do not change them except for adding some printk logs.
i have five disks, and use five shells to copy 4GB files from disks to disks concurrently. this problem happens while i am doing sync. one of the shells is like:
#!/bin/bash
for ((i=0; i<9999; i++))
do
cp disk1/4GB.tar disk2/4GB-chen.tar
sync
rm disk2/4GB-chen.tar
sync
done
i do a sync after each copy is done. after the shells run for some times, i find that the sync command will be blocked for a long time(longer than 2 minutes). i find sync will call a system call, the code is as follows:
SYSCALL_DEFINE0(sync)
{
int nowait = 0, wait = 1;
wakeup_flusher_threads(0, WB_REASON_SYNC);
iterate_supers(sync_inodes_one_sb, NULL);
iterate_supers(sync_fs_one_sb, &nowait);
iterate_supers(sync_fs_one_sb, &wait);
iterate_bdevs(fdatawrite_one_bdev, NULL);
iterate_bdevs(fdatawait_one_bdev, NULL);
if (unlikely(laptop_mode))
laptop_sync_completion();
return 0;
}
in iterate_supers(sync_inodes_one_sb, NULL), kernel will call sync_inodes_one_sb for each disk'super block. sync_inodes_one_sb will eventually call sync_inodes_sb, the code is:
void sync_inodes_sb(struct super_block *sb)
{
DEFINE_WB_COMPLETION_ONSTACK(done);
struct wb_writeback_work work = {
.sb = sb,
.sync_mode = WB_SYNC_ALL,
.nr_pages = LONG_MAX,
.range_cyclic = 0,
.done = &done,
.reason = WB_REASON_SYNC,
.for_sync = 1,
};
struct backing_dev_info *bdi = sb->s_bdi;
/*
* Can't skip on !bdi_has_dirty() because we should wait for !dirty
* inodes under writeback and I_DIRTY_TIME inodes ignored by
* bdi_has_dirty() need to be written out too.
*/
if (bdi == &noop_backing_dev_info)
return;
WARN_ON(!rwsem_is_locked(&sb->s_umount));
bdi_split_work_to_wbs(bdi, &work, false); /* split work to wbs */
wb_wait_for_completion(bdi);
wait_sb_inodes(sb);
}
and in bdi_split_work_to_wbs(bdi, &work, false)(in fs/fs-writeback.c), queue the write back works to the work queue:
static void bdi_split_work_to_wbs(struct backing_dev_info *bdi,
struct wb_writeback_work *base_work,
bool skip_if_busy)
{
struct bdi_writeback *last_wb = NULL;
struct bdi_writeback *wb = list_entry(&bdi->wb_list,
struct bdi_writeback, bdi_node);
might_sleep();
restart:
rcu_read_lock();
list_for_each_entry_continue_rcu(wb, &bdi->wb_list, bdi_node) {
DEFINE_WB_COMPLETION_ONSTACK(fallback_work_done);
struct wb_writeback_work fallback_work;
struct wb_writeback_work *work;
long nr_pages;
if (last_wb) {
wb_put(last_wb);
last_wb = NULL;
}
/* SYNC_ALL writes out I_DIRTY_TIME too */
if (!wb_has_dirty_io(wb) &&
(base_work->sync_mode == WB_SYNC_NONE ||
list_empty(&wb->b_dirty_time)))
continue;
if (skip_if_busy && writeback_in_progress(wb))
continue;
nr_pages = wb_split_bdi_pages(wb, base_work->nr_pages);
work = kmalloc(sizeof(*work), GFP_ATOMIC);
if (work) {
*work = *base_work;
work->nr_pages = nr_pages;
work->auto_free = 1;
wb_queue_work(wb, work); /*** here to queue write back work ***/
continue;
}
/* alloc failed, execute synchronously using on-stack fallback */
work = &fallback_work;
*work = *base_work;
work->nr_pages = nr_pages;
work->auto_free = 0;
work->done = &fallback_work_done;
wb_queue_work(wb, work);
/*
* Pin #wb so that it stays on #bdi->wb_list. This allows
* continuing iteration from #wb after dropping and
* regrabbing rcu read lock.
*/
wb_get(wb);
last_wb = wb;
rcu_read_unlock();
wb_wait_for_completion(bdi, &fallback_work_done);
goto restart;
}
rcu_read_unlock();
if (last_wb)
wb_put(last_wb);
}
use wb_queue_work(wb, work) to queue a work to work structure, in fs/fs-writeback.c wb_queue_work is:
static void wb_queue_work(struct bdi_writeback *wb,
struct wb_writeback_work *work)
{
trace_writeback_queue(wb, work);
if (work->done)
atomic_inc(&work->done->cnt);
spin_lock_bh(&wb->work_lock);
if (test_bit(WB_registered, &wb->state)) {
list_add_tail(&work->list, &wb->work_list);
mod_delayed_work(bdi_wq, &wb->dwork, 0); /*** queue work to work queue ***/
} else
finish_writeback_work(wb, work);
spin_unlock_bh(&wb->work_lock);
}
here the mod_delayed_work(bdi_wq, &wb->dwork, 0) will actually queue the wb->dwork to the bdi_wq work queue, the work function of wb->dwork is wb_workfn()(in fs/fs-writeback.c), i add some printks when prepare to queue the work and in the work function, i find the printk logs in the work function are not printed out until approximately 300 seconds later some times(most of the times, they will be printed less than 1 seconds after the work has been queued to the work queue). and the bdi_wq work queue will be blocked until 300 seconds later when the work function begin to be executed.

Segmentation fault when changing value of attribute

I'm working in a C++11 class that will fetch via I2C the value of a temperature sensor in a Raspberry Pi. It will be polling the value until it's stopped. It does the polling in a separate thread, so that it does not stop the application flow. The problem is that in the line 64 of this file: https://github.com/OpenStratos/server/blob/feature/temperature/temperature/Temperature.cpp#L64
void Temperature::read_temperature()
{
while (this->reading)
{
#ifndef OS_TESTING
int value = wiringPiI2CRead(this->filehandle);
#else
int value = 16000;
#endif
float voltage = value * 5 / 32768; // 2^15
float temp = r_to_c(TEMP_R * (TEMP_VIN / voltage - 1));
this->temperature = temp; // Gives segmentation fault
this_thread::sleep_for(chrono::milliseconds(50));
}
}
it gives a segmentation fault. The curius thing is that it does not always happen. After compiling, running the binary many times about the 75% of the time will crash.
This is the file that invoques the code:https://github.com/OpenStratos/server/blob/feature/temperature/testing/temperature_test.cpp
Temperature temp(20);
temp.start_reading();
AssertThat(temp.is_reading(), Equals(true));
// this_thread::sleep_for(chrono::milliseconds(100)); if uncommented less segmentation faults
temp.stop_reading();
AssertThat(temp.is_reading(), Equals(false));
What could be happening? How can it be fixed?
You need to wait for Temperature::read_temperature() to quit, so you need:
bool reading;
volatile bool stopped; // volatile required to make the compiler re-read
// the value everytime we expect it to.
//
bool is_stopped(){ return stopped; }
and
void Temperature::start_reading()
{
if (!reading)
{
stopped = false;
reading = true;
// etc
and
void Temperature::read_temperature()
{
while (this->reading)
{
// etc
}
stopped=true;
}
and
temp.stop_reading();
while(!temp.is_stopped();
AssertThat(temp.is_reading(), Equals(false));

How to make a fast context switch from one process to another?

I need to run unsafe native code on a sandbox process and I need to reduce bottleneck of process switch. Both processes (controller and sandbox) shares two auto-reset events and a coherent view of a mapped file (shared memory) that is used for communication.
To make this article smaller, I removed initializations from sample code, but the events are created by the controller, duplicated using DuplicateHandle, and then sent to sandbox process prior to work.
Controller source:
void inSandbox(HANDLE hNewRequest, HANDLE hAnswer, volatile int *shared) {
int before = *shared;
for (int i = 0; i < 100000; ++i) {
// Notify sandbox of a new request and wait for answer.
SignalObjectAndWait(hNewRequest, hAnswer, INFINITE, FALSE);
}
assert(*shared == before + 100000);
}
void inProcess(volatile int *shared) {
int before = *shared;
for (int i = 0; i < 100000; ++i) {
newRequest(shared);
}
assert(*shared == before + 100000);
}
void newRequest(volatile int *shared) {
// In this test, the request only increments an int.
(*shared)++;
}
Sandbox source:
void sandboxLoop(HANDLE hNewRequest, HANDLE hAnswer, volatile int *shared) {
// Wait for the first request from controller.
assert(WaitForSingleObject(hNewRequest, INFINITE) == WAIT_OBJECT_0);
for(;;) {
// Perform request.
newRequest(shared);
// Notify controller and wait for next request.
SignalObjectAndWait(hAnswer, hNewRequest, INFINITE, FALSE);
}
}
void newRequest(volatile int *shared) {
// In this test, the request only increments an int.
(*shared)++;
}
Measurements:
inSandbox() - 550ms, ~350k context switches, 42% CPU (25% kernel, 17% user).
inProcess() - 20ms, ~2k context switches, 55% CPU (2% kernel, 53% user).
The machine is Windows 7 Pro, Core 2 Duo P9700 with 8gb of memory.
An interesting fact is that sandbox solution uses 42% of CPU vs 55% of in-process solution. Another noteworthy fact is that sandbox solution contains 350k context switches, which is much more than the 200k context switches that we can infer from source code.
I need to know if there's a way to reduce the overhead of transfer control to another process. I already tried to use pipes instead of events, and it was much worse. I also tried to use no event at all, by making the sandbox call SuspendThread(GetCurrentThread()) and making the controller call ResumeThread(hSandboxThread) on every request, but the performance was similar to using events.
If you have a solution that uses assembly (like performing a manual context switch) or Windows Driver Kit, please let me know as well. I don't mind having to install a driver to make this faster.
I heard that Google Native Client does something similar, but I only found this documentation. If you have more information, please let me know.
The first thing to try is raising the priority of the waiting thread. This should reduce the number of extraneous context switches.
Alternatively, since you're on a 2-core system, using spinlocks instead of events would make your code much much faster, at the cost of system performance and power consumption:
void inSandbox(volatile int *lock, volatile int *shared)
{
int i, before = *shared;
for (i = 0; i < 100000; ++i) {
*lock = 1;
while (*lock != 0) { }
}
assert(*shared == before + 100000);
}
void newRequest(volatile int *shared) {
// In this test, the request only increments an int.
(*shared)++;
}
void sandboxLoop(volatile int *lock, volatile int * shared)
{
for(;;) {
while (*lock != 1) { }
newRequest(shared);
*lock = 0;
}
}
In this scenario, you should probably set thread affinity masks and/or lower the priority of the spinning thread so that it doesn't compete with the busy thread for CPU time.
Ideally, you'd use a hybrid approach. When one side is going to be busy for a while, let the other side wait on an event so that other processes can get some CPU time. You could trigger the event a little ahead of time (using the spinlock to retain synchronization) so that the other thread will be ready when you are.

Resources