August 26, 2001
Russell Bornschlegel wrote:
> Ah, on this note, while I don't feel strongly one way or another about the presence/absence of an asm statement, I _do_ think that "volatile" should be retained in D; if you have reasonably portable multithreading, the volatile attribute is very useful and far more portable than inline asm. Not to mention that it shouldn't be difficult to implement for a compiler savant. :)
> 
> Alternately, maybe there's something you can do with a synchronize block to ensure that variables are always reloaded on their first use within a synch -- i.e. implicitly volatile.
> 
> (Ooh! "synch"! There's your solution to synchronize/synchronise!)
> 
> -RB

WRT the volatile functionality, I'd be curious what the D way of doing this is.  My first guess would be to us an object, a global or a dynamicaly allocated variable reference (like an object).

Dan
August 26, 2001
Dan Hursh wrote in message <3B8890A9.82A61BDA@infonet.isl.net>...
>WRT the volatile functionality, I'd be curious what the D way of doing this is.  My first guess would be to us an object, a global or a dynamicaly allocated variable reference (like an object).


The way to do it in D is:

    synchronize
    {
            foo = blah;
    }

Whatever happens in the synchronize block is guaranteed to be atomic. My problem with the volatile keyword is the x86 CPU is not helpful - it doesn't guarantee writes of over 32 bits to be atomic (this includes 80 bit floats). Hence, to implement volatile, it would have to be wrapped in a mutex anyway.


August 27, 2001

Walter wrote:
> 
> Dan Hursh wrote in message <3B8890A9.82A61BDA@infonet.isl.net>...
> >WRT the volatile functionality, I'd be curious what the D way of doing this is.  My first guess would be to us an object, a global or a dynamicaly allocated variable reference (like an object).
> 
> The way to do it in D is:
> 
>     synchronize
>     {
>             foo = blah;
>     }
> 
> Whatever happens in the synchronize block is guaranteed to be atomic. My problem with the volatile keyword is the x86 CPU is not helpful - it doesn't guarantee writes of over 32 bits to be atomic (this includes 80 bit floats). Hence, to implement volatile, it would have to be wrapped in a mutex anyway.

My understanding of "volatile" is different from this -- I'd have to read the C spec to be sure, but I've always assumed that I was "on my own" for atomicity and that volatile merely told the compiler/optimizer that something outside the current thread of execution could modify the variable.

-RB
August 27, 2001
Russell Bornschlegel wrote in message <3B89DEA1.10F530B2@estarcion.com>...
>My understanding of "volatile" is different from this -- I'd have to read the C spec to be sure, but I've always assumed that I was "on my own" for atomicity and that volatile merely told the compiler/optimizer that something outside the current thread of execution could modify the variable.


In C, volatile essentially means the generated code should not cache the value in a register. But in the advent of multithreaded programming, volatile has been generalized to mean that it is accessed atomically. Today, I believe the C definition of volatile is obsolete and the atomic meaning is what is needed.

Volatile is such a rarely used attribute in C that it seems also to be an excessive burden to propagate it all through the internal typing system of the compiler.


August 27, 2001
"Walter" <walter@digitalmars.com> writes:

> Russell Bornschlegel wrote in message <3B89DEA1.10F530B2@estarcion.com>...
> >My understanding of "volatile" is different from this -- I'd have to read the C spec to be sure, but I've always assumed that I was "on my own" for atomicity and that volatile merely told the compiler/optimizer that something outside the current thread of execution could modify the variable.
> 
> 
> In C, volatile essentially means the generated code should not cache the value in a register. But in the advent of multithreaded programming, volatile has been generalized to mean that it is accessed atomically. Today, I believe the C definition of volatile is obsolete and the atomic meaning is what is needed.

volatile in its original C interpretation is very important for
accessing device registers or local memory that may be DMA'd to by
hardware.  Essentially it tells the compiler that it's *not* OK to use
the value it read 50 instructions ago that happens to still be
in a register because something *external* to the program may have
changed the location's value.

-Kevin
August 27, 2001
Russ Lewis <russ@deming-os.org> writes:

> Kevin Quick wrote:
> 
> > Linux has several implementations of threads available, including pthreads and sstthreads (http://sourceforge.net/projects/ssthreads/). Because of this, D itself has to be rebuilt depending on which threads package I'm intending to use, even on the same platform.
> >
> > This also removes any binary portability of D output... I can't take a D exectuable I built on Linux and run it on another POSIX x86 OS.
> 
> Why not dynamically link your D executable with a library?  You could export your threading features to a binary library.  Better yet, export it to a .d module; then the author of that .d module can call a C function directly, include assembly language code, or just declare the function (which means that D will look for it in a library you import).

That library would need to provide a full threading implementation (start_thread, stop_thread, signal_thread, ...) as well as the mutex operations.

Since this library might be provided by someone else, the library's API needs to be standardized, in part so that the D compiler can generate the correct thread_mutex calls, and in the other part so that my code can do its thread stuff.  This is necessary even to provide source compatibility between platforms.

The current D specification assumes the first part (above), and makes
no provisions for the second part.  IMHO, it needs to jump off the
fence onto one side or the other:
 (a) no process/thread/sync in the language and leave it all to
     libraries (dynamically or statically linked), or
 (b) implement a full threading interface in the language (even if the
     language then simply generates *specified* standardized API calls
     to a thread library provided on the target).

-Kevin
August 27, 2001
"Walter" <walter@digitalmars.com> writes:

> I confess I don't see the problem. D binaries will be as portable or unportable as C ones. The source will be more portable, as with the synchronize statement you needn't know or care which threading library is used.

None of the statements in the C language depend on external libraries. I can compile pure C code on a Linux x86 and run it under another OS supporting ELF object formats (e.g. FreeBSD, NetBSD, UnixWare, Solaris, etc.)

If I chose to use a library (e.g. stdio for printf, etc.), I can use a standardized library which is *usually* available on most platforms, or I can use a different library which may be available only on the subset of platforms interesting to me.  However, use of that library is through *function calls* with a defined API.  I'd expect a call to printf embedded in my executable to work the same way on the above-named platforms.

D will need to translate the "synchronize" statement into an external library call.  The threads library on the target platform must support that call, therefore the API must be specified (as part of D).  If this isn't done, then the executable I create for Linux x86 pthreads won't run under any other OS (unless it has the same pthreads support).

That's the first part of the problem.

The second part of the problem is allowing the programmer to select the threading support base.  For example, if I'm using Linux, D may be built using pthreads, which is a widely used threading library.

However, what if I wanted to use the D implementation of SST threads instead?  My D code would use calls like sst_thread_create, etc. but the synchronize statement would still call pthread_mutex_lock... not good.

I have to care what threading library I'm using unless D fully specifies all thread-related functionality (e.g. thread_create, thread_delete, thread_signal, etc.) so that I don't need to call the thread library myself.

-Kevin

August 27, 2001
In article <m3d75hzdu8.fsf@surgient.com>, Kevin Quick wrote:
> "Walter" <walter@digitalmars.com> writes:
> 
> > Russell Bornschlegel wrote in message <3B89DEA1.10F530B2@estarcion.com>
> > >My understanding of "volatile" is different from this -- I'd have to read the C spec to be sure, but I've always assumed that I was "on my own" for atomicity and that volatile merely told the compiler/optimizer that something outside the current thread of execution could modify the variable.
> > 
> > 
> > In C, volatile essentially means the generated code should not cache the value in a register. But in the advent of multithreaded programming, volatile has been generalized to mean that it is accessed atomically. Today, I believe the C definition of volatile is obsolete and the atomic meaning is what is needed.
> 
> volatile in its original C interpretation is very important for
> accessing device registers or local memory that may be DMA'd to by
> hardware.  Essentially it tells the compiler that it's *not* OK to use
> the value it read 50 instructions ago that happens to still be
> in a register because something *external* to the program may have
> changed the location's value.


There is more to this that meets the eye.  Allow me.

1) There is volatile, the ability something outside of the compilers control to modify some state in the environment the program is running in.  DMA, control registers, etc.

2) There is atomic, the ability to make sure things get modified in one swoop.  The ability of multiple threads/processes to modify the same thing at the same time, and only 1 of N will be there.  There is no corruption happening, even with more than one thing going after the same memory location.

