Shared memory functions for 32-bit Linux (for exp/shiny)

410 views
Skip to first unread message

Lucio De Re

unread,
Oct 20, 2016, 2:51:25 AM10/20/16
to golang-dev
It all starts with exp/shiny which I would dearly like to see running
on my Plan 9 equipment, one day.

Until then, I'd like to track developments on my Ubuntu desktop, but
32-bit Linux is not yet supported by the x11driver. I do not have
access to 64-bit equipment (except my HP Chromebook and that offers
its own set of challenges).

It seems like a small enough obstacle for me to overcome, involving
the implementation of shmOpen and shmClose functions, in turn using
sycalls (I think) for the four shm*() operations: shmget(), shmctl(),
shmat() and shmdt().

My uneducated guess is that these will need to be added to the go.sys
package, feel free to recommend a more appropriate approach.

I don't quite understand the exact semantics of the //sys and //sysnb
directives, specifically in syscall_linux_386.go, but there are enough
examples for me to figure it out. If there is moderately clear
documentation around this subject I ought to consult, this would be a
nice opportunity to let me know.

Any other recommendations will be gratefully accepted.

--
Lucio De Re

Ian Lance Taylor

unread,
Oct 20, 2016, 2:23:51 PM10/20/16
to Lucio De Re, golang-dev
On Wed, Oct 19, 2016 at 11:51 PM, Lucio De Re <lucio...@gmail.com> wrote:
>
> It seems like a small enough obstacle for me to overcome, involving
> the implementation of shmOpen and shmClose functions, in turn using
> sycalls (I think) for the four shm*() operations: shmget(), shmctl(),
> shmat() and shmdt().

I don't know what Plan 9 provides, but on modern Unix systems the way
to do this is not shmat and friends, but instead for all the
cooperating processes to mmap a single shared file using MAP_SHARED.
Note in particular that on GNU/Linux futex works on shared memory.
More thought would be required on other systems. Also more thought
would be required to understand how to implement sync.Mutex in a way
that works across processes.


> I don't quite understand the exact semantics of the //sys and //sysnb
> directives, specifically in syscall_linux_386.go, but there are enough
> examples for me to figure it out. If there is moderately clear
> documentation around this subject I ought to consult, this would be a
> nice opportunity to let me know.

The difference between //sys and //sysnb is that //sysnb promises that
the system call never blocks. It is always safe to use //sys. You
must not use //sysnb for any operation that may block, which includes
any operation that may call into a FUSE file system.

Ian

Lucio De Re

unread,
Oct 20, 2016, 3:51:24 PM10/20/16
to Ian Lance Taylor, golang-dev
On 10/20/16, Ian Lance Taylor <ia...@golang.org> wrote:
>
> I don't know what Plan 9 provides, but on modern Unix systems the way
> to do this is not shmat and friends, but instead for all the
> cooperating processes to mmap a single shared file using MAP_SHARED.
> Note in particular that on GNU/Linux futex works on shared memory.
> More thought would be required on other systems. Also more thought
> would be required to understand how to implement sync.Mutex in a way
> that works across processes.
>
Plan 9 is not terribly important here, but the point you make is: do
we want a specific solution for linux_386 (see
exp/shiny/driver/x11driver/shm_linux_amd64.go) which is the obvious
objective, or do I implement a Posix (say) solution and shoe-horn it
into Nigel's efforts.

At this point, my idea was to mirror the module above as closely as
possible, although I confess I have little idea how the IPC/SHM
facilities work in Linux (my Unix education is closer to NetBSD, so
this is a bit of an adventure) and, somewhat tantalizing, why there
are syscall entries for amd64, but not for 386 in Linux.

On the other hand, it is all very experimental, so the objective may
well be to plug the hole needed by the X11 driver, as simply as
possible.

> The difference between //sys and //sysnb is that //sysnb promises that
> the system call never blocks. It is always safe to use //sys. You
> must not use //sysnb for any operation that may block, which includes
> any operation that may call into a FUSE file system.
>
I got it, thank you for your help, from reading the perl code and
doing some guessing. Now I'm seriously lost in the maze of macro
definitions that implement syscalls in the Linux library. I wish I
could admire the cleverness of it all, but I confess it scares me,
instead. Who will maintain this stuff, twenty years from now?

Lucio.

Nigel Tao

unread,
Oct 20, 2016, 7:06:45 PM10/20/16
to Ian Lance Taylor, Lucio De Re, golang-dev
On Fri, Oct 21, 2016 at 5:23 AM, Ian Lance Taylor <ia...@golang.org> wrote:
> I don't know what Plan 9 provides, but on modern Unix systems the way
> to do this is not shmat and friends, but instead for all the
> cooperating processes to mmap a single shared file using MAP_SHARED.

Unfortunately, I think that the X11 server (and its MIT Shared Memory
Extension) speaks only System V shared memory, not POSIX.

X11 is therefore not modern Unix, or you could say that it's not
cooperating, but that ain't news.

minux

unread,
Oct 20, 2016, 8:55:13 PM10/20/16
to Lucio De Re, golang-dev
On Thu, Oct 20, 2016 at 2:51 AM, Lucio De Re <lucio...@gmail.com> wrote:
It seems like a small enough obstacle for me to overcome, involving
the implementation of shmOpen and shmClose functions, in turn using
sycalls (I think) for the four shm*() operations: shmget(), shmctl(),
shmat() and shmdt().

My uneducated guess is that these will need to be added to the go.sys
package, feel free to recommend a more appropriate approach.

The reason they are not available in the syscall package is that on certain
architectures (386, ppc64, ppc64le and s390x), the System V IPC functions
are using multiplexed onto the one syscall (SYS_IPC).

On amd64, arm, arm64, mips64, mips64, they appear as separate dedicated
syscalls.

I created https://golang.org/cl/31652, but I couldn't test it. It seems a 32-bit
process can't attach the shm when the X server is running as 64-bit process?

Lucio De Re

unread,
Oct 20, 2016, 11:48:01 PM10/20/16
to minux, golang-dev
Minux, it sure looks simple enough to be right, I will at least try it.

> The reason they are not available in the syscall package is that on certain
> architectures (386, ppc64, ppc64le and s390x), the System V IPC functions
> are using multiplexed onto the one syscall (SYS_IPC).
>
> On amd64, arm, arm64, mips64, mips64, they appear as separate dedicated
> syscalls.
>
> I created https://golang.org/cl/31652, but I couldn't test it.
>
I started to reply, but I must have discarded my reply instead of
sending it. But I was merely saying thanks to Ian for picking my query
up and providing helpful answers and bemoaning the complexities of
Linux and I'm sure all modern Unixes' advanced macro infection.

> It seems a 32-bit
> process can't attach the shm when the X server is running as 64-bit
> process?
>

I will report back in a moment. I can't help with the 32-bit/64-bit
thing, but we can probably live with that?

Lucio.

PS: Thanks, Nigel and Minux, too. This has been very instructive,
indeed. Any suggestion where I can find a useful reference for the
kernel stuff involved here that you all seem to find so familiar? In
Plan 9, the source is helpful and Nemo's book does the rest, but Linux
is scary (I'm going to be curious enough to see how NetBSD features,
now, too).

Sadly, the elasticity of my primary neural net seems to have been
sorely impacted by age (I hope it is only age!) as is amply
demonstrated in the late evening after a long day. But there is a
little bit of mileage left, I hope!

minux

unread,
Oct 21, 2016, 12:03:27 AM10/21/16
to Lucio De Re, golang-dev
On Thu, Oct 20, 2016 at 11:47 PM, Lucio De Re <lucio...@gmail.com> wrote:
PS: Thanks, Nigel and Minux, too. This has been very instructive,
indeed. Any suggestion where I can find a useful reference for the
kernel stuff involved here that you all seem to find so familiar?

I also wish there are better docs for this, but so far I didn't find anything
beyond the usual sources (read various libc source code is certainly one
way to go, I suggest mucl, which is simpler than glibc because glibc is
too portable....)

If you know where to look though, the ipc(2) man page explains that
the System V IPC syscalls are multiplexed onto one syscall on certain
architectures. However, I don't know how would one figure out to look
for the ipc syscall in the first place.

Lucio De Re

unread,
Oct 21, 2016, 12:15:01 AM10/21/16
to minux, golang-dev
Thanks, Minux. It's probably helpful to note this in a public forum as
we're doing now. I guess we owe Google a greater debt than we'll ever
compensate them for.

I guess I ought to look in the wikipedia, maybe even contribute the
little understanding I have gained so far. That, I am not quite ready
for, yet. :-)

Lucio.
--
Lucio De Re
2 Piet Retief St
Kestell (Eastern Free State)
9860 South Africa

Ph.: +27 58 653 1433
Cell: +27 83 251 5824
FAX: +27 58 653 1435

Lucio De Re

unread,
Oct 21, 2016, 12:52:59 AM10/21/16
to minux, golang-dev
I seem to jam up against:

2016/10/21 06:48:07 x11driver: shmOpen: shmat: bad address

where the (most recent) value returned by shmget is 0x19000a. The
trailing "a" is a little suspicious, although I think (having played a
long time ago with memory allocators of my own) that it means the
first 10 bytes are used for internal purposes.

Minux, anything jumps out at you?

Lucio.

PS: I'm using UBUNTU 14.04 (I think) on my workstation.


On 10/21/16, minux <mi...@golang.org> wrote:

Lucio De Re

unread,
Oct 21, 2016, 9:06:16 AM10/21/16
to minux, golang-dev
On 10/21/16, Lucio De Re <lucio...@gmail.com> wrote:
> I seem to jam up against:
>
> 2016/10/21 06:48:07 x11driver: shmOpen: shmat: bad address
>
> where the (most recent) value returned by shmget is 0x19000a.

If the proof of the pudding is in the eating, then I've actually fixed
the problem and now have at least a view of shiny from Linux (32-bit).

Minux, you were on the right track, but the exact order of the
arguments to the IPC syscalls needed re-arranging. Also, the address
returned from SHM_AT was one of the arguments, not a return register.

I actually built a set of shm{get,at,dt,ctl} functions to check the
behaviour and I think they deserve to be published, albeit with a bit
of finishing off.

For now, though, I think we ought to make sure other underprivileged
developers with only 32-bit capabilities can contribute, too.

Minux, do you mind if I send you the minimal patch that will work in
place of yours? Or shall I cascade the patches? My GIT/GERRIT foo is
pretty poor. I guess it needs to be improved.

Lucio.

Lucio De Re

unread,
Oct 21, 2016, 1:24:21 PM10/21/16
to Nigel Tao, Ian Lance Taylor, golang-dev
On 10/21/16, Nigel Tao <nige...@golang.org> wrote:
>
> Unfortunately, I think that the X11 server (and its MIT Shared Memory
> Extension) speaks only System V shared memory, not POSIX.
>
> X11 is therefore not modern Unix, or you could say that it's not
> cooperating, but that ain't news.
>

I've bent shiny just enough to have it run on my 32-bit Ubuntu system.
Between Minux and myself I expect we'll be able to ask you to review
the little code required in the next few days.

The examples are remarkable; "fluid", in particular, caught my imagination...

Lucio.
Reply all
Reply to author
Forward
0 new messages