public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* Query and behavior confirmation for pthread_barrier_destroy(3)
@ 2020-09-03  9:07 Shashank Agarwal
  2020-09-03 11:43 ` Florian Weimer
  0 siblings, 1 reply; 7+ messages in thread
From: Shashank Agarwal @ 2020-09-03  9:07 UTC (permalink / raw)
  To: libc-alpha

[-- Attachment #1: Type: text/plain, Size: 1146 bytes --]

Hello,

Greetings of the day.

As per current implementation, a barrier can be destroyed as soon as no
threads are blocked on the barrier. In order to confirm the behaviour, I
have created a test case attached to this email as
pthread_barrier_destroy_sample.c.

The Description of the test case is as follows -

1. Main thread initializes the pthread barrier with the count as 2.
2. Main thread creates 2 threads.
3. Thread 1 waits for the synchronization at the barrier using
pthread_barrier_wait(3).
4. Thread 2 tries to destroy the barrier, and as per the new
implementation, it should get block because only 1 thread
has performed pthread_barrier_wait(3).
5. After 10 seconds of sleep Main thread calls pthread_barrier_wait(3) and
thread 2 returns from the pthread_barrier_destroy(3)
successfully. But thread 1 still waiting at the barrier for the
synchronization.

As per our understanding thread, 1 should successfully return from
pthread_barrier_wait(2) and it should not block as this is not the graceful
behaviour.

Please let me know your views on the same.

Regards

Shashank Agarwal
HCL Technologies Limited

shashank_agarwal@hcl.com

[-- Attachment #2: pthread_barrier_destroy_sample.c --]
[-- Type: application/octet-stream, Size: 1934 bytes --]

#include <stdio.h>
#include <stdbool.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

/* THREAD DECLARATIONS */
void *thread1_routine(void *args);
void *thread2_routine(void *args);

/* GLOBAL VARIABLES */
pthread_barrier_t my_barrier;
volatile bool exited = false;

/* FUNCTION DEFINITIONS */
int main(void)
{
	pthread_t t1,t2;
        int ret_val = 0;

	/* INITIALIZE my_barrier */
	pthread_barrier_init(&my_barrier, NULL, 2);
	
        /* CREATE thread_1 */
	pthread_create(&t1, NULL, thread1_routine, NULL);

        /* CREATE thread_2 */
	pthread_create(&t2, NULL, thread2_routine, NULL);

	sleep(10);
	printf("Main thread calling pthread_wait\n");
	/* WAIT on my_barrier to continue execution */
    if(pthread_barrier_wait(&my_barrier) == 0)
			printf("\t[SUCCESS][THREAD2]: pthread_barrier_wait\n\n");
	pthread_join(t2, NULL);
	printf("Thread 2 exited\n");
	pthread_join(t1, NULL);

	return EXIT_SUCCESS;
}

void *thread1_routine(void *args)
{
        int ret_val = 0;


        printf("THREAD_1: Calling pthread_barrier_wait API...\n");
	/* WAIT on my_barrier to continue execution */
        if(pthread_barrier_wait(&my_barrier) == 0)
			printf("\t[SUCCESS][THREAD1]: pthread_barrier_wait\n\n");

        printf("THREAD_1: EXITING...\n");
	pthread_exit(NULL);
}
void *thread2_routine(void *args)
{
        int ret_val = 0;

	printf("\nMaking an ERRONEOUS call to pthread_barrier_destroy()\n");
	printf("If the program goes into a hang, "
				"MPMT_FT_libraryAPI196 SUCCESS...\n\n");
	/* pthread_barrier_destroy()
	 *
	 * May hang
	 * 	if there are threads waiting to synchronize on the barrier.
	 *
	 */

	/* ERRONEOUS call to pthread_barrier_destroy() */
        if(pthread_barrier_destroy(&my_barrier) == 0)
			printf("\t[SUCCESS]:  pthread_barrier_destroy() SUCCESS...\n\n");


        printf("THREAD_2: EXITING...\n");
	pthread_exit(NULL);
}

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Query and behavior confirmation for pthread_barrier_destroy(3)
  2020-09-03  9:07 Query and behavior confirmation for pthread_barrier_destroy(3) Shashank Agarwal
@ 2020-09-03 11:43 ` Florian Weimer
  2020-09-03 11:55   ` Shashank Agarwal
  0 siblings, 1 reply; 7+ messages in thread
From: Florian Weimer @ 2020-09-03 11:43 UTC (permalink / raw)
  To: Shashank Agarwal via Libc-alpha; +Cc: Shashank Agarwal

* Shashank Agarwal via Libc-alpha:

> 1. Main thread initializes the pthread barrier with the count as 2.
> 2. Main thread creates 2 threads.
> 3. Thread 1 waits for the synchronization at the barrier using
> pthread_barrier_wait(3).
> 4. Thread 2 tries to destroy the barrier, and as per the new
> implementation, it should get block because only 1 thread
> has performed pthread_barrier_wait(3).

This test is invalid according to POSIX, which says:

| The results are undefined if pthread_barrier_destroy() is called when
| any thread is blocked on the barrier

I do not believe such a test would be valid for the glibc
implementation.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Query and behavior confirmation for pthread_barrier_destroy(3)
  2020-09-03 11:43 ` Florian Weimer
@ 2020-09-03 11:55   ` Shashank Agarwal
  2020-09-03 12:04     ` Florian Weimer
  0 siblings, 1 reply; 7+ messages in thread
From: Shashank Agarwal @ 2020-09-03 11:55 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Shashank Agarwal via Libc-alpha

Hello Florian,

Thanks for the confirmation. Please let me know if my understanding is
correct about pthread_barrier_destroy(3).

*A barrier can be destroyed as soon as no threads are blocked on the
barrier.  *

If yes please let me know how I can verify this behaviour.

Thanks and Regards,
Shashank Agarwal

On Thu, Sep 3, 2020 at 5:13 PM Florian Weimer <fweimer@redhat.com> wrote:

> * Shashank Agarwal via Libc-alpha:
>
> > 1. Main thread initializes the pthread barrier with the count as 2.
> > 2. Main thread creates 2 threads.
> > 3. Thread 1 waits for the synchronization at the barrier using
> > pthread_barrier_wait(3).
> > 4. Thread 2 tries to destroy the barrier, and as per the new
> > implementation, it should get block because only 1 thread
> > has performed pthread_barrier_wait(3).
>
> This test is invalid according to POSIX, which says:
>
> | The results are undefined if pthread_barrier_destroy() is called when
> | any thread is blocked on the barrier
>
> I do not believe such a test would be valid for the glibc
> implementation.
>
> Thanks,
> Florian
>
>

-- 
shashank

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Query and behavior confirmation for pthread_barrier_destroy(3)
  2020-09-03 11:55   ` Shashank Agarwal
@ 2020-09-03 12:04     ` Florian Weimer
  2020-09-07  4:04       ` Rich Felker
  0 siblings, 1 reply; 7+ messages in thread
From: Florian Weimer @ 2020-09-03 12:04 UTC (permalink / raw)
  To: Shashank Agarwal; +Cc: Shashank Agarwal via Libc-alpha

* Shashank Agarwal:

> Thanks for the confirmation. Please let me know if my understanding is
> correct about pthread_barrier_destroy(3).
>
>> A barrier can be destroyed as soon as no threads are blocked on the
>> barrier.
>
> If yes please let me know how I can verify this behaviour.

“As soon as” is imprecise; the specification predates the C/C++ memory
model.  The caller of pthread_barrier_destroy has to establish a
happens-before relationship with the return from the
pthread_barrier_wait calls on the other threads.

The intent with the current glibc implementation is that the
synchronization can be achieved using the same barrier (if no thread
blocks again on the barrier after the current round of waiting).  That
is, in your test, thread 2 would have to wait on the barrier as well,
unblocking both tests, and then destroy the barrier.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Query and behavior confirmation for pthread_barrier_destroy(3)
  2020-09-03 12:04     ` Florian Weimer
@ 2020-09-07  4:04       ` Rich Felker
  2020-09-07  5:36         ` Florian Weimer
  0 siblings, 1 reply; 7+ messages in thread
From: Rich Felker @ 2020-09-07  4:04 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Shashank Agarwal, Shashank Agarwal via Libc-alpha

On Thu, Sep 03, 2020 at 02:04:28PM +0200, Florian Weimer via Libc-alpha wrote:
> * Shashank Agarwal:
> 
> > Thanks for the confirmation. Please let me know if my understanding is
> > correct about pthread_barrier_destroy(3).
> >
> >> A barrier can be destroyed as soon as no threads are blocked on the
> >> barrier.
> >
> > If yes please let me know how I can verify this behaviour.
> 
> “As soon as” is imprecise; the specification predates the C/C++ memory
> model.  The caller of pthread_barrier_destroy has to establish a
> happens-before relationship with the return from the
> pthread_barrier_wait calls on the other threads.

No, return from the function is irrelevant. pthread_barrier_wait is
specified to block "until the required number of threads have called
pthread_barrier_wait()" (note "called", not "returned from calling").
As soon as the last call is made (before any of them return), the
condition ending this "block" is satisfied, and no threads remain
blocked on the barrier.

A pthread_barrier_destroy is only undefined if it "is called when any
thread is blocked on the barrier, or ... with an uninitialized
barrier". If any of the waits return, that means that no thread is
currently blocked on the barrier, so destruction is well-defined. For
example you might elect a thread to destroy the barrier immediately
based on PTHREAD_BARRIER_SERIAL_THREAD or by virtue of one having a
special role already.

In other words, barriers admit "self-synchronized destruction". Indeed
if they didn't, it would be impossible to destroy them without
coupling them with another synchronization primitive, making them
mostly useless.

> The intent with the current glibc implementation is that the
> synchronization can be achieved using the same barrier (if no thread
> blocks again on the barrier after the current round of waiting).  That
> is, in your test, thread 2 would have to wait on the barrier as well,
> unblocking both tests, and then destroy the barrier.

I don't understand what you're saying here. Do you mean that glibc
conforms but that you deem this not a conformance requirement, just an
implementation-specific property? Or something else?

Rich

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Query and behavior confirmation for pthread_barrier_destroy(3)
  2020-09-07  4:04       ` Rich Felker
@ 2020-09-07  5:36         ` Florian Weimer
  2020-09-07 17:47           ` Rich Felker
  0 siblings, 1 reply; 7+ messages in thread
From: Florian Weimer @ 2020-09-07  5:36 UTC (permalink / raw)
  To: Rich Felker; +Cc: Shashank Agarwal, Shashank Agarwal via Libc-alpha

* Rich Felker:

>> The intent with the current glibc implementation is that the
>> synchronization can be achieved using the same barrier (if no thread
>> blocks again on the barrier after the current round of waiting).  That
>> is, in your test, thread 2 would have to wait on the barrier as well,
>> unblocking both tests, and then destroy the barrier.
>
> I don't understand what you're saying here. Do you mean that glibc
> conforms but that you deem this not a conformance requirement, just an
> implementation-specific property?

Yes, that's what I meant.  I don't think POSIX formally requires this.

Thanks,
Florian
-- 
Red Hat GmbH, https://de.redhat.com/ , Registered seat: Grasbrunn,
Commercial register: Amtsgericht Muenchen, HRB 153243,
Managing Directors: Charles Cachera, Brian Klemm, Laurie Krebs, Michael O'Neill


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Query and behavior confirmation for pthread_barrier_destroy(3)
  2020-09-07  5:36         ` Florian Weimer
@ 2020-09-07 17:47           ` Rich Felker
  0 siblings, 0 replies; 7+ messages in thread
From: Rich Felker @ 2020-09-07 17:47 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Shashank Agarwal, Shashank Agarwal via Libc-alpha

On Mon, Sep 07, 2020 at 07:36:10AM +0200, Florian Weimer wrote:
> * Rich Felker:
> 
> >> The intent with the current glibc implementation is that the
> >> synchronization can be achieved using the same barrier (if no thread
> >> blocks again on the barrier after the current round of waiting).  That
> >> is, in your test, thread 2 would have to wait on the barrier as well,
> >> unblocking both tests, and then destroy the barrier.
> >
> > I don't understand what you're saying here. Do you mean that glibc
> > conforms but that you deem this not a conformance requirement, just an
> > implementation-specific property?
> 
> Yes, that's what I meant.  I don't think POSIX formally requires this.

This is going to be the argument with Torvald over mutexes/condvars
and self-synchronized destruction all over again, isn't it?

Rich

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-09-07 17:47 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-03  9:07 Query and behavior confirmation for pthread_barrier_destroy(3) Shashank Agarwal
2020-09-03 11:43 ` Florian Weimer
2020-09-03 11:55   ` Shashank Agarwal
2020-09-03 12:04     ` Florian Weimer
2020-09-07  4:04       ` Rich Felker
2020-09-07  5:36         ` Florian Weimer
2020-09-07 17:47           ` Rich Felker

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 read-only IMAP folder(s) and NNTP newsgroup(s).