| summaryrefslogtreecommitdiff | 
diff options
| author | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2017-06-29 15:20:24 +0200 | 
|---|---|---|
| committer | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2017-06-29 15:20:24 +0200 | 
| commit | 8d5c996aef28fae9f848e1fab419b4d2821e8862 (patch) | |
| tree | a2b5fac4ee5b3e21711fe80c273f300541d16844 /src | |
| parent | f7c5db9a32bb0082b59e73fa01656cd083756c3d (diff) | |
First shot at finer mutexes.
Diffstat (limited to 'src')
| -rw-r--r-- | src/knowledge/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/knowledge/knowledge.c | 108 | ||||
| -rw-r--r-- | src/knowledge/knowledge.h | 117 | ||||
| -rw-r--r-- | src/knowledge/knowledge_finalize.c | 5 | ||||
| -rw-r--r-- | src/knowledge/knowledge_get_random_sequence.c | 19 | ||||
| -rw-r--r-- | src/knowledge/knowledge_get_random_target.c | 54 | ||||
| -rw-r--r-- | src/knowledge/knowledge_learn_markov_sequence.c | 62 | ||||
| -rw-r--r-- | src/knowledge/knowledge_learn_sequence.c | 3 | ||||
| -rw-r--r-- | src/knowledge/knowledge_learn_word.c | 79 | ||||
| -rw-r--r-- | src/knowledge/knowledge_locks.c | 342 | ||||
| -rw-r--r-- | src/knowledge/knowledge_swt_tws_modifications.c | 20 | ||||
| -rw-r--r-- | src/knowledge/knowledge_types.h | 8 | ||||
| -rw-r--r-- | src/sequence/sequence_creation.c | 45 | ||||
| -rw-r--r-- | src/sequence/sequence_from_string.c | 6 | ||||
| -rw-r--r-- | src/sequence/sequence_to_string.c | 4 | ||||
| -rw-r--r-- | src/server/server_worker_handle_request.c | 74 | 
16 files changed, 714 insertions, 233 deletions
| diff --git a/src/knowledge/CMakeLists.txt b/src/knowledge/CMakeLists.txt index ba3293d..ab96392 100644 --- a/src/knowledge/CMakeLists.txt +++ b/src/knowledge/CMakeLists.txt @@ -7,6 +7,7 @@ set(     ${CMAKE_CURRENT_SOURCE_DIR}/knowledge_learn_markov_sequence.c     ${CMAKE_CURRENT_SOURCE_DIR}/knowledge_learn_sequence.c     ${CMAKE_CURRENT_SOURCE_DIR}/knowledge_learn_word.c +   ${CMAKE_CURRENT_SOURCE_DIR}/knowledge_locks.c     ${CMAKE_CURRENT_SOURCE_DIR}/knowledge_search.c     ${CMAKE_CURRENT_SOURCE_DIR}/knowledge_swt_tws_modifications.c  ) diff --git a/src/knowledge/knowledge.c b/src/knowledge/knowledge.c index 93351da..9ef9c6e 100644 --- a/src/knowledge/knowledge.c +++ b/src/knowledge/knowledge.c @@ -24,9 +24,36 @@ int JH_knowledge_initialize (struct JH_knowledge k [const restrict static 1])     k->sequences_sorted = (JH_index *) NULL;  #ifndef JH_RUNNING_FRAMA_C -   error = pthread_mutex_init(&(k->mutex), (const pthread_mutexattr_t *) NULL); +   error = +      pthread_rwlock_init +      ( +         &(k->words_lock), +         (const pthread_rwlockattr_t *) NULL +      ); +#else +   error = 0; +#endif + +   if (error != 0) +   { +      JH_FATAL +      ( +         stderr, +         "Unable to initialize knowledge's words lock: %s.", +         strerror(error) +      ); + +      return -1; +   } + +#ifndef JH_RUNNING_FRAMA_C +   error = +      pthread_rwlock_init +      ( +         &(k->sequences_lock), +         (const pthread_rwlockattr_t *) NULL +      );  #else -   k->mutex = 1;     error = 0;  #endif @@ -35,7 +62,7 @@ int JH_knowledge_initialize (struct JH_knowledge k [const restrict static 1])        JH_FATAL        (           stderr, -         "Unable to initialize knowledge mutex: %s.", +         "Unable to initialize knowledge's sequences lock: %s.",           strerror(error)        ); @@ -75,82 +102,30 @@ int JH_knowledge_initialize (struct JH_knowledge k [const restrict static 1])     return 0;  } -int JH_knowledge_lock_access -( -   struct JH_knowledge k [const restrict static 1], -   FILE io [const restrict static 1] -) -{ -   int err; - -#ifndef JH_RUNNING_FRAMA_C -   err = pthread_mutex_lock(&(k->mutex)); -#else -   /*@ assert (k->mutex == 1); @*/ -   k->mutex = 0; -   err = 0; -#endif - -   if (err != 0) -   { -      JH_ERROR -      ( -         io, -         "Unable to get exclusive access to knowledge: %s", -         strerror(err) -      ); - -      return -1; -   } - -   return 0; -} - -void JH_knowledge_unlock_access -( -   struct JH_knowledge k [const restrict static 1], -   FILE io [const restrict static 1] -) -{ -   int err; - -#ifndef JH_RUNNING_FRAMA_C -   err = pthread_mutex_unlock(&(k->mutex)); -#else -   /*@ assert (k->mutex == 0); @*/ -   k->mutex = 1; -   err = 0; -#endif - -   if (err != 0) -   { -      JH_ERROR -      ( -         io, -         "Unable to release exclusive access to knowledge: %s", -         strerror(err) -      ); -   } -} -  void JH_knowledge_get_word  ( -   const struct JH_knowledge k [const static 1], +   struct JH_knowledge k [const static 1],     const JH_index word_ref,     const JH_char * word [const restrict static 1], -   JH_index word_length [const restrict static 1] +   JH_index word_length [const restrict static 1], +   FILE io [const restrict static 1]  )  { +   JH_knowledge_readlock_words(k, io); +     *word = k->words[word_ref].word;     *word_length = k->words[word_ref].word_length; + +   JH_knowledge_readunlock_words(k, io);  }  int JH_knowledge_rarest_word  ( -   const struct JH_knowledge k [const static 1], +   struct JH_knowledge k [const static 1],     const JH_index sequence [const restrict static 1],     const size_t sequence_length, -   JH_index word_id [const restrict static 1] +   JH_index word_id [const restrict static 1], +   FILE io [const restrict static 1]  )  {     JH_index current_max_score; @@ -163,6 +138,7 @@ int JH_knowledge_rarest_word     for (i = 0; i < sequence_length; ++i)     { +      JH_knowledge_readlock_word(k, sequence[i], io);        if        (           (k->words[sequence[i]].occurrences <= current_max_score) @@ -174,6 +150,8 @@ int JH_knowledge_rarest_word           *word_id = sequence[i];           success = 0;        } + +      JH_knowledge_readunlock_word(k, sequence[i], io);     }     return success; diff --git a/src/knowledge/knowledge.h b/src/knowledge/knowledge.h index 20293bc..fc4c5bc 100644 --- a/src/knowledge/knowledge.h +++ b/src/knowledge/knowledge.h @@ -8,43 +8,77 @@  #include "knowledge_types.h" -/*@ -   requires \valid(k); -   requires \separated(k, io); +int JH_knowledge_readlock_words +( +   struct JH_knowledge k [const restrict static 1], +   FILE io [const restrict static 1] +); -// Do not use if lock is already yours. -   requires (k->mutex == 1); +int JH_knowledge_writelock_words +( +   struct JH_knowledge k [const restrict static 1], +   FILE io [const restrict static 1] +); -// Returns zero on success, -1 on failure. -   assigns \result; -   ensures ((\result == 0) || (\result == -1)); +int JH_knowledge_readunlock_words +( +   struct JH_knowledge k [const restrict static 1], +   FILE io [const restrict static 1] +); -// On success, lock is acquired. -   ensures ((\result == 0) ==> (k->mutex == 0)); +int JH_knowledge_writeunlock_words +( +   struct JH_knowledge k [const restrict static 1], +   FILE io [const restrict static 1] +); -// Changes the status of the lock. -   assigns (k->mutex); -@*/ -int JH_knowledge_lock_access +int JH_knowledge_readlock_word  (     struct JH_knowledge k [const restrict static 1], +   const JH_index i,     FILE io [const restrict static 1]  ); -/*@ -   requires \valid(k); -   requires \separated(k, io); +int JH_knowledge_writelock_word +( +   struct JH_knowledge k [const restrict static 1], +   const JH_index i, +   FILE io [const restrict static 1] +); -// Do not use if lock is not yours. -   requires (k->mutex == 0); +int JH_knowledge_readunlock_word +( +   struct JH_knowledge k [const restrict static 1], +   const JH_index i, +   FILE io [const restrict static 1] +); -// Lock is released. -   ensures (k->mutex == 1); +int JH_knowledge_writeunlock_word +( +   struct JH_knowledge k [const restrict static 1], +   const JH_index i, +   FILE io [const restrict static 1] +); -// Changes the status of the lock. -   assigns (k->mutex); -@*/ -void JH_knowledge_unlock_access +int JH_knowledge_readlock_sequences +( +   struct JH_knowledge k [const restrict static 1], +   FILE io [const restrict static 1] +); + +int JH_knowledge_writelock_sequences +( +   struct JH_knowledge k [const restrict static 1], +   FILE io [const restrict static 1] +); + +int JH_knowledge_readunlock_sequences +( +   struct JH_knowledge k [const restrict static 1], +   FILE io [const restrict static 1] +); + +int JH_knowledge_writeunlock_sequences  (     struct JH_knowledge k [const restrict static 1],     FILE io [const restrict static 1] @@ -112,10 +146,11 @@ int JH_knowledge_learn_markov_sequence  void JH_knowledge_get_word  ( -   const struct JH_knowledge k [const static 1], +   struct JH_knowledge k [const static 1],     const JH_index word_ref,     const JH_char * word [const restrict static 1], -   JH_index word_length [const restrict static 1] +   JH_index word_length [const restrict static 1], +   FILE io [const restrict static 1]  );  /* @@ -127,6 +162,8 @@ void JH_knowledge_get_word   *    {word} is not in {k}.   *    {*result} is where {word} was expected to be found in   *    {k->sorted_indices}. + * + * Does not acquire locks   */  int JH_knowledge_find_word_id  ( @@ -136,6 +173,9 @@ int JH_knowledge_find_word_id     JH_index result [const restrict static 1]  ); + /* + * Does not acquire locks + */  int JH_knowledge_find_sequence  (     const struct JH_knowledge k [const static 1], @@ -146,12 +186,16 @@ int JH_knowledge_find_sequence  int JH_knowledge_rarest_word  ( -   const struct JH_knowledge k [const static 1], +   struct JH_knowledge k [const static 1],     const JH_index sequence [const restrict static 1],     const size_t sequence_length, -   JH_index word_id [const restrict static 1] +   JH_index word_id [const restrict static 1], +   FILE io [const restrict static 1]  ); +/* +* Does not acquire locks +*/  int JH_knowledge_find_markov_sequence  (     const JH_index sequence_id, @@ -159,6 +203,9 @@ int JH_knowledge_find_markov_sequence     JH_index result [const restrict static 1]  ); +/* +* Does not acquire locks +*/  int JH_knowledge_find_sequence_target  (     const JH_index target_id, @@ -168,23 +215,25 @@ int JH_knowledge_find_sequence_target  int JH_knowledge_random_tws_target  ( -   const struct JH_knowledge k [const static 1], +   struct JH_knowledge k [const static 1],     JH_index target [const restrict static 1],     const JH_index word_id, -   const JH_index sequence_id +   const JH_index sequence_id, +   FILE io [const restrict static 1]  );  int JH_knowledge_random_swt_target  ( -   const struct JH_knowledge k [const static 1], +   struct JH_knowledge k [const static 1],     const JH_index sequence_id,     const JH_index word_id, -   JH_index target [const restrict static 1] +   JH_index target [const restrict static 1], +   FILE io [const restrict static 1]  );  int JH_knowledge_copy_random_swt_sequence  ( -   const struct JH_knowledge k [const static 1], +   struct JH_knowledge k [const static 1],     JH_index sequence [const restrict static 1],     const JH_index word_id,     const JH_index markov_order, diff --git a/src/knowledge/knowledge_finalize.c b/src/knowledge/knowledge_finalize.c index 8020b9a..0665e59 100644 --- a/src/knowledge/knowledge_finalize.c +++ b/src/knowledge/knowledge_finalize.c @@ -69,6 +69,8 @@ static void knowledge_word_finalize     knowledge_sequence_collection_finalize(&(w->swt));     knowledge_sequence_collection_finalize(&(w->tws)); + +   pthread_rwlock_destroy(&(w->lock));  }  /* See: "knowledge.h" */ @@ -118,5 +120,6 @@ void JH_knowledge_finalize (struct JH_knowledge k [const restrict static 1])        k->sequences_sorted = (JH_index *) NULL;     } -   pthread_mutex_destroy(&(k->mutex)); +   pthread_rwlock_destroy(&(k->words_lock)); +   pthread_rwlock_destroy(&(k->sequences_lock));  } diff --git a/src/knowledge/knowledge_get_random_sequence.c b/src/knowledge/knowledge_get_random_sequence.c index 60a075f..5a214fd 100644 --- a/src/knowledge/knowledge_get_random_sequence.c +++ b/src/knowledge/knowledge_get_random_sequence.c @@ -49,7 +49,7 @@ static int weighted_random_pick  int JH_knowledge_copy_random_swt_sequence  ( -   const struct JH_knowledge k [const static 1], +   struct JH_knowledge k [const static 1],     JH_index sequence [const restrict static 1],     const JH_index word_id,     const JH_index markov_order, @@ -58,6 +58,8 @@ int JH_knowledge_copy_random_swt_sequence  {     JH_index sequence_id; +   JH_knowledge_readlock_word(k, word_id, io); +     if     (        weighted_random_pick @@ -65,7 +67,8 @@ int JH_knowledge_copy_random_swt_sequence           &(k->words[word_id].swt),           k->words[word_id].occurrences,           &sequence_id -      ) < 0 +      ) +      < 0     )     {        JH_S_PROG_ERROR @@ -73,11 +76,17 @@ int JH_knowledge_copy_random_swt_sequence           io,           "Knowledge inconsistency; there are no acceptable markov sequences "           "linked to a word that has been picked as being an acceptable pillar." -      ) -   ; +      ); + +      JH_knowledge_readunlock_word(k, word_id, io); +        return -1;     } +   JH_knowledge_readunlock_word(k, word_id, io); + +   JH_knowledge_readlock_sequences(k, io); +     memcpy     (        (void *) sequence, @@ -85,5 +94,7 @@ int JH_knowledge_copy_random_swt_sequence        (((size_t) (markov_order - 1)) * sizeof(JH_index))     ); +   JH_knowledge_readunlock_sequences(k, io); +     return 0;  } diff --git a/src/knowledge/knowledge_get_random_target.c b/src/knowledge/knowledge_get_random_target.c index d5f321d..1e878cf 100644 --- a/src/knowledge/knowledge_get_random_target.c +++ b/src/knowledge/knowledge_get_random_target.c @@ -48,14 +48,17 @@ static int weighted_random_pick  int JH_knowledge_random_tws_target  ( -   const struct JH_knowledge k [const static 1], +   struct JH_knowledge k [const static 1],     JH_index target [const restrict static 1],     const JH_index word_id, -   const JH_index sequence_id +   const JH_index sequence_id, +   FILE io [const restrict static 1]  )  {     JH_index s_index; +   JH_knowledge_readlock_word(k, word_id, io); +     if     (        JH_knowledge_find_markov_sequence @@ -66,27 +69,46 @@ int JH_knowledge_random_tws_target        ) < 0     )     { +      JH_knowledge_readunlock_word(k, word_id, io); +        return -1;     } -   return +   if +   (        weighted_random_pick        (           &(k->words[word_id].tws.sequences_ref[s_index]),           target -      ); +      ) +      < 0 +   ) +   { +      JH_knowledge_readunlock_word(k, word_id, io); + +      return -1; +   } +   else +   { +      JH_knowledge_readunlock_word(k, word_id, io); + +      return 0; +   }  }  int JH_knowledge_random_swt_target  ( -   const struct JH_knowledge k [const static 1], +   struct JH_knowledge k [const static 1],     const JH_index sequence_id,     const JH_index word_id, -   JH_index target [const restrict static 1] +   JH_index target [const restrict static 1], +   FILE io [const restrict static 1]  )  {     JH_index s_index; +   JH_knowledge_readlock_word(k, word_id, io); +     if     (        JH_knowledge_find_markov_sequence @@ -97,13 +119,29 @@ int JH_knowledge_random_swt_target        ) < 0     )     { +      JH_knowledge_readunlock_word(k, word_id, io); +        return -1;     } -   return +   if +   (        weighted_random_pick        (           &(k->words[word_id].swt.sequences_ref[s_index]),           target -      ); +      ) +      < 0 +   ) +   { +      JH_knowledge_readunlock_word(k, word_id, io); + +      return -1; +   } +   else +   { +      JH_knowledge_readunlock_word(k, word_id, io); + +      return 0; +   }  } diff --git a/src/knowledge/knowledge_learn_markov_sequence.c b/src/knowledge/knowledge_learn_markov_sequence.c index 4a770e2..74e29a7 100644 --- a/src/knowledge/knowledge_learn_markov_sequence.c +++ b/src/knowledge/knowledge_learn_markov_sequence.c @@ -380,6 +380,8 @@ int JH_knowledge_learn_markov_sequence        }     } +   JH_knowledge_readlock_sequences(k, io); +     if     (        JH_knowledge_find_sequence @@ -388,9 +390,49 @@ int JH_knowledge_learn_markov_sequence           sequence,           markov_order,           sequence_id -      ) == 0 +      ) +      == 0     )     { +      JH_knowledge_readunlock_sequences(k, io); + +      JH_DEBUG +      ( +         io, +         JH_DEBUG_KNOWLEDGE_LEARN_SEQUENCE, +         "Markov sequence is known. ID: %u", +         *sequence_id +      ); + +      return 0; +   } + +   /* +    * We need to write, but we currently have reading access. +    * We can't get the writing access while someone (even us) has the reading +    * access, so we release the reading access. +    */ +   JH_knowledge_readunlock_sequences(k, io); + +   JH_knowledge_writelock_sequences(k, io); +   /* +    * Now we have writer access, but someone else might have modified 'k' before +    * we did, so we need to find the sequence's location again. +    */ +   if +   ( +      JH_knowledge_find_sequence +      ( +         k, +         sequence, +         markov_order, +         sequence_id +      ) +      == 0 +   ) +   { +      JH_knowledge_writeunlock_sequences(k, io); +        JH_DEBUG        (           io, @@ -405,7 +447,8 @@ int JH_knowledge_learn_markov_sequence     sorted_id = *sequence_id;     *sequence_id = k->sequences_length; -   return +   if +   (        add_sequence        (           k, @@ -414,5 +457,18 @@ int JH_knowledge_learn_markov_sequence           *sequence_id,           sorted_id,           io -      ); +      ) +      < 0 +   ) +   { +      JH_knowledge_writeunlock_sequences(k, io); + +      return -1; +   } +   else +   { +      JH_knowledge_writeunlock_sequences(k, io); + +      return 0; +   }  } diff --git a/src/knowledge/knowledge_learn_sequence.c b/src/knowledge/knowledge_learn_sequence.c index 90dbc88..9502f2e 100644 --- a/src/knowledge/knowledge_learn_sequence.c +++ b/src/knowledge/knowledge_learn_sequence.c @@ -256,8 +256,11 @@ int JH_knowledge_learn_sequence           return -1;        } +      JH_knowledge_writelock_word(k, sequence[i], io);        k->words[sequence[i]].occurrences += 1; + +      JH_knowledge_writeunlock_word(k, sequence[i], io);     }     return 0; diff --git a/src/knowledge/knowledge_learn_word.c b/src/knowledge/knowledge_learn_word.c index 1389cdb..9320f10 100644 --- a/src/knowledge/knowledge_learn_word.c +++ b/src/knowledge/knowledge_learn_word.c @@ -20,17 +20,40 @@ static void initialize_sequence_collection     c->sequences_ref_sorted = (JH_index *) NULL;  } -static void initialize_word +static int initialize_word  (     struct JH_knowledge_word w [const restrict static 1]  )  { +   int error; +     w->word = (const JH_char *) NULL;     w->word_length = 0;     w->occurrences = 0;     initialize_sequence_collection(&(w->swt));     initialize_sequence_collection(&(w->tws)); + +   error = +      pthread_rwlock_init +      ( +         &(w->lock), +         (const pthread_rwlockattr_t *) NULL +      ); + +   if (error != 0) +   { +      JH_ERROR +      ( +         stderr, +         "Unable to initialize a knowledge's word lock: %s.", +         strerror(error) +      ); + +      return -1; +   } + +   return 0;  }  /******************************************************************************/ @@ -269,6 +292,45 @@ int JH_knowledge_learn_word        return -1;     } +   JH_knowledge_readlock_words(k, io); + +   if +   ( +      JH_knowledge_find_word_id +      ( +         k, +         word, +         (((size_t) word_length) * sizeof(JH_char)), +         word_id +      ) == 0 +   ) +   { +      JH_knowledge_readunlock_words(k, io); + +      JH_DEBUG +      ( +         io, +         JH_DEBUG_KNOWLEDGE_LEARN_WORD, +         "Word of size %u is already known (id: %u).", +         (JH_index) word_length, +         *word_id +      ); + +      return 0; +   } + +   /* +    * We need to write, but we currently have reading access. +    * We can't get the writing access while someone (even us) has the reading +    * access, so we release the reading access. +    */ +   JH_knowledge_readunlock_words(k, io); + +   JH_knowledge_writelock_words(k, io); +   /* +    * Now we have writer access, but someone else might have modified 'k' before +    * we did, so we need to find the word's location again. +    */     if     (        JH_knowledge_find_word_id @@ -280,6 +342,8 @@ int JH_knowledge_learn_word        ) == 0     )     { +      JH_knowledge_writeunlock_words(k, io); +        JH_DEBUG        (           io, @@ -305,5 +369,16 @@ int JH_knowledge_learn_word        sorted_id     ); -   return add_word(k, word, (JH_index) word_length, *word_id, sorted_id, io); +   if (add_word(k, word, (JH_index) word_length, *word_id, sorted_id, io) < 0) +   { +      JH_knowledge_writeunlock_words(k, io); + +      return -1; +   } +   else +   { +      JH_knowledge_writeunlock_words(k, io); + +      return 0; +   }  } diff --git a/src/knowledge/knowledge_locks.c b/src/knowledge/knowledge_locks.c new file mode 100644 index 0000000..8d83664 --- /dev/null +++ b/src/knowledge/knowledge_locks.c @@ -0,0 +1,342 @@ +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdint.h> /* defines SIZE_MAX */ + +#include "../error/error.h" + +#include "knowledge.h" + +/** WORDS *********************************************************************/ +/**** LOCK ********************************************************************/ +int JH_knowledge_readlock_words +( +   struct JH_knowledge k [const restrict static 1], +   FILE io [const restrict static 1] +) +{ +   int err; + +   err = pthread_rwlock_rdlock(&(k->words_lock)); + +   if (err != 0) +   { +      JH_ERROR +      ( +         io, +         "Unable to gain read access to knowledge's words: %s", +         strerror(err) +      ); + +      return -1; +   } + +   return 0; +} + +int JH_knowledge_writelock_words +( +   struct JH_knowledge k [const restrict static 1], +   FILE io [const restrict static 1] +) +{ +   int err; + +   err = pthread_rwlock_wrlock(&(k->words_lock)); + +   if (err != 0) +   { +      JH_ERROR +      ( +         io, +         "Unable to gain write access to knowledge's words: %s", +         strerror(err) +      ); + +      return -1; +   } + +   return 0; +} + +/**** UNLOCK ******************************************************************/ +int JH_knowledge_readunlock_words +( +   struct JH_knowledge k [const restrict static 1], +   FILE io [const restrict static 1] +) +{ +   int err; + +   err = pthread_rwlock_unlock(&(k->words_lock)); + +   if (err != 0) +   { +      JH_ERROR +      ( +         io, +         "Unable to release read access to knowledge's words: %s", +         strerror(err) +      ); + +      return -1; +   } + +   return 0; +} + +int JH_knowledge_writeunlock_words +( +   struct JH_knowledge k [const restrict static 1], +   FILE io [const restrict static 1] +) +{ +   int err; + +   err = pthread_rwlock_unlock(&(k->words_lock)); + +   if (err != 0) +   { +      JH_ERROR +      ( +         io, +         "Unable to release write access to knowledge's words: %s", +         strerror(err) +      ); + +      return -1; +   } + +   return 0; +} + +/** SEQUENCES *****************************************************************/ +/**** LOCK ********************************************************************/ +int JH_knowledge_readlock_sequences +( +   struct JH_knowledge k [const restrict static 1], +   FILE io [const restrict static 1] +) +{ +   int err; + +   err = pthread_rwlock_rdlock(&(k->sequences_lock)); + +   if (err != 0) +   { +      JH_ERROR +      ( +         io, +         "Unable to gain read access to knowledge's sequences: %s", +         strerror(err) +      ); + +      return -1; +   } + +   return 0; +} + +int JH_knowledge_writelock_sequences +( +   struct JH_knowledge k [const restrict static 1], +   FILE io [const restrict static 1] +) +{ +   int err; + +   err = pthread_rwlock_wrlock(&(k->sequences_lock)); + +   if (err != 0) +   { +      JH_ERROR +      ( +         io, +         "Unable to gain write access to knowledge's sequences: %s", +         strerror(err) +      ); + +      return -1; +   } + +   return 0; +} + +/**** UNLOCK ******************************************************************/ +int JH_knowledge_readunlock_sequences +( +   struct JH_knowledge k [const restrict static 1], +   FILE io [const restrict static 1] +) +{ +   int err; + +   err = pthread_rwlock_unlock(&(k->sequences_lock)); + +   if (err != 0) +   { +      JH_ERROR +      ( +         io, +         "Unable to release read access to knowledge's sequences: %s", +         strerror(err) +      ); + +      return -1; +   } + +   return 0; +} + +int JH_knowledge_writeunlock_sequences +( +   struct JH_knowledge k [const restrict static 1], +   FILE io [const restrict static 1] +) +{ +   int err; + +   err = pthread_rwlock_unlock(&(k->sequences_lock)); + +   if (err != 0) +   { +      JH_ERROR +      ( +         io, +         "Unable to release write access to knowledge's sequences: %s", +         strerror(err) +      ); + +      return -1; +   } + +   return 0; +} + +/** WORD **********************************************************************/ +/**** LOCK ********************************************************************/ +int JH_knowledge_readlock_word +( +   struct JH_knowledge k [const restrict static 1], +   const JH_index i, +   FILE io [const restrict static 1] +) +{ +   int err; + +   if (JH_knowledge_readlock_words(k, io) < 0) +   { +      return -1; +   } + +   err = pthread_rwlock_rdlock(&(k->words[i].lock)); + +   if (err != 0) +   { +      JH_ERROR +      ( +         io, +         "Unable to gain read access to a knowledge's word: %s", +         strerror(err) +      ); + +      return -1; +   } + +   return 0; +} + +int JH_knowledge_writelock_word +( +   struct JH_knowledge k [const restrict static 1], +   const JH_index i, +   FILE io [const restrict static 1] +) +{ +   int err; + +   if (JH_knowledge_readlock_words(k, io) < 0) +   { +      return -1; +   } + + +   err = pthread_rwlock_wrlock(&(k->words[i].lock)); + +   if (err != 0) +   { +      JH_ERROR +      ( +         io, +         "Unable to gain write access to a knowledge's word: %s", +         strerror(err) +      ); + +      return -1; +   } + +   return 0; +} + +/**** UNLOCK ******************************************************************/ +int JH_knowledge_readunlock_word +( +   struct JH_knowledge k [const restrict static 1], +   const JH_index i, +   FILE io [const restrict static 1] +) +{ +   int err; + +   if (JH_knowledge_readunlock_words(k, io) < 0) +   { +      return -1; +   } + +   err = pthread_rwlock_unlock(&(k->words[i].lock)); + +   if (err != 0) +   { +      JH_ERROR +      ( +         io, +         "Unable to release read access to a knowledge's word: %s", +         strerror(err) +      ); + +      return -1; +   } + +   return 0; +} + +int JH_knowledge_writeunlock_word +( +   struct JH_knowledge k [const restrict static 1], +   const JH_index i, +   FILE io [const restrict static 1] +) +{ +   int err; + +   if (JH_knowledge_readunlock_words(k, io) < 0) +   { +      return -1; +   } + +   err = pthread_rwlock_unlock(&(k->words[i].lock)); + +   if (err != 0) +   { +      JH_ERROR +      ( +         io, +         "Unable to release write access to a knowledge's word: %s", +         strerror(err) +      ); + +      return -1; +   } + +   return 0; +} diff --git a/src/knowledge/knowledge_swt_tws_modifications.c b/src/knowledge/knowledge_swt_tws_modifications.c index 2acd093..cc8a938 100644 --- a/src/knowledge/knowledge_swt_tws_modifications.c +++ b/src/knowledge/knowledge_swt_tws_modifications.c @@ -163,6 +163,8 @@ int JH_knowledge_strengthen_swt  {     JH_index s_index, t_index; +   JH_knowledge_writelock_word(k, word_id, io); +     if     (        JH_knowledge_find_markov_sequence @@ -184,6 +186,8 @@ int JH_knowledge_strengthen_swt           ) < 0        )        { +         JH_knowledge_writeunlock_word(k, word_id, io); +           return -1;        }     } @@ -210,6 +214,8 @@ int JH_knowledge_strengthen_swt           ) < 0        )        { +         JH_knowledge_writeunlock_word(k, word_id, io); +           return -1;        }     } @@ -233,12 +239,16 @@ int JH_knowledge_strengthen_swt           "[W] Unable to strengthen SWT link: link is already at max strength."        ); +      JH_knowledge_writeunlock_word(k, word_id, io); +        return 1;     }     k->words[word_id].swt.sequences_ref[s_index].occurrences += 1;     k->words[word_id].swt.sequences_ref[s_index].targets[t_index].occurrences += 1; +   JH_knowledge_writeunlock_word(k, word_id, io); +     return 0;  } @@ -253,6 +263,8 @@ int JH_knowledge_strengthen_tws  {     JH_index s_index, t_index; +   JH_knowledge_writelock_word(k, word_id, io); +     if     (        JH_knowledge_find_markov_sequence @@ -274,6 +286,8 @@ int JH_knowledge_strengthen_tws           ) < 0        )        { +         JH_knowledge_writeunlock_word(k, word_id, io); +           return -1;        }     } @@ -300,6 +314,8 @@ int JH_knowledge_strengthen_tws           ) < 0        )        { +         JH_knowledge_writeunlock_word(k, word_id, io); +           return -1;        }     } @@ -323,11 +339,15 @@ int JH_knowledge_strengthen_tws           "[E] Unable to strengthen TWS link: link is already at max strength."        ); +      JH_knowledge_writeunlock_word(k, word_id, io); +        return -1;     }     k->words[word_id].tws.sequences_ref[s_index].occurrences += 1;     k->words[word_id].tws.sequences_ref[s_index].targets[t_index].occurrences += 1; +   JH_knowledge_writeunlock_word(k, word_id, io); +     return 0;  } diff --git a/src/knowledge/knowledge_types.h b/src/knowledge/knowledge_types.h index 82073ff..780d4df 100644 --- a/src/knowledge/knowledge_types.h +++ b/src/knowledge/knowledge_types.h @@ -40,14 +40,18 @@ struct JH_knowledge_word     /* [Target] [Word] [Sequence] */     struct JH_knowledge_sequence_collection tws; + +   pthread_rwlock_t lock;  };  struct JH_knowledge  {  #ifndef JH_RUNNING_FRAMA_C -   pthread_mutex_t mutex; +   pthread_rwlock_t words_lock; +   pthread_rwlock_t sequences_lock;  #else -   int mutex; +   int words_lock; +   int sequences_lock;  #endif     struct JH_knowledge_word * words; diff --git a/src/sequence/sequence_creation.c b/src/sequence/sequence_creation.c index 0b5e393..2e8e17e 100644 --- a/src/sequence/sequence_creation.c +++ b/src/sequence/sequence_creation.c @@ -45,10 +45,10 @@ static int extend_left  {     JH_index sequence_id, word_id; -   (void) JH_knowledge_lock_access(k, io); -     /* preceding_words_weights_sum > 0 */ +   JH_knowledge_readlock_sequences(k, io); +     if     (        JH_knowledge_find_sequence @@ -60,16 +60,14 @@ static int extend_left        ) < 0     )     { -      (void) JH_knowledge_unlock_access(k, io); +      JH_knowledge_readunlock_sequences(k, io);        JH_S_ERROR(io, "Could not find matching TWS sequence.");        return -1;     } -   (void) JH_knowledge_unlock_access(k, io); - -   (void) JH_knowledge_lock_access(k, io); +   JH_knowledge_readunlock_sequences(k, io);     if     ( @@ -78,19 +76,16 @@ static int extend_left           k,           &word_id,           (*sequence)[0], -         sequence_id +         sequence_id, +         io        ) < 0     )     { -      (void) JH_knowledge_unlock_access(k, io); -        JH_S_ERROR(io, "Could not find matching TWS target.");        return -1;     } -   (void) JH_knowledge_unlock_access(k, io); -     if     (        JH_sequence_append_left @@ -243,10 +238,10 @@ static int extend_right  {     JH_index sequence_id, word_id; -   (void) JH_knowledge_lock_access(k, io); -     /* preceding_words_weights_sum > 0 */ +   JH_knowledge_readlock_sequences(k, io); +     if     (        JH_knowledge_find_sequence @@ -258,7 +253,7 @@ static int extend_right        ) < 0     )     { -      (void) JH_knowledge_unlock_access(k, io); +      JH_knowledge_readunlock_sequences(k, io);        JH_S_PROG_ERROR        ( @@ -270,9 +265,7 @@ static int extend_right        return -1;     } -   (void) JH_knowledge_unlock_access(k, io); - -   (void) JH_knowledge_lock_access(k, io); +   JH_knowledge_readunlock_sequences(k, io);     if     ( @@ -281,12 +274,11 @@ static int extend_right           k,           sequence_id,           (*sequence)[*sequence_length - 1], -         &word_id +         &word_id, +         io        ) < 0     )     { -      (void) JH_knowledge_unlock_access(k, io); -        JH_S_PROG_ERROR        (           io, @@ -297,9 +289,6 @@ static int extend_right        return -1;     } -   (void) JH_knowledge_unlock_access(k, io); - -     /* following_words_weights_sum > 0 */     if @@ -314,13 +303,9 @@ static int extend_right        ) < 0     )     { -      (void) JH_knowledge_unlock_access(k, io); -        return -3;     } -   (void) JH_knowledge_unlock_access(k, io); -     return 0;  } @@ -454,8 +439,6 @@ static int initialize_sequence  {     sequence[(markov_order - 1)] = initial_word; -   (void) JH_knowledge_lock_access(k, io); -     if     (        JH_knowledge_copy_random_swt_sequence @@ -468,13 +451,9 @@ static int initialize_sequence        ) < 0     )     { -      (void) JH_knowledge_unlock_access(k, io); -        return -1;     } -   (void) JH_knowledge_unlock_access(k, io); -     if (JH_DEBUG_SEQUENCE_CREATION_INIT)     {        JH_index i; diff --git a/src/sequence/sequence_from_string.c b/src/sequence/sequence_from_string.c index 5b92943..5e434f3 100644 --- a/src/sequence/sequence_from_string.c +++ b/src/sequence/sequence_from_string.c @@ -30,8 +30,6 @@ static int add_word_to_sequence  {     JH_index word_id; -   (void) JH_knowledge_lock_access(k, io); -     if     (        JH_knowledge_learn_word @@ -44,13 +42,9 @@ static int add_word_to_sequence        ) < 0     )     { -      (void) JH_knowledge_unlock_access(k, io); -        return -1;     } -   (void) JH_knowledge_unlock_access(k, io); -     if     (        JH_sequence_append_right diff --git a/src/sequence/sequence_to_string.c b/src/sequence/sequence_to_string.c index 6794fcb..70dcf1a 100644 --- a/src/sequence/sequence_to_string.c +++ b/src/sequence/sequence_to_string.c @@ -114,9 +114,7 @@ static int add_word        return 0;     } -   (void) JH_knowledge_lock_access(k, io); -   JH_knowledge_get_word(k, word_id, &word, &word_size); -   (void) JH_knowledge_unlock_access(k, io); +   JH_knowledge_get_word(k, word_id, &word, &word_size, io);     insertion_point = *destination_length; diff --git a/src/server/server_worker_handle_request.c b/src/server/server_worker_handle_request.c index 256ed06..25f93bc 100644 --- a/src/server/server_worker_handle_request.c +++ b/src/server/server_worker_handle_request.c @@ -19,44 +19,22 @@ static int load_reply     if     ( -      JH_knowledge_lock_access -      ( -         worker->params.knowledge, -         worker->socket_as_file -      ) < 0 -   ) -   { -      return -1; -   } - -   if -   (        JH_knowledge_rarest_word        (           worker->params.knowledge,           worker->sequence_buffer,           worker->sequence_buffer_length, -         &rarest_word_id +         &rarest_word_id, +         worker->socket_as_file        ) < 0     )     { -      JH_knowledge_unlock_access -      ( -         worker->params.knowledge, -         worker->socket_as_file -      );        JH_S_ERROR(worker->socket_as_file, "Could not find rarest word.");        return -1;     } -   JH_knowledge_unlock_access -   ( -      worker->params.knowledge, -      worker->socket_as_file -   ); -     JH_DEBUG     (        worker->socket_as_file, @@ -162,18 +140,6 @@ static int handle_rl     if     ( -      JH_knowledge_lock_access -      ( -         worker->params.knowledge, -         worker->socket_as_file -      ) < 0 -   ) -   { -      return JH_server_worker_send_negative(worker); -   } - -   if -   (        JH_knowledge_learn_sequence        (           worker->params.knowledge, @@ -184,21 +150,9 @@ static int handle_rl        ) < 0     )     { -      JH_knowledge_unlock_access -      ( -         worker->params.knowledge, -         worker->socket_as_file -      ); -        return JH_server_worker_send_negative(worker);     } -   JH_knowledge_unlock_access -   ( -      worker->params.knowledge, -      worker->socket_as_file -   ); -     return JH_server_worker_send_positive(worker);  } @@ -226,18 +180,6 @@ static int handle_rlr     if     ( -      JH_knowledge_lock_access -      ( -         worker->params.knowledge, -         worker->socket_as_file -      ) < 0 -   ) -   { -      return JH_server_worker_send_negative(worker); -   } - -   if -   (        JH_knowledge_learn_sequence        (           worker->params.knowledge, @@ -248,21 +190,9 @@ static int handle_rlr        ) < 0     )     { -      JH_knowledge_unlock_access -      ( -         worker->params.knowledge, -         worker->socket_as_file -      ); -        return JH_server_worker_send_negative(worker);     } -   JH_knowledge_unlock_access -   ( -      worker->params.knowledge, -      worker->socket_as_file -   ); -     if (load_reply(worker) < 0)     {        return JH_server_worker_send_negative(worker); | 


