Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Mutexes must be global???

938 views
Skip to first unread message

Paul Calato

unread,
Sep 21, 1998, 3:00:00 AM9/21/98
to
On solaris 2.5.1 the man page for pthread_mutex_init says

"All mutexes must be global."

Is this really true or can they be allocated on the heap and then
initialized appropriately (for intra-process)?


Paul

P.S. I've include the first part of the man page below.

=====================================================================
mutex(3T) Threads Library mutex(3T)

NAME
mutex, pthread_mutex_init, pthread_mutex_lock,
pthread_mutex_trylock, pthread_mutex_unlock,
pthread_mutex_destroy, mutex_init, mutex_lock,
mutex_trylock, mutex_unlock, mutex_destroy - mutual exclu-
sion locks

SYNOPSIS
POSIX
cc [ flag ... ] file ... -lpthread [ library ... ]

#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mp,
const pthread_mutexattr_t *attr);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int pthread_mutex_lock(pthread_mutex_t *mp);
int pthread_mutex_trylock(pthread_mutex_t *mp);
int pthread_mutex_unlock(pthread_mutex_t *mp);
int pthread_mutex_destroy(pthread_mutex_t *mp);

Solaris
cc [ flag ... ] file ... -lthread [ library ... ]

#include <thread.h>
#include <synch.h>
int mutex_init(mutex_t *mp, int type, void * arg);
int mutex_lock(mutex_t *mp);
int mutex_trylock(mutex_t *mp);
int mutex_unlock(mutex_t *mp);
int mutex_destroy(mutex_t *mp);

MT-LEVEL
MT-Safe

DESCRIPTION
Mutual exclusion locks (mutexes) prevent multiple threads
from simultaneously executing critical sections of code
which access shared data (that is, mutexes are used to seri-
alize the execution of threads). All mutexes must be glo-
bal. A successful call for a mutex lock via
pthread_mutex_lock() or mutex_lock() will cause another
thread that is also trying to lock the same mutex to block
until the owner thread unlocks it via pthread_mutex_unlock()
or mutex_unlock(). Threads within the same process or
within other processes can share mutexes.

Dave Butenhof

unread,
Sep 22, 1998, 3:00:00 AM9/22/98
to
Paul Calato wrote:

> On solaris 2.5.1 the man page for pthread_mutex_init says
>
> "All mutexes must be global."
>
> Is this really true or can they be allocated on the heap and then
> initialized appropriately (for intra-process)?

What it means is that you cannot declare a stack-local ("automatic")
mutex and expect everything to work correctly. (Allocating any shared
data on a thread's stack is almost always a really bad idea. And, of
course, a mutex must be shared to have any purpose at all in existing.)

Yes, you can initialize a mutex out of heap storage, as well as
declaring it "extern" or "static" in any scope. You can't use static
initialization for heap mutexes; you always need to call
pthread_mutex_init().

/---------------------------[ Dave Butenhof ]--------------------------\
| Compaq Computer Corporation bute...@zko.dec.com |
| 110 Spit Brook Rd ZKO2-3/Q18 http://members.aol.com/drbutenhof |
| Nashua NH 03062-2698 http://www.awl.com/cseng/titles/0-201-63392-2/ |
\-----------------[ Better Living Through Concurrency ]----------------/


ld kelley (larry)

unread,
Sep 22, 1998, 3:00:00 AM9/22/98
to
Paul Calato wrote:
>
> On solaris 2.5.1 the man page for pthread_mutex_init says
>
> "All mutexes must be global."
>
> Is this really true or can they be allocated on the heap and then
> initialized appropriately (for intra-process)?
>
> Paul

Malloc'ed memory is global, the stack of each thread is not. Be sure
to destroy any mutex you use in malloced memory before you free that
block. Failure to do this will result in random segmentation faults
(very hard to find).

--
-larry

Larry D. Kelley: l...@ldkelley.com

"Great spirits have always encountered violent opposition
from mediocre minds." Albert Einstein.

finite_...@hotmail.com

unread,
Sep 22, 1998, 3:00:00 AM9/22/98
to
In article <3606B9B9...@cabletron.com>,

Paul Calato <cal...@cabletron.com> wrote:
> On solaris 2.5.1 the man page for pthread_mutex_init says
>
> "All mutexes must be global."
>
> Is this really true or can they be allocated on the heap and then
> initialized appropriately (for intra-process)?
> snip...

Paul,

Mutexes need not be global, but theu must exist for the entire duration of
the code/threads that use them. I routinely use mutexes as data members of
classes which are constructed and destructed as the programs work.

Darren Allen
Finite Automata, Inc.
10029 Hwy 92, Suite 100-103
Woodstock, Ga 30188

-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum

Mark Stead

unread,
Sep 23, 1998, 3:00:00 AM9/23/98
to
In article <6u8uh2$o...@espresso.cafe.net>, Kaz Kylheku <k...@cafe.net> wrote:
>In article <360784EF...@zko.dec.com>,
>Dave Butenhof <bute...@zko.dec.com> wrote:

>>Paul Calato wrote:
>>
>>> On solaris 2.5.1 the man page for pthread_mutex_init says
>>>
>>> "All mutexes must be global."
>>>
>>> Is this really true or can they be allocated on the heap and then
>>> initialized appropriately (for intra-process)?
>>
>>What it means is that you cannot declare a stack-local ("automatic")
>>mutex and expect everything to work correctly. (Allocating any shared

The pthread_create man page also says:
A newly created thread shares all of the calling process'
global data with the other threads in this process; however,
it has its own set of attributes and private execution
stack.

>I suspect that this strange restriction is perhaps particular to Solaris
>threads.

Now I am very sure that in Solaris 2.5 this restriction does not apply,
because we have objects created on the stack which are used by other
threads. But we are concerned all the same, for either portability
to other platforms - or for portability to a future Solaris version.

>>data on a thread's stack is almost always a really bad idea. And, of
>>course, a mutex must be shared to have any purpose at all in existing.)
>

>I don't see why this should be the case. It sounds like the mutex
>implementation is simply limited (or broken) in strange ways.

It is really nothing to do with mutexes, condition variables etc, it
is that Solaris (and probably POSIX) make no guarantee that the
contents of the stack of one thread will be readable and writable
by another thread. Worse still, thread stacks could be put at the
same virtual address but different physical addresses - and handled
by the MMU during thread context switches.

I expect that all this would rely on threads being done at the
kernel level - but because of the way that user level pthread threads
can be switched between kernel lwp's that even the lwp threads don't
have this problem (yet).

>I use mutexes embedded in class objects all the time, and make no
>qualms about defining local instances of this class, for example:

Neither did we, but I would prefer to avoid qualms now I am aware
of this problem.

The only solution I can see is:

- Provide your own stack to pthread_create which is
allocated on the heap (real global memory).

- Thread 1 (main) needs to pthread_create another thread
to actually call the application_main().

This of course introduces other complexities - like deciding on
the stack size for a thread, and how to deallocate the stack for
a thread that is terminating.


| // Mark Stead - ma...@unico.com.au |
| // Hofstadter's Law: "It always takes longer than you expect, |
| // even when you take into account Hofstadter's Law." |
| // Windows 95 : Busy or Unstable? Don't ask me, I run OS/2 |

Wolfram Gloger

unread,
Sep 23, 1998, 3:00:00 AM9/23/98
to
ma...@unico.com.au (Mark Stead) writes:

> The pthread_create man page also says:
> A newly created thread shares all of the calling process'
> global data with the other threads in this process; however,
> it has its own set of attributes and private execution
> stack.

