blob: 513cce23bb863c29148b9e7c30d23cde3d53a4c5 [file] [log] [blame]
// umlrtmutex.cc
/*******************************************************************************
* Copyright (c) 2014-2015 Zeligsoft (2009) Limited and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
#include <errno.h>
#include <time.h>
#include "basefatal.hh"
#include "umlrtmutex.hh"
#include "umlrttimespec.hh"
// UMLRTMutex is platform-independent mutual-exclusion.
// Bug 32 tracks the move of this implementation to +/os/linux/osmutex.cc
UMLRTMutex::UMLRTMutex() : guard(), condition(), locked(false)
{
pthread_mutex_init(&guard, NULL);
pthread_cond_init(&condition, NULL);
}
UMLRTMutex::~UMLRTMutex()
{
pthread_mutex_destroy(&guard);
pthread_cond_destroy(&condition);
}
// Wait forever for mutex.
void UMLRTMutex::take()
{
UMLRTMutexGuard g(guard);
while (locked)
{
pthread_cond_wait(&condition, &guard);
}
locked = true;
}
// Timed - returns non-zero for success, zero for timeout.
#if (((__GNUC__ * 100) + __GNUC_MINOR__) >= 406)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
bool UMLRTMutex::take( uint32_t msec )
{
struct timespec timeout;
UMLRTTimespec::timespecAbsAddMsec( &timeout, msec );
UMLRTMutexGuard g(guard);
while (locked)
{
if (pthread_cond_timedwait(&condition, &guard, &timeout) != 0)
{
int errno_ = errno;
if (errno_ != ETIMEDOUT)
{
FATAL_ERRNO("pthread_cond_timedwait");
}
return false; // Timed out - return error indication.
}
}
locked = true;
return true; // Obtained lock within timeout.
}
#if (((__GNUC__ * 100) + __GNUC_MINOR__) >= 406)
#pragma GCC diagnostic pop
#endif
// Give mutex back.
void UMLRTMutex::give()
{
UMLRTMutexGuard g(guard);
locked = false;
pthread_cond_signal(&condition);
}