why does linux driver use semaphore and spin_lock simutaneously? - linux-device-driver

I come across a linux driver code that use semaphore and spinlock at the same time:
struct semaphore lock;
spinlock_t int_lock;
unsigned long flag;
void dequeue()
{
down_interruptible(lock);
spin_lock_irqsave(int_lock,flag);
}
is it necessary to use the two together?

Related

Mutex is not held in this async block

I'm doing the Advanced coroutines with Kotlin flow and LiveData code lab and encountered this function in CacheOnSuccess.kt.
There is a comment that says "// Note: mutex is not held in this async block". What does this mean exactly? Why wouldn't the mutex be held in the async block? And what is the significance of that?
suspend fun getOrAwait(): T {
return supervisorScope {
// This function is thread-safe _iff_ deferred is #Volatile and all reads and writes
// hold the mutex.
// only allow one coroutine to try running block at a time by using a coroutine-base
// Mutex
val currentDeferred = mutex.withLock {
deferred?.let { return#withLock it }
async {
// Note: mutex is not held in this async block
block()
}.also {
// Note: mutex is held here
deferred = it
}
}
// await the result, with our custom error handling
currentDeferred.safeAwait()
}
}
according to withLock implementation, mutex is held on the just stack-frame, which means, after withLock execution the mutex is released, but code inside async may not execute right in that frame (maybe in another thread according to current Dispatchers), so probably when the block of async get executed, withLock call could have already returned, as for the also call, it is marked as inline, so it is executed in the current frame, right before withLock returned
The mutex is held by at most one coroutine at any time. async launches a coroutine which doesn't attempt to acquire the mutex. The significance of that is the same as for any other mutex -- the code inside the async block isn't guarded by the mutex, so it must not touch the state that is required to be guarded by it.

Writing a semaphore using a monitor

I'm having this excercise, which I don't know how to solve it:
Build semaphores using monitors: please define variables val (the
semaphore value) and Qu (of type condition), on which would be
possible suspending that process that if calling qWait() finds val =
0. Implement it and qSignal(), defining the code that initializes the semaphore as well.
I came up with this :
monitor Semaphore {
integer val;
condition Qu; //value > 0
procedure qWait() {
val--;
if (val < 0)
Qu.wait();
}
procedure qSignal() {
val++;
Qu.signal();
}
Semaphore(int init) {
val = init;
}
}
do you think it's the right solution?
I am not familiar with the programming language you are writing this in. If I can assume that only one thread of execution can be actively executing within the monitor at a time, then I think your implementation is sufficient. If that is not the case, then you need some extra code to handle this.
Using a simple language, like C, can help to clarify the requirements. To implement a semaphore (or a monitor) would require a mutex and a condition variable, like so:
struct Sem {
int value;
mutex lock;
condvar cond;
};
int qsignal(struct Sem *s) {
Lock(&s->lock);
if (++(s->val) <= 0) {
Signal(&s->cond);
}
Unlock(&s->lock);
return 0;
}
int qwait(struct Sem *s) {
Lock(&s->lock);
if (s->val-- <= 0) {
Wait(&s->cond, &s->lock);
}
Unlock(&s->lock);
}
Notice here that both functions are bracketed in a lock which prevents the Sem structure from changing while this is executing. The Wait() function atomically releases the lock and blocks the caller until the cond is Signaled(). Once signaled, it re-acquires the lock (waiting if necessary), and continues.
You can see the structural similarity to your code; but the lock transitions are more explicit. I hope this helps!

variable sharing between isr and function call

Consider the following code
int Var;
Function1() {
[CS_Start]
Var++;
[CS_End]
}
Function2() {
[CS_Start]
Var += 2;
[CS_End]
}
ISR() {
[CS_Start]
Var--;
[CS_End]
}
How to protect Var in multitasking environment? One of the design I understand is to keep Var as volatile such that it is safe in multiprocessor scheduling scheme. Additionally Spin lock (in place of mutex) can be implemented to protect the critical section.
What happens if Spinlock is acquired by Function1 and ISR occurs (with higher priority than scheduler timer) ISR will keep on polling and Function1 never gets a chance to release the lock. Any solution to this problem ?

Register function that will be called before system call

How can we register function such that it will be called before executing system call.
For example, pthread_atfork() registers functions that will be called before and after fork().
Below is the example on Linux system.
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
//http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_atfork.html
void prepare_function() {
printf("%d : In Prepare Function\n", getpid());
}
void parent_fuction() {
printf("%d : In Parent Function\n", getpid());
}
void child_function() {
printf("%d : In Child Function\n", getpid());
}
int main() {
pthread_atfork(prepare_function, parent_fuction, child_function);
if (fork() == 0) {
//sleep(1);
printf("%d : In Child\n", getpid());
return 0;
}
//sleep(1);
printf("%d : In Parent\n", getpid());
return 0;
}
I'm curious about how this can be implemented.
What is the actual goal here?
Fork has hooks because the state of the child with presence of threads in undefined. So by hooking yourself up you can ensure whatever mechanisms you want to use remain operational (for instance, if the fork happened after one of your threads takes a lock, the lock will remain taken within the child - what now?).
In general there is no mechanism which provides hooks for all syscalls.
For the most part syscalls are wrapped in glibc so there are few entry points which actually call the kernel. Someone bored enough could hack this up by e.g. inserting a jump in generated code to which would land the execution in their routine. But such a routine would have to have its own way of calling syscalls or a hack.
But wait, any piece of code is free to call a syscall without the use of such wrappers and such code could be dynamically generated, so you can't binary patch it prior to execution.
You can trace syscall entry/exit with ptrace, but you need a separate process for that.

Using classes with the Arduino

I'm trying to use class objects with the Arduino, but I keep running into problems. All I want to do is declare a class and create an object of that class. What would an example be?
On Arduino 1.0, this compiles just fine:
class A
{
public:
int x;
virtual void f() { x=1; }
};
class B : public A
{
public:
int y;
virtual void f() { x=2; }
};
A *a;
B *b;
const int TEST_PIN = 10;
void setup()
{
a=new A();
b=new B();
pinMode(TEST_PIN,OUTPUT);
}
void loop()
{
a->f();
b->f();
digitalWrite(TEST_PIN,(a->x == b->x) ? HIGH : LOW);
}
There is an excellent tutorial on how to create a library for the Arduino platform. A library is basically a class, so it should show you how its all done.
On Arduino you can use classes, but there are a few restrictions:
No new and delete keywords
No exceptions
No libstdc++, hence no standard functions, templates or classes
You also need to make new files for your classes, you can't just declare them in your main sketch. You also will need to close the Arduino IDE when recompiling a library. That is why I use Eclipse as my Arduino IDE.
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1230935955 states:
By default, the Arduino IDE and
libraries does not use the operator
new and operator delete. It does
support malloc() and free(). So the
solution is to implement new and
delete operators for yourself, to use
these functions.
Code:
#include <stdlib.h> // for malloc and free
void* operator new(size_t size) { return malloc(size); }
void operator delete(void* ptr) { free(ptr); }
This let's you create objects, e.g.
C* c; // declare variable
c = new C(); // create instance of class C
c->M(); // call method M
delete(c); // free memory
Regards,
tamberg
I created this simple one a while back. The main challenge I had was to create a good build environment - a makefile that would compile and link/deploy everything without having to use the GUI. For the code, here is the header:
class AMLed
{
private:
uint8_t _ledPin;
long _turnOffTime;
public:
AMLed(uint8_t pin);
void setOn();
void setOff();
// Turn the led on for a given amount of time (relies
// on a call to check() in the main loop()).
void setOnForTime(int millis);
void check();
};
And here is the main source
AMLed::AMLed(uint8_t ledPin) : _ledPin(ledPin), _turnOffTime(0)
{
pinMode(_ledPin, OUTPUT);
}
void AMLed::setOn()
{
digitalWrite(_ledPin, HIGH);
}
void AMLed::setOff()
{
digitalWrite(_ledPin, LOW);
}
void AMLed::setOnForTime(int p_millis)
{
_turnOffTime = millis() + p_millis;
setOn();
}
void AMLed::check()
{
if (_turnOffTime != 0 && (millis() > _turnOffTime))
{
_turnOffTime = 0;
setOff();
}
}
It's more prettily formatted here: http://amkimian.blogspot.com/2009/07/trivial-led-class.html
To use, I simply do something like this in the .pde file:
#include "AM_Led.h"
#define TIME_LED 12 // The port for the LED
AMLed test(TIME_LED);
My Webduino library is all based on a C++ class that implements a web server on top of the Arduino Ethernet shield. I defined the whole class in a .h file that any Arduino code can #include. Feel free to look at the code to see how I do it... I ended up just defining it all inline because there's no real reason to separately compile objects with the Arduino IDE.
Can you provide an example of what did not work? As you likely know, the Wiring language is based on C/C++, however, not all of C++ is supported.
Whether you are allowed to create classes in the Wiring IDE, I'm not sure (my first Arduino is in the mail right now). I do know that if you wrote a C++ class, compiled it using AVR-GCC, then loaded it on your Arduino using AVRDUDE, it would work.