That seems to contradict the POSIX specification (see below), but of
course it depends on what `private' really means.

> Now I am very sure that in Solaris 2.5 this restriction does not apply,
> because we have objects created on the stack which are used by other
> threads. But we are concerned all the same, for either portability
> to other platforms - or for portability to a future Solaris version.

Don't worry -- a _complete_ shared address space, even for the stack,
is guaranteed by POSIX threads. I think David Butenhof's advice in
this case was more one `should not' use mutexes on the stack rather
than `can not'.

> It is really nothing to do with mutexes, condition variables etc, it
> is that Solaris (and probably POSIX) make no guarantee that the
> contents of the stack of one thread will be readable and writable
> by another thread. Worse still, thread stacks could be put at the
> same virtual address but different physical addresses - and handled
> by the MMU during thread context switches.

Yes, this would be horrible -- also for performance.

Here is an old posting by Dave Butenhof which makes this issue
unambiguously clear:

--------------------------- begin quote ------------------------------
From: Dave Butenhof <bute...@zko.dec.com>
Subject: Re: thread's stack visibility.
Newsgroups: comp.programming.threads
Date: Mon, 13 Jan 1997 22:04:21 -0500
Message-ID: <32DAF7...@zko.dec.com>

Wolfram Gloger wrote:
> > By "Thread Private" are you implying something different?
>
> I meant `private' or `non-shared' in the sense of memory management,
> i.e. areas of the address space where the hardware pages are either
> set up to copy-on-write or completely separate between the different
> threads. Stacks, for example, _can_ be set up with private memory,
> but shouldn't, IMHO, for the performance reasons outlined in my other
> postings.

I've avoided any response to this long thread for a while because I'm
not sure I want to confuse the issue with facts. And, despite, the
facts, I like the idea of people learning to treat thread stacks "as if
they might be" private.

Nevertheless, at some time I thought it might be helpful to point out
what POSIX says about the matter... and I guess this is a good time.

POSIX very specifically disallows "non-shared" memory between threads.
That is, it requires that the address space is associated with the
PROCESS, not with the individual THREADS. All threads share a single
virtual address space, and no memory address is private. Stacks, in
particular, CANNOT be set up with private memory. Although, for safe
programming, you should almost always pretend that it's private.
------------------------------ end quote ------------------------------

Regards,
Wolfram.

Dave Butenhof

unread,
Sep 23, 1998, 3:00:00 AM9/23/98
to
Kaz Kylheku wrote:

> In article <360784EF...@zko.dec.com>,
> Dave Butenhof <bute...@zko.dec.com> wrote:
> >Paul Calato wrote:
> >
> >> On solaris 2.5.1 the man page for pthread_mutex_init says
> >>
> >> "All mutexes must be global."
> >>
> >> Is this really true or can they be allocated on the heap and then
> >> initialized appropriately (for intra-process)?
> >
> >What it means is that you cannot declare a stack-local ("automatic")
> >mutex and expect everything to work correctly. (Allocating any shared
>

> I suspect that this strange restriction is perhaps particular to Solaris
> threads.

Yes, it is. The only real point to my post was to clarify that "global" did not
exclude heap space. I "incidentally" commented on what the man page might mean,
and I probably shouldn't have bothered.

I've already stated and explained the POSIX rules many times, and I wasn't going
to do it "one more time". But... attempting to avoid redundancy in a newsgroup is
pointless and doomed to failure, so, here we go one more time yet again.

POSIX requires that all threads within a process share a fully common address
space. One is allowed to declare a pthread_mutex_t, or any other type, anywhere
within that address space. In particular, as has been pointed out, an
implementation cannot disallow allocating a mutex on a stack. However, as I
pointed out, it's a potentially dangerous thing to do, and rarely worth the risk.
If, through some coding error, you leave the scope of the mutex while another
thread has the address of the mutex, severe, unrecoverable, and extremely
difficult to diagnose memory corruption is highly likely to result.

Yeah, sure, a sufficiently careful program can get away with it. It's legal. (At
least, in POSIX threads.) So do it if you really, really need to, or if you
really like to dance in front of speeding cars on the highway. Otherwise, choose
a safer venue, OK?

> >data on a thread's stack is almost always a really bad idea. And, of
> >course, a mutex must be shared to have any purpose at all in existing.)
>
> I don't see why this should be the case. It sounds like the mutex
> implementation is simply limited (or broken) in strange ways.

IF Solaris truely doesn't support a pthread_mutex_t variable declared on a stack,
then it does not conform to POSIX 1003.1c-1995. On the other hand, another reply
has already suggested that stack-local declarations do in fact work. So perhaps
the man page text is just a somewhat heavy handed way of making the excellent
suggestion that you avoid such practices.

> I use mutexes embedded in class objects all the time, and make no
> qualms about defining local instances of this class, for example:

