Re: Recent version of Iceweasel along with fixes

2014-09-16 Thread Richard Braun
On Tue, Sep 16, 2014 at 11:18:04PM +0800, Zhang Cong wrote:
 @Mike,  what things need to do to make this work upstream, as we talked in,

Zhang, please don't take it wrong, but it's not your business. You didn't
do the work, you didn't actually contribute to anything yet, don't try
and boss other people. Mike will handle the bug when he decides to, and
I'll keep providing packages in the mean time.

-- 
Richard Braun



Re: Recent version of Iceweasel along with fixes

2014-09-15 Thread Richard Braun
On Thu, Feb 27, 2014 at 10:17:07PM +0100, Richard Braun wrote:
 I intend to regularly update these packages to track the experimental
 branch until the changes are merged in the official repository.

Iceweasel 31.1.0esr-1 (from unstable) is available. 

-- 
Richard Braun



Re: GDB testsuite: »Memory at address 0 is possibly executable«

2014-09-13 Thread Richard Braun
On Sat, Sep 13, 2014 at 01:39:05AM +0200, Samuel Thibault wrote:
 So it seems we need what is not actually documented, i.e. a vm_map
 with anywhere=1, but which takes into account the suggested address.
 I'm fine with officially supporting that, we just need to fix the
 documentation, and fix all places which weren't aware of this behavior
 (there are very few). Do we agree on this?

Personally, I do prefer this approach, since that's how mmap is expected
to behave (with the interesting addition that, if MAP_FIXED isn't set,
but the hint is non-zero, the returned mapping must not start at
address 0).

-- 
Richard Braun



Re: Small test example for: cannot create /dev/null: Interrupted system call

2014-07-10 Thread Richard Braun
On Mon, Jul 07, 2014 at 01:29:20PM +0200, Svante Signell wrote:
 ./test.sh: 6: ./test.sh: cannot create /dev/null: Interrupted system

All right, it looks like open() gets interrupted by SIGCHLD here. It's
my understanding that signal handling is highly system-specific in such
cases, but we probably want to align on what others do, as usual.

-- 
Richard Braun



Re: Small test example for: cannot create /dev/null: Interrupted system call

2014-07-10 Thread Richard Braun
On Thu, Jul 10, 2014 at 11:18:17PM +0200, Richard Braun wrote:
 All right, it looks like open() gets interrupted by SIGCHLD here. It's
 my understanding that signal handling is highly system-specific in such
 cases, but we probably want to align on what others do, as usual.

By the way, it looks like it happens with dash only, not bash. I suppose
dash relies on the Linux-specific behaviour of interrupting a blocked
open(). See if switching to bash helps.

-- 
Richard Braun



Re: Small test example for: cannot create /dev/null: Interrupted system call

2014-07-10 Thread Richard Braun
On Thu, Jul 10, 2014 at 02:21:06PM -0700, Roland McGrath wrote:
 Is the SIGCHLD set with SA_RESTART?

From what I see, no.

-- 
Richard Braun



Re: Bug#752237: libc0.3: send() asked to transmit 0 chars still triggers recv() on Hurd

2014-06-28 Thread Richard Braun
On Sat, Jun 21, 2014 at 03:56:46PM +0200, Andreas Cadhalpun wrote:
 This is because the client is calling:
   send(sockfd, , 0, 0)
 
 Normally this doesn't trigger recv() in the server and thus can be
 used to test, whether the socket is working.
 But on Hurd it actually sends an empty message, so that the real
 message, which is sent later, is not received.

Hello,

Thanks for the report. There are actually two sides of the problem.
First, I agree that there seems to be a bug, but let's take a closer
look at the spec. The return value for recv() is defined as :

Upon successful completion, recv() shall return the length of the
message in bytes. If no messages are available to be received and the
peer has performed an orderly shutdown, recv() shall return 0.

This doesn't creates a strict equivalence between orderly shutdown and
shall return 0. But in practice, this seems to be the actual
assumption, so let's say that there is indeed a Hurd bug here. By the
way, although the send() and recv() functions themselves (in glibc) may
benefit from additions to filter out empty messages (at least send()),
the server functions are those found in pflocal concerning AF_UNIX
sockets.

But there is also a bug in the client code, IMO. Here is how send() is
specified :

The length of the message to be sent is specified by the length
argument.

[...]

If the socket argument refers to a socket and the flags argument is 0,
the send() function is equivalent to write().

And here is write() :

If nbyte is zero and the file is not a regular file, the results are
unspecified.

We might also want to change this though, since the behaviour observed
on other systems seems more appropriate.

-- 
Richard Braun



Re: Bug#752237: libc0.3: send() asked to transmit 0 chars still triggers recv() on Hurd

2014-06-28 Thread Richard Braun
On Sat, Jun 28, 2014 at 10:48:56AM +0200, Richard Braun wrote:
 On Sat, Jun 21, 2014 at 03:56:46PM +0200, Andreas Cadhalpun wrote:
  This is because the client is calling:
  send(sockfd, , 0, 0)
  
  Normally this doesn't trigger recv() in the server and thus can be
  used to test, whether the socket is working.
  But on Hurd it actually sends an empty message, so that the real
  message, which is sent later, is not received.
 
 Hello,
 
 Thanks for the report. There are actually two sides of the problem.
 First, I agree that there seems to be a bug, but let's take a closer

I've committed a fix upstream [1], please see if it solves your issues
as well.

-- 
Richard Braun

[1] 
http://git.savannah.gnu.org/cgit/hurd/hurd.git/commit/?id=6f856c62613ffc82bf3572a372d2851638c2fb90



Re: Bug#752237: libc0.3: send() asked to transmit 0 chars still triggers recv() on Hurd

2014-06-28 Thread Richard Braun
On Sat, Jun 28, 2014 at 12:09:15PM +0200, Samuel Thibault wrote:
 Richard Braun, le Sat 28 Jun 2014 11:51:42 +0200, a écrit :
  On Sat, Jun 28, 2014 at 10:48:56AM +0200, Richard Braun wrote:
   On Sat, Jun 21, 2014 at 03:56:46PM +0200, Andreas Cadhalpun wrote:
This is because the client is calling:
send(sockfd, , 0, 0)

Normally this doesn't trigger recv() in the server and thus can be
used to test, whether the socket is working.
But on Hurd it actually sends an empty message, so that the real
message, which is sent later, is not received.
  
  I've committed a fix upstream [1], please see if it solves your issues
  as well.
  
  [1] 
  http://git.savannah.gnu.org/cgit/hurd/hurd.git/commit/?id=6f856c62613ffc82bf3572a372d2851638c2fb90
 
 Mmm, I'm not sure we want to fix it in libpipe: other users of libpipe
 may want to pass empty messages (e.g. as mere tokens). Strictly
 speaking, it could be fixed in glibc's send() function. It however makes
 sense to me to fix it at the socket RPC protocol, i.e. in pflocal's
 S_socket_send.

In addition, I just noticed that passing control data relies on always
passing regular data, so this needs to be fixed too. However, I'm not
sure I understand why other users would rely on a stream protocol for
tokens. This would merely result in spurious wakeups, and AIUI, control
data is meant exactly for that purpose.

I'll see if simply catching completely empty messages at socket_send is
a good enough solution.

-- 
Richard Braun



Re: Bug#752237: libc0.3: send() asked to transmit 0 chars still triggers recv() on Hurd

2014-06-28 Thread Richard Braun
On Sat, Jun 28, 2014 at 12:42:40PM +0200, Richard Braun wrote:
 I'll see if simply catching completely empty messages at socket_send is
 a good enough solution.

The solution seems to work, and I couldn't see anything against it,
unlike the previous attempt. However I'd really like to put it into
libpipe as I don't see any need, but only potential problems, for empty
data packets. I'll wait for your reply before taking action.

-- 
Richard Braun



Re: Recent version of Iceweasel along with fixes

2014-06-21 Thread Richard Braun
On Thu, Feb 27, 2014 at 10:17:07PM +0100, Richard Braun wrote:
 I intend to regularly update these packages to track the experimental
 branch until the changes are merged in the official repository.

Iceweasel 30.0-2 (from unstable) is available. 

-- 
Richard Braun



Re: Please merge the random translator into the Hurd repository

2014-06-12 Thread Richard Braun
On Thu, Jun 12, 2014 at 09:38:48AM +0200, Justus Winter wrote:
  I think I’ve already asked this one, but still: why not a Git
  submodule?  
 
 Complexity.  We are trying to reduce it.
 
  One problem with the “merge ’em all” approach is
  that one can /add/ a thing to the repository, but one cannot
  really /delete/ it later.  (In the sense that from that point
  on, the code added would remain in the Git history, – and be
  $ git clone’d forever.)
 
 In my head, that is exactly the point of a vcs, but ymmv.
 
  On the contrary, submodules may be added and removed without any
  hassle.  And from this point, I’d rather see Hurd – a collection
  of servers – living as a collection of Git repositories.
 
 I'd rather see the Hurd not being a major pain in the ass to develop,
 but again, ymmv, as I guess it's a matter of perspective.
 
  The only downside I could think of is that a single commit
  (unless made to the “upper level” repository) cannot really span
  multiple Git repositories.  Which may be a problem as long as
  there’re strong interdependencies in the servers’ code.
 
 There are strong interdependencies, some are explicit, some are
 implicit.  And being able to change some aspects of the Hurd is part
 of why I advocated this merge in the first place (as clearly stated in
 my original mail).

I strongly agree with Justus on this.

-- 
Richard Braun



Re: let's make libpager single-threaded

2014-05-30 Thread Richard Braun
On Fri, May 30, 2014 at 09:35:37AM +0200, Justus Winter wrote:
 Quoting Richard Braun (2014-05-29 19:12:13)
  On Thu, May 29, 2014 at 07:04:48PM +0200, Samuel Thibault wrote:
   But precisely: once the only thread gets a data_request, it'll call
   pager_read_page, which will typically call store_read, which will wait
   on the eventual I/O, and no other request will be processed during that
   time, and thus not pipelining the I/O requests.
  
  Right, I assumed the store interface wasn't synchronous...
 
 So we want a fixed number of pager threads?

Let's see if a single thread is actually that bad: what other request
could actually be processed while a paging thread is waiting for I/O
completion ?

-- 
Richard Braun



Re: let's make libpager single-threaded

2014-05-30 Thread Richard Braun
On Fri, May 30, 2014 at 08:15:43PM +0200, Samuel Thibault wrote:
 Justus Winter, le Fri 30 May 2014 09:35:37 +0200, a écrit :
  Quoting Richard Braun (2014-05-29 19:12:13)
   On Thu, May 29, 2014 at 07:04:48PM +0200, Samuel Thibault wrote:
But precisely: once the only thread gets a data_request, it'll call
pager_read_page, which will typically call store_read, which will wait
on the eventual I/O, and no other request will be processed during that
time, and thus not pipelining the I/O requests.
   
   Right, I assumed the store interface wasn't synchronous...
  
  So we want a fixed number of pager threads?
 
 We can use a fixed number of pager threads, yes.  Perhaps just 1 indeed
 currently gives the best performance because the device backends that we
 currently use don't get benefit from piling up requests.  But at least
 we keep the infrastructure to pile up requests for when we fix the
 backends.

Agreed.

-- 
Richard Braun



Re: let's make libpager single-threaded

2014-05-29 Thread Richard Braun
On Thu, May 29, 2014 at 07:04:48PM +0200, Samuel Thibault wrote:
 But precisely: once the only thread gets a data_request, it'll call
 pager_read_page, which will typically call store_read, which will wait
 on the eventual I/O, and no other request will be processed during that
 time, and thus not pipelining the I/O requests.

Right, I assumed the store interface wasn't synchronous...

-- 
Richard Braun



Re: let's make libpager single-threaded

2014-05-27 Thread Richard Braun
On Fri, May 23, 2014 at 01:44:09AM +0200, Samuel Thibault wrote:
 Richard Braun, le Mon 05 May 2014 18:32:26 +0200, a écrit :
  On Mon, May 05, 2014 at 06:01:17PM +0200, Samuel Thibault wrote:
   ? The patch makes both ext2fs's service_paging_requests and libdiskfs'
   service_paging_requests become singlethreaded.
  
  That's what I call the paging part. The front side, where client calls
  are processed, is still multithreaded, which is what really matters.
 
 But the paging part also comes from client events, doesn't it?  E.g.
 on-demand loads of parts of mapped libraries, etc.

If on-demand here means on page fault, then no. In Mach, client threads
don't process their page faults, the kernel merely sends async requests
to external pagers. There is normally no I/O when the underlying
physical pages are already resident. External pagers are used only when
I/O must be done, in which case a single thread per backing device is
fine since processing incoming requests is normally orders of magnitude
faster than the underlying device latency.

Note that one of the future directions of the thread migration paper [1]
was about making client threads service their own page faults. The two
advantages of this strategy that I can think of are 1/ concurrency in
diskless file systems where I/O latency can actually be very low and 2/
maintaining scheduling properties. We could use a multithreaded pool to
help case 1/, and 2/ actually doesn't matter that much since scheduling
properties are most important to real time applications, which are
supposed to lock memory in anyway, but it's better for processor time
accounting nonetheless.

-- 
Richard Braun

[1] http://www.bford.info/pub/os/thread-migrate.pdf



Some test results about libihash

2014-05-21 Thread Richard Braun
On Tue, May 13, 2014 at 10:37:05AM +0200, Richard Braun wrote:
 It disappeared a few months ago, and since it's not widespread, I
 suggest, despite providing to Justus in the first place, to use the
 Murmur finalizer instead. But we need to test that part a bit more.
 I'm currently doing just that.

Here are some results I could obtain :

1/ Using an extremely simple microbenchmark [1] that merely inserts
keys, either random integers or sequential ones to match the way port
names are managed, it seems that the previous code, despite its apparent
flaws, did quite well.

Using an integer hashing function actually reduces performance on the
sequential integer test case. It makes sense because, considering a set
of consecutive integers starting from 0, and a hash table that always
has more slots than items, a modulo is a perfect hash function. Even
when taking into account that only names for receive rights are normally
managed with libihash, i.e. that keys aren't actually sequential, they
are almost all equally distributed, leading to very few collisions.

Therefore, as a third option, I've removed the hashing function, leaving
only a fast modulo (an AND) and this variant provided the best raw
results.

2/ I've also built hurd packages multiple times and got average build
times with each variant (previous, new, new without hash function) and
here are the results I obtained respectively : 52m59s, 52m31s, 52m22s.

In the end, no surprise, but still a decent improvement. Good job :).

-- 
Richard Braun

[1] http://darnassus.sceen.net/gitweb/rbraun/ihtest.git



Re: GSOC - Valgrind for Hurd

2014-05-20 Thread Richard Braun
On Tue, May 20, 2014 at 10:50:07PM +0200, Samuel Thibault wrote:
 I would advise starting with trivial system calls, such as
 mach_thread_self, mach_task_self, and mach_host_self, which don't take
 any parameter, and just returns a port. That'll make you implement the
 basic infrastructure for the trap call.

Keep in mind that, while most system calls are actually RPCs, a few of
them actually are real system calls (i.e. traps) in addition to
mach_msg. mach_thread_self and mach_task_self are such calls.

-- 
Richard Braun



Re: GSOC - Valgrind for Hurd

2014-05-20 Thread Richard Braun
On Tue, May 20, 2014 at 11:50:28PM +0200, Samuel Thibault wrote:
 Richard Braun, le Tue 20 May 2014 23:42:24 +0200, a écrit :
  On Tue, May 20, 2014 at 10:50:07PM +0200, Samuel Thibault wrote:
   I would advise starting with trivial system calls, such as
   mach_thread_self, mach_task_self, and mach_host_self, which don't take
   any parameter, and just returns a port. That'll make you implement the
   basic infrastructure for the trap call.
  
  Keep in mind that, while most system calls are actually RPCs, a few of
  them actually are real system calls (i.e. traps) in addition to
  mach_msg. mach_thread_self and mach_task_self are such calls.
 
 Well, valgrind will only see system calls, not RPCs.

Yes, and that's important to stress since calls like vm_map are RPCs.
Subhashish must be well aware of what to expect (if it's already been
done, good, otherwise consider this a reminder).

-- 
Richard Braun



Re: Recent version of Iceweasel along with fixes

2014-05-14 Thread Richard Braun
On Thu, Feb 27, 2014 at 10:17:07PM +0100, Richard Braun wrote:
 I intend to regularly update these packages to track the experimental
 branch until the changes are merged in the official repository.

Iceweasel 29.0.1 (from unstable) is available.

-- 
Richard Braun



Re: [PATCH 07/11] libihash: use an integer hash function on the keys

2014-05-13 Thread Richard Braun
On Tue, May 13, 2014 at 09:47:31AM +0200, Neal H. Walfield wrote:
 This URL is not valid (ttwang.cnc.net Not Available. The domain
 ttwang.cnc.net which you are trying to access is currently
 unavailable...).  Do you have a more stable URL?  At least mention
 the name of the paper.

It disappeared a few months ago, and since it's not widespread, I
suggest, despite providing to Justus in the first place, to use the
Murmur finalizer instead. But we need to test that part a bit more.
I'm currently doing just that.

-- 
Richard Braun



Re: [PATCH 03/11] include: add lock-less reference counting primitives

2014-05-13 Thread Richard Braun
On Tue, May 13, 2014 at 12:56:03PM +0200, Samuel Thibault wrote:
   AIUI this cast is a case of type-puning.  Why not making refcounts_t the
   union itself?  That way would be clearly safe with gcc's extension.
  
  As stated in the comment for refcounts_t, I like the idea of using the
  type system to enforce the use of the accessor functions.
 
 I understand, but type-puning will break with smart compilers.  We do
 have had bugs like that in the past.

I agree, you should directly use the proper type here, or maybe void *
but I don't see the point.

-- 
Richard Braun



Re: [PATCH 03/11] include: add lock-less reference counting primitives

2014-05-12 Thread Richard Braun
On Tue, May 13, 2014 at 12:23:48AM +0200, Samuel Thibault wrote:
 Justus Winter, le Mon 12 May 2014 12:05:41 +0200, a écrit :
  +  const union _references op = { .refs = { .hard = 1 } };
  +  refcounts_t r = __atomic_add_fetch (ref, op.rc, __ATOMIC_RELAXED);
 
 Mmm, I don't think it is allowed by C to write into a field and read
 from another field.  The legacy Hurd code used to tend to do it in some
 places, but it breaks with smart compilers.

It's not defined by C, but all major compilers support it as it's the
cleanest way, if done properly, not to violate strict aliasing currently.

-- 
Richard Braun



Re: let's make libpager single-threaded

2014-05-05 Thread Richard Braun
On Mon, May 05, 2014 at 04:55:19PM +0200, Samuel Thibault wrote:
 It's an interesting alternative indeed.  This however means our ext2fs
 is not multithreaded any longer, which is a bit sad considered that
 we'll want to go parallel in the end.

Well, no, only the paging part becomes single threaded, which is fine
since it's the I/O bound part.

-- 
Richard Braun



Re: let's make libpager single-threaded

2014-05-05 Thread Richard Braun
On Mon, May 05, 2014 at 06:01:17PM +0200, Samuel Thibault wrote:
 ? The patch makes both ext2fs's service_paging_requests and libdiskfs'
 service_paging_requests become singlethreaded.

That's what I call the paging part. The front side, where client calls
are processed, is still multithreaded, which is what really matters.

-- 
Richard Braun



Re: let's make libpager single-threaded

2014-04-28 Thread Richard Braun
On Mon, Apr 28, 2014 at 12:19:55PM +0200, Justus Winter wrote:
 We will try this change on darnassus and follow-up with the results.

Unfortunately, this looks too unstable to merge as it is. There seems to
be a port leak somewhere, and it looks like support for notifications
is needed, as I could freeze a file system by merely writing to it (e.g.
with dd) and interrupting with Ctrl-C.

But it's certainly on the right path and shouldn't be far from being
reliable (or at least, a lot more reliable than the current code).
Thanks a lot for working on this.

-- 
Richard Braun



Re: GCC's -fsplit-stack disturbing Mach's vm_allocate

2014-04-15 Thread Richard Braun
On Fri, Apr 11, 2014 at 11:51:44PM +0200, Samuel Thibault wrote:
 It's indeed:
 
 /* This function is called at program startup time to make sure that
mmap, munmap, and getpagesize are resolved if linking dynamically.
We want to resolve them while we have enough stack for them, rather
than calling into the dynamic linker while low on stack space.  */
 
 void
 __morestack_load_mmap (void)
 {
   /* Call with bogus values to run faster.  We don't care if the call
  fails.  Pass __MORESTACK_CURRENT_SEGMENT to make sure that any
  TLS accessor function is resolved.  */
   mmap (__morestack_current_segment, 0, PROT_READ, MAP_ANONYMOUS, -1, 0);
   mprotect (NULL, 0, 0);
   munmap (0, getpagesize ());
 }
 
 Yes...
 
 So, do we really want to let munmap poke a hole at address 0 and thus
 let further vm_map() return address 0?

We probably don't. AIUI, the first page is always mapped, and always
with PROT_NONE to make sure null pointers are catched. Considering other
systems have predefined ranges depending on the mapping type, instead
of blindly starting at the beginning of the map like vm_map() does, it's
perfectly valid to unmap the first page, which is normally the right
way to catch null pointers. So, since we do want to catch null pointers,
we do want to keep that first page, but only the first page. Or rather,
a range large enough to catch accesses through null pointers, e.g. it
could even be 64 or 128 KiB. We could alter glibc so that the first
mapping has this special size, and have munmap override its given range
to skip that area.

-- 
Richard Braun



Re: Problem with glibc and libihash

2014-04-14 Thread Richard Braun
On Sun, Apr 13, 2014 at 11:56:44PM +0200, Samuel Thibault wrote:
 Manolis Ragkousis, le Sun 13 Apr 2014 21:50:17 +, a écrit :
  First of all libihash and any of the hurd libraries cannot be built
  without a working glibc. Hurd libs depend heavily on header files
  found in glibc like lowlevellock.h,
 
 Mmm, if it's only headers, wouldn't it be possible to install just them?

Keep in mind that, when boostrapping toolchains, it is common practice
to install headers only, and build partially in multiple stages until
the final versoin is obtained.

-- 
Richard Braun



Re: Hurd support in libpcap

2014-04-11 Thread Richard Braun
On Thu, Apr 10, 2014 at 02:01:17AM +0200, Richard Braun wrote:
 The first issue that can be noticed is that, despite the filter being
 filled with both NETF_IN and NETF_OUT, only incoming packets seem
 to be captured. This is probably a minor bug in libbpf but I didn't
 investigate yet.

The issue seems to be in libmachdev, which simply doesn't forward
sent packets to any packet filter. Is there a reason why libmachdev
is only built statically ?

-- 
Richard Braun



Re: Cleaning up dde for the Hurd (was: Hurd support in libpcap)

2014-04-11 Thread Richard Braun
On Fri, Apr 11, 2014 at 03:13:02PM +0200, Justus Winter wrote:
 This is most likely just an oversight.  I started going over the dde
 code.  Zheng Da got lot's of little details wrong.  This is not meant
 to sound harsh, I'm full of respect that he got dde-based drivers
 up and running during a gsoc.

Agreed.

 Now let's team up and clean up his work so that we can merge it
 upstream and have a good template for more dde-based drivers :)

It won't be easy and I'll probably won't have time to do much about it,
for a change... But at least, I'm currently working on fixing locking
on packet filters and actually relaying sent packets so that packet
capture works. Note that this may slightly reduce performance because
of the way filters work, i.e. a net_msg must be completely forged,
with memory copies, before being sent to packet filters, even if there
is no filter installed. If someone wants to work on optimizing this,
feel free to do it, but please mind the details because that's where
the tricky bugs will come from.

-- 
Richard Braun



Hurd support in libpcap

2014-04-09 Thread Richard Braun
Hello,

A while ago, I added support for Hurd (actually Mach) network devices
in libpcap. I've refreshed this work so that it now tries to fetch
data from netdde before trying a Mach device, just like pfinet does.
Debian packages built with the patch [1] are available from my
repository for tests :

deb http://ftp.sceen.net/debian-hurd-i386 experimental/
deb-src http://ftp.sceen.net/debian-hurd-i386 experimental/

The first issue that can be noticed is that, despite the filter being
filled with both NETF_IN and NETF_OUT, only incoming packets seem
to be captured. This is probably a minor bug in libbpf but I didn't
investigate yet.

-- 
Richard Braun

[1] 
http://darnassus.sceen.net/~rbraun/0001-Debian-GNU-Hurd-with-NETDDE-support.patch



Re: Recent version of Iceweasel along with fixes

2014-04-08 Thread Richard Braun
On Thu, Feb 27, 2014 at 10:17:07PM +0100, Richard Braun wrote:
 I intend to regularly update these packages to track the experimental
 branch until the changes are merged in the official repository.

Iceweasel 28.0-1 and NSPR 4.10.4 are now available.

-- 
Richard Braun



Re: Please merge the random translator into the Hurd repository

2014-04-07 Thread Richard Braun
On Mon, Apr 07, 2014 at 01:49:52PM +0200, Thomas Schwinge wrote:
 If there is agreement, despite my comment b), that it'd be beneficial to
 merge the current external translators into the Hurd core repository's
 master branch, if this substantially makes any workflows easier, then I'm
 fine with accepting this.  There is, I guess, no need to make our lives
 harder, for some abstract (?) benefits, just for the elegance of
 explicitly modularized system architecture?

Grouping translators together along with the Hurd libraries and build
system makes the life of developers a lot easier. It reduces the
overhead related to build system settings, and it also reduces the
likeliness of mistakes. It really is the pragmatic approach, and IMO,
it strongly beats the apparent advantages of separate repositories.
From experience, on this project or others, I've never actually seen
or felt in any way any of these advantages in practice, but I've hit
the issues many times...

-- 
Richard Braun



Re: portseal - tools to locate port management bugs

2014-04-01 Thread Richard Braun
On Sun, Mar 30, 2014 at 07:40:50PM +0200, Justus Winter wrote:
 here is another prototype of mine, also employing a
 source-transformation, that can detect port leaks:

Well, that's impressive, once more. Excellent job.

-- 
Richard Braun



GSoC deadline for proposals

2014-03-20 Thread Richard Braun
Hello,

Apparently, the deadline for proposals is tomorrow (March 21). Students
indenting to participate should be careful not to miss it.

-- 
Richard Braun



Re: New installation CDs and qemu image

2014-03-18 Thread Richard Braun
On Tue, Mar 18, 2014 at 10:46:26AM +0100, Riccardo Mottola wrote:
 without success and further help, I just attempted a clean reinstall
 .As a note, I add that the machine I am using worked with hurd for
 years, until its hard-disk trashed.
 
 The installer went fine (it is quite slow, CD-ROM access seems quite
 painful) through all the steps, up to the last one where it says
 unmounting volumes. After 10 minutes it was still there without
 any disk activity, I shut down the machine. At boot, I do run fsck,
 as expected.
 
 At the next boot, I'm in the same situation as before. fsck says it
 can't check a mounted partition, my /proc is empty as is /var/run
 
 I will, as I did before, reconfigure the hurd package.
 
 But what can I do vor /var/run? and generally the problem? something
 else that could benefit of being reconfigured?

Honestly, I'm not sure you'll get help for such a specific problem. The
failed reinstall, though, is more troubling (and then interesting). I
suggest you reattempt to reinstall, and use the other virtual terminals
to check the status of the system if reinstallation fails again.

-- 
Richard Braun



Re: New installation CDs and qemu image

2014-03-18 Thread Richard Braun
On Tue, Mar 18, 2014 at 11:59:44AM +0100, Gabriele Giacone wrote:
 Did you install it again on / and /home distinct filesystems? If so,
 try to reinstall it on / only.
 Plus, don't set any mirror so that install takes all packages from CD.

Just for the record, it's strongly advised to use separate / and /home
partitions.

-- 
Richard Braun



Re: New installation CDs and qemu image

2014-03-18 Thread Richard Braun
On Tue, Mar 18, 2014 at 02:27:02PM +0100, Riccardo Mottola wrote:
 Also, if I can fix this installation, I'd prefer.. it took me two
 days to reinstall hurd: not continuously attented, but the operation
 was quite slow.. CD-ROM and HDD seem to be quite slow in access,
 especially the former.

It's not disk access that is slow. It's the page cache that is in bad
shape. It could also be due to a writeback caused thread storm (a kind
of thundering herd problem with spin locks in userspace). If any
potential GSoC candidate is reading this, fixing that particular issue
is one project we'd very much appreciate mentoring.

-- 
Richard Braun



Re: I got visudo working

2014-03-15 Thread Richard Braun
On Fri, Mar 14, 2014 at 05:21:23PM -0500, Peter Baumgarten wrote:
 On Fri, 2014-03-14 at 09:29 +0100, Samuel Thibault wrote:
  Use patch -ur between an unmodified version of sudo and your modified
  version. Send that to debian-h...@lists.debian.org for review, and then
 I sent the patch to debian-h...@lists.debian.org does that qualify me
 now for google summer of code to work on the hurd?

What qualifies a student is the quality, seriousness and relevance of
his proposal. Prior positive experience sure helps.

Would you say replacing configure.in with configure.ac and adding
it in a series file is enough ?

-- 
Richard Braun



Re: Trying to solve file lock problem with /etc/sudoers

2014-03-11 Thread Richard Braun
On Tue, Mar 11, 2014 at 02:44:36AM -0500, Peter Baumgarten wrote:
 I'm trying to be a hurd developer by jumping straight in and trying to
 tackle a bug. This may not be a hurd bug, but I only see it with the
 hurd version of sudo. I am trying to figure out why I get this message
 visudo: /etc/sudoers busy, try again later when I run visudo as root.
 I suspect something has a file lock on /etc/sudoers. I would normally
 use lsof to see what processes have a lock on a file, but apparently
 lsof is not available for hurd. When I say not available I mean not
 installed by default on the debian hurd qemu image and not available in
 the debian hurd repos. Does anyone know what tools are available to me
 to see what has a lock on file or what processes are using a file on?

To everyone who's trying to be a free software contributor, this is the
right (or at least recommended) approach.

The Hurd is a distributed system, and it's not straightforward to come
up with tools like lsof. The closest one is probably portinfo, but it
won't give you as much information. The issue is known, although I'm
not familiar with the details. You need to understand the general
architecture of the Hurd, and then dig in libdiskfs/libfshelp and the
ext2fs translator, I suppose. It is definitely a Hurd bug, which may
require development (i.e. it may be a feature missing, not a mere bug).

Unless I'm mistaken, the issue is described on the wiki [1].

-- 
Richard Braun

[1] http://darnassus.sceen.net/~hurd-web/open_issues/file_locking/



Re: New installation CDs and qemu image

2014-03-05 Thread Richard Braun
On Wed, Mar 05, 2014 at 02:43:01PM +0100, Riccardo Mottola wrote:
 /dev/hd0s1:clean
 /dev/hd0s2 is mounted
 e2fsck cannot continue aborting.
 Automatic boot failed... help!
 #
 
 at the prompt I could type cat /etc/fstab
 
 /dev/hd0s1/ext2defaults0 1
 /dev/hd0s2/bootext3defaults0 3
 /dev/hd0s3noneswapsw0 0
 /dev/hd2/media/cdrom0iso9660noauto0 0
 
 what could be the problem? what is failing? it looks quite correct
 to me. Swap and CDROM shouldn't be fsck'd and they appear correct.

You set hd0s2 to type ext3.

-- 
Richard Braun



Re: Recent version of Iceweasel along with fixes

2014-03-05 Thread Richard Braun
On Sat, Mar 01, 2014 at 12:13:18PM +0800, Zhang Cong wrote:
 1. Crash once for clipboard assert=NULL?,  I lost the detail.

Please try to reproduce, or at least give more details about what you
did before the crash occurred.

-- 
Richard Braun



Recent version of Iceweasel along with fixes

2014-02-27 Thread Richard Braun
Hello,

I've started working on porting more recent versions of Iceweasel (our
binary packages are from version 17), and fixing some important issues
at the same time.

The current status is that packages are available for version 27.0-2,
and all major bugs have been fixed. I have reliably used it for several
days straight, without terminating the test processes, with many tabs,
with custom GTK themes, IPv4/IPv6 sites, SSL/TLS, and even SWF applets
through Gnash. I consider that reliable enough for practical use,
although the lack of acceleration and sound will make watching videos
a bit frustrating at times ;-).

The thread-safety issues that would lead to random crashes have been
fixed in libc0.3 2.18-1. The SSL/TLS issue is addressed in a patch
attached to bug #739658 [1]. The Iceweasel FTBFS issues themselves are
still being worked on until I'm satisfied with the result. The patch
fixing them can be found in the source packages on my personal
repository, along with the binary packages for Iceweasel and nspr :

deb http://ftp.sceen.net/debian-hurd-i386 experimental/
deb-src http://ftp.sceen.net/debian-hurd-i386 experimental/

I intend to regularly update these packages to track the experimental
branch until the changes are merged in the official repository.

Enjoy.

-- 
Richard Braun

[1] 
https://bugs.debian.org/cgi-bin/bugreport.cgi?msg=5;filename=0001-Define-_PR_HAVE_SOCKADDR_LEN-for-the-Hurd.patch;att=1;bug=739658



Re: [PATCH 1/5] ipc: add protected payload

2014-02-21 Thread Richard Braun
On Fri, Feb 21, 2014 at 12:48:49PM +0100, Justus Winter wrote:
 Add a field ip_protected_payload and a flag ip_has_protected_payload
 to struct ipc_port.

 diff --git a/ipc/ipc_port.h b/ipc/ipc_port.h
 index 27d2e49..4c7c742 100644
 --- a/ipc/ipc_port.h
 +++ b/ipc/ipc_port.h
 @@ -71,6 +71,10 @@ typedef unsigned int ipc_port_timestamp_t;
  struct ipc_port {
   struct ipc_target ip_target;
  
 + /* Flags.  */
 + unsigned intip_has_protected_payload:1; /* A pp has
 +been set.  */
 +
   /* This points to the ip_target above if this port isn't on a port set;
  otherwise it points to the port set's ips_target.  */
   struct ipc_target *ip_cur_target;
 @@ -96,6 +100,7 @@ struct ipc_port {
   mach_port_msgcount_t ip_msgcount;
   mach_port_msgcount_t ip_qlimit;
   struct ipc_thread_queue ip_blocked;
 + unsigned long ip_protected_payload;
  };

Increasing the port structure size by 4 bytes for a single bit is a
little frustrating. Instead, how about storing that bit in
ip_target.ipt_object.io_bits, right next to IO_BITS_ACTIVE ?

-- 
Richard Braun



Re: [PATCH 1/5] ipc: add protected payload

2014-02-21 Thread Richard Braun
On Fri, Feb 21, 2014 at 05:49:24PM +0100, Justus Winter wrote:
 -#define IO_BITS_OTYPE0x7fff  /* determines a cache */
 +#define IO_BITS_OTYPE0x3fff  /* determines a cache */
 +/* The following masks are used to store attributes of ipc ports.  */
 +#define  IO_BITS_PROTECTED_PAYLOAD   0x4000  /* pp set? */

Thanks :-).

-- 
Richard Braun



Re: protected payloads for GNU Mach

2014-02-19 Thread Richard Braun
On Tue, Feb 18, 2014 at 09:49:23PM -0800, Samuel Thibault wrote:
 Apart from that and perhaps a function to clear the protected payload
 value (which may however not be really useful), the whole thing seems
 interesting and good to me, do other people agree?

Well, since I've pushed that as a project idea [1], I'm quite happy to
see it happening. Very good job again, Justus.

-- 
Richard Braun

[1] 
http://www.gnu.org/software/hurd/community/gsoc/project_ideas/object_lookups.html



Re: [PATCH 04/11] doc: document mach_port_set_protected_payload

2014-02-17 Thread Richard Braun
On Mon, Feb 17, 2014 at 06:20:54PM +0100, Justus Winter wrote:
 +@deftypefun kern_return_t mach_port_set_protected_payload (@w{ipc_space_t 
 @var{task}}, @w{mach_port_t @var{name}}, @w{unsigned long @var{payload}})
 +The function @code{mach_port_set_protected_payload} sets the protected
 +payload to @var{payload}.  If @var{payload} is non-zero, the
 +@code{msgh_protected_payload} field will be set to @var{payload} if a
 +message is delivered to @var{name}.

If I'm right, this also means switching back from the protected payload
is done by calling this RPC with a payload of 0. It could be worth
emphasizing that 0 is an invalid value for a protected payload.

-- 
Richard Braun



Re: [PATCH 1/8] kern: fix printing of kmem_cache names

2014-02-01 Thread Richard Braun
On Sun, Feb 02, 2014 at 12:11:59AM +0100, Samuel Thibault wrote:
 Justus Winter, le Sat 01 Feb 2014 16:34:20 +0100, a écrit :
  I thought about doing that.  But that would waste one character just
  for the termination.
 
 That's little compared to security :)

  GNU Machs printf implementation supports strings with the precision
  given as argument:
  
printf (%.*s, sizeof foo-name, foo-name);
  
  I think thats clean, concise and easy to use.
 
 But people would tend to forget doing it.  We can't really fight that.

Null-terminated strings is what people will naturally expect and have
in mind while reading/editing the code. Doing things differently for
something like mere names isn't worth the trouble.

-- 
Richard Braun



Re: [PATCH v16] kern: simple futex for gnumach

2014-01-18 Thread Richard Braun
On Fri, Jan 17, 2014 at 07:45:15PM -0800, Roland McGrath wrote:
  This is why I was insisting on passing *memory* through IPC. 
 
 It's not at all clear that makes any kind of sense, unless you mean
 something I haven't imagined.  Can you be specific about exactly what the
 interface (say, a well-commented MiG .defs fragment) you have in mind would
 look like?
 
 If it's an RPC that passes out of line memory, that (IIRC) always has
 virtual-copy semantics, never page-sharing semantics.  So it would be
 fundamentally the wrong model for matching up with other futex calls (from
 the same task or others) to synchronize on a shared int, which is what the
 futex semantics is all about.

That's right, IPC can only copy private memory, not make it shared. So
technically, not through IPC, but through the VM system.

 What I always anticipated for a Machish futex interface was vm_futex_*
 calls, which is to say, technically RPCs to the task port (which need not
 be the task port of the caller), passing an address as an integer literal
 just as calls like vm_write do (and each compareexchange value as a datum,
 i.e. an integer literal, just as vm_write takes a datum of byte-array type,
 with semantics unchanged by whether that's inline or out of line memory).

That's more what I had in mind too.

 The task port and address serve as a proxy by which the kernel finds the
 memory object and offset, and the actual synchronization semantics are
 about that offset in that memory object and the contents of the word at
 that location.  (Like all such calls, they would likely be optimized
 especially for the case of calls to task-self and probably even to the
 extent of having a bespoke syscall for the most-optimized case, as with
 vm_allocate.  But that's later optimization.)
 
 Given the specified usage patterns for the futex operations, it might be
 reasonable enough to implement those semantics solely by translating to a
 physical page, including blocking to fault one in, and then associating the
 wait queues with offsets into the physical page rather than the memory
 object abstraction.  (Both a waiter and a waker will have just faulted in
 the page before making the futex call anyway.)  But note that the semantics
 require that if a waiter was blocked when the virtual page got paged out,
 then when you page it back in inside vm_futex_wake, that old waiter must
 get woken.  I don't know the kernel's VM internals much at all, but I
 suspect that all tasks mapping a shared page do not get eagerly updated
 when the memory object page is paged in to service a page fault in some
 other task, but rather service minor faults on demand (i.e. later) to
 rediscover the new assocation between the virtual page and the new physical
 page incidentally brought in by someone else's page fault a little earlier.
 Since you need to track waiters at the memory object level while their page
 is nonresident anyway, it probably makes sense just to hang the {offset =
 wait queue} table off the memory object and always use that.  At least,
 that seems like the approach for the first version that ensures correctness
 in all the corners of the semantics.  It can get fancier as needed in later
 optimizations.  When it comes to optimizing it, a fairly deep understanding
 of the Linux futex implementation (which I don't have off hand, though I
 have read it in the past) is probably instructive.

Locking physical pages could be used for denial of service, i.e. a user
may implicitely starve the system of wired memory, unless they're
accounted as such, but then users might be randomly unable to use
mutexes. Trying to cope with object/offset to pages associations would
imply some container very similar to what has been considered until now
for the regular case (that is, a hash table or tree for all shared
futexes) so that futexes can immediately be reassociated to pages after
faulting them in. So I expect we have to use VM objects.

What I had in mind is already partially explained in previous mails
but I still didn't take the time to get a clear view of every use case
so it's probably incomplete. But it would start with a union of either
(task translated to map, address) or (object, offset), depending on the
futex type (private, shared, respectively). Problems I can see with that
approach are :
- do we have to check that shared futexes refer to shareable memory ?
- if so, how to make that check reliably ?
- what happens when unmapping a futex ?
- does copy-on-right have any effect on a private futex - if implemented
  as a (map, address) pair, I imagine it wouldn't, but is it true ?

These are the kind of things I was hoping to discuss with this patch.

-- 
Richard Braun



Re: [PATCH v16] kern: simple futex for gnumach

2014-01-17 Thread Richard Braun
On Sat, Jan 18, 2014 at 02:06:05AM +0100, Samuel Thibault wrote:
 Diego Nieto Cid, le Fri 17 Jan 2014 22:49:25 -0200, a écrit :
  El ene 17, 2014 11:36 a.m., Marin Ramesa m...@hi.t-com.hr escribió:
   +
   +kern_return_t
   +futex_wait(task_t task, vm_offset_t futex_address, int value,
   +          mach_msg_timeout_t msec, boolean_t private_futex)
   +{
   +       if (private_futex) {
   +               struct private_futex *futex;
   +
   +               futex = futex_private_lookup_address(futex_address);
   +               if (futex == NULL) {
   +                       futex = futex_private_init(futex_address);
   +                       if (futex == NULL)
   +                               return KERN_RESOURCE_SHORTAGE;
   +               }
   +
   +               if (__atomic_load_n(
   +                       (int *) futex_address, __ATOMIC_RELAXED) == 
   value) {
  
  Are you sure you can dereference futex_address?
  
  It's a user supplied virtual address which is probably not valid in the
  kernel's virtual address space (unless things like copyin are used)
  
  I have the vague idea that the kernel has it's own address space. Can 
  somebody
  confirm that? :-)
 
 Yes. Care has to be taken when dereferencing user pointers.

This is why I was insisting on passing *memory* through IPC. But this
does work in most cases on i386 since the kernel page tables are shared
by all user page tables to avoid a complete TLB flush on kernel entry,
as it's done for practically every system. So in practice, setting some
user data and accessing it from the kernel soon after will succeed most
of the time because writing the content will cause page faults if
needed, after which the kernel can simply read it.

That is how e.g. mach_print is able to do its job, although, for this
special call, it was done on purpose to avoid the VM system (since it's
a debugging call).

-- 
Richard Braun



Re: [PATCH v14] kern: simple futex for gnumach

2014-01-13 Thread Richard Braun
On Mon, Jan 13, 2014 at 03:38:19PM +0100, Marin Ramesa wrote:
 Fixed a bug in private wakeups by calling ipc_entry_alloc_name().
 
 This is the last version as everything works now.

*Sigh*

You didn't understand my comment mentioning IPC spaces at all... You
keep wrongly using the red-black tree interface. You keep making basic
locking mistakes. You still pass raw addresses/values instead of passing
*memory*. You obviously didn't take the time to look at how assert_wait
and thread_will_wait_with_timeout were used elsewhere and implemented.
You didn't change the timeout parameter type, despite your claim for a
final version. And worst of all, you dare claim everything works.

You clearly have little clue about what you're actually doing, and don't
make the effort to check your assumptions and learn. I won't review any
more of your work.

-- 
Richard Braun



Re: [RFC] kern: simple futex for gnumach (version 11)

2014-01-10 Thread Richard Braun
On Fri, Jan 10, 2014 at 08:28:12AM +0100, Marin Ramesa wrote:
 On 01/10/2014 01:59:55 AM, Richard Braun wrote:
 On Thu, Jan 09, 2014 at 09:51:51PM +0100, Marin Ramesa wrote:
  On 01/09/2014 05:52:21 PM, Richard Braun wrote:
  On Thu, Jan 09, 2014 at 05:06:09PM +0100, Marin Ramesa wrote:
   Shouldn't the compare be atomic. Maybe I don't understand what
   atomic really
   means but the GCC manual says this function is. Or is it
 enough to
   hold the lock.
  
  From the GCC manual :
  These built-in functions perform an atomic compare and swap.
 That is,
  if the current value of *ptr is oldval, then write newval into
 *ptr.
  So tell us what the point of replacing oldval with itself is.
 
  I do a swap so it returns true if they are equal.
 
 I'll say it again because it doesn't look like you got it : when I
 point
 something out to you, consider you're wrong, and make the effort to
 question your assumptions. You may end up being right at times,
 but most
 often not. Now please, read your code again, then answer the
 question I
 asked : So tell us what the point of replacing oldval with itself
 is.
 
 OK, sorry. There's no point. I couldn't find just an atomic compare, so
 I'm using the compare-and-swap this way. I'll read more in the GCC
 manual,
 maybe there is another way.

Reading correctly aligned integers that are not wider than the processor
word size is already atomic. But there still is a problem I mentioned in
another review and forgot this time :

On Thu, Jan 09, 2014 at 03:45:35PM +0100, Richard Braun wrote:
 On Wed, Jan 08, 2014 at 08:43:28PM +0100, Marin Ramesa wrote:
  +routine futex_wait(
  +   task: task_t;
  +   address : vm_offset_t;
  +   value   : int;
  +   msec: int;
  +   private_futex   : boolean_t);
  +
  +routine futex_wake(
  +   task: task_t;
  +   address : vm_offset_t;
  +   wake_all: boolean_t);
 
 Looks good. You'll probably want the requeue operation too some day, but
 that can wait.

Actually, this isn't good. Rework the futex_wait routine so that it
passes *memory* to the kernel, not raw values. Once the kernel can
directly access the futex value, a plain memory access should do the
job, but since I haven't read the futex paper in depth, I'm not even
sure why this is done before queueing a thread on a futex, and what
are the exact constraints on the system call.

-- 
Richard Braun



Re: About Regular IRC Meetings.

2014-01-10 Thread Richard Braun
On Sat, Jan 11, 2014 at 03:26:50AM +0530, Subhashish Pradhan wrote:
 Hello,
 
 Currently, the meetings take place in the *#hurd channel every Thursday at
 19:00 UTC* and are open to any interested party.
 
 Are these held regularly? How long do they last?
 
 Can anyone drop in and discuss their queries related to the project?

That was done for the summer of code, and it will probably be done again
next time. And yes, in the mean time, just come on the channel and ask
your questions. But keep in mind that, in accordance with Hurd and IRC
traditions, we may be long to answer, in particular during work/week
ends/holidays, so let your client lurk there a few hours/days at least.

-- 
Richard Braun



Re: [RFC] kern: simple futex for gnumach (version 11)

2014-01-09 Thread Richard Braun
)) != SMUTEX_UNLOCKED) {
 + if (c != SMUTEX_WAITERS)
 + c = __sync_lock_test_and_set(smutex-value, 
 SMUTEX_WAITERS);
 + while (c != SMUTEX_UNLOCKED) {
 + futex_wait(current_thread()-task, 
 (vm_offset_t)smutex-value, SMUTEX_WAITERS, 0, 1);
 + c = __sync_lock_test_and_set(smutex-value, 
 SMUTEX_WAITERS);
 + }
 + }
 +}
 +
 +void simple_mutex_unlock(struct simple_mutex *smutex)
 +{
 + if (__sync_lock_test_and_set(smutex-value, smutex-value - 1) != 
 SMUTEX_NO_WAITERS) {
 + smutex-value = SMUTEX_UNLOCKED;
 + futex_wake(current_thread()-task, (vm_offset_t)smutex-value, 
 0);
 + }
 +}

Userspace tests please.

 +struct futex;
 +
 +void futex_setup(void);
 +
 +/*
 + * This is a method for a thread to wait for a change of value at a given 
 address.
 + * If msec is non-zero, thread blocks for msec amount of time. If it's zero, 
 no
 + * timeout is used. If private_futex is one, futex is not shared between 
 tasks.
 + */
 +void futex_wait(task_t task, vm_offset_t address, int value, int msec, 
 boolean_t private_futex);

s/one/true/

 +/*
 + * This is a method for waking up one or all threads waiting for a change of 
 + * value at a given address.
 + * 
 + * If wake_all is one, all threads are awakened. If it's zero, only one 
 thread is 
 + * awakened.
 + */
 +void futex_wake(task_t task, vm_offset_t address, boolean_t wake_all);

This requires more description. For example, state the address
requirements (pointing and aligned to an int).

-- 
Richard Braun



Re: [RFC] kern: simple futex for gnumach (version 11)

2014-01-09 Thread Richard Braun
On Thu, Jan 09, 2014 at 02:36:18PM -0200, Diego Nieto Cid wrote:
 2014/1/8 Marin Ramesa m...@hi.t-com.hr
 
  +
  +static unsigned long futex_init(task_t task, vm_offset_t address, 
  boolean_t private_futex, struct futex *futex)
  +{
  +   unsigned long node_slot = 0;
  +
  +   futex = (struct futex *)kalloc(sizeof(*futex));
 
 This only changes the value of the parameter. futex could very well
 be a local variable instead.
 
 If what you want is to update the value seen by the caller you should
 declare futex as a struct futex ** and then do something like this:
 
 *futex = (struct futex *)kalloc(sizeof(**futex));

Right, this was already mentioned in an earlier review, and is still
there. Fix it.

  +void futex_wait(task_t task, vm_offset_t address, int value, int /* TODO 
  Use time_value_t */ msec, boolean_t private_futex)
  +{
  +   unsigned long node_slot = 0;
  +
  +   node_slot = futex_lookup_address(address);
  +   if (node_slot == 0) {
  +   if (private_futex) {
  +   pfutexes = (struct futex *)kalloc(sizeof(pfutexes));
  +   if (pfutexes == NULL)
  +   return;
  +   node_slot = futex_init(task, address, TRUE, 
  pfutexes[ARRAY_SIZE(pfutexes) - 1]);
 
 I don't really get this stuff.
 
 First of all, you are allocating sizeof(pfutexes) and pfutexes is
 defined as struct futex *. Thus, you are just allocating memory for
 a pointer (4 bytes in a 32-bit machine) and then casting it to a
 pointer to struct futex. So, if you dereference pfutexes to access
 some member of the futex structure you will probably go past the end
 of the allocated space (for the futex structure is bigger than a
 pointer).

I agree. this array isn't needed, get rid of it.

 Secondly, you are calling the macro ARRAY_SIZE with pfutexes as
 parameter. This will be evaluated to 0. Here's why:

Simply put, ARRAY_SIZE() is intended for statically allocated arrays
where the size is known at compile time. Don't use it on pointers.
But again, since there shouldn't be an array in the first place, this
function should be entirely reworked.

-- 
Richard Braun



Re: [RFC] kern: simple futex for gnumach (version 11)

2014-01-09 Thread Richard Braun
On Thu, Jan 09, 2014 at 05:06:09PM +0100, Marin Ramesa wrote:
 On 01/09/2014 03:45:35 PM, Richard Braun wrote:
  +/* TODO Should be per-task. */
  +static struct futex *pfutexes;
 
 Most locks are private, so yes, do work on that too.
 
 I actually did not implement this because I don't know how.
 How to make a variable visible only and private to a task?
 I tried to find code examples of this but I don't know what
 should I look for.

Just as tasks have IPC spaces (struct ipc_space *itk_space in struct
task), you could create a futex space and add it to the task
structure. It's as simple as that. I said per task, not only visible
to one task.

  +static vm_offset_t futex_gen_unique_event_num(vm_offset_t sum,
 vm_offset_t add1, vm_offset_t add2)
  +{
  +  if (sum == 0) return 0;
  +  
  +  struct rbtree_node *node;
  +
  +  for(node = futex_tree.root; node != NULL; node =
 node-children[RBTREE_RIGHT]) {
  +
  +  struct futex *futex;
  +  futex = rbtree_entry(node, struct futex, node);
  +
  +  vm_offset_t futex_event_num = (vm_offset_t)futex-event;
  +  
  +  if (futex_event_num == sum) {
  +  
  +  if (futex_event_num - add2 == add1)
  +  continue;
  +  else
  +  return futex_gen_unique_event_num(sum - 1, 
  add1, add2);
  +
  +  }   
  +  }
  +
  +  return sum;
  +}
 
 ??
 
 Consider a case where you have an address/map or an object
 address/offset pair
 of (x, y) and another one (z, w) where x != z and y != w, but x + y
 = z + w. So,
 in order for the events to work correctly I need to make the sum
 unique. But if
 I implement the trees differently this function might become reduntant.

That's the idea, use one global tree for shared futexes, per task trees
for private ones.

  +  if (private_futex) {
  +  pfutexes = (struct futex *)kalloc(sizeof(pfutexes));
  +  if (pfutexes == NULL)
  +  return;
  +  node_slot = futex_init(task, address, TRUE,
 pfutexes[ARRAY_SIZE(pfutexes) - 1]);
  +  } else {
  +  shared_futexes = (struct futex
 *)kalloc(sizeof(shared_futexes));
  +  if (shared_futexes == NULL)
  +  return;
  +  node_slot = futex_init(task, address, FALSE,
 shared_futexes[ARRAY_SIZE(shared_futexes) - 1]);
  +  }
  +  if (node_slot == 0) return;
  +  }
  +  
  +  if (__sync_bool_compare_and_swap((int *)address, value,
 value)) {
 
 What are you trying to do here ?? This call has no particular effect,
 except being a memory barrier ...
 
 Shouldn't the compare be atomic. Maybe I don't understand what
 atomic really
 means but the GCC manual says this function is. Or is it enough to
 hold the lock.

From the GCC manual :
These built-in functions perform an atomic compare and swap. That is,
if the current value of *ptr is oldval, then write newval into *ptr.
So tell us what the point of replacing oldval with itself is.

In addition, use __sync_val_compare_and_swap please.

  +  if (msec != 0) {
  +
  +  simple_lock(futex_shared_lock);
  +  
  +  thread_timeout_setup(current_thread());
  +
  +  assert_wait(NULL, TRUE);
  +  thread_will_wait_with_timeout(current_thread(), 
  (unsigned
 int)msec);
  +
  +  simple_unlock(futex_shared_lock);
  +  
  +  thread_block(NULL);
  +  
  +  return;
  +
  +  }
 
 This can't work... You're completely isolating the bounded wait case
 from the unbounded one. This is merely a sleep, not waiting for
 anything.
 
 But it works. I tested it. How do I rewrite this?

Oh I do believe the sleep works... But think again, this code isn't
waiting on any event at all, so how do you wake up the thread ??
Look at the implementation of thread_sleep to understand how to merge
this into the unbounded case.

  +  simple_lock(pfutex-futex_private_lock);
  +
  +  pfutex-num_waiters++;
  +
  +  pfutex-event = (event_t)futex_gen_unique_event_num
  +  ((vm_offset_t)pfutex-map + address,
 (vm_offset_t)pfutex-map, address);
 
 Use the address of the futex object in kernel memory for events, this
 is the traditional way of using them.
 
 I can't because currently I can have two futexes with the same event
 value. But
 if I implement the tree differently maybe this will be possible. I
 can get rid of
 futex_gen_unique_event_num().

Yes, do that.

-- 
Richard Braun



Re: [RFC] kern: simple futex for gnumach (version 11)

2014-01-09 Thread Richard Braun
On Thu, Jan 09, 2014 at 05:52:21PM +0100, Richard Braun wrote:
 On Thu, Jan 09, 2014 at 05:06:09PM +0100, Marin Ramesa wrote:
   +simple_lock(futex_shared_lock);
   +
   +thread_timeout_setup(current_thread());
   +
   +assert_wait(NULL, TRUE);
   +thread_will_wait_with_timeout(current_thread(), 
   (unsigned
  int)msec);
   +
   +simple_unlock(futex_shared_lock);
   +
   +thread_block(NULL);

By the way, why is thread_timeout_setup called here ? It really looks
wrong here.

-- 
Richard Braun



Re: [RFC] kern: simple futex for gnumach (version 11)

2014-01-09 Thread Richard Braun
On Thu, Jan 09, 2014 at 09:51:51PM +0100, Marin Ramesa wrote:
 On 01/09/2014 05:52:21 PM, Richard Braun wrote:
 On Thu, Jan 09, 2014 at 05:06:09PM +0100, Marin Ramesa wrote:
  Shouldn't the compare be atomic. Maybe I don't understand what
  atomic really
  means but the GCC manual says this function is. Or is it enough to
  hold the lock.
 
 From the GCC manual :
 These built-in functions perform an atomic compare and swap. That is,
 if the current value of *ptr is oldval, then write newval into *ptr.
 So tell us what the point of replacing oldval with itself is.
 
 I do a swap so it returns true if they are equal.

I'll say it again because it doesn't look like you got it : when I point
something out to you, consider you're wrong, and make the effort to
question your assumptions. You may end up being right at times, but most
often not. Now please, read your code again, then answer the question I
asked : So tell us what the point of replacing oldval with itself is.

 In addition, use __sync_val_compare_and_swap please.
 
 Don't you think it's better this way. The function already
 returns a boolean. What would I do with the contents of *ptr
 before the operation. It doesn't tell me if the swap was
 successful. I would need to introduce a new variable.

Actually it does, but since you probably didn't understand CAS, it's not
so surprising you're thinking that. Now, after reading the code again,
I'm not yet sure how to correctly deal with the previous value, and will
have to read about futexes a bit more. The boolean version should do for
now.

-- 
Richard Braun



Re: [RFC] kern: simple futex for gnumach (version 11)

2014-01-08 Thread Richard Braun
On Wed, Jan 08, 2014 at 08:43:28PM +0100, Marin Ramesa wrote:
 First threads were blocked and awakened when called from userspace. :)
 
 Timed waits work as expected. Private and shared futexes always block threads
 when called from futex_wait(). 
 
 This is now ready for test. What needs to be tested is:

This does look much better, but there is still quite some work to be
done before it gets right. I'll send a detailed review later.

-- 
Richard Braun



Re: [PATCH 2/2] Align kmem_cache objects using __cacheline_aligned

2014-01-08 Thread Richard Braun
On Thu, Jan 09, 2014 at 12:40:49AM +0100, Samuel Thibault wrote:
 Samuel Thibault, le Thu 09 Jan 2014 00:39:30 +0100, a écrit :
  Mmm, perhaps it would be more useful to define a typedef with the
  attribute, and use it instead of struct kmem_cache?
 
 Mmm, from slab.h it would seem that you can apply the attribute directly
 to the structure, thus even avoiding the typedef altogether?

Yes, that's the preferred way.

-- 
Richard Braun



Re: Valgrind porting

2014-01-06 Thread Richard Braun
On Mon, Jan 06, 2014 at 01:27:08AM +0530, Subhashish Pradhan wrote:
 Has anyone started working on porting valgrind to hurd?
 
 If not, I'd like to take up the task (and for GSOC).
 
 What would be the essential skills that would be required for this task?
 
 Shell scripting, understanding of C, and anything else?

Operating system knowledge from the userspace point of view, essentially
system calls, address space layout, and a decent grasp on the Mach and
Hurd concepts.

-- 
Richard Braun



Re: [PATCH 4/4] kern: optimize the layout of struct kmem_cache

2014-01-06 Thread Richard Braun
On Mon, Jan 06, 2014 at 11:47:10AM +0100, Justus Winter wrote:
 No, but I profiled this.  This is the output of pahole (on the left)
 and the results of my profiling on the right.  The rightmost number is
 the access count.  This is the situation before my patch:

This looks fine to me, although I'm usually not keen on micro
optimizations before fixing system encompassing design issues :).

-- 
Richard Braun



Re: [RFC] kern: simple futex for gnumach (version 10)

2014-01-06 Thread Richard Braun
);

External users don't care whether there is a tree and a lock.

 +/*
 + * This is a method for a thread to wait for a change of value at a given 
 address.
 + * 
 + * Function performs a lookup of the address in the futex tree. If address is
 + * found, value at the address is atomically compared with the argument 
 value.
 + * If the values are same, offset from the task's map and futex address is
 + * calculated and thread blocks.
 + */
 +int futex_wait(int *address, int value);

Again, external users don't care about the implementation, only the
behaviour they can expect.

 +/*
 + * This is a method for waking up one or all threads waiting for a change of 
 + * value at a given address.
 + * 
 + * Function performs a lookup of the address in the futex tree. If address is
 + * found and wake_all argument is TRUE, all threads with the same offsets are
 + * awakened. If wake_all is FALSE, only one thread from the futex is 
 awakened. 
 + */
 +int futex_wake(int *address, _Bool wake_all);

Likewise.

 +/* RPCs to call from userspace. */
 +int r_futex_wait(task_t task, pointer_t address, int value);
 +int r_futex_wake(task_t task, pointer_t address, boolean_t wake_all);

?

 +/*
 + * The idea is that each thread calls sync_circle_wait() with the same 
 object as 
 + * the argument. Then a thread outside of the sync circle calls 
 sync_circle_signal() 
 + * to send a wakeup signal. Function sync_circle_signal() first modifies the 
 sync_circle's 
 + * value, which closes the sync circle and then calls futex_wake().
 + */
 +struct sync_circle {
 +
 + int value;
 +
 +};
 +
 +#define decl_sync_circle(class, name) \
 +class struct sync_circle name;
 +
 +void sync_circle_init(struct sync_circle *scircle);
 +int sync_circle_wait(struct sync_circle *scircle);
 +int sync_circle_signal(struct sync_circle *scircle);
 +
 +/* Simple mutex implementation based on futex calls and GCC builtins. */
 +struct simple_mutex {
 +
 + #define SMUTEX_UNLOCKED 0
 + #define SMUTEX_NO_WAITERS 1
 + #define SMUTEX_WAITERS 2
 +
 + int value;
 +
 +};
 +
 +#define decl_simple_mutex(class, name) \
 +class struct simple_mutex name;
 +
 +void simple_mutex_init(struct simple_mutex *smutex);
 +void simple_mutex_lock(struct simple_mutex *smutex);
 +void simple_mutex_unlock(struct simple_mutex *smutex);

What does all this have antyhing to do in the public header ?

 @@ -158,6 +159,8 @@ void setup_main(void)
   recompute_priorities(NULL);
   compute_mach_factor();
  
 + futex_setup();
 +

Well, you got that one right, but I suppose it won't be needed once all
the other changes are made, since there should be no globally shared
structure after that point.

-- 
Richard Braun



Re: [RFC] kern: simple futex for gnumach (version 10)

2014-01-06 Thread Richard Braun
On Mon, Jan 06, 2014 at 12:34:32PM +0100, Richard Braun wrote:
  +static struct rbtree futex_tree;
 
 http://lists.gnu.org/archive/html/bug-hurd/2013-12/msg00545.html :
 Personally, I'd use a per-task red-black tree.

 
 http://lists.gnu.org/archive/html/bug-hurd/2013-12/msg00546.html :
 To finish with, the more I think about it, the less I understand why
 there is a need for futex objects in the first place. Instead of
 dynamically allocating such structures, it probably makes more sense
 to use the addresses of the physical page descriptors instead.
^^

After some thinking, this would actually not work, as physical pages can
be paged out. You can use a (VM object, offset) pair instead, but you
have to deal with private futexes, which should probably use a
(VM map, address) pair.

So, you actually need a global, shared container for process shared
futexes, and per-task containers for private ones. We also need to make
sure nothing bad happens to an (object, offset) pair when, say,
copy-on-write is performed by the VM system... All this looks quite
tricky to me, and certainly not a small hack entry :-/.

-- 
Richard Braun



Re: [RFC] kern: simple futex for gnumach (version 8)

2013-12-31 Thread Richard Braun
On Tue, Dec 31, 2013 at 04:26:01PM +0100, Richard Braun wrote:
 On Sun, Dec 29, 2013 at 09:44:51PM +0100, Marin Ramesa wrote:
  +   simple_lock(futex-futex_wait_lock);
  +
  +   /* If the value is still the same. */
  +   if (*address == value) {

In addition, such an access should go through some userspace memory
accessor (something like copyin at least, although passing it through
a message would be far cleaner), and it must be atomic. To finish with,
the more I think about it, the less I understand why there is a need
for futex objects in the first place. Instead of dynamically allocating
such structures, it probably makes more sense to use the addresses of
the physical page descriptors instead.

-- 
Richard Braun



Re: [RFC] kern: simple futex for gnumach (version 6)

2013-12-28 Thread Richard Braun
On Sat, Dec 28, 2013 at 02:30:01AM +0100, Marin Ramesa wrote:
 On 12/27/2013 07:14:40 PM, Richard Braun wrote:
  +void futex_cross_address_space_wake(futex_t futex, boolean_t
 wake_all)
  +{
  +  #define min(x, y) (x = y ? x : y)
  +
  +  queue_iterate(futex-chain, futex, futex_t, chain) {
  +
  +  simple_lock(futex-futex_wait_lock);
  +
  +  int i;
  +
  +  for (i = 0; i  min(futex-num_futexed_threads,
  +  ((futex_t)futex-chain.next)-num_futexed_threads); 
  i++) {
 
 If you have a list, you just walk it, there is no need to count the
 number of items.
 
 Threads are not in a list and I need to count the number of threads
 to use indexes for comparison of offsets.
 
  +void futex_wake_threads(futex_t futex, boolean_t wake_all)
  +{
  +  if (wake_all) {
  +  int i;
  +  for (i = 0; i  futex-num_futexed_threads; i++)
  +  futex_wake_one_thread(futex, i);
  +  } else
  +  futex_wake_one_thread(futex, futex-num_futexed_threads-1);
  +}
 
 What's the difference between this and
 futex_cross_address_space_wake ??
 
 futex_cross_address_space_wake() wakes all threads with the same
 offset. It
 doesn't matter in which futex they are in. This function is just for one
 futex, it doesn't matter which offsets the threads have.

Here is how it probably should be :

There should be one futex_waiter struct per thread, allocated on the
stack when a thread is about to wait. That structure is then queued on
the futex it's waiting for, using the address of the futex as the
wakeup event. When another thread wakes the futex, it walks the list
of futex_waiters, and for each of them, wakes up the associated thread.
No need to count anything here, just a simple list to walk, and no
need to have distinct cases between cross address space wakeups or not.
What makes a futex cross address space is simply that its a non first
class kernel object, just like ports, referenced with a (map, address)
pair. Once in the kernel, it's merely a wait queue.

-- 
Richard Braun



Re: [RFC] kern: simple futex for gnumach (version 6)

2013-12-27 Thread Richard Braun
allocated in futex_wait ? In that case, the target thread might end up
trying to use memory that has already been freed by the waker. And this
is the kind of mistakes that someone with proper experience with
concurrency would not do.

I may already have said that, but better safe than sorry so: I don't
see the point of maintaining the number of threads.

 +void futex_cross_address_space_wake(futex_t futex, boolean_t wake_all)
 +{
 + #define min(x, y) (x = y ? x : y)
 +
 + queue_iterate(futex-chain, futex, futex_t, chain) {
 +
 + simple_lock(futex-futex_wait_lock);
 +
 + int i;
 +
 + for (i = 0; i  min(futex-num_futexed_threads, 
 + ((futex_t)futex-chain.next)-num_futexed_threads); 
 i++) {

If you have a list, you just walk it, there is no need to count the
number of items.

 + 
 futex_wake_one_thread((futex_t)futex-chain.next, i);
 + 
 + if 
 (((futex_t)futex-chain.next)-num_futexed_threads == 0) {
 + simple_unlock(futex-futex_wait_lock);
 + 
 simple_unlock(((futex_t)futex-chain.next)-futex_wait_lock);
 + 
 futex_hash_table_delete_futex((futex_t)futex-chain.next);
 + #undef min
 + return; 
 + }
 + }
 + }
 + 
 + simple_unlock(((futex_t)futex-chain.next)-futex_wait_lock);
 + simple_unlock(futex-futex_wait_lock);
 + 
 + }
 +
 +#undef min

This isn't C, it's a preprocessor directive, and you've already
undefined min earlier.

 +void futex_wake_threads(futex_t futex, boolean_t wake_all)
 +{
 + if (wake_all) {
 + int i;
 + for (i = 0; i  futex-num_futexed_threads; i++) 
 + futex_wake_one_thread(futex, i);
 + } else 
 + futex_wake_one_thread(futex, futex-num_futexed_threads-1);
 +}

What's the difference between this and futex_cross_address_space_wake ??

 +unsigned int futex_hash(int *address)
 +{
 + unsigned int hash_val = 0;
 +
 + hash_val = (unsigned int)address + (hash_val  5) - hash_val;
 +
 + if (table != NULL) {
 + unsigned int ret = hash_val % table-size; 

A modulo is expensive. Make the hash table size a power-of-two and use
an AND.

 +int futex_hash_table_add_address(int *address)
 +{
 + futex_t new_futex;
 +
 + unsigned int hash_val = futex_hash(address);
 +
 + if (table != NULL) {
 + simple_lock(table-futex_hash_table_lock);
 + }
 +
 + if ((new_futex = (futex_t)kalloc(sizeof(struct futex))) == NULL) {
 + if (table != NULL)
 + simple_unlock(table-futex_hash_table_lock);

Uh ? Do you have a hash table or not ? How can this work if it's not
there ??

 + table-futex_elements[hash_val] = *new_futex;
 + table-size++;

Looks like you have one after all...

 +int futex_thread_init(futex_t futex, futex_thread_t thread)
 +{
 + if ((thread = (futex_thread_t)kalloc(sizeof(futex_thread_t))) == NULL)

Why do you pass thread as an argument ?? This means futex_wait is bound
to crash on its first access to the thread variable...

 + return FUTEX_RESOURCE_SHORTAGE;
 + 
 + thread-thread = current_thread();
 + thread-futex = futex;
 +
 + *thread-map = current_map();

You don't have to store the map since you can find it through the task
of the thread.

 + if ((vm_map_lookup(thread-map, (vm_offset_t)futex-address, 
 VM_PROT_READ, thread-version, thread-object,
 + thread-offset, thread-out_prot, 
 thread-wired) != KERN_SUCCESS)) {
 + kfree((vm_offset_t)thread, sizeof(struct futex_thread));
 + return FUTEX_MEMORY_ERROR;
 + }

Futexes are only concerned with (map, address) pairs, why are
VM objects involved ?

 +++ b/kern/futex.h

The public header should at least define struct futex as an opaque type.

 +++ b/kern/futex_i.h

You didn't use the private header correctly. What you put into it
should instead be declared as static functions inside the .c file.

There are undoubtedly other problems but I don't have the time nor
the motivation to look through them now. If you really insist on this
task, you should really, really, REALLY get better with the basics
first. There are just too many mistakes here to do anything with that
patch.

-- 
Richard Braun



Re: [RFC] kern: simple futex for gnumach (version 6)

2013-12-27 Thread Richard Braun
On Fri, Dec 27, 2013 at 07:55:02PM +0100, Marin Ramesa wrote:
 On 12/27/2013 07:14:40 PM, Richard Braun wrote:
 What do you mean when you say you test on the Hurd and Linux ? How do
 you use GDB with Mach to determine it's actually kalloc thta
 segfaults ?
 
 I link it with gnumach .o files and then run it trough GDB to see if
 I don't
 make big mistakes in the code.

Do you mean you're expecting kalloc() to actually work in a POSIX
environment ?

-- 
Richard Braun



Re: [RFC] kern: simple futex for gnumach (version 6)

2013-12-27 Thread Richard Braun
On Fri, Dec 27, 2013 at 10:23:01PM +0100, Marin Ramesa wrote:
 On 12/27/2013 09:58:07 PM, Richard Braun wrote:
 Do you mean you're expecting kalloc() to actually work in a POSIX
 environment ?
 
 I expected it to work on Hurd running gnumach, but I don't understand
 what it means to function to work in a POSIX environment.

If running GNU Mach as the kernel, it should. If running it from GDB
in userspace (and that's what I mean when I say a POSIX environment),
there is no way it can.

 But it's OK, I can test the code without kalloc().

Not completely, because you won't have address spaces (not due to kalloc
missing but rather because kalloc also relies on the virtual memory
system, and at this point, I guess kalloc doesn't work because the
environment in which you test is neither real hardware nor a virtual
machine emulating the appropriate architecture, preventing the VM system
from working).

-- 
Richard Braun



Re: [RFC] kern: simple futex for gnumach (version 5)

2013-12-26 Thread Richard Braun
On Thu, Dec 26, 2013 at 02:30:10PM +0100, Marin Ramesa wrote:
 + futex-address = address;
 + futex-num_futexed_threads = 0;
 + futex-next_futex = NULL;
 + futex-prev_futex = (table-futex_elements[prev_hash_val]);
 + futex-prev_futex-next_futex = futex;
 + *futex-map = current_thread()-task-map;

A futex shouldn't be a task-local object since it's used for inter
process synchronization. There should be per-thread objects (probably
allocated on the stack since a thread can only be doing one wait at
a time), and these per-thread objects should be listed in the global
futex object. Waking up the futex then simply walks the list and wakes
up threads.

 + if ((vm_map_lookup(futex-map, (vm_offset_t)address, VM_PROT_READ, 
 futex-version, futex-object,
 + futex-offset, futex-out_prot, futex-wired) 
 != KERN_SUCCESS)) {
 + unsigned int temp_hash_val = futex_hash(address);
 + __builtin_free((table-futex_elements[temp_hash_val]));

Why __builtin_malloc and __builtin_free ??

 + if (futex-num_futexed_threads == 128)
 + return FUTEX_RESOURCE_SHORTAGE;

I assume this limit is temporary. If not, remove it, there is no reason
to add a constraint like this one.

 + suspend:
 + assert_wait(current_thread()-state , FALSE);
 + simple_unlock(futex-futex_wait_lock);
 + kern_return_t ret = thread_suspend(current_thread());

I really doubt assert_wait can be used with thread_suspend and
thread_resume... Use thread_block and thread_wakeup instead. Again, be
more careful.

 +struct futex {

As previously said, rework that structure.

 + /* Next futex in queue. */
 + futex_t next_futex;
 +
 + /* Previous futex in queue. */
 + futex_t prev_futex;

Do NOT reimplement generic doubly-linked lists...

 + /* Number of futexed threads at the same address. */
 + unsigned int num_futexed_threads;
 +
 + /* Array of futexed threads at the same address. */
 + //thread_t futexed_threads;
 +
 + thread_t futexed_threads[128];

Ugh. No.

 +int futex_init(futex_t futex, int *address);
 +extern int futex_wait(int *address, int value);
 +extern int futex_wake(int *address, boolean_t wake_all);
 +void futex_cross_address_space_wake(futex_t futex, boolean_t wake_all);
 +void futex_wake_threads(futex_t futex, boolean_t wake_all);
 +int futex_hash_table_init(void);
 +unsigned int futex_hash(int *address);
 +futex_t futex_hash_table_lookup_address(int *address);
 +int futex_hash_table_add_address(int *address);
 +void futex_hash_table_delete_futex(futex_t futex);

I know this isn't the traditional way to do it in Mach, but please,
extensively document the API in the header, e.g. as it's done for the
slab allocator. I also suggest moving everything not public (such as
the hash table) in the .c file, and if there is anything private that
still needs to be in a header, move that to a _i.h file (i could mean
internal/implementation/inline/whatever), so that the main header only
documents the public API.

-- 
Richard Braun



Re: [RFC] kern: simple futex for gnumach (version 5)

2013-12-26 Thread Richard Braun
On Thu, Dec 26, 2013 at 02:58:01PM +0100, Richard Braun wrote:
 I know this isn't the traditional way to do it in Mach, but please,
 extensively document the API in the header, e.g. as it's done for the
 slab allocator. I also suggest moving everything not public (such as

Actually, kern/rbtree.h is a better example concerning the separation
of private/public stuff.

-- 
Richard Braun



Re: [RFC] kern: simple futex for gnumach (version 5)

2013-12-26 Thread Richard Braun
On Thu, Dec 26, 2013 at 03:15:24PM +0100, Marin Ramesa wrote:
 I get segfaults in kalloc(). I don't know what I'm doing wrong.

Show us how you use it.

-- 
Richard Braun



Re: [RFC] kern: simple futex for gnumach (version 5)

2013-12-26 Thread Richard Braun
On Thu, Dec 26, 2013 at 03:51:30PM +0100, Marin Ramesa wrote:
 futex-futexed_threads =
 (thread_t)kalloc((futex-num_futexed_threads+1)*sizeof(struct
 thread));
 
 When futexed_threads is a pointer to struct thread.

Why are you allocating a thread structure ??

I strongly suspect kalloc does what you want it to do, but something
in your code makes an illegal access. In the worst case, use prints
to find the faulty instruction.

-- 
Richard Braun



[PATCH] Implement thread destruction

2013-12-26 Thread Richard Braun
This change makes libpthread release almost every resource allocated for
a thread, including the kernel thread, its send right, its reply port
and its stack. This improves resource usage after peaks of activity
during which servers can create hundreds or even thousands of threads.

To achieve it, the library relies on the recently added
thread_terminate_release one-way GNU Mach RPC, which allows threads to
release their last resources along with terminating in a single
operation. The pthread_exit function unconditionally releases all the
resources it can, including other kernel objects (namely the port used
for blocking and waking up) and signal states. When releasing the
pthread structure, a reference counter is used so that joinable threads
remain available. Once the reference counter drops to 0, the pthread
structure can be recycled. Thread local storage (TLS) is also recycled
since it needs to remain allocated while terminating the thread, as it
is there that the reply port is stored. TLS could be released too, after
grabbing the reply port name, but it is difficult to make sure no RPC
involving a reply port is used afterwards, so the simpler solution of
recycling TLS was chosen.

This patch can be applied on top of the master-threadvars branch, as
a few commits are still not present in master.
---
 Makefile|  2 +-
 pthread/pt-alloc.c  | 21 ++
 pthread/pt-create.c | 69 +++
 pthread/pt-dealloc.c|  5 +++
 pthread/pt-detach.c | 24 +++
 pthread/pt-exit.c   | 35 
 pthread/pt-internal.h   | 36 ++---
 pthread/pt-join.c   | 18 +
 sysdeps/mach/hurd/pt-sigstate-destroy.c |  2 +-
 sysdeps/mach/hurd/pt-sigstate-init.c| 18 -
 sysdeps/mach/hurd/pt-sysdep.c   |  5 +++
 sysdeps/mach/hurd/pt-sysdep.h   |  3 +-
 sysdeps/mach/pt-thread-alloc.c  | 31 --
 sysdeps/mach/pt-thread-dealloc.c|  3 +-
 sysdeps/mach/pt-thread-halt.c   | 37 -
 sysdeps/mach/pt-thread-start.c  |  4 +-
 sysdeps/mach/pt-thread-terminate.c  | 72 +
 17 files changed, 194 insertions(+), 191 deletions(-)
 delete mode 100644 sysdeps/mach/pt-thread-halt.c
 create mode 100644 sysdeps/mach/pt-thread-terminate.c

diff --git a/Makefile b/Makefile
index c57f1a0..61e59fc 100644
--- a/Makefile
+++ b/Makefile
@@ -121,7 +121,7 @@ libpthread-routines := pt-attr pt-attr-destroy 
pt-attr-getdetachstate   \
pt-thread-alloc \
pt-thread-dealloc   \
pt-thread-start \
-   pt-thread-halt  \
+   pt-thread-terminate \
pt-startup  \
\
pt-getconcurrency pt-setconcurrency \
diff --git a/pthread/pt-alloc.c b/pthread/pt-alloc.c
index 604d376..aa0c9e2 100644
--- a/pthread/pt-alloc.c
+++ b/pthread/pt-alloc.c
@@ -47,7 +47,7 @@ struct __pthread *__pthread_free_threads;
 pthread_mutex_t __pthread_free_threads_lock;
 
 static inline error_t
-initialize_pthread (struct __pthread *new, int recycling)
+initialize_pthread (struct __pthread *new)
 {
   error_t err;
 
@@ -55,6 +55,7 @@ initialize_pthread (struct __pthread *new, int recycling)
   if (err)
 return err;
 
+  new-nr_refs = 1;
   new-cancel_lock = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
   new-cancel_hook = NULL;
   new-cancel_hook_arg = NULL;
@@ -62,14 +63,6 @@ initialize_pthread (struct __pthread *new, int recycling)
   new-cancel_type = PTHREAD_CANCEL_DEFERRED;
   new-cancel_pending = 0;
 
-  if (recycling)
-/* Since we are recycling PTHREAD, we can assume certains things
-   about PTHREAD's current state and save some cycles by not
-   rewriting the memory.  */
-return 0;
-
-  new-stack = 0;
-
   new-state_lock = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
   new-state_cond = (pthread_cond_t) PTHREAD_COND_INITIALIZER;
 
@@ -117,12 +110,6 @@ __pthread_alloc (struct __pthread **pthread)
 
   if (new)
 {
-  /* The thread may still be running.  Make sure it is stopped.
-If this is the case, then the thread is either at the end of
-__pthread_dealloc or in __pthread_thread_halt.  In both
-cases, we are interrupt it.  */
-  __pthread_thread_halt (new);
-
 #ifdef ENABLE_TLS
   if (new-tcb)
{
@@ -132,7 +119,7 @@ __pthread_alloc (struct __pthread **pthread)
}
 #endif /* ENABLE_TLS */
 
-  err = initialize_pthread (new, 1);
+  

Re: [PATCH] Implement thread destruction

2013-12-26 Thread Richard Braun
On Thu, Dec 26, 2013 at 05:44:56PM +0100, Samuel Thibault wrote:
 loses, actually :)
 (and ditto further down)

Right, thanks.

-- 
Richard Braun



Re: [PATCH] kern: simple futex for gnumach (version 4)

2013-12-24 Thread Richard Braun
On Sun, Dec 22, 2013 at 03:58:55PM +0100, Marin Ramesa wrote:
 +simpleroutine futex_rpc(
 + thread  : thread_t;
 + address : pointer_t;
 + value   : int;
 + operation   : int);
 +
 +simpleroutine futex_wait_rpc(
 + thread  : thread_t;
 + address : pointer_t;
 + value   : int);
 +
 +simpleroutine futex_wake_rpc(
 + thread  : thread_t;
 + address : pointer_t;
 + thread_num  : int);

Obviously, you rushed your work without trying to understand what you
were doing, and this is becoming frustrating. Don't blindly and
mindlessly copy the first thing you see around...

1/ A simpleroutine is a one-way RPC, without a return value other than
that of the message transmission.

2/ Futex calls should operate on futexes, not threads. If you actually
only want to specify addresses in the calls, use a task_t as first
parameter, because there is no risk of right reference leak when calling
mach_task_self, whereas there are with mach_thread_self.

And again, I insist on *not* creating ioctl-style calls with an
operation parameter. The operation is the RPC itself. Also, AIUI, the
operations are wait and wake, so why create a third futex RPC ?

To finish with, don't suffix RPCs with _rpc ...

Personal question: why are you working on this ? Considering the
beginner mistakes you did at the C level itself, and that you've never
even run a real GNU Mach instance, what makes you think you have the
proper experience to work on such a low-level tool that involves both
virtual memory and concurrency, two of the most difficult domains in
computer science ?

-- 
Richard Braun



Re: [PATCH] kern: simple futex for gnumach (version 4)

2013-12-24 Thread Richard Braun
On Tue, Dec 24, 2013 at 12:52:23PM +0100, Marin Ramesa wrote:
 I need to start somewhere. I really want to learn how kernels are
 programmed.
 This task was listed in the small hacks entry, I really thought it
 would be a
 small hack.

That's probably a mistake on our part.

 There is a one call to vm_map lookup to retrive the offset and the
 object. Simple

How do you implement cross address space synchronization ?

 locks are used and there are calls to thread_resume() and
 thread_suspend(). I don't
 see anything so much difficult that I can't learn while doing it.

Well, using thread_resume/thread_suspend might work for non preemptible
kernels, but not for a preemptible one, or a multiprocessor one like
Mach was.

Look at your call to thread_suspend. If thread_resume is called after
the futex lock is released (it can't be called before since it's called
with that same lock reacquired), but before thread_suspend is called,
the thread will miss its wakeup. This is why interlocks (usually hidden
in wait queues) are normally used. See assert_wait().

 But I won't work on this if it's frustrating. I don't want to cause
 any trouble.

For now, I'm the only one reacting to this, not much of a trouble.
But I'm pretty sure we would all like contributors to pay great care
to what they're doing, whatever their technical level.

-- 
Richard Braun



Re: [PATCH] kern: simple futex for gnumach (version 4)

2013-12-24 Thread Richard Braun
On Tue, Dec 24, 2013 at 04:55:47PM +0100, Marin Ramesa wrote:
 I use a recursive futex_wake(). It first scans all the futexes if
 they are on the same offset and if they share the same vm_object.
 If they do, recursion is used to wake a number of threads in those
 futexes. The number of threads awakened is constant troughout the
 same offsets and in the same objects. In this way synchronization
 is possible. I don't do anything in futex_wait().

Right. Well, consider how small stacks usually are in a kernel, and
you should understand why anything recursive (except if bounded) is
unacceptable.

Then, why a scan through vm_objects ? Why not directly find the one
futex associated with a (map, address) and wake all threads waiting
on it ?

Also, why pass a number of threads to wake ? Why not simply choose
between one or all ?

-- 
Richard Braun



Re: [PATCH] kern: simple futex for gnumach (version 4)

2013-12-24 Thread Richard Braun
On Tue, Dec 24, 2013 at 05:38:59PM +0100, Marin Ramesa wrote:
 I have read in Futexes are tricky that futex() is used with INT_MAX
 argument. I want to keep that usage. So, if a number of threads to
 wake is greater than number of threads in a futex I wake all.

And it also says everything else than 1 and INT_MAX make little sense
in practice.

Please, take the habit to re-read and reconsider every time I (or
someone else from the community) questions you about something. Don't
wait for us to reply to start thinking... I'm saying this because almost
every exchange we've had until now is 1/ you do something wrong 2/ I
tell you it's wrong 3/ you justify why you did something wrong without
making the effort to reconsider 4/ I show you it's definitely wrong
5/ you end up agreeing. Let's make it a 3-step process.

-- 
Richard Braun



Re: [PATCH] kern: simple futex for gnumach (version 3)

2013-12-23 Thread Richard Braun
On Sun, Dec 22, 2013 at 11:56:39PM +0100, Marin Ramesa wrote:
 Can you please show me the gnumach menuentry generated by grub?

How about looking at the documentation ? For example
http://www.gnu.org/software/grub/manual/grub.html#GNU_002fHurd

-- 
Richard Braun



Re: [PATCH] kern: simple futex for gnumach (version 3)

2013-12-23 Thread Richard Braun
On Sun, Dec 22, 2013 at 11:56:39PM +0100, Marin Ramesa wrote:
 On 22/12/13 22:04:15, Richard Braun wrote: 
  Whether it's in a virtual machine or a real one doesn't matter at 
  all. On Debian, simply copy the gnumach binary to /boot and run
  update-grub. You'll get a new entry at boot time for your kernel.
 
 I don't have the update-grub command (I'm not using Debian). So I have 
 to modify files by hand and when I write 'multiboot /boot/gnumach.gz' I 
 get a 'invalid magic number' error at boot time.
 
 Can you please show me the gnumach menuentry generated by grub?

Now that I think about it, you should already have at least one such
entry on your system, whether Debian or not. Or are you saying you're
not even running the Hurd at all ?!

-- 
Richard Braun



Re: [PATCH] kern: simple futex for gnumach (version 3)

2013-12-22 Thread Richard Braun
On Sun, Dec 22, 2013 at 03:32:42PM +0100, Marin Ramesa wrote:
 On 22.12.2013 01:28:37, Richard Braun wrote:
  On Sat, Dec 21, 2013 at 11:29:34PM +0100, Marin Ramesa wrote:
   On 21.12.2013 23:20:43, Richard Braun wrote:
How about adding everything necessary to actually test it from
userspace ?
   
   Sure, what needs to be added? I don't have the conditions to test
   this. I earlier wrote some proof-of-concept stuff that might be 
   used as a test, but I don't know how.
  
  Learn about MiG and how to write RPCs. There is a lot you can find on
  the wiki and through search engines. If possible, don't create an
  ioctl-style of call, with many possible behaviours through the same
  entry point, but make several distinct RPCs instead, then add them to
  include/mach/gnumach.defs. Look at how it's done for existing RPCs,
  but make sure you read and understand the documentation about MiG and 
  Mach IPC if you want to work on such low-level stuff.
 
 OK, I'm reading the documentation. In the meantime I have defined 
 several simple RPCs for testing purposes. I will send the updated patch 
 shortly.

Test it yourself from userspace before you resubmit.

-- 
Richard Braun



Re: [PATCH] kern: simple futex for gnumach (version 3)

2013-12-22 Thread Richard Braun
On Sun, Dec 22, 2013 at 06:22:03PM +0100, Marin Ramesa wrote:
 On 22.12.2013 17:56:32, Richard Braun wrote:
  Test it yourself from userspace before you resubmit.
 
 That's the problem. I don't know how to test this. How to boot up a 
 modified gnumach and then execute a program over it? I tried with QEMU, 
 but I can't get it to work.

Are you saying you've been sending us patches without ever
testing them ?

-- 
Richard Braun



Re: [PATCH] kern: simple futex for gnumach (version 3)

2013-12-22 Thread Richard Braun
On Sun, Dec 22, 2013 at 06:57:50PM +0100, Marin Ramesa wrote:
 On 22.12.2013 18:25:10, Richard Braun wrote:
  Are you saying you've been sending us patches without ever
  testing them ?
 
 Yes. But that's different, that's just cleaning the code. Removing 
 forward declarations and unused variables doesn't change the behavior. 
 Now, I need to test this, but I don't know how.

Cleaning isn't supposed to change the behaviour, but that sometimes
happens, in particular with the kind of optimizations applied by a
modern compiler such as gcc, so please, test before sending...

-- 
Richard Braun



Re: [PATCH] kern: simple futex for gnumach (version 3)

2013-12-22 Thread Richard Braun
On Sun, Dec 22, 2013 at 06:22:03PM +0100, Marin Ramesa wrote:
 On 22.12.2013 17:56:32, Richard Braun wrote:
   OK, I'm reading the documentation. In the meantime I have defined 
   several simple RPCs for testing purposes. I will send the updated
   patch shortly.
  
  Test it yourself from userspace before you resubmit.
 
 That's the problem. I don't know how to test this. How to boot up a 
 modified gnumach and then execute a program over it? I tried with QEMU, 
 but I can't get it to work.

Whether it's in a virtual machine or a real one doesn't matter at all.
On Debian, simply copy the gnumach binary to /boot and run update-grub.
You'll get a new entry at boot time for your kernel.

-- 
Richard Braun



Re: [PATCH] kern: simple futex for gnumach (version 3)

2013-12-21 Thread Richard Braun
On Sat, Dec 21, 2013 at 10:55:14PM +0100, Marin Ramesa wrote:
 I noticed some bugs. I'm sending a fixed patch. The prevoius version is here:
 http://lists.gnu.org/archive/html/bug-hurd/2013-12/msg00493.html

How about adding everything necessary to actually test it from
userspace ?

-- 
Richard Braun



Re: [RFC] Simple futex for gnumach (version 2)

2013-12-21 Thread Richard Braun
On Sat, Dec 21, 2013 at 11:26:37PM +0100, Marin Ramesa wrote:
  Why not e.g. a GPL licence, even if this function is good it might 
  not be accepted due to this.
 
 I don't know much about licenses, I copied this from kern/slab.c. It 
 doesn't make a difference to me what license it is as long as it has 
 this 'lack of warranty' text.

It does matter. If you look closely, there are two licenses in the file
kern/slab.c. You picked up the original one, not the one covering the
GNU Mach fork. Currently, you're required to assign copyright of your
contributions to the FSF.

The slab allocator did not originate from GNU Mach and its history is a
bit messy. It is really not a good template for contributions.

-- 
Richard Braun



Re: [PATCH] kern: simple futex for gnumach (version 3)

2013-12-21 Thread Richard Braun
On Sat, Dec 21, 2013 at 11:29:34PM +0100, Marin Ramesa wrote:
 On 21.12.2013 23:20:43, Richard Braun wrote:
  How about adding everything necessary to actually test it from
  userspace ?
 
 Sure, what needs to be added? I don't have the conditions to test this. 
 I earlier wrote some proof-of-concept stuff that might be used as a 
 test, but I don't know how.

Learn about MiG and how to write RPCs. There is a lot you can find on
the wiki and through search engines. If possible, don't create an
ioctl-style of call, with many possible behaviours through the same
entry point, but make several distinct RPCs instead, then add them to
include/mach/gnumach.defs. Look at how it's done for existing RPCs, but
make sure you read and understand the documentation about MiG and Mach
IPC if you want to work on such low-level stuff.

-- 
Richard Braun



Re: [PATCH 1/3] ipc: avoid dereference of null pointer and quiet the GCC warning about uninitialized variable

2013-12-18 Thread Richard Braun
On Wed, Dec 18, 2013 at 10:37:03AM +0100, Marin Ramesa wrote:
 Compiler needs to check both !a and !b. In order to evaluate !b it must 
 evaluate b. So when the code path is that when entry is a null pointer, 
 the evaluation of b results in a dereference of a null pointer.

No, that's wrong. The  and || operators are guaranteed to be evaluated
left-to-right, and yield if the first operand compares equal to 0. And
that's exactly why this check against NULL is done first.

-- 
Richard Braun



Re: [PATCH 1/3] ipc: avoid dereference of null pointer and quiet the GCC warning about uninitialized variable

2013-12-18 Thread Richard Braun
On Wed, Dec 18, 2013 at 10:46:40AM +0100, Richard Braun wrote:
 On Wed, Dec 18, 2013 at 10:37:03AM +0100, Marin Ramesa wrote:
  Compiler needs to check both !a and !b. In order to evaluate !b it must 
  evaluate b. So when the code path is that when entry is a null pointer, 
  the evaluation of b results in a dereference of a null pointer.
 
 No, that's wrong. The  and || operators are guaranteed to be evaluated
 left-to-right, and yield if the first operand compares equal to 0. And
 that's exactly why this check against NULL is done first.

Compares equal to 0 for , and not equal to 0 for ||, obviously.

-- 
Richard Braun



Re: [PATCH 1/3] ipc: avoid dereference of null pointer and quiet the GCC warning about uninitialized variable

2013-12-18 Thread Richard Braun
On Wed, Dec 18, 2013 at 10:55:47AM +0100, Marin Ramesa wrote:
 On 18.12.2013 10:46:40, Richard Braun wrote:
  No, that's wrong. The  and || operators are guaranteed to be
  evaluated left-to-right, and yield if the first operand compares 
  equal to 0. And that's exactly why this check against NULL is done 
  first.
 
 In the expression (!a  !b), if !a equals 0, the compiler must check 
 !b == 0 in order to return TRUE. If !a equals 0, that means the entry 
 is a null pointer, and evaluation of !b is a dereference of a null 
 pointer.

The expression is ((a == NULL) || a-something), and I agree it is
equivalent to !((a != NULL)  !a-something). And again, both the
 and || operators are guaranteed to be evaluated left-to-right and
*yield* without evaluating the second operand if the first compares
or not to 0, depending on the operator.

So, let's take the seconds form since that's what you've used, without
the negation for simplicity : ((a != NULL)  !a-something)

If a isn't NULL, then it returns !a-something. If a is NULL, then
(a != NULL) compares equal to 0, and  returns 0 before evaluating
!a-something. So no, there can't be a null pointer dereference here.

And this really is basic C, so please double check your changes.

-- 
Richard Braun



Re: [PATCH 2/3] ipc/mach_debug.c (host_ipc_hash_info): quiet GCC warning about uninitialized variable

2013-12-18 Thread Richard Braun
On Wed, Dec 18, 2013 at 09:17:48AM +0100, Marin Ramesa wrote:
 Don't initialize to zero, rather move the initialization of size before
 the break statement. Break on the first iteration should never happen, so the
 position of initialization doesn't matter.
 
 * ipc/mach_debug.c (host_ipc_hash_info) (size): Don't initialize to zero.
 (host_ipc_hash_info) (size): Move initialization before the break statement.
 
 ---
  ipc/mach_debug.c | 6 --
  1 file changed, 4 insertions(+), 2 deletions(-)
 
 diff --git a/ipc/mach_debug.c b/ipc/mach_debug.c
 index dd9057a..d7c454b 100644
 --- a/ipc/mach_debug.c
 +++ b/ipc/mach_debug.c
 @@ -112,7 +112,7 @@ host_ipc_hash_info(
   mach_msg_type_number_t  *countp)
  {
   vm_offset_t addr;
 - vm_size_t size = 0; /* Suppress gcc warning */
 + vm_size_t size;
   hash_info_bucket_t *info;
   unsigned int potential, actual;
   kern_return_t kr;
 @@ -127,6 +127,9 @@ host_ipc_hash_info(
  
   for (;;) {
   actual = ipc_hash_info(info, potential);
 +
 + size = round_page(actual * sizeof *info);
 +
   if (actual = potential)
   break;
  
 @@ -135,7 +138,6 @@ host_ipc_hash_info(
   if (info != *infop)
   kmem_free(ipc_kernel_map, addr, size);

See that kmem_free() right here, it uses the size computed during the
previous iteration. It works as it is because ipc_hash_info returns
ipc_hash_global_size, a value that doesn't change after initialization.
But it will break if the hash table is made resizable.

 - size = round_page(actual * sizeof *info);
   kr = kmem_alloc_pageable(ipc_kernel_map, addr, size);
   if (kr != KERN_SUCCESS)
   return KERN_RESOURCE_SHORTAGE;

-- 
Richard Braun



Re: [PATCH 3/3] vm/vm_debug.c: quiet GCC warning about uninitialized variable

2013-12-18 Thread Richard Braun
On Wed, Dec 18, 2013 at 09:17:49AM +0100, Marin Ramesa wrote:
 The same situation as the previous patch.

Same comment as for the previous patch.

-- 
Richard Braun



Re: [PATCH 1/3] ipc: avoid dereference of null pointer and quiet the GCC warning about uninitialized variable

2013-12-18 Thread Richard Braun
On Wed, Dec 18, 2013 at 11:25:36AM +0100, Marin Ramesa wrote:
 Yes, vou're right. I got confused. But then something else is happening 
 here. When I write the assertion this way: 
 
 assert((entry == IE_NULL) ||  ((entry != IE_NULL) ? IE_BITS_TYPE
 (entry-ie_bits) : TRUE));
 
 GCC stops complaing about uninitialized variable.

I don't get this warning, can you tell us how you configure GNU Mach ?

-- 
Richard Braun



Re: [PATCH 1/3] ipc: avoid dereference of null pointer and quiet the GCC warning about uninitialized variable

2013-12-18 Thread Richard Braun
On Wed, Dec 18, 2013 at 11:40:09AM +0100, Marin Ramesa wrote:
 On 18.12.2013 11:34:03, Richard Braun wrote:
  I don't get this warning, can you tell us how you configure GNU 
  Mach ?
 
 --enable-kdb --prefix=
 
 But the warning is turned off by: 
 
 ipc_port_t notify_port = 0;
 
 in ipc/ipc_kmsg.c.
 
 I don't think that's a good solution. I think something else is 
 happening here.

How can a local variable in ipc_kmsg.c have any effect on another local
variable in ipc_entry.c ??

-- 
Richard Braun



Re: [PATCH 3/4] device/chario.c: qualify pointers that access their dereferenced values under locks with __restrict__

2013-12-17 Thread Richard Braun
On Tue, Dec 17, 2013 at 06:51:49PM +0100, Samuel Thibault wrote:
 I don't think we benefit very much here, do we?  restrict is a very
 difficult thing to maintain, few programmers really understand what it
 means, I'd rather avoid introducing too many of them.

I agree. Note that GNU Mach is built with -fno-strict-aliasing exactly
for such reasons, as are other well known projects. Besides, the
restrict keyword is only really useful when you have more than one
pointer of the same type, since strict aliasing would already apply for
pointers of different types. And as you mention it, the lock semantics
are actually what matter most here with regard to code ordering, and
they actually reduce the effectiveness of optimizations.

-- 
Richard Braun



Re: [PATCH 3/4] device/chario.c: qualify pointers that access their dereferenced values under locks with __restrict__

2013-12-17 Thread Richard Braun
On Tue, Dec 17, 2013 at 03:58:27PM +0100, Marin Ramesa wrote:
 Qualifier __restrict__ means that only the pointer under __restrict__ will be 
 used
 to access dereferenced values. So if a code is under locks and no function is 
 called
 in the critical section with pointer as an argument, it's safe to use 
 __restrict__.
 This allows the compiler to make optimizations.

Marin, to begin with, I'd like to thank you for the work you've done so
far. It's tedious and not something people usually want to do, and yet
it's important. But please, learn from experience and don't try to
overengineer. Keep it simple, limit yourself to cleaning the code, not
making it more complicated (and then dirtier) than it could be.

-- 
Richard Braun



Re: [PATCH 4/4] device/chario.c (char_write): avoid segmentation fault

2013-12-15 Thread Richard Braun
On Sat, Dec 14, 2013 at 01:32:27PM +0100, Marin Ramesa wrote:
 On 14.12.2013 12:45:32, Richard Braun wrote:
  I really don't see a problem in that code, you'll have to describe it
  better. 
 
 So a pointer to io_data is cast to a pointer to a vm_map_copy structure 
 and then passed to vm_map_copyout() which uses the vm_map_copy 
 structure members as if the contents of the memory at the source 
 address were vm_map_copy structure objects, not objects of io_data 
 which is of unknown size and origin to the function. This can lead to a 
 segmentation fault, as is shown in that short test program.
 
 My patch makes sure the io_data actually came from a vm_map_copy 
 structure.

What makes you think the content could be something else than a
vm_map_copy object ?

  On the other hand, your patch relies on knowing the target
  types, although vm_map_copy_t is explicitely described as being
  opaque.
 
 I don't see a problem with it. There is an explicit cast to 
 vm_map_copy_t. It's first member type is known.

The target type of the cast is a pointer (a very bad historical practice
in Mach that consists of typedef'ing pointers to structures in order to
somehow add an abstraction level intended to make the coding style more
object-oriented). In proper C, a cast means the programmer is certain
about the data type. Here, it is used to call vm_map_copyout without
emitting warnings. It has nothing to do with accessing the data itself,
just passing it around, so no, the member type is not know, not from the
point of view of modules outside the VM system. By doing that, you're
violating the intended opacity of the type (see vm_map.h, vm_map_copy_t
[exported; contents invisible]). The problem with that approach is
that, if someone, someday, decides to change that type, he wouldn't know
he would also have to change the code you introduce, and actually, he
shouldn't have to. That knowledge should be completely contained in the
vm_map module.

  and I also don't understand why you assume the data to be null-
  terminated.
 
 Structures are always null-terminated in memory. So if data came from a 
 structure (like vm_map_copy) it has to be null-terminated. If not, a 
 random '\0' will be found, sizes will not match, and function will 
 return.

No, nothing guarantees that structures are null-terminated. This is a
very wrong assumption. In addition, even if it was possible for the
data to be something else than a vm_map_copy (in which case we'd want
an assertion, because it should *never* happen), the data size could be
0, in which case simply accessing the first byte might cause a crash.

-- 
Richard Braun



Re: [PATCH 4/4] device/chario.c (char_write): avoid segmentation fault

2013-12-15 Thread Richard Braun
On Sun, Dec 15, 2013 at 02:43:50PM +0100, Marin Ramesa wrote:
 On 15.12.2013 14:00:22, Richard Braun wrote:
  What makes you think the content could be something else than a
  vm_map_copy object ?
 
 Well io_data is a pointer to char, not a pointer to vm_map_copy. And 
 there is not one member in io_req structure that keeps track of the 
 io_data size. The function char_write() could be called with io_data 
 having it's origin in something other than vm_map_copy.

You're reasoning only on what you see at the language level. If you look
more closely, you'll see this case only applies when the data hasn't
been transferred in-band. I'm pretty certain the VM system will have
used a vm_map_copy object to list the pages concerned in the ou-of-band
case.

  No, nothing guarantees that structures are null-terminated. This is a
  very wrong assumption. In addition, even if it was possible for the
  data to be something else than a vm_map_copy (in which case we'd want
  an assertion, because it should *never* happen), the data size could
  be 0, in which case simply accessing the first byte might cause a 
  crash.
 
 The tests I've run always show null-termination. But you're right, the 
 structure could very well contain a '\0' in which case strlen() 
 wouldn't work. But there has to be some way to detect the end of a 
 structure in memory without knowing the types.

Now you're reasoning only on what you saw with a few tests ! And no,
what you want to do here makes no sense. You can't detect the end of
a structure in memory. You have to know, either directly, or through
some mechanism (e.G. a header containing the real type and length).

-- 
Richard Braun



Re: [PATCH 4/4] device/chario.c (char_write): avoid segmentation fault

2013-12-14 Thread Richard Braun
On Fri, Dec 13, 2013 at 09:06:55PM +0100, Marin Ramesa wrote:
 Check if the source of the data in the source structure
 memory is a target structure data. Do this by comparing the 
 length of the char values starting with the source address until 
 null-termination to the size of the target structure. Start by 
 initializing the counter to the size of the first member in the 
 target structure. Then char values in memory are counted until 
 null-termination, and finally the counted result is compared to the 
 size of the target structure. If the values don't match, return from the 
 function.

I really don't see a problem in that code, you'll have to describe it
better. On the other hand, your patch relies on knowing the target
types, although vm_map_copy_t is explicitely described as being opaque.
In addition, you basically reimplement strlen inline, and I also don't
understand why you assume the data to be null-terminated.

-- 
Richard Braun



<    1   2   3   4   5   6   >