/pliant/language/schedule/fastsem.pli
 
 1  # Copyright  Hubert Tonneau  hubert.tonneau@pliant.cx 
 2  # 
 3  # This program is free software; you can redistribute it and/or 
 4  # modify it under the terms of the GNU General Public License version 2 
 5  # as published by the Free Software Foundation. 
 6  # 
 7  # This program is distributed in the hope that it will be useful, 
 8  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 9  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 10  # GNU General Public License for more details. 
 11  # 
 12  # You should have received a copy of the GNU General Public License 
 13  # version 2 along with this program; if not, write to the Free Software 
 14  # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
 15   
 16  scope "/pliant/language/" "/pliant/install/" 
 17  module "/pliant/install/ring2.pli" 
 18  module "pentium.pli" 
 19   
 20   
 21  constant busy_wait false # processor_is_pentium and processor_count>1 
 22  constant busy_sleep 2^9 
 23  constant busy_timeout 2^12 
 24   
 25   
 26  if processor_name="i386" 
 27   
 28    function i386_lock_xchg a b 
 29      arg Int a ; arg_rw Int b 
 30   
 31    function generate_i386_lock_xchg i f 
 32      arg_rw Instruction i ; arg_rw Function f 
 33      code_immediat 0F0h 1 # lock 
 34      if i:0:where=argument_register 
 35        i386_regmem 10000111b 1 i:0:register i:1 
 36      else 
 37        error error_id_unexpected "i386 code generation: Invalid or arguments" 
 38   
 39    (the_function i386_lock_xchg Int Int) set_generate_binary (the_function generate_i386_lock_xchg Instruction Function) 
 40   
 41   
 42    function atomic_read_and_set a b -> r 
 43      arg_rw uInt a ; arg uInt r 
 44      has_side_effects ; gcc_inline "asm([dq]lock\n[dq] [dq]xchg %0,(%1)[dq] : [dq]=r[dq] ($3) : [dq]r[dq] (@1) , [dq]0[dq] ($2) : [dq]memory[dq] );" 
 45   
 46    function assemble_atomic_read_and_set i gc 
 47      arg_rw Instruction i ; arg_rw GeneratorContext gc 
 48      var Pointer:Instruction cur :> i 
 49      var Link:Argument reg :> argument a_register 
 50      cur :> gc insert_after_instruction cur (instruction (the_function i386_mov Int Int) i:reg) 
 51      cur :> gc insert_after_instruction cur (instruction (the_function i386_lock_xchg Int Int) reg i:0) 
 52      cur :> gc insert_after_instruction cur (instruction (the_function i386_mov Int Int) reg i:2) 
 53      gc remove i 
 54   
 55    (the_function atomic_read_and_set uInt uInt -> uInt) set_generate_assembly (the_function assemble_atomic_read_and_set Instruction GeneratorContext) 
 56   
 57   
 58  type FastSem 
 59    field uInt status 
 60   
 61   
 62  function build sem 
 63    arg_w FastSem sem 
 64    sem status := 0 
 65   
 66  method sem request 
 67    arg_rw FastSem sem 
 68    if busy_wait 
 69      while true 
 70        if (atomic_read_and_set sem:status 1)=0 
 71          return 
 72        pentium_counter (var uInt start_low) (var uInt start_high) 
 73        while { pentium_counter (var uInt lap_low) (var uInt lap_high) ; ( lap_high=start_high or (lap_high .-. start_high)=1 and lap_low<start_low ) and (lap_low .-. start_low)<busy_timeout } 
 74          while { pentium_counter (var uInt low) (var uInt high) ; ( high=lap_high or (high .-. lap_high)=1 and low<lap_low ) and (low .-. lap_low)<busy_sleep } 
 75            void # the busy loop 
 76          if (atomic_read_and_set sem:status 1)=0 # retry 
 77            return 
 78        os_yield # timeout 
 79    else 
 80      while (atomic_read_and_set sem:status 1)<>0 
 81        os_yield 
 82   
 83   
 84  method sem release 
 85    arg_rw FastSem sem 
 86    has_side_effects 
 87    sem status := 0 
 88   
 89  export FastSem '. request' '. release' 
 90  export atomic_read_and_set