Using two semaphores in one method - c

I'm stuck on this assignment and I just can't get my head around it.
Let's say there's a queue of visitors waiting to get into one of the cars which are also queued. Only one car at a time is supposed to drive up to the platform to pick up 2 waiting people. As soon as 2 visitors enter the car it has to leave the platform.
I need to change the following methods "carArrives()" and "visitorArrives()" from Busy - Waiting to using either only Mutex or Semaphores.
Sorry for any mistakes.
int availableCars = 0;
int availableSeats = 0;
void carArrives(){
while(availableCars > 0){noop;} //exchange this with Mutex/Semaphore
availableCars = 1;
driveToPlatform();
openDoors();
availableSeats = 2;
while(availableSeats > 0){noop;} //exchange this with Mutex/Semaphore
closeDoors();
leavePlatform();
availableCars = 0;
}
void visitorArrives(){
while(availableSeats < 1){noop;} //exchange this with Mutex/Semaphore
enterCar();
availableSeats = availableSeats - 1;
}

if you generate a mutex:
pthread_mutex MyMutex = PTHREAD_MUTEX_INIT;
Then to stop any other part of the program from modifying some resource while the current thread is modifying/accessing the resource:
pthread_mutex_lock( &MyMutex );
// modify or access resource here
pthread_mutex_unlock( &MyMutex );
Note: to be effective, all places in the code that access that resource must use the same 'MyMutex'
regarding:
availableSeats = 2;
while(availableSeats > 0){noop;}
Suggest between locking a mutex for that same resource, to pause a bit, while not locked, to allow some other thread some time to modify the 'availableSeats' value. For instance:
pthread_mutex SeatsFilled = PTHREAD_MUTEX_INIT;
...
pthread_mutex_lock( &SeatsFilled );
availableSeats = 2;
pthread_mutex_unlock( &SeatsFilled );
...
do
{
int numSeats;
pthread_mutex_lock( &SeatsFilled );
numSeats = availableSeats;
pthread_mutex_unlock( &SeatsFilled );
if( !numSeats )
{
nanosleep( 1000 );
}
} while( numSeats );
...

Related

Thread don't terminate their job

I am writing a concurrent C program where I want to wait for all threads to finish in the main().
Based on this solution, I wrote the following code in main():
// Create threads
pthread_t cid[num_mappers];
int t_iter;
for (t_iter = 0; t_iter < num_mappers; t_iter++){
pthread_create(&(cid[t_iter]), NULL, &map_consumer, NULL);
}
// Wait for all threads to finish
for (t_iter = 0; t_iter < num_mappers; t_iter++){
printf("Joining %d\n", t_iter);
int result = pthread_join(cid[t_iter], NULL);
}
printf("Done mapping.\n");
The function passed into threads is defined as:
// Consumer function for mapping phase
void *map_consumer(void *arg){
while (1){
pthread_mutex_lock(&g_lock);
if (g_cur >= g_numfull){
// No works to do, just quit
return NULL;
}
// Get the file name
char *filename = g_job_queue[g_cur];
g_cur++;
pthread_mutex_unlock(&g_lock);
// Do the mapping
printf("%s\n", filename);
g_map(filename);
}
}
The threads are all successfully created and executed, but the join loop will never finish if num_mappers >= 2.
You return without unlocking the mutex:
pthread_mutex_lock(&g_lock);
if (g_cur >= g_numfull){
// No works to do, just quit
return NULL; <-- mutex is still locked here
}
// Get the file name
char *filename = g_job_queue[g_cur];
g_cur++;
pthread_mutex_unlock(&g_lock);
So only one thread ever returns and ends - the first one, but since it never unlocks the mutex, the other threads remain blocked.
You need something more like
pthread_mutex_lock(&g_lock);
if (g_cur >= g_numfull){
// No works to do, just quit
pthread_mutex_unlock(&g_lock);
return NULL;
}
// Get the file name
char *filename = g_job_queue[g_cur];
g_cur++;
pthread_mutex_unlock(&g_lock);

Why does my multi-threaded program blocks sometimes?

We have to write a program, which has 2 threads. One of them reads the content token by token and stores them into a array. The other reads the tokens from the array and writes it into a file.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define MAX 10
int buffer[MAX];
int buf_pos; // the actual position of the buffer
void copy();
int flag; // if flag is 0, the whole content of the file was read
FILE *source;
FILE *dest;
// read the content of a file token by token and stores it into a buffer
void *read_from_file();
// write the content of a buffer token by token into a file
void *write_to_file();
pthread_cond_t condition = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex;
int main( int argc, char *argv[] )
{
flag = 1;
pthread_t writer;
pthread_t reader;
pthread_mutex_init( &mutex, NULL );
if( argc != 3 )
{
printf( "Error\n" );
exit( EXIT_FAILURE );
}
source = fopen( argv[1], "r" );
dest = fopen( argv[2], "w" );
if( source == NULL || dest == NULL )
{
printf( "Error\n" );
exit( EXIT_FAILURE );
}
pthread_create( &reader, NULL, read_from_file, NULL );
pthread_create( &writer, NULL, write_to_file, NULL );
pthread_join( reader, NULL );
pthread_join( writer, NULL );
}
void *read_from_file()
{
int c;
while( ( c = getc( source ) ) != EOF )
{
if( buf_pos < MAX - 1 ) // the buffer is not full
{
pthread_mutex_lock( &mutex );
buffer[buf_pos++] = c;
pthread_mutex_unlock( &mutex );
pthread_cond_signal( &condition );
}
else
{
buffer[buf_pos++] = c; // store the last token
pthread_mutex_lock( &mutex );
pthread_cond_wait( &condition, &mutex ); // wait until the other thread sends a signal
pthread_mutex_unlock( &mutex );
}
}
flag = 0; // EOF
return NULL;
}
void *write_to_file()
{
int c;
while( flag || buf_pos > 0 )
{
if( buf_pos > 0 ) // The buffer is not empty
{
fputc( buffer[0], dest ); // write the first token into file
pthread_mutex_lock( &mutex );
copy();
--buf_pos;
pthread_mutex_unlock( &mutex );
pthread_cond_signal( &condition );
}
else
{
pthread_mutex_lock( &mutex );
pthread_cond_wait( &condition, &mutex );
pthread_mutex_unlock( &mutex );
}
}
return NULL;
}
void copy()
{
int i = 0;
for( ; i < buf_pos - 1; ++i )
buffer[i] = buffer[i + 1];
}
If I want to run the program, it sometimes blocks, but i do not know why. But if the program terminates, the outputfile is the same as the inputfile.
Can somebody explain me, why this could happen?
There are a number of problems with the code, but the reason for your lockups is most probably that you send out signals without the mutex locked, and without checking your condition with the mutex locked. Both are necessary to make sure that you don't end up with lost signals.
As noted by Useless, make sure that you know what your shared variables are, and that they are mutex-protected where necessary. For instance, your buf_pos is modified without protection in your reader thread, and used as a condition for waiting without mutex-protection in both threads.
Also, when doing pthread_cond_wait, you typically want a guard-expression to make sure you don't react to socalled spurios wakeups (have a look at the "Condition Wait Semantics" section at http://linux.die.net/man/3/pthread_cond_wait), and to make sure that the condition you're waiting for hasn't actually happened between testing for it, and starting the wait.
For instance, in your writer thread you could do:
pthread_mutex_lock(&mutex);
while(buf_pos == 0) pthread_cond_wait(&condition, &mutex);
pthread_mutex_unlock(&mutex);
But still, have a thorough look at your program, identify your shared variables, and make sure that they are mutex-protected where necessary. Also, it's far from correct that you only need to mutex-protect shared data for write access. In some cases you can get away with removing the mutex-protection when reading shared variables, but you'll have to analyze your code to make sure that that's actually the case.
Your problem with the deadlock is that you have both threads do this:
pthread_mutex_lock( &mutex );
pthread_cond_wait( &condition, &mutex );
pthread_mutex_unlock( &mutex );
on the same mutex, and the same condition variable. Suppose your reading thread executes those three lines immediately before your writing thread does. They're both going to be waiting on the same condition variable forever. Remember, signaling a condition variable does nothing if there are no threads actually waiting on it at the time. Right now you only avoid deadlock when one of your threads waits on that variable if, by chance, it happens to signal it before waiting for it itself.
Sonicwave's answer does a good job of identifying the other problems in your code, but in general you're not being careful enough about protecting your shared data, and you're not using condition variables properly so your threads are not properly synchronizing with each other. Among other things, if one of your threads is waiting on a condition variable, you need to make sure that there are no circumstances in which the other thread can wait on the same or different one before the other one receives a signal and wakes up.

pthread_cancel always crashes

I have a program that is trying to use create and cancel through an implemented pool.
The creation is as follows:
while (created<threadsNum){
pthread_t newThread;
pthread_struct *st; //Open the thread that handle the deleting of the sessions timeout.
st = (pthread_struct*)malloc(sizeof(pthread_struct));
st->id = created;
st->t = &newThread;
pthread_mutex_lock( &mutex_threadsPool );
readingThreadsPool[created] = st;
pthread_mutex_unlock( &mutex_threadsPool );
if((threadRes1 = pthread_create( &newThread, NULL, pcapReadingThread, (void*)created)))
{
syslog(LOG_CRIT, "Creating Pcap-Reading Thread %d failed.",created);
printf( "Creating Pcap-Reading Thread %d failed.\n",created);
exit(1);
}
syslog(LOG_INFO, "Created Pcap-Reading Thread %d Successfully.",created);
created++;
}
Later I try to cancel them and restart them :
pthread_t* t;
pthread_struct* tstr;
int i;
pthread_mutex_unlock( &mutex_threadsPool );
//first go on array and kill all threads
for(i = 0; i<threadsNum ; i++ ){
tstr = readingThreadsPool[i];
if (tstr!=NULL){
t = tstr->t;
//Reaches here :-)
if (pthread_cancel(*t)!=0){
perror("ERROR : Could not kill thread");
}
else{
printf("Killed Thread %d \n",i);
}
//doesnt reach here
}
}
I checked the addresses in the memory of the created thread in part one and the address of the about to be cancelled thread in the second part..they match..
I read about the thread manager that can't work if one calls killall().
But I don't..
Anyone have any idea?
Thanks
while (created<threadsNum){
pthread_t newThread;
pthread_struct *st;
/* ... */
st->t = &newThread;
/* ... */
}
You've got st->t pointing to a local variable newThread. newThread is only in scope during the current loop iteration. After this iteration st->t will contain an invalid address.
newThread is on the stack, so after it goes out of scope that stack space will be used for other variables. That could be different pthread_ts on successive iterations, or once the loop is over then that stack space will be used for completely different types of values.
To fix this I'd probably change pthread_struct.t to be a pthread_t instead of a pthread_t *, and then change the pthread_create call to:
pthread_create(&st->t, /*...*/)
Also, you should be careful about adding st to the thread pool before you've called pthread_create. It should probably be added after. As it stands, there's a small window where st->t is on the thread pool but has not been initialized.

Measuring efficiency of Mutex and Busy waiting

The program is to create several threads where each thread increments a shared variable by 10000 using a for loop that increments it by 1 in every iteration. Both mutex lock and spin lock (busy waiting) versions are required. According to what I've learned, mutex version should work faster than spin lock. But what I implemented gave me an opposite answer...
This is the inplementation of each thread in the mutex version:
void *incr(void *tid)
{
int i;
for(i = 0; i < 10000; i++)
{
pthread_mutex_lock(&the_mutex); //Grab the lock
sharedVar++; //Increment the shared variable
pthread_mutex_unlock(&the_mutex); //Release the lock
}
pthread_exit(0);
}
And this is the implementation in the spin lock version:
void *incr(void *tid)
{
int i;
for(i = 0; i < 10000; i++)
{
enter_region((int)tid); //Grab the lock
sharedVar++; //Increment the shared variable
leave_region((int)tid); //Release the lock
}
pthread_exit(0);
}
void enter_region(int tid)
{
interested[tid] = true; //Show this thread is interested
turn = tid; //Set flag
while(turn == tid && other_interested(tid)); //Busy waiting
}
bool other_interested(int tid) //interested[] is initialized to all false
{
int i;
for(i = 0; i < tNumber; i++)
if(i != tid)
if(interested[i] == true) //There are other threads that are interested
return true;
return false;
}
void leave_region(int tid)
{
interested[tid] = false; //Depart from critical region
}
I also iterated the process of threads creating and running for hundreds of times to make sure the execution time can be distinguished.
For example, if tNumber is 4, and I iterated the program for 1000 times, mutex will take me 2.22 sec, and spin lock will take me 1.35 sec. The difference grows as tNumber increases. Why is this happening? Is my code wrong?
The code between enter_region and leave_region is not protected.
You can prove this by making it more complicated to ensure that it will trip itself up.
Create an array of bools (check) of length 10000 set up false. Make the code between enter and leave:
if (check[sharedVar]) cout << "ERROR" << endl;
else check[sharedVar++] = true;
The "difference" in speed is that you are implementing synchronization using
interested[tid] = true; //Show this thread is interested
turn = tid; //Set flag
while(turn == tid && other_interested(tid));
which are sequential operations. Any thread can be preempted while he is doing that, and the next thread read an erroneous state.
It need to be done atomically, by implementing either a compare-and-swap or a test-and-set. These instructions are usually provided by the hardware.
For eg on x86 you have xchg, cmpxchg/cmpxchg8b, xadd
Your test could be rewritten as
while( compare_and_swap_atomic(myid,id_meaning_it_is_free) == false);
The issue is that atomicity is expensive .

Thread Monitoring in c using heartbeat signals

I want to monitor threads. I used condition variables for send & receive HeartBeat & Acknowlagement signals for that.
scnMonitor_t is a monitor structure. As new threads are added it register with monitor & added to scnThreadlist_t.
monitorHeartbeatCheck is the thread that starts with program,
monitorHeartbeatProcess is API which are added to all thread functions.
Actually my problem is that the index of process is not properly followed
It ends with a wait HB condition for 3rd Thread & dead-lock is created.
what should be the problem?
thanks in advance.
typedef struct scnThreadList_{
osiThread_t thread;
struct scnThreadList_ *next;
} scnThreadList_t;
typedef struct scnMonitor_{
bool started;
osiThread_t heartbeatThread;
osiMutex_t heartbeatMutex;
osiMutex_t ackMutex;
osiCond_t heartbeatCond;
scnThreadList_t *threads;
} scnMonitor_t;
static scnMonitor_t *s_monitor = NULL;
// Main heartbeat check thread
void* monitorHeartbeatCheck( void *handle )
{
scnThreadList_t *pObj = NULL;
static int idx = 0;
static bool waitAck = false;
while ( 1 ) {
pObj = s_monitor->threads;
while ( pObj && ( pObj != s_monitor->heartbeatThread ) ) { //skip it-self from monitoring.
++idx;
printf("\"HB Check No.%d\"\n",idx);
// send heartbeat
usleep( 250 * 1000 );
pthread_mutex_lock( s_monitor->heartbeatMutex, 1 );
pthread_cond_signal( s_monitor->heartbeatCond );
printf("-->C %d HB sent\n",idx);
pthread_mutex_unlock( s_monitor->heartbeatMutex );
// wait for ACK
while( !waitAck ){
pthread_mutex_lock( s_monitor->ackMutex, 1 );
printf("|| C %d wait Ack\n",idx);
waitAck = true;
pthread_cond_wait( s_monitor->heartbeatCond, s_monitor->ackMutex );
waitAck = false;
printf("<--C %d received Ack\n",idx);
pthread_mutex_unlock( s_monitor->ackMutex );
LOG_INFO( SCN_MONITOR, "ACK from thread %p \n", pObj->thread );
}
pObj = pObj->next;
}
} // while, infinite
return NULL;
}
// Waits for hearbeat and acknowledges
// Call this API from every thread function that are registered
int monitorHeartbeatProcess( void )
{
static int id = 0;
static bool waitHb = false;
++ id;
printf("\"HB Process No.%d\"\n",id);
// wait for HB
while(!waitHb){
pthread_mutex_lock( s_monitor->heartbeatMutex, 1 );
printf("|| P %d wait for HB\n",id);
waitHb = true;
pthread_cond_wait( s_monitor->heartbeatCond, s_monitor->heartbeatMutex );
waitHb = false;
printf("<--P %d HB received \n",id);
pthread_mutex_unlock( s_monitor->heartbeatMutex );
}
// send ACK
uleep( 250 * 1000 );
pthread_mutex_lock( s_monitor->ackMutex, 1 );
pthread_cond_signal( s_monitor->heartbeatCond );
printf("-->P %d ACK sent\n",id);
pthread_mutex_unlock( s_monitor->ackMutex );
return 1;
}
You should always associate only one mutex with a condition at a time. Using two different mutexes with the same condition at the same time could lead to unpredictable serialization issues in your application.
http://publib.boulder.ibm.com/infocenter/iseries/v5r4/index.jsp?topic=%2Fapis%2Fusers_78.htm
You have 2 different mutexes with your condition heartbeatCond.
I think you are experiencing a deadlock here. The thread calling monitorHeartbeatProcess() takes mutex on heartbeatMutex and waits for signal on the condition variable, heartbeatCond. While thread calling monitorHeartbeatCheck() takes mutex on ackMutex and waits for sognal on condition variable, heartbeatCond. Thus both threads waits on the condition variable heartbeatCond causing deadlock. If you are so particular in using two mutexes, why not two condition variables?

Resources