On linux, when I use a mutex and try to lock it (pthread_mutex_lock), it
waits forever with no timeout. I could use an error checking mutex, so the
lock return immidiately, but then the timeout for 100 msec (which is
required) is difficult to accomplish. A trylock would have the same problem.
I would not fancy the idea of using trylock and sleep in an loop either,
because data can also be realtime data, and a sleep might cause actual data
to be missed.
Any more thoughts on how i should implement this on linux?
Since mutex's are for mutual exclusion of a code segment, and it sounds
that this is not what you are doing. On the timeout, do you do your code
anyway, or just not do it at all. The former would be disasterous unless
its not a non-reentrant piece of code, in which case you don't need the
mutex at all. The later, would be more understandable.
What are you waiting on? Could you use some sort of named pipe instead.
That way you can read with a select statement which gives you a timeout
if nothing arrives. But then this may have other side effects. Just
a thought.
-- Steve
My first idea would be using a portable framework. The second idea would be
to think about my design. If I need a mutex to do some synchronized stuff,
I just _need_ the mutex. There's nothing else to do, so its no problem to
wait. If there's other work to do, why isn't there another thread which
does this work? If you serialize some parallel jobs into one thread - why
are you using threads? Your thread is waiting for the lock _and_ for
realtime data. It sounds like there should be two threads for this job...
Mathias
pls mind the f'up
Use the GNAT Ada compiler on your Linux system. It has these facilities
built in at a high level of abstraction.
If you want to create a "mutex" locked area of memory using GNAT you
will simply create a "protected object". You can then conditionally call an
entry for that selected object.
See the following code for an example.
protected Buffer is
entry Put(Item : in Integer);
entry Get(Item : out Integer);
private
Internal : Integer;
Is_New : Boolean := False;
end Buffer;
protected body Buffer is
entry Put(Item : in Integer) when not Is_New is
begin
Internal := Item;
Is_New := True;
end Put;
entry Get(Item : out Integer) when Is_New is
begin
Item := Internal;
Is_New := False;
end Get;
end Buffer;
task Writer is
end Writer;
task body Writer is
begin
for My_Int in 1..10 loop
select
Buffer.Put(My_Int);
or
delay 0.01;
Ada.Text_IO.Put_Line(
"Perform processing in response to timeout here");
end select;
end loop;
end Writer;
In this very simple example I present two objects, a Buffer and a
Writer. The Buffer will block the writer on the if the Buffer contains
a value which has not yet been read. The first attempt to write to
the Buffer succeeds. The second attempt will block because
there is no reader.
The Writer task (a.k.a. thread) contains a loop which iterates
10 times. Each time through the iteration it attempts to write
to the Buffer. Each time it sets a timeout of 0.01 seconds.
If the timeout expires before the Put completes the Put is
abandonded and the string "Perform processing in response
to timeout here" is printed to standard output.
After all 10 iterations are complete the Writer completes.
One advantage of doing all this in Ada is that the source code
remains unchanged if you want to port the program to Win32,
Solaris, or a real time operating system. Simply recompile the
same source for the new target.
Jim Rogers
Linux is not an RTOS. Neither is Windows. I suspect the application isn't
really a realtime app, just some misguided logic. Well if you just want to
port the logic as is without fixing or changing it, I suppose there are packages
out there that will provide the function you want. They'll have additional
overhead and probably won't be hard realtime but I don't think those are really
issues here.
Joe Seigh
You might want to take a look at mutex-"watchdog" aka pthread_mutex_timedlock()
"ADVANCED REALTIME" function:
http://www.opengroup.org/onlinepubs/007904975/functions/pthread_mutex_timedlock.html
regards,
alexander.
--
"IBM n. A computer company - reputedly Microsoft's biggest customer.
Supposedly abbreviations for I've Been Moved, I've Been Misled,
Insert Bug under Mask, and International Brotherhood of Mechanics.
It really stands for "I Buy Microsoft"." -<http://tinyurl.com/3ecv>
Regards,
Volodymyr.
you need a mutex and a condition variable to simulate the windows
mutex (a windows mutex is not really a mutex)
what is needed:
pthread_mutex_t mutex;
pthread_cond_t lockAvailable;
int nestingLevel;
pthread_t owner;
in my case impl holds the stuff. (this is a c-ifyed version
of c++ code)
initilalizing:
pthread_mutex_init(&impl->mutex, NULL);
pthread_cond_init(&impl->lockAvailable, NULL);
impl->nestingLevel = 0;
impl->owner = 0;
deleting:
pthread_mutex_destroy(&impl->mutex);
pthread_cond_destroy(&impl->lockAvailable);
timed lock:
pthread_t current = pthread_self();
// Acquire the guard.
pthread_mutex_lock(&impl->mutex);
// If there's no contention, just grab the lock immediately.
// || If we already own the lock, then increment the nesting level.
if (impl->nestingLevel == 0 || current == impl->owner)
{
impl->owner = current;
impl->nestingLevel++;
pthread_mutex_unlock(&impl->mutex);
return true;
}
if (time == 0)
{
pthread_mutex_unlock(&impl->mutex);
return false;
}
// Wait until the nesting level has dropped to zero, at
// which point we can acquire the lock.
struct timeval now;
struct timespec timeout;
gettimeofday(&now, NULL);
uint usec = (time % 1000)*1000 + now.tv_usec;
timeout.tv_sec = now.tv_sec + time/1000 + usec/1000000;
timeout.tv_nsec = (usec % 1000000)*1000;
while (impl->nestingLevel > 0)
{
int result = pthread_cond_timedwait(&impl->lockAvailable,
&impl->mutex, &timeout);
if (result == ETIMEDOUT)
{
pthread_mutex_unlock(&impl->mutex);
return false; // timeout occured
}
}
// now acquire the lock (the lock on the data is still held)
impl->owner = current;
impl->nestingLevel = 1;
pthread_mutex_unlock(&impl->mutex);
return true;
unlock:
// Acquire the guard.
pthread_mutex_lock(&impl->mutex);
impl->nestingLevel--;
if (impl->nestingLevel == 0)
{
// Inform a waiter that the lock is free.
if (pthread_cond_signal(&impl->lockAvailable) == -1)
{
// error has occured
}
}
pthread_mutex_unlock(&impl->mutex);
Jochen Wilhelmy wrote:
>
> > I am porting a program from Windows to Linux.
> > In windows, the function WaitForSingleObject, waits for a mutex to be set
> > for a certain time (100 msec)
> > If this does not happen it returns.
>
> you need a mutex and a condition variable to simulate the windows
> mutex (a windows mutex is not really a mutex)
>
> what is needed:
>
> pthread_mutex_t mutex;
> pthread_cond_t lockAvailable;
> int nestingLevel;
> pthread_t owner;
>
> in my case impl holds the stuff. (this is a c-ifyed version
> of c++ code)
>
<snip>
> int result = pthread_cond_timedwait(&impl->lockAvailable,
> &impl->mutex, &timeout);
>
> if (result == ETIMEDOUT)
> {
> pthread_mutex_unlock(&impl->mutex);
> return false; // timeout occured
> }
> }
>
<snip>
It's not clear from the documentation for pthread_cond_timedwait that a
thread getting ETIMEDOUT couldn't be the one that was unblocked by
pthread_cond_signal. I'd be inclined to do a pthread_cond_signal here
just to be on the safe side.
Joe Seigh
Me too.
regards,
alexander.
--
"mainframe n. An obsolete device still used by thousands of obsolete
companies serving billions of obsolete customers and making huge
obsolete profits for their obsolete shareholders. And this year's
run twice as fast as last year's." -<http://tinyurl.com/3ecv>
--
Vennlig hilsen/Best Regards
Nils Olav Selåsdal
System Engineer
UtelSystems a/s