3) There is syncronisation, the ability to have a certain set of things
finished, before you test/modify something else.  The most common case
is to have an alpha cpu do a whole bunch of floating-point operations
in an asynchronous mode (the quickest available), and at the end of them,
synchronise, and let any exceptions filter through (this requires the
equivelant of a pipeline flush).  Note that the synchronisation primitive
can not be "moved".  IE: strength-recude in a loop, etc.

4) There is ordering, which can be (although tedious) done by using
synchronisation primitives.


Anyhow, if D supports all of these, that would be cool...  Note, C only really supports #1 by spec, although #2 can be implemented for all purposes with a combination of a register sized variable and #1.

--Toby.
August 27, 2001
Tobias Weingartner wrote:
> 
> In article <m3d75hzdu8.fsf@surgient.com>, Kevin Quick wrote:
> > "Walter" <walter@digitalmars.com> writes:
> >
> > > Russell Bornschlegel wrote in message <3B89DEA1.10F530B2@estarcion.com>
> > > >My understanding of "volatile" is different from this -- I'd have to read the C spec to be sure, but I've always assumed that I was "on my own" for atomicity and that volatile merely told the compiler/optimizer that something outside the current thread of execution could modify the variable.
> > >
> > >
> > > In C, volatile essentially means the generated code should not cache the value in a register. But in the advent of multithreaded programming, volatile has been generalized to mean that it is accessed atomically. Today, I believe the C definition of volatile is obsolete and the atomic meaning is what is needed.
> >
> > volatile in its original C interpretation is very important for
> > accessing device registers or local memory that may be DMA'd to by
> > hardware.  Essentially it tells the compiler that it's *not* OK to use
> > the value it read 50 instructions ago that happens to still be
> > in a register because something *external* to the program may have
> > changed the location's value.
> 
> There is more to this that meets the eye.  Allow me.
> 
> 1) There is volatile, the ability something outside of the compilers control to modify some state in the environment the program is running in.  DMA, control registers, etc.
> 
> 2) There is atomic, the ability to make sure things get modified in one swoop.  The ability of multiple threads/processes to modify the same thing at the same time, and only 1 of N will be there.  There is no corruption happening, even with more than one thing going after the same memory location.
> 
> 3) There is syncronisation, the ability to have a certain set of things
> finished, before you test/modify something else.  The most common case
> is to have an alpha cpu do a whole bunch of floating-point operations
> in an asynchronous mode (the quickest available), and at the end of them,
> synchronise, and let any exceptions filter through (this requires the
> equivelant of a pipeline flush).  Note that the synchronisation primitive
> can not be "moved".  IE: strength-recude in a loop, etc.
> 
> 4) There is ordering, which can be (although tedious) done by using
> synchronisation primitives.
> 
> Anyhow, if D supports all of these, that would be cool...  Note, C only really supports #1 by spec, although #2 can be implemented for all purposes with a combination of a register sized variable and #1.

	I agree that it great that D supports all of these.  I guess I just
took the synchronize keyword to mean "atomic" but not "don't cache".  I
was just wondering how I would read a flag from an interrupt handler or
another thread w/o caching.  I guess the loads and stores are supposed
to be a part of the atomic operation.

Dan
1 2
Next ›   Last »