Hi Joe,

I note the changes around the nhash C function and despite it not being the root cause of the initially reported JTMSK crashes it seems appropriate to suggest that we make use of the Fortran/C interoperability features of modern Fortran to ensure that interoperation is more robust and potentially a little more efficient.

As an example I have prepared a module the defines the interface to the nhash C function for calling from Fortran which looks like:

module hashing
  interface
integer(c_int32_t) function nhash (key, length, initval) bind(C, name="nhash")
       use iso_c_binding, only: c_ptr, c_size_t, c_int32_t
       type(c_ptr), intent(in), value :: key
       integer(c_size_t), intent(in), value :: length
       integer(c_int32_t), intent(in), value :: initval
     end function nhash
  end interface
end module hashing

This can be called without any extra wrapping code, argument manipulation or, function renaming and allows any contiguous block of memory that is represented by a Fortran scalar or contiguous vector to be hashed. For example in the source lib/hash.f90:

subroutine hash(string,len,ihash)
  use iso_c_binding, only: c_loc
  use hashing
  parameter (MASK15=32767)
  character*(*), target :: string
     i=nhash(c_loc(string),len,146)
     ihash=iand(i,MASK15)

!     print*,'C',ihash,len,string
  return
end subroutine hash

rather than the current copy to an integer array.

A more complete patch is attached that uses the module to define the interface in all places nhash is called from Fortran.

I have tested this patch in ^/branches/wsjtx_exp in a trivial back to back JTMSK QSO more as a test of building that a thorough regression test.

I also wonder why the nhash algorithm has been used for a CRC on JTMSK messages since there are probably simpler well tried and tested CRC algorithms in common usage.

Comments?

73
Bill
G4WJS.

On 30/08/2015 15:47, Joe Taylor wrote:
Hi Steve,

I was about to write to you along the same lines.  The copies of nhash.h
and nhash.c in .../wsjtx_exp/lib have been used only for building the
executable testmsk, not for wsprx.  I was clearly on the wrong track
yesterday.

It turns out, I believe, that the problem is entirely elsewhere.  Under
certain conditions an undefined value for TRperiod could be passed to
function getfile(), which is used to read *.wav files from disk.  As a
consequence a big memory segment could be zeroed when this statement
(line 56 of getfile.cpp) was executed:

    memset(jt9com_.d2,0,2*npts);

I have now protected against this occurrence.  Please try building and
testing revision 5831.

        -- Joe, K1JT

On 8/30/2015 10:15 AM, Steven Franke wrote:
Joe -

In perusing the wsjtx_exp code this morning, I noticed two things:

1. All references to nhash.c in CMakeLists.txt are to the version in /lib/wsprd 
- so it seems that changes in /lib/nhash.c are not going to make any 
difference. If this is working for you, then perhaps we can just delete the 
nhash.c/nhash.h in /lib?

2. in /lib/nhash.h, length is declared size_t in nhash and uint32_t in nhash_, 
whereas in /lib/nhash.c is it uint32_t in nhash.c and uint32_t in nhash_

I’m guessing that item 2 is not the problem due to item 1?

I think that we need to resolve the differences between the two nhash.c’s and 
get rid of one of them.

Steve

------------------------------------------------------------------------------
_______________________________________________
wsjt-devel mailing list
wsjt-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/wsjt-devel
------------------------------------------------------------------------------
_______________________________________________
wsjt-devel mailing list
wsjt-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/wsjt-devel

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 679eaa2..df022fb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -328,6 +328,7 @@ set (wsjt_FSRCS
   lib/grayline.f90
   lib/grid2deg.f90
   lib/hash.f90
+  lib/hashing.f90
   lib/hspec.f90
   lib/image.f90
   lib/indexx.f90
diff --git a/lib/genmsk.f90 b/lib/genmsk.f90
index c5fe416..2de6fe8 100644
--- a/lib/genmsk.f90
+++ b/lib/genmsk.f90
@@ -14,18 +14,19 @@ subroutine genmsk(msg0,ichk,msgsent,i4tone,itype)
 !                 5 = type 2 suffix
 !                 6 = free text (up to 13 characters)
 
+  use iso_c_binding, only: c_loc
   use packjt
+  use hashing
   character*22 msg0
   character*22 message                    !Message to be generated
   character*22 msgsent                    !Message as it will be received
   integer*4 i4Msg6BitWords(13)            !72-bit message as 6-bit words
-  integer*1 i1Msg8BitBytes(13)            !72 bits and zero tail as 8-bit bytes
+  integer*1, target:: i1Msg8BitBytes(13)  !72 bits and zero tail as 8-bit bytes
   integer*1 e1(198)                       !Encoded bits before re-ordering
   integer*1 i1EncodedBits(198)            !Encoded information-carrying bits
   integer i4tone(234)                     !Tone #s, data and sync (values 0-1)
   integer*1 i1hash(4)
   integer b11(11)
-  integer*8 len8
   data b11/1,1,1,0,0,0,1,0,0,1,0/         !Barker 11 code
   equivalence (ihash,i1hash)
   save
@@ -53,8 +54,7 @@ subroutine genmsk(msg0,ichk,msgsent,i4tone,itype)
      call unpackmsg(i4Msg6BitWords,msgsent)      !Unpack to get msgsent
      if(ichk.ne.0) go to 999
      call entail(i4Msg6BitWords,i1Msg8BitBytes)  !Add tail, make 8-bit bytes
-     len8=9
-     ihash=nhash(i1Msg8BitBytes,len8,146)
+     ihash=nhash(c_loc(i1Msg8BitBytes),9,146)
      ihash=2*iand(ihash,32767)                   !Generate the CRC
      i1Msg8BitBytes(10)=i1hash(2)                !CRC to bytes 10 and 11
      i1Msg8BitBytes(11)=i1hash(1)
diff --git a/lib/hash.f90 b/lib/hash.f90
index 679e00c..ed497a8 100644
--- a/lib/hash.f90
+++ b/lib/hash.f90
@@ -1,13 +1,9 @@
 subroutine hash(string,len,ihash)
-
+  use iso_c_binding, only: c_loc
+  use hashing
   parameter (MASK15=32767)
-  character*(*) string
-  integer*1 ic(12)
-
-     do i=1,len
-        ic(i)=ichar(string(i:i))
-     enddo
-     i=nhash(ic,len,146)
+  character*(*), target :: string
+     i=nhash(c_loc(string),len,146)
      ihash=iand(i,MASK15)
 
 !     print*,'C',ihash,len,string
diff --git a/lib/hashing.f90 b/lib/hashing.f90
new file mode 100644
index 0000000..5534fa9
--- /dev/null
+++ b/lib/hashing.f90
@@ -0,0 +1,10 @@
+module hashing
+  interface
+     integer(c_int32_t) function nhash (key, length, initval) bind(C, 
name="nhash")
+       use iso_c_binding, only: c_ptr, c_size_t, c_int32_t
+       type(c_ptr), intent(in), value :: key
+       integer(c_size_t), intent(in), value :: length
+       integer(c_int32_t), intent(in), value :: initval
+     end function nhash
+  end interface
+end module hashing
diff --git a/lib/syncmsk.f90 b/lib/syncmsk.f90
index 528c77c..80c3209 100644
--- a/lib/syncmsk.f90
+++ b/lib/syncmsk.f90
@@ -2,7 +2,9 @@ subroutine 
syncmsk(cdat,npts,jpk,ipk,idf,rmax,snr,metric,decoded)
 
 ! Attempt synchronization, and if successful decode using Viterbi algorithm.
 
+  use iso_c_binding, only: c_loc
   use packjt
+  use hashing
   parameter (NSPM=1404)
   complex cdat(npts)                    !Analytic signal
   complex cb(66)                        !Complex waveform for Barker-11 code
@@ -18,7 +20,7 @@ subroutine 
syncmsk(cdat,npts,jpk,ipk,idf,rmax,snr,metric,decoded)
   real rd2(198)
   complex z,z0,z1,cfac
   integer*1 e1(198)
-  integer*1 d8(13)
+  integer*1, target :: d8(13)
   integer*1 i1hash(4)
   integer*1 i1
   integer*4 i4Msg6BitWords(12)            !72-bit message as 6-bit words
@@ -27,7 +29,6 @@ subroutine 
syncmsk(cdat,npts,jpk,ipk,idf,rmax,snr,metric,decoded)
   integer jpksave(1000)
   integer indx(1000)
   integer b11(11)                      !Barker-11 code
-  integer*8 len8
   real rsave(1000)
   real xp(29)
   character*22 decoded
@@ -261,8 +262,7 @@ subroutine 
syncmsk(cdat,npts,jpk,ipk,idf,rmax,snr,metric,decoded)
      call vit213(e1,nb1,mettab,d8,metric)
      call system_clock(count1,clkfreq)
      tvit=tvit + (count1-count0)/float(clkfreq)
-     len8=9
-     ihash=nhash(d8,len8,146)
+     ihash=nhash(c_loc(d8),9,146)
      ihash=2*iand(ihash,32767)
      decoded='                      '
      if(d8(10).eq.i1hash(2) .and. d8(11).eq.i1hash(1)) then
diff --git a/lib/wsprd/nhash.c b/lib/wsprd/nhash.c
index 4149a84..9376954 100644
--- a/lib/wsprd/nhash.c
+++ b/lib/wsprd/nhash.c
@@ -370,11 +370,3 @@ uint32_t nhash( const void *key, size_t length, uint32_t 
initval)
 
   return c;
 }
-
-/*
- * Fortran argument compatible wrapper
- */
-uint32_t nhash_( const void * key, size_t const * length, uint32_t const * 
initval)
-{
-  return nhash (key, *length, *initval);
-}
diff --git a/lib/wsprd/nhash.h b/lib/wsprd/nhash.h
index d13268d..9e59773 100644
--- a/lib/wsprd/nhash.h
+++ b/lib/wsprd/nhash.h
@@ -9,6 +9,5 @@
 #endif
 
 uint32_t nhash( const void * key, size_t length, uint32_t initval);
-uint32_t nhash_( void const * key, size_t const * length, uint32_t const * 
initval);
 
 #endif
------------------------------------------------------------------------------
_______________________________________________
wsjt-devel mailing list
wsjt-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/wsjt-devel

Reply via email to