Address of data that is static, be it shared or tls or __gshared or immutable on o/s <x>

Cecil Ward via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun Sep 10 14:38:03 PDT 2017


On Wednesday, 6 September 2017 at 15:55:35 UTC, Ali Çehreli wrote:
> On 09/06/2017 08:27 AM, Cecil Ward wrote:
> > If someone has some static data somewhere, be it in tls or
> marked shared
> > __gshared or immutable or combinations (whatever), and
> someone takes the
> > address of it and pass that address to some other routine of
> mine that
> > does not have access to the source code of the original
> definition of
> > the object in question, then is it possible to just use 'the
> address'
> > passed without knowing anything about that data? I'm assuming
> that the
> > answer might also depend on compilers, machine architectures
> and
> > operating systems?
> >
> > If this kind of assumption is very ill-advised, is there
> anything
> > written up about implementation details in different
> operating systems /
> > compilers ?
>
> Yes, they are all valid operations. Further, the object need 
> not be a static one; you can do the same with any object even 
> it's on the stack. However,
>
> - The object must remain alive whenever the other routine uses 
> it. This precludes the case of the object being on the stack 
> and the other routine saving it for later use. When that later 
> use happens, there is no object any more. (An exception: The 
> object may be kept alive by a closure; so even that case is 
> valid.)
>
> - Remember that in D data is thread-local by default; e.g. a 
> module variable will appear to be on the same address to all 
> threads but each thread will have its own copy. So, if the data 
> is going to be used in another thread, it must be defined as 
> 'shared'. Otherwise, although the code will look like it's 
> working, different threads will be accessing different data. 
> (Sometimes this is exactly what is desired but not what you're 
> looking for.) (Fortunately, many high-level thread operations 
> like the ones in std.concurrency will not let you share data 
> unless it's 'shared'.)
>
> Ali

Ali, I have worked on operating systems' development in r+d. My 
definitions of terms are hopefully the same as yours. If we refer 
to two threads, if they both belong to the same process, then 
they share a common address space, by my definition of the terms 
'thread' and 'process'. I use thread to mean basically a stack, 
plus register set, a cpu execution context, but has nothing to do 
with virtual memory spaces or o/s ownership of resources, the one 
exception being a tls space, which by definition is 
one-per-thread. A process is one or more threads plus an address 
space and a set of all the resources owned by the process 
according to the o/s. I'm just saying this so you know how I'm 
used to approving this.

Tls could I suppose either be dealt with by having allocated 
regions within a common address space that are all visible to one 
another. Objects inside a tls could (1) be referenced by absolute 
virtual addresses that are meaningful to all the threads in the 
process, but not meaningful to (threads belong to) other 
processes. (By definition of 'process'.) or (2) be referenced 
most often by section-offsets, relative addresses from the start 
of a tls section, which constantly have to be made usable by 
having the tls base virtual address added to them before they can 
be dereferenced adding a big runtime cost and making tls very bad 
news. I have worked on a system like (2). But even in (2) an 
address of a type-2 tls object can still be converted to a 
readily usable absolute virtual address and used by any thread in 
the process with zero overhead. A third option though could be to 
use processor segmentation, so tls objects have to (3a) be 
dereferenced using a segment prefixed operation, and then it's 
impossible to just have a single dereference operation such as 
star without knowing whether to use the segment prefix or not. 
But if it is again possible to use forbidden or official 
knowledge to convert the segmented form into a process-wide 
meaningful straight address (as in 8086 20-bit addresses) then we 
could term this 3a addressing. If this is not possible because vm 
hardware translation is in use then I will term this 3b. In 3a I 
am going to assume that vm hardware is used merely to provide 
relocation, address offsetting, so the use of a segmentation 
prefix basically merely adds a per-thread fixed offset to the 
virtual address and if you could discover that offset then you 
don't need to bother with the segment prefix. In 3b, vm hardware 
maps virtual addresses to a set of per-tls pages using 
who-knows-what mechanism, anyway something that apps cannot just 
bypass using forbidden knowledge to generate a single 
process-wide virtual address. This means that 3b threads are 
probably breaking my definition of thread vs process, although 
they threads of one process do also have a common address space 
and they share resources.

I don't know what d's assumptions if any are. I have very briefly 
looked at some code generated by GDC and LDC for Linux x64. It 
seems to me that these are 3a systems, optimised strongly enough 
by the compilers to remove 3a inefficiency that they are nearly 
1. But I must admit, I haven't looked into it properly, just 
noted a few things in passing and haven't written any test cases 
as I don't know d well enough yet. I haven't seen the code these 
compilers generate for Windows.

[Many thanks for your superb book btw, which I am just reading 
for the second time round. I wouldn't have got very far without 
it.]


More information about the Digitalmars-d-learn mailing list