Understanding code sbuf_remove(sbuf_t *sp) from book CSAPP? : issue for location of P(&sp->items) - c

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.

Related

Mutex Implementation in C

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.

Critical sections and shutdown / destruction?

I can't figure out what a proper shutdown procedure is when you have an object OBJ1 which contains a critical section CS and a pointer to another object OBJ2
Say you have two functions A and B.
A enters the critical section, modifies data in OBJ2 and leaves the critical section.
B is a shutdown/destruction procedure and is supposed to destroy everything (OBJ2, CS and OBJ1)
My question is :
How do you solve the scenario where A is waiting to enter the critical section because B already entered it? B will destroy everything. If the 'destruction' (for some funny reason) causes/allows A to enter the critical section, then A will generate an exception since it is trying access an object which no longer exists. If the 'destruction' doesn't cause A to enter the critical section, then A just hangs forever waiting to enter the critical section.
What is the proper way to destroy an instance of a class which contains a critical section and a pointer to an object?
To me it seems like the only solution is to have the critical section as a global variable while the data can be put in a "class" (structure)....but I don't like that solution!
The language I'm using is C. I know that you don't have classes in C. I have instances of structures.
Example:
typedef struct classX_t
{
CRITICAL_SECTION cs;
classY* thisY;
} classX;
typedef struct classY_t
{
int some_variable;
} classY;
I create an instance of X and an instance of Y. The variable 'thisY' points to the instance of Y. My two functions are:
void funcA(classX* thisClassX)
{
if (thisClassX == NULL) return;
EnterCriticalSection(thisClassX->cs);
thisClassX->thisY->some_variable++;
LeaveCriticalSection(thisClass->cs);
}
void funcB(classX* thisClassX)
{
if (thisClassX == NULL) return;
EnterCriticalSection(thisClassX->cs);
/* free stuff here */
free(thisClassX->thisY);
DeleteCriticalSection(thisClass->cs);
/* and destroy instance */
free(thisClassX)
}
If funcA is waiting to enter the critical section because B already entered the critical section, then I don't see how funcA can properly execute without causing problems. What is the solution to this?
EDIT:
Maybe I need some kind of "lock" count; i.e. a counter which increments by 1 when some code enters a critical section and decrements when the code leaves the critical section? If I had that, then the shutdown procedure could check the count to see if it is greater than 1 (indicating that some other code is waiting to enter the critical section) and if the count is > 1 then it could sleep until the count goes back down to 1. So here's what I'm suggesting:
Each function does this:
void someFunction(...)
{
if (thisClassX == NULL) return;
thisClassX->counter++;
EnterCriticalSection(thisClassX->cs);
/* do something */
LeaveCriticalSection(thisClassX->cs);
thisClassX->counter--;
}
What you can do is add a switch (an integer or whatever you prefer) which tells each function if it is still valid/ allowed to alter your OBJ.

Need for XEventsQueued(display, QueuedAfterReading) in XCB

I am migrating some code of CYBOI from Xlib to XCB.
CYBOI uses a couple of threads for different communication channels like:
serial_port, terminal, socket, x_window_system.
However, it uses these threads only for signal/event/data detection;
the actual receiving and sending is done in the main thread,
in order to avoid any multi-threading conflicts of address space.
For the x_window_system channel, I previously detected events in a thread:
int n = XEventsQueued(display, QueuedAfterReading);
Upon detection of an event, an "interrupt flag" was set.
Afterwards, the main thread was reading the actual event using:
XNextEvent(display, &event);
When no more events were available, the main thread stopped receiving events
and the x_window_system channel thread started listening with XEventsQueued again.
Now, I am migrating the code to X C Binding (XCB).
There is a blocking function "xcb_wait_for_event" which is fine for reading an event.
What I miss is some function "peeking ahead" if there are events pending,
WITHOUT actually returning/removing the event from the queue.
I was reading the web for a couple of hours now, but am not able to find such a function.
The "xcb_poll_for_event" does not help. Blocking is fine for me,
since my event detection runs in its own thread.
The "xcb_request_check" as third input function does not seem to be what I want.
Could somebody help me out?
Thanks,
Christian
Are you looking for xcb_poll_for_queued_event(xcb_connection_t *c) which returns the next event without reading from the connection?
First, thanks to Julien for his reply.
I have studied the XCB 1.9 sources and found out that the
"xcb_poll_for_queued_event" function is not what I need.
The functions "xcb_poll_for_event" and "xcb_poll_for_queued_event"
both call "poll_for_next_event".
The functions "poll_for_next_event" and "xcb_wait_for_event"
both call "get_event".
If "get_event" finds an event, it changes the internal
linked list to point to the next event. However, I would
prefer NOT to change the event queue AT ALL, independent
from whether or not events are available.
I therefore propose to add a function like the following to XCB:
void* NULL_POINTER = (void*) 0;
int xcb_test_for_event(xcb_connection_t* c) {
int r = 0;
if (c != NULL_POINTER) {
struct _xcb_in in = c->in;
struct event_list* l = in.events;
if (l != NULL_POINTER) {
xcb_generic_event_t* e = l->event;
if (e != NULL_POINTER) {
r = 1;
}
}
}
return r;
}
This would allow me to write an endless loop like:
while (!xcb_test_for_event(connection)) {
sleep(t);
}
This is comparable to the old Xlib function:
int n = XEventsQueued(d, QueuedAfterReading);
which just checked the number of events in the event queue.
The "XEventsQueued" function always returns immediately WITHOUT
input/output, if there are events already in the queue.
Thanks
Christian

Returning program to pre-triggered state

First this gets triggered:
if ((temperatureChannel[channelID].currentTemperature > temperatureChannel[channelID].highLimit) | (temperatureChannel[channelID].currentTemperature < temperatureChannel[channelID].lowLimit))
activateAlarm(channelID);
Activate alarm is triggered, then from there:
void activateAlarm(int channelID);
{ while (temperatureChannel[channelID].currentTemperature > temperatureChannel[channelID].highLimit || temperatureChannel[channelID].currentTemperature < temperatureChannel[channelID].lowLimit)
{
logSubsystem(temperatureChannel[channelID].currentTemperature);
}
}
Then alarm screen is triggered with following case:
int logSubsystem(int currentTemperature)
case 'F': //if user input is 'F'
case 'f': //if user input is 'f'
currentTemperature--;
printf("your current exceeded temp is %i\n \n", currentTemperature);
if (currentTemperature <= 100 || currentTemperature >= 50);
compareLimit();
break; //exits loop
How do I set up this function so that if the user decrements with F and gets the current temperature to below the limit (<100, or >50), then it will return back to the compareLimit function and the requirement for the high limit/low limit triggered state will be FALSE, returning the program to its original pre-alarm state?
I think you would benefit considerably from thinking a lot about how your program flows. Right now, what I can deduce of your program flow is:
You have an outer loop that checks the temperature, on at least one channel ID. Inside that loop, you have the if statement you first showed us.
Then activate alarm does some other stuff, but loops until the temperature goes down, calling logSubsystem.
logSubsystem then presumably gets some kind of user input, and from there, you want it to call to your initial function, presumably called prepare limit.
The problem with this is that none of these functions ever complete. They all call each other, and you'll eventually get a stack overflow. Nice, since that's the name of this site, but not something you want to aspire to.
What you basically need is a state machine. You need something that keeps track of values, looks at those values, and calls functions that return that operate on those values. There should only be one loop, and it should do all the control of what happens based on what those values are. The good news is, you have all of this in place already. temperatureChannel is keeping track of the values for you, and you have while loops a-plenty.
Let me give you my suggestion of the way I suggest your program should flow:
bool checkTemperatureValuesOutOfRange(int channelID) {
// this is just a convenience, to make the state machine flow easier.
return (temperatureChannel[channelID].currentTemperature > temperatureChannel[channelID].highLimit) || // note the || not just one |
(temperatureChannel[channelID].currentTemperature < temperatureChannel[channelID].lowLimit);
}
void actOnUserInput() {
char input = // ... something that gets a user input. It should check if any is available, otherwise return.
switch (input) {
case 'F':
case 'f':
temperatureChannel[channelID].currentTemperature--;
break; // This doesn't exit the loop - it gets you out of the switch statement
}
void activateAlarm(int channelID) {
// presumably this does something other than call logSubsystem?
// if that's all it does, just call it directly
// note - no loop here
logSubsystem(channelID);
}
void logSubsystem(int channelID) { // Not the current temperature - that's a local value, and you want to set the observed value
// I really think actOnUserInput should be (an early) part of the while loop below.
// It's just another input for the state machine, but I'll leave it here per your design
// Presumably actually logs things, too, otherwise it's an unnecessary function
actOnUserInput();
}
while (TRUE) { // this is the main loop of your function, and shouldn't exit unless the program does
// do anything else you need to - check other stuff
// maybe have a for loop going through different channelIDs?
if (checkTemperatureValuesOutOfRange(channelID)) {
activateAlarm(channelId);
// do anything else you need to
}
I'm sure you can see lots of differences between your code and mine. Here are some key things to consider:
All the functions now return. The master while loop calls functions that check status, and calls function that change status.
I would highly suggest acting on the user input as part of the master while loop. It's just another input to the state machine. Get it, act on it, and then check your statuses. You presumably need to have some input from the user, otherwise you'll never get in a bad state in the first place.
Right now, activate alarm happens every time. With the code you showed, that's fine - because logSubsystem was all that was being called. If you only want the alarm to ring once, keep a boolean tracker inside temperatureChannel[channelId] that says if the alarm rang, set it true within activateAlarm, and then reset it to false based on the return value of checkTemperatureValuesOutOfRange.
Rather than leaving yourself in the activateAlarm/logSubsystem area, you return each time, and check your values each time to see if you're still there. This is the key point - your functions should be fast, and not monopolize your processor. Make each function do just one sort of thing, and have all the control come from within the master loop.
I made a lot of changes to your code, and I don't know if you're allowed to make all of them, but you'll need something similar to this. It's much more robust, and gives you room to grow all around.

Problem with Array of Queues in FreeRTOS

I am building a FreeRTOS application. I created a module which registers a freeRTOS queue handle from another module and when an interrupt in this module module occurs, it sends a message to all the registered queues. But it seems I am able to send the message from the queue but not able to receive it at the other module.
Here is my code.
remote module:-
CanRxMsg RxMessage;
can_rx0_queue = xQueueCreate( 10, sizeof(CanRxMsg) ); // can_rx0_queue is globally defined
// Register my queue with can module
if (registerRxQueueWithCAN(can_rx0_queue) == -1)
{
TurnLedRed();
}
while(1)
{
if(can_rx0_queue){
while( xQueueReceive( can_rx0_queue, ( void * ) &RxMessage, portMAX_DELAY))
{
}
.....
Here is the registration module
#define MAX_NUMBER_OF_RX_QUEUES 2
//xQueueHandle rxQueueStore[MAX_NUMBER_OF_RX_QUEUES];
typedef struct QUEUE_REGISTRY_ITEM
{
// signed char *pcQueueName;
xQueueHandle xHandle;
} xQueueRegistryItem;
xQueueRegistryItem rxQueueStore[MAX_NUMBER_OF_RX_QUEUES];
int numberOfQueuesRegistered;
#define cError -1
#define cSuccess 0
void processInterrupt()
{
for(int i=0; i < numberOfQueuesRegistered; i++)
{
if(xQueueSendFromISR(rxQueueStore[i].xHandle,(void *) &RxMessage,&tmp) != pdTRUE)
TurnLedRed();
if(tmp)resched_needed = pdTRUE;
}
portEND_SWITCHING_ISR(resched_needed);
}
int registerRxQueueWithCAN(xQueueHandle myQueue)
{
if(numberOfQueuesRegistered == MAX_NUMBER_OF_RX_QUEUES)
{
// Over Flow of registerations
TurnLedRed();
return cError;
}else
{
rxQueueStore[numberOfQueuesRegistered].xHandle = myQueue;
numberOfQueuesRegistered++;
}
return cSuccess;
}
Few points:-
xQuehandle is typdefed to "void *"
The code works if remove the registration thing and just do with directly pointer of queue in xQueueSendFromISR if I take the pointer by extern.
Any advice or information required?
At first glance I cannot see anything obviously wrong. The problem might be outside of the code you have shown, like how is can_rx0_queue declared, how is the interrupt entered, which port are you using, etc.
There is a FreeRTOS support forum, linked to from the FreeRTOS home page http://www.FreeRTOS.org
Regards.
I think Richard is right. The problem could be issues that are not within your code that you have posted here.
Are you calling any form of suspension on the receiving Task that is waiting on the Queue? When you invoke a vTaskSuspend() on a Task that is blocked waiting on a Queue, the Task that is suspended will be moved to the pxSuspendedTaskList and it will "forget" that it is waiting on an Event Queue because the pvContainer of xEventListItem in that Task will be set to NULL.
You might want to check if your receiving Task is ever suspended while waiting on a Queue. Hope that helped. Cheers!
Your shared memory should at least be declared volatile:
volatile xQueueRegistryItem rxQueueStore[MAX_NUMBER_OF_RX_QUEUES] ;
volatile int numberOfQueuesRegistered ;
otherwise the compiler may optimise out read or writes to these because it has no concept of different threads of execution (between the ISR and the main thread).
Also I recall that some PIC C runtime start-up options do not apply zero-initialisation of static data in order to minimise start-up time, if you are using such a start-up, you should explicitly initialise numberOfQueuesRegistered. I would suggest that to do so would be a good idea in any case.
It is not clear from your code that RxMessage in the ISR is not the same as RxMessage in the 'remote module'; they should not be shared, since that would allow the ISR to potentially modify the data while the receiving thread was processing it. If they could be shared, there would ne no reason to have a queue in the first place, since shared memory and a semaphore would suffice.
As a side-note, there is never any need to cast a pointer to void*, and you should generally avoid doing so, since it will prevent the compiler from issuing an error if you were to pass something other than a pointer. The whole point of a void* is rather that it can accept any pointer type.

Resources