Well, "qualms" are called for in this area. While C++ destructors can help to
ensure that the local mutexes are destroyed before you leave the scope, they
cannot easily ensure that no other thread can have an active handle on the
mutexes at that time.

You want to do it, you do it. Fine. But realize that you're tempting fate. If
you're just doing it "because you can", I strongly suggest that you meditate on
the true meaning of "convenience", which is not doing something easy now that may
cost you endless hours of difficult debugging at a critical customer's site.

> // .. declaration of Service class
>
> int main()
> {
> Service s;
> // s contains sync objects and a plurality of threads
>
> s.StartAllThreads();
> s.ShutdownWait();
> return 0;
> }
>
> The Unix98 description of pthread_mutex_init() doesn't mention any limitations
> regarding where you store a pthread_mutex_t object. I don't have the POSIX
> spec, so I can't comment on that.

There are no limitations in the standard, for non-pshared mutexes. (A pshared
mutex must be in shared memory.) It's not always a good idea to do something
merely because it's not prohibited.

sa...@bear.com

unread,
Sep 24, 1998, 3:00:00 AM9/24/98
to
In article <360784EF...@zko.dec.com>,
Dave Butenhof <bute...@zko.dec.com> wrote:
> Paul Calato wrote:
>
> > On solaris 2.5.1 the man page for pthread_mutex_init says
> >
> > "All mutexes must be global."
> >
> > Is this really true or can they be allocated on the heap and then
> > initialized appropriately (for intra-process)?
>
> What it means is that you cannot declare a stack-local ("automatic")
> mutex and expect everything to work correctly. (Allocating any shared
> data on a thread's stack is almost always a really bad idea. And, of
> course, a mutex must be shared to have any purpose at all in existing.)
>

As Dave says, a shared data should not be on a thread's stack. I regularly
flout this convention when I have one object on the main thread's stack
and the main thread waits for the objects' completion (typically a server).

(I never pthread_exit() from the main thread; so automatic objects on
the main thread have same lifetime as the global variables.)

example:

int main()
{
Manager obj();
...
obj.join(); // wait for it to complete whatever it is doing.
return 0;
}

class Manager
{
public:

private:
Mutex mutex_;
void* idle_action() { // this is idle thread
MutexLock lock(&mutex_);

for (;;) {
...
}
return 0;
}
void* midnight_action() { // this is midnight thread - archives at midnight.
MutexLock lock(&mutex_);
for (;; ) {
...
}
return 0;
}

// possibly other threads

// all these threads are encapsulated within the Manager class and started
// in the constructor or in a public method.

public:
void quit() {
// set some flag and broadcast all the cond. vars.
}

void join() {
// wait for all the threads to shutdown.
}

Manager() {
// start some threads.
}
};

Hope it helps,
Saroj Mahapatra

Logic

unread,
Sep 26, 1998, 3:00:00 AM9/26/98
to
To simplify:

global mutex's will exist for the duration of the program. Other's *could*
be destroyed before other threads are done with them (depending on how you
write your code).

If a mutex with local scope were destroyed while another thread were using
it ... well, you know how ugly these things can get :)

A good compromise is to declare/alloc/manage them in the main thread.

Paul Calato wrote in message <3606B9B9...@cabletron.com>...


>On solaris 2.5.1 the man page for pthread_mutex_init says
>
> "All mutexes must be global."
>
>Is this really true or can they be allocated on the heap and then
>initialized appropriately (for intra-process)?
>
>

Bil Lewis

unread,
Sep 28, 1998, 3:00:00 AM9/28/98
to
Paul Calato wrote:
>
> On solaris 2.5.1 the man page for pthread_mutex_init says
>
> "All mutexes must be global."
>
> Is this really true or can they be allocated on the heap and then
> initialized appropriately (for intra-process)?
>
> Paul

The tech writers were trying to get across the idea that a mutex
is not much use if it can't be shared between threads. I think this
line has been removed for 2.7 docs.

The POSIX spec is indeed followed in the actual implementation.

-Bil
--
================
B...@LambdaCS.com

http://www.LambdaCS.com
Lambda Computer Science
555 Bryant St. #194
Palo Alto, CA,
94301

Phone/FAX: (650) 328-8952

0 new messages