Advertisement
Guest User

Untitled

a guest
Feb 13th, 2017
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ada 4.14 KB | None | 0 0
  1. -- Copyright 2017 Steven Stewart-Gallus
  2. --
  3. -- Licensed under the Apache License, Version 2.0 (the "License");
  4. -- you may not use this file except in compliance with the License.
  5. -- You may obtain a copy of the License at
  6. --
  7. --     http://www.apache.org/licenses/LICENSE-2.0
  8. --
  9. -- Unless required by applicable law or agreed to in writing, software
  10. -- distributed under the License is distributed on an "AS IS" BASIS,
  11. -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  12. -- implied.  See the License for the specific language governing
  13. -- permissions and limitations under the License.
  14. private with Linted.ABAs;
  15. private with Linted.Atomics;
  16. private with Linted.Mod_Atomics;
  17. private with Linted.Sched;
  18.  
  19. generic
  20.    type Element_T is private;
  21. package Linted.Strange_Locks with Spark_Mode is
  22.    pragma Elaborate_Body;
  23.  
  24.    --  Inspired by seqlocks these are weird;
  25.  
  26.    type Strange_Lock is limited private;
  27.  
  28.    procedure Set (Lock : in out Strange_Lock; Element : Element_T);
  29.    procedure Get (Lock : in out Strange_Lock; Element : out Element_T);
  30.  
  31. private
  32.    pragma Spark_Mode (Off);
  33.  
  34.    type Word is mod 2 ** 16 with Default_Value => 0;
  35.    package Word_ABAS is new ABAs (Word);
  36.    package Atomic_Word_ABAS is new Atomics (Word_ABAS.ABA);
  37.    package Seqno_Atomics is new Mod_Atomics (Word_ABAS.Tag_T);
  38.  
  39.    type Storage is array (1 .. Element_T'Size / 32) of Word;
  40.  
  41.    type Atomic_Storage is array (1 .. Element_T'Size / 32) of Atomic_Word_ABAS.Atomic;
  42.  
  43.    type Strange_Lock is record
  44.       Seqno : Seqno_Atomics.Atomic;
  45.       Storage : Atomic_Storage;
  46.       Contention : Sched.Contention;
  47.    end record;
  48. end Linted.Strange_Locks;
  49.  
  50.  
  51. -- Copyright 2017 Steven Stewart-Gallus
  52. --
  53. -- Licensed under the Apache License, Version 2.0 (the "License");
  54. -- you may not use this file except in compliance with the License.
  55. -- You may obtain a copy of the License at
  56. --
  57. --     http://www.apache.org/licenses/LICENSE-2.0
  58. --
  59. -- Unless required by applicable law or agreed to in writing, software
  60. -- distributed under the License is distributed on an "AS IS" BASIS,
  61. -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  62. -- implied.  See the License for the specific language governing
  63. -- permissions and limitations under the License.
  64. with Ada.Unchecked_Conversion;
  65.  
  66. package body Linted.Strange_Locks with Spark_Mode => Off is
  67.    use type Word_ABAS.Tag_T;
  68.  
  69.    function Unsafe_To_Storage is new Ada.Unchecked_Conversion (Element_T, Storage);
  70.    function Unsafe_From_Storage is new Ada.Unchecked_Conversion (Storage, Element_T);
  71.  
  72.    procedure Set (Lock : in out Strange_Lock; Element : Element_T) is
  73.       Element_Storage : Storage;
  74.       Old_Chunk : Word_ABAS.ABA;
  75.       New_Chunk : Word;
  76.       Seqno : Word_ABAS.Tag_T;
  77.       Success : Boolean;
  78.    begin
  79.       Element_Storage := Unsafe_To_Storage (Element);
  80.  
  81.       Seqno_Atomics.Increment (Lock.Seqno, Seqno);
  82.  
  83.       for II in Storage'Range loop
  84.      New_Chunk := Element_Storage (II);
  85.  
  86.      loop
  87.         Atomic_Word_ABAS.Get (Lock.Storage (II), Old_Chunk);
  88.  
  89.         exit when Word_ABAS.Tag (Old_Chunk) > Seqno;
  90.  
  91.         Atomic_Word_ABAS.Compare_And_Swap (Lock.Storage (II),
  92.                            Old_Chunk,
  93.                            Word_ABAS.Initialize (New_Chunk, Seqno),
  94.                            Success);
  95.         exit when Success;
  96.      end loop;
  97.       end loop;
  98.    end Set;
  99.  
  100.    procedure Get (Lock : in out Strange_Lock; Element : out Element_T) is
  101.       Seqno : Word_ABAS.Tag_T;
  102.       Element_Storage : Storage;
  103.       Chunk : Word_ABAS.ABA;
  104.    begin
  105.       loop
  106.      Seqno_Atomics.Get (Lock.Seqno, Seqno);
  107.  
  108.      Read_Loop : for II in Storage'Range loop
  109.         loop
  110.            Atomic_Word_ABAS.Get (Lock.Storage (II), Chunk);
  111.            exit when Word_ABAS.Tag (Chunk) = Seqno;
  112.            exit Read_Loop when Word_ABAS.Tag (Chunk) > Seqno;
  113.  
  114.            if Word_ABAS.Tag (Chunk) < Seqno then
  115.           Sched.Backoff (Lock.Contention);
  116.            end if;
  117.         end loop;
  118.         Sched.Success (Lock.Contention);
  119.  
  120.         Element_Storage (II) := Word_ABAS.Element (Chunk);
  121.      end loop Read_Loop;
  122.      exit when Word_ABAS.Tag (Chunk) <= Seqno;
  123.       end loop;
  124.  
  125.       Element := Unsafe_From_Storage (Element_Storage);
  126.    end Get;
  127. end Linted.Strange_Locks;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement