From 8d5c996aef28fae9f848e1fab419b4d2821e8862 Mon Sep 17 00:00:00 2001 From: Nathanael Sensfelder Date: Thu, 29 Jun 2017 15:20:24 +0200 Subject: First shot at finer mutexes. --- src/knowledge/CMakeLists.txt | 1 + src/knowledge/knowledge.c | 108 +++----- src/knowledge/knowledge.h | 117 +++++--- src/knowledge/knowledge_finalize.c | 5 +- src/knowledge/knowledge_get_random_sequence.c | 19 +- src/knowledge/knowledge_get_random_target.c | 54 +++- src/knowledge/knowledge_learn_markov_sequence.c | 62 ++++- src/knowledge/knowledge_learn_sequence.c | 3 + src/knowledge/knowledge_learn_word.c | 79 +++++- src/knowledge/knowledge_locks.c | 342 ++++++++++++++++++++++++ src/knowledge/knowledge_swt_tws_modifications.c | 20 ++ src/knowledge/knowledge_types.h | 8 +- src/sequence/sequence_creation.c | 45 +--- src/sequence/sequence_from_string.c | 6 - src/sequence/sequence_to_string.c | 4 +- src/server/server_worker_handle_request.c | 74 +---- 16 files changed, 714 insertions(+), 233 deletions(-) create mode 100644 src/knowledge/knowledge_locks.c 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 +#include +#include +#include /* 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 @@ -17,18 +17,6 @@ static int load_reply { JH_index rarest_word_id; - if - ( - JH_knowledge_lock_access - ( - worker->params.knowledge, - worker->socket_as_file - ) < 0 - ) - { - return -1; - } - if ( JH_knowledge_rarest_word @@ -36,27 +24,17 @@ static int load_reply 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, @@ -160,18 +138,6 @@ static int handle_rl return JH_server_worker_send_negative(worker); } - 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 @@ -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); } @@ -224,18 +178,6 @@ static int handle_rlr return JH_server_worker_send_negative(worker); } - 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 @@ -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); -- cgit v1.2.3-70-g09d2