I am trying to implement a mutex in c using the fetch and increment algorithm (sort of like the bakery algorithm). I have implemented the fetch and add part atomically. I have every thread obtain a ticket number and wait for their number to be "displayed". However, I have not found a way to tackle the issue of waiting for your ticket to be displayed. I have thought of using a queue to store your thread ID and descheudle/yield yourself until someone who has the lock, wakes you up. However, I would need a lock for the queue as well! :(
Are there any recommendations on what I could do to make the queue insertion safe or perhaps a different approach to using a queue?
Here is some code of my initial implementation:
void mutex_lock( mutex_t *mp ) {
while (compareAndSwap(&(mp->guard), 0, 1) == 1) {
// This will loop for a short period of time, Need to change this <--
}
if ( mp->lock == 1 ) {
queue_elem_t elem;
elem.data.tid = gettid();
enq( &(mp->queue), &(elem) );
mp->guard = 0;
deschedule();
}
else {
mp->lock = 1; // Lock the mutex
mp->guard = 0; // Allow others to enq themselves
}
}
Also, lets for now ignore the potential race condition where someone can call make_runnable before you call deschedule, I can write another system call that will say we are about to deschedule so queue make_runnable calls.
Related
As reading the book < Computer Systems: A Programmer's Perspective > and in the chapter of Concurrent Programming, I saw a this function:
int sbuf_remove(sbuf_t *sp){
int item; '
P(&sp->items);
P(&sp->mutex);
if (++sp->front >= sp->n)
sp-> front = 0;
item = sp->buf[sp->front]
V(&sp->mutex);
V(&sp->slots);
return item;
}
After reading the code, I think some problematic situation.
Problematic Situation's conditions :
&sp->items = 1 ,
two consumers reach at P(&sp->items) code at same time (before none of them reach to P(&sp->mutex);
In this situation, I think two consumers should have race and make problem.
(After one consumer_1 finish sbuf_remove, items become 0 but consumer_2 already pass P(&sp->items) code. Therefore consumer_2 fail to get correct item and return unexpectable value.)
I am wondering why package developer did not use mutex's lock code before enter items, slots semasphore.
I mean the code should be changed like this. Isn't it more safe than original code?
P(&sp->mutex);
P(&sp->items);
if (++sp->front >= sp->n)
sp-> front = 0;
item = sp->buf[sp->front]
V(&sp->slots);
V(&sp->mutex);
Remember that sem_wait waits until the semaphore is nonzero before atomically decrementing it. So if two consumers reach P(&sp->items) at the same time with sp->items==1, one of them will decrement items and go on to remove the last item. The other will see that items == 0 and block until some producer adds an item. They cannot both pass P(&sp->items). I don't see any race here.
On the other hand your "more safe" suggestion is a little too safe. Suppose a consumer enters sbuf_remove when the queue is empty, so sp->items == 0. It takes the mutex and then blocks (still holding the mutex!) waiting for sp->items to become positive, which will only happen when a producer adds an item. But in order to add an item to the queue, the producer presumably would need to take the mutex, which it can't do because the consumer holds it. We thus have a classic deadlock.
Below questions many times asked me in multiple interview and every time i confused to give answer properly.
Suppose RTOS running in single processor system. There are two tasks in that. Task1 print the data like "Up" and Task2 print data like "Down". How do you make sure that Task1 print first then Task2? So output is like below
Up
Down
Up
Down
.....
I have suggested the mechanism using global variable like initially global variable have value 1. Ex. int globaleVar = 1; Now two task written like below
Task1
while(1)
{
if(globaleVar == 1)
{
printf("Up");
globaleVar = 2;
}
}
Task2
while(1)
{
if(globaleVar == 2)
{
printf("Down");
globaleVar = 1;
}
}
But they said like what if Task2 get chance before the variable updated from Task1? Why not try using semaphor?
So i am not aware about how it possible using semaphor? Anyone have idea?
A natural way to do this in an RTOS environment is with two binary semaphores, one for each task. In pseudocode:
BinarySempahore up, dn;
void task_up(void) {
while (1) {
wait(up);
printf("UP ");
signal(dn);
}
}
void task_dn(void) {
while (1) {
wait(dn);
printf("DOWN ");
signal(up);
}
}
void main(void) {
dn = create_binary_sempahore(0);
up = create_binary_semaphore(1);
start_task(task_dn);
start_task(task_up);
}
Initially task dn blocks in wait because its semaphore has value zero, but up runs, prints its message, wakes up dn, then blocks on its own semaphore, which is now zero. Task dn is now unblocked from wait so prints its message, wakes up, then blocks on its sempahore, etc., etc.
For FreeRTOS you can use mutexes Mutexes
or
Event groups
I would like to be able wait/post more than one resource at a time. Is there a built-in c structure and interface that allows for this?
Currently I am using semaphore.h however this interface has the limitation that it can only request a single resource at a time.
I could do something like this:
for (int i = 0; i < resources; i++)
sem_wait(my_sem);
But this would be time consuming if resources is large and I would also need to add another lock before this so that I am guaranteed that the requester has priority over other threads that may be requesting resources.
It would end up looking something like this:
sem_wait(my_lock);
for (int i = 0; i < resources; i++)
sem_wait(my_sem);
sem_post(my_lock);
not to mention extra error checks that would need to happen.
What I would like to be able to do is something like this:
sem_wait(my_lock, resources);
This would simply wait until all resources are available and then return after decrementing the semaphore by the requested number of resources. I feel like I've seen something like this a while back but can't seem to figure it out.
You are presently using POSIX semaphores. They do not directly afford the possibility of atomically changing the semaphore value by more than one, except when creating a new semaphore.
System V semaphores (semget / semctl / semop) are generally considered inferior, but they do have some features that the POSIX flavor lacks, and this is one of them. Specifically, you can use semop() to atomically deduct any positive number from the semaphore's value, blocking until this can be done without reducing the value below zero.
But System V IPC is enough of a pain overall that I'd suggest instead setting up a shared variable representing the number of resources presently available, and using a mutex + condition variable instead of a semaphore. That would look something like this:
unsigned resources_available = ALL_RESOURCES;
pthread_mutex_t resource_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t resource_cv = PTHREAD_COND_INITIALIZER;
// ...
int acquire_resources(unsigned resources_wanted) {
int result;
// ...
result = pthread_mutex_lock(resource_mutex);
// handle errors ...
while (resources_available < resources_wanted) {
result = pthread_cond_wait(resource_cv, resource_mutex);
// handle errors ...
}
resources_available -= resources_wanted;
result = pthread_mutex_unlock(resource_mutex);
// ...
}
int release_resources(unsigned resources_released) {
int result;
// ...
result = pthread_mutex_lock(resource_mutex);
// handle errors ...
resources_available += resources_released;
result = pthread_cond_broadcast(resource_cv);
// handle errors ...
result = pthread_mutex_unlock(resource_mutex);
// ...
}
I have an issue in my use of critical sections. My app has a large number of threads, say 60, which all need access to a global resource. I therefore protect that resource with a critical section. This works perfectly during operation, however when my application shuts down, I trigger the threads to quit, and then destroy the critical section.
The problem comes if some of those threads are waiting on the critical section at exit time, and thus are blocked from quitting themselves.
I've written a wrapper around the windows CriticalSection calls that has an 'Initialised' flag, which I set to true when the crit is created, and set to false when I'm about to leave the crit (both cases are set when inside the crit). This flag is checked before the 'enter crit' wrapper function tries entering the crit, bypassing the request if the flag is false. The flag is also checked the moment any thread successfully enters the crit, making it immediately leave the crit if it's false.
What I to do prior to deleting the crit is set the flag to false, then wait for any waiting threads to: be allowed into the crit; see the Initialised flag is false; then leave the crit (which should be a pretty quick operating for each thread).
I check the number of threads waiting for access to the crit by checking the LockCount inside the CRITICAL_SECTION struct, and waiting until it hits 0 (in XP, that's LockCount - (RecursionCount-1); in 2003 server and above, the lock count is ((-1) - (LockCount)) >> 2), before I then destroy the critical section.
This should be sufficient, however I'm finding that the LockCount reaches 0 when there's still one thread (always just one thread, never more) waiting to enter the crit, meaning if I delete the crit at that point, the other thread subsequently wakes up from waiting on the crit, and causes a crash as the CRITICAL_SECTION object has by that time been destroyed.
If I keep my own internal lock count of threads waiting for access, I have the correct count; however this isn't ideal as I have to increment this count outside of the crit, meaning that value isn't protected and therefore can't be entirely relied upon at any one time.
Does anyone know why the LockCount in the CRITICAL_SECTION struct would be out by 1? If I use my own lock count, then check the CRITICAL_SECTION's lock count after that last thread has exited (and before I destroy the crit), it's still 0...
Or, is there a better way for me to protect the global resource in my app with that many threads, other than a critical section?
This is my wrapper struct:
typedef struct MY_CRIT {
BOOL Initialised;
CRITICAL_SECTION Crit;
int MyLockCount;
}
Here's my Crit init function:
BOOL InitCrit( MY_CRIT *pCrit )
{
if (pCrit)
{
InitializeCriticalSection( &pCrit->Crit );
pCrit->Initialised = TRUE;
pCrit->MyLockCount = 0;
return TRUE;
}
// else invalid pointer
else
return FALSE;
}
This is my enter crit wrapper function:
BOOL EnterCrit( MY_CRIT *pCrit )
{
// if pointer valid, and the crit is initialised
if (pCrit && pCrit->Initialised)
{
pCrit->MyLockCount++;
EnterCriticalSection( &pCrit->Crit );
pCrit->MyLockCount--;
// if still initialised
if (pCrit->Initialised)
{
return TRUE;
}
// else someone's trying to close this crit - jump out now!
else
{
LeaveCriticalSection( &pCrit->Crit );
return FALSE;
}
}
else // crit pointer is null
return FALSE;
}
And here's my FreeCrit wrapper function:
void FreeCrit( MY_CRIT *pCrit )
{
LONG WaitingCount = 0;
if (pCrit && (pCrit->Initialised))
{
// set Initialised to FALSE to stop any more threads trying to get in from now on:
EnterCriticalSection( &pCrit->Crit );
pCrit->Initialised = FALSE;
LeaveCriticalSection( &pCrit->Crit );
// loop until all waiting threads have gained access and finished:
do {
EnterCriticalSection( &pCrit->Crit );
// check if any threads are still waiting to enter:
// Windows XP and below:
if (IsWindowsXPOrBelow())
{
if ((pCrit->Crit.LockCount > 0) && ((pCrit->Crit.RecursionCount - 1) >= 0))
WaitingCount = pCrit->Crit.LockCount - (pCrit->Crit.RecursionCount - 1);
else
WaitingCount = 0;
}
// Windows 2003 Server and above:
else
{
WaitingCount = ((-1) - (pCrit->Crit.LockCount)) >> 2;
}
// hack: if our own lock count is higher, use that:
WaitingCount = max( WaitingCount, pCrit->MyLockCount );
// if some threads are still waiting, leave the crit and sleep a bit, to give them a chance to enter & exit:
if (WaitingCount > 0)
{
LeaveCriticalSection( &pCrit->Crit );
// don't hog the processor:
Sleep( 1 );
}
// when no other threads are waiting to enter, we can safely delete the crit (and leave the loop):
else
{
DeleteCriticalSection( &pCrit->Crit );
}
} while (WaitingCount > 0);
}
}
You are responsible to make sure that CS is not in use any longer before destroying it. Let us say that no other thread is currently trying to enter, but there is a chance that it is going to attempt very soon. Now you destroy the CS, what this concurrent thread is going to do? At its full pace it hits deleted critical section causing memory access violation?
The actual solution depends on your current app design, but if you are destroying threads, then you will perhaps want to flag your request to stop those threads, and then wait on theit handles to wait for their destruction. And then complete with deleting critical section when you are sure that threads are done.
Note that it is unsafe to rely on CS member values such as .LockCount, and having done things right way you will prehaps not even need thing like IsWindowsXPOrBelow. Critical section API suggest that you use CRITICAL_SECTION structure as "black box" leaving the internals to be implementation specific.
I've got a producer and a consumer. The producer writes fixed size items on a given shared memory area, and the consumer retrieves them.
The producer can be noticeably slower or faster than the consumer, randomly.
What we want is that
If the producer is running faster than the consumer, when it fills the circular buffer, it keeps writing on the oldest frames (other than the one that the consumer is consuming, of course - I stress this point, producer and consumer must be synchronized in the solution, because they are unrelated processes).
If, instead, the consumer is faster than the producer, it must wait for a new frame and consume it when it's there.
I found implementations of producer/consumers with circular buffers, but only ones that didn't respect the first request (ie, if the circular buffer is full, they wait for the consumer to finish, while what I want is to overwrite the oldest frames).
I'd prefer not to roll my own (prone to bugs) solution, but use a pre-canned, tested one. Can someone point me to a good C implementation? (C++ is also ok).
Many thanks.
Basically when the consumers are slow, it means that no one is using the buffer, so there is no difference between dropping the new frames and overriding the old frames. So maybe the following code can help. The producerRTLock cannot lock the buffer because there are consumers using the bufffer and therefore at the application level you can indicate to drop the frames.
class SampleSynchronizer {
mutex mux;
condition_variable con_cond;
unsigned int con_num;
condition_variable pro_cond;
bool prod;
public:
SampleSynchronizer(): con_num(0), prod(false) {
}
void consumerLock() {
unique_lock<mutex> locker(mux);
while(prod)
pro_cond.wait(locker);
con_num++;
}
void consumerUnlock() {
lock_guard<mutex> locker(mux);
con_num--;
con_cond.notify_one();
}
void producerLock() {
unique_lock<mutex> locker(mux);
while(con_num > 0)
con_cond.wait(locker);
prod = true;
}
bool producerRTLock() {
lock_guard<mutex> locker(mux);
if(con_num > 0)
return false;
prod = true;
return true;
}
void producerUnlock() {
lock_guard<mutex> locker(mux);
prod = false;
pro_cond.notify_all();
}
};