mailing list of musl libc
 help / color / mirror / code / Atom feed
From: Rich Felker <dalias@libc.org>
To: musl@lists.openwall.com
Subject: Re: [PATCH 7/8] add the thrd_xxxxxx functions
Date: Sun, 31 Aug 2014 10:05:33 -0400	[thread overview]
Message-ID: <20140831140533.GX12888@brightrain.aerifal.cx> (raw)
In-Reply-To: <1409491161.4476.283.camel@eris.loria.fr>

On Sun, Aug 31, 2014 at 03:19:21PM +0200, Jens Gustedt wrote:
> Am Sonntag, den 31.08.2014, 08:57 -0400 schrieb Rich Felker:
> > On Sun, Aug 31, 2014 at 09:57:34AM +0200, Jens Gustedt wrote:
> > > > >  	if (attrp) attr = *attrp;
> > > > >  
> > > > >  	__acquire_ptc();
> > > > > @@ -234,7 +253,10 @@ static int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restr
> > > > >  	new->canary = self->canary;
> > > > >  
> > > > >  	a_inc(&libc.threads_minus_1);
> > > > > -	ret = __clone(start, stack, flags, new, &new->tid, TP_ADJ(new), &new->tid);
> > > > > +	if (c11)
> > > > > +		ret = __clone(start_c11, stack, flags, new, &new->tid, TP_ADJ(new), &new->tid);
> > > > > +	else
> > > > > +		ret = __clone(start, stack, flags, new, &new->tid, TP_ADJ(new), &new->tid);
> > > > 
> > > > Couldn't this be "c11 ? start_c11 : start" to avoid duplicating the
> > > > rest of the call?
> > > 
> > > I think that the ternary expression together with the other
> > > parenthesized paramenter and the length of the line would make the
> > > line barely readable.
> > > 
> > > This are some of the pivots lines of the implementation, I'd rather
> > > have them stick out.
> > > 
> > > Also the assembler that is produced should be identical.
> > 
> > Whether or not the output is identical, your code is much less
> > readable and maintainable: an active effort is required by the reader
> > to determine that the only difference between the two code paths is
> > the function pointer being passed. This is why I prefer the use of ?:.
> > 
> > The following looks perfectly readable to me:
> > 
> > 		ret = __clone(c11 ? start_c11 : start, stack, flags,
> > 			new, &new->tid, TP_ADJ(new), &new->tid);
> 
> No to me (seriously!) because my builtin parser has difficulties to
> capture the end of the ternary expression.
> 
> Would it be acceptable to have parenthesis around?

I wouldn't even mind if you'd prefer to rename start to start_pthread
and then make start a local variable:

	start = c11 ? start_c11 : start_pthread;
	ret = __clone(start, stack, flags, new,
		&new->tid, TP_ADJ(new), &new->tid);

Would that be nicer?

> > > > Also, since it doesn't depend on anything in pthread_create.c,
> > > 
> > > It does, __THRD_C11 :)
> > 
> > How about naming it to __ATTRP_C11_THREAD and putting it in
> > pthread_impl.h then?
> 
> ok, I'll do that
> 
> But hopefully we didn't overlook any possible use pattern that would
> drag in different versions of the tsd symbols. I am not too
> comfortable with that.

What do you mean here? I don't follow.

> > Yes I'm aware, but I don't want gratuitous incentives for patch 8/8
> > just because patch 7/8 is done intentionally suboptimally. :-) If the
> > approaches are being compared, we should be comparing the preferred
> > efficient versions of both. And I'd like to wait to seriously think
> > about 8/8 until everything else is fully ready to commit, or
> > preferably already committed.
> 
> I know.
> 
> But I just discovered another such incentive :) You were right, that
> the error handling for thrd_create was not correct for C11, but it
> wasn't my fault :) POSIX (and thus __pthread_create) basically maps
> all errors to EAGAIN, where C11 requires us to distinguish ENOMEM from
> other failures.
> 
> Thus I had to integrate this difference into __pthread_create, which
> was not difficult, but which intrudes even a little bit more into the
> existing code.

I think POSIX's EAGAIN is fully equivalent to C11's thrd_nomem: both
should reflect any condition where the thread could not be created due
to a resource exhaustion type failure. While you could argue that
thrd_nomem should only indicate failure of the mmap, not the clone, I
think this would be a useless distinction to callers (both of them are
fundamentally allocation operations) and then you'd be forced to use
thrd_error for clone failures, whereas I would think thrd_error should
be reserved for either erroneous usage (but that's UB anyway) or more
permanent failures (like lack of thread support on the OS).

> > > > I'd really just prefer that all of these can't-fail cases be a
> > > > straight tail call with no support for nonzero thrd_success values.
> > > > But as long as the code is correct and the inefficiency is trivially
> > > > optimized out, I'm not going to spend a lot of time arguing about it.
> > > > I do think it's telling, though, that the (albeit minimal) complexity
> > > > of trying to handle the case where thrd_success is nonzero seems to
> > > > have caused a couple bugs -- this is part of why I don't like having
> > > > multiple code paths where one path is untestable/untested. To me, a
> > > > code path that's never going to get tested is a much bigger offense
> > > > than an assumption that a constant has the value we decided it has.
> > 
> > Do you have any thoughts on this part?
> 
> ah, I should have deleted that in my reply, since I basically
> agree. In the new version that I am preparing there are tail calls
> with corresponding comments.

OK.

> > I'm aware that you can't cast the int* to void**, but you can still
> > implement the function as a trivial wrapper that doesn't introduce any
> > duplication of internal logic for cleaning up an exited thread:
> > 
> > int thrd_join(thrd_t t, int *res)
> > {
> > 	void *pthread_res;
> > 	__pthread_join(t, &pthread_res);
> > 	if (res) *res = (int)(intptr_t)pthread_res;
> > 	return thrd_success;
> > }
> 
> dunno, doesn't look much simpler to me and drags in one more TU into C
> thread applications

What's simpler is that this version does not:

- Need pthread_impl.h
- Have knowledge of the mechanism for waiting for thread exit.
- Have knowledge of how to obtain the exit code out of thread struct.
- Have knowledge of thread deallocation mechanism.

It does encode one piece of semi-implementation-specific knowledge,
that the C11 result code is being returned via casting the int to
void* rather than storing it in some other way. But to me that's
knowledge of the way the wrapping is being performed, which is
appropriate knowledge for a C11 threads implementation file, as
opposed to knowledge of how the underlying pthreads implementation
works, which is "inappropriate knowledge". Please note that I'm not
fully against the latter when there's a good reason for it (like
making something more efficient or less ugly), but I don't like it to
be there gratuitously. Consider what would happen if we were switching
to a mechanism like glibc does of caching and reusing thread stacks
after exit (not something I'd want to do, but a good example); then
we'd have two places to update the code with much more complex logic,
rather than just one. Or as another example that may be more
reasonable, consider that we might want to make exiting threads do
their own unmapping of all but the 1 (or 2 when it straddles) page
containing the struct __pthread, so that memory isn't tied up when
there's a long gap between pthread_exit and pthread_join, and only
leave unmapping of that last page (or 2) to the joining thread. This
would also potentially require big changes in two places with your
approach.

Rich


  reply	other threads:[~2014-08-31 14:05 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-08-30 18:46 [PATCH 0/8] C thread patch series, v. 8.3 and 9.4 Jens Gustedt
2014-08-30 18:46 ` [PATCH 1/8] interface additions for the C thread implementation Jens Gustedt
2014-08-30 18:46 ` [PATCH 2/8] additions to src/time Jens Gustedt
2014-08-31  0:13   ` Rich Felker
2014-08-31  7:15     ` Jens Gustedt
2014-08-31 12:45       ` Rich Felker
2014-08-30 18:46 ` [PATCH 3/8] use weak symbols for the POSIX functions that will be used by C threads Jens Gustedt
2014-08-31  0:17   ` Rich Felker
2014-08-31  7:18     ` Jens Gustedt
2014-08-30 18:47 ` [PATCH 4/8] add the functions for tss_t and once_flag Jens Gustedt
2014-08-30 18:47 ` [PATCH 5/8] add the functions for mtx_t Jens Gustedt
2014-08-30 18:47 ` [PATCH 6/8] add the functions for cnd_t Jens Gustedt
2014-08-31  0:35   ` Rich Felker
2014-08-31  7:26     ` Jens Gustedt
2014-08-30 18:47 ` [PATCH 7/8] add the thrd_xxxxxx functions Jens Gustedt
2014-08-31  0:46   ` Rich Felker
2014-08-31  7:57     ` Jens Gustedt
2014-08-31  9:51       ` Alexander Monakov
2014-08-31 10:50         ` Jens Gustedt
2014-08-31 11:06           ` Alexander Monakov
2014-08-31 11:31             ` Szabolcs Nagy
2014-08-31 12:57       ` Rich Felker
2014-08-31 13:19         ` Jens Gustedt
2014-08-31 14:05           ` Rich Felker [this message]
2014-08-31 15:07             ` Jens Gustedt
2014-08-31 16:06               ` Rich Felker
2014-08-31 16:36                 ` Jens Gustedt
2014-08-31 17:02                   ` Rich Felker
2014-08-31 19:10                     ` Jens Gustedt
2014-09-01  0:04                       ` Rich Felker
2014-08-30 18:47 ` [PATCH 8/8] Separate pthread_create and thrd_create Jens Gustedt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140831140533.GX12888@brightrain.aerifal.cx \
    --to=dalias@libc.org \
    --cc=musl@lists.openwall.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).