comp.lang.ada
 help / color / mirror / Atom feed
From: Hadrien Grasland <hadrien.grasland@gmail.com>
Subject: Re: Lock-Free stack in Ada SPARK
Date: Sat, 11 Feb 2017 01:57:56 -0800 (PST)
Date: 2017-02-11T01:57:56-08:00	[thread overview]
Message-ID: <52b3faef-34b7-485f-98fb-6f488692ae9b@googlegroups.com> (raw)
In-Reply-To: <c7c7fd16-9302-4ea0-99c0-c6c48c775348@googlegroups.com>

Le samedi 11 février 2017 04:07:43 UTC+1, stevensele...@gmail.com a écrit :
> It's probably buggy. I still can't figure out how I'm supposed to prove properties about a volatile (protected) object.
> 
> https://sstewartgallus.com/git?p=linted.git;a=blob;f=src/ada-core/src/linted-lock_free_stack.adb;h=ee17ba8dcff26527fa4f06dfa750d0846a16f255;hb=HEAD
> 
> There's also a lock-free condition variable like thing
> 
> https://sstewartgallus.com/git?p=linted.git;a=blob;f=src/ada-core/src/linted-wait_lists.adb;h=be46f99cb2907e13a37f2e848b901a4dcdd02109;hb=HEAD

Actually, I'm not convinced that Ada atomics provide the required properties for what you're trying to do here.

To me, Ada's "Atomic", as defined by section C.6 of the Ada 2012 RM, provides essentially the same synchronization guarantees as Java's "volatile":

1/Each read from an atomic variable is atomic.
2/Each write to an atomic variable is atomic.
3/Each thread sees the same atomic writes occuring, without reordering.

What it does not guarantee, however, is that nothing will happen between the time where a thread reads from a variable, and the time where a thread writes to a variable. Which means, for example, that "X := X + 1" is a race condition in Ada even if X is atomic.

It also means that the Linted.Compare_And_Swap primitive that your lock-free stack is using has a race condition inside of it, as far as I can tell. From https://sstewartgallus.com/git?p=linted.git;a=blob;f=src/ada-core/src/linted-atomics.adb;h=a0a59e66568c8b5e11318691d97608dc33363315;hb=HEAD ...

  26       procedure Compare_And_Swap
  27         (Old_Ptr : Element_T;
  28          New_Ptr : Element_T;
  29          Success : in out Boolean)
  30       is
  31       begin
  32          if Old_Ptr = Ptr then
  33             Ptr := New_Ptr;
  34             Success := True;
  35          else
  36             Success := False;
  37          end if;
  38       end Compare_And_Swap;

...you actually cannot guarantee that Ptr will not be updated by another thread between the time where you check it at line 32 and the time where you write to it at line 33, which means that you have a data race on your hands.

You could expose this by running two tasks in parallel, have them call compare-and-swap on a shared memory location, and see if you can observe an inconsistent memory state (i.e. one where a task should have not written to memory but did so anyway).


  reply	other threads:[~2017-02-11  9:57 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-11  3:07 Lock-Free stack in Ada SPARK stevenselectronicmail
2017-02-11  9:57 ` Hadrien Grasland [this message]
2017-02-11 10:07   ` Hadrien Grasland
2017-02-11 10:08     ` Hadrien Grasland
2017-02-11 10:14       ` Hadrien Grasland
2017-02-11 17:34         ` stevenselectronicmail
2017-02-11 19:36           ` Jeffrey R. Carter
2017-02-11 20:42             ` stevenselectronicmail
2017-02-11 22:40             ` Dmitry A. Kazakov
2017-02-11 23:02               ` stevenselectronicmail
2017-02-12  8:30                 ` Dmitry A. Kazakov
2017-02-12 12:26             ` Hadrien Grasland
2017-02-12 12:49               ` Dmitry A. Kazakov
2017-02-12 13:19                 ` Hadrien Grasland
2017-02-12 14:57                   ` Dmitry A. Kazakov
2017-02-12 13:04               ` Hadrien Grasland
2017-02-12 22:25 ` Robert Eachus
2017-02-13  8:22   ` Dmitry A. Kazakov
2017-02-13 20:04   ` stevenselectronicmail
2017-02-21  1:51     ` Robert Eachus
2017-02-21  8:44       ` Dmitry A. Kazakov
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox