diff --git a/doc/CK_RWCOHORT_INIT b/doc/CK_RWCOHORT_INIT index 1d543e8..e097039 100644 --- a/doc/CK_RWCOHORT_INIT +++ b/doc/CK_RWCOHORT_INIT @@ -33,18 +33,20 @@ Concurrency Kit (libck, \-lck) .Sh SYNOPSIS .In ck_rwcohort.h -.Fn CK_RWCOHORT_INIT "COHORT_NAME cohort_name" "LOCK *lock" "unsigned int wait_limit" +.Fn CK_RWCOHORT_NEUTRAL_INIT "COHORT_NAME cohort_name" "LOCK *lock" +.Fn CK_RWCOHORT_RP_INIT "COHORT_NAME cohort_name" "LOCK *lock" "unsigned int wait_limit" +.Fn CK_RWCOHORT_WP_INIT "COHORT_NAME cohort_name" "LOCK *lock" "unsigned int wait_limit" .Sh DESCRIPTION This macro initializes the lock instance pointed to by the .Fa lock argument. Until a lock instance is initialized using the CK_RWCOHORT_INIT macro, any operations -involving it will have undefined behavior. The +involving it will have undefined behavior. Note that the .Fa wait_limit argument should only be used with reader-preference or writer-preference locks. For neutral locks, this argument should be excluded. If you are unsure of a value to use for the .Fa wait_limit -argument, you should use CK_RWCOHORT_DEFAULT_LOCAL_WAIT_LIMIT. +argument, you should use CK_RWCOHORT_STRATEGY_DEFAULT_LOCAL_WAIT_LIMIT. .Sh SEE ALSO .Xr ck_rwcohort 3 , .Xr CK_RWCOHORT_PROTOTYPE 3 , diff --git a/doc/CK_RWCOHORT_INSTANCE b/doc/CK_RWCOHORT_INSTANCE index c4e7f10..fcdfeea 100644 --- a/doc/CK_RWCOHORT_INSTANCE +++ b/doc/CK_RWCOHORT_INSTANCE @@ -33,7 +33,9 @@ Concurrency Kit (libck, \-lck) .Sh SYNOPSIS .In ck_cohort.h -.Fn CK_RWCOHORT_INSTANCE "COHORT_NAME cohort_name" +.Fn CK_RWCOHORT_NEUTRAL_INSTANCE "COHORT_NAME cohort_name" +.Fn CK_RWCOHORT_RP_INSTANCE "COHORT_NAME cohort_name" +.Fn CK_RWCOHORT_WP_INSTANCE "COHORT_NAME cohort_name" .Sh DESCRIPTION The user must use this macro to declare instances of lock types that they have defined using the @@ -47,7 +49,7 @@ CK_RWCOHORT_INSTANCE(foo) cohort; This macro should also be used when allocating memory for cohorts. For instance, to allocate a block of 4 cohorts: .br -CK_RWCOHORT_INSTANCE(foo) *cohorts = malloc(4 * sizeof(CK_RWCOHORT_INSTANCE(foo))); +CK_RWCOHORT_WP_INSTANCE(foo) *cohorts = malloc(4 * sizeof(CK_RWCOHORT_WP_INSTANCE(foo))); .Sh SEE ALSO .Xr ck_rwcohort 3 , .Xr CK_RWCOHORT_PROTOTYPE 3 , diff --git a/doc/CK_RWCOHORT_PROTOTYPE b/doc/CK_RWCOHORT_PROTOTYPE index cd8710d..fb4d25a 100644 --- a/doc/CK_RWCOHORT_PROTOTYPE +++ b/doc/CK_RWCOHORT_PROTOTYPE @@ -33,7 +33,9 @@ Concurrency Kit (libck, \-lck) .Sh SYNOPSIS .In ck_rwcohort.h -.Fn CK_RWCOHORT_PROTOTYPE "COHORT_NAME cohort_name" +.Fn CK_RWCOHORT_NEUTRAL_PROTOTYPE "COHORT_NAME cohort_name" +.Fn CK_RWCOHORT_RP_PROTOTYPE "COHORT_NAME cohort_name" +.Fn CK_RWCOHORT_WP_PROTOTYPE "COHORT_NAME cohort_name" .Sh DESCRIPTION The ck_rwcohort.h header file does not define any cohort types. Instead, the user must use the CK_RWCOHORT_PROTOTYPE macro to define any types they want to use. diff --git a/doc/CK_RWCOHORT_READ_LOCK b/doc/CK_RWCOHORT_READ_LOCK index 68e8da0..bf65853 100644 --- a/doc/CK_RWCOHORT_READ_LOCK +++ b/doc/CK_RWCOHORT_READ_LOCK @@ -33,7 +33,11 @@ Concurrency Kit (libck, \-lck) .Sh SYNOPSIS .In ck_cohort.h -.Fn CK_RWCOHORT_READ_LOCK "COHORT_NAME cohort_name" "LOCK *lock" "COHORT *cohort"\ +.Fn CK_RWCOHORT_NEUTRAL_READ_LOCK "COHORT_NAME cohort_name" "LOCK *lock" "COHORT *cohort"\ +"void *global_context" "void *local_context" +.Fn CK_RWCOHORT_RP_READ_LOCK "COHORT_NAME cohort_name" "LOCK *lock" "COHORT *cohort"\ +"void *global_context" "void *local_context" +.Fn CK_RWCOHORT_WP_READ_LOCK "COHORT_NAME cohort_name" "LOCK *lock" "COHORT *cohort"\ "void *global_context" "void *local_context" .Sh DESCRIPTION This call will acquire read-only permission from diff --git a/doc/CK_RWCOHORT_READ_UNLOCK b/doc/CK_RWCOHORT_READ_UNLOCK index 04f2ff9..4dd26e1 100644 --- a/doc/CK_RWCOHORT_READ_UNLOCK +++ b/doc/CK_RWCOHORT_READ_UNLOCK @@ -33,7 +33,11 @@ Concurrency Kit (libck, \-lck) .Sh SYNOPSIS .In ck_cohort.h -.Fn CK_RWCOHORT_READ_LOCK "COHORT_NAME cohort_name" "LOCK *lock" "COHORT *cohort"\ +.Fn CK_RWCOHORT_NEUTRAL_READ_UNLOCK "COHORT_NAME cohort_name" "LOCK *lock" "COHORT *cohort"\ +"void *global_context" "void *local_context" +.Fn CK_RWCOHORT_RP_READ_UNLOCK "COHORT_NAME cohort_name" "LOCK *lock" "COHORT *cohort"\ +"void *global_context" "void *local_context" +.Fn CK_RWCOHORT_WP_READ_UNLOCK "COHORT_NAME cohort_name" "LOCK *lock" "COHORT *cohort"\ "void *global_context" "void *local_context" .Sh DESCRIPTION This call will relinquish read-only permission to diff --git a/doc/CK_RWCOHORT_WRITE_LOCK b/doc/CK_RWCOHORT_WRITE_LOCK index 724d4b5..b34b0ee 100644 --- a/doc/CK_RWCOHORT_WRITE_LOCK +++ b/doc/CK_RWCOHORT_WRITE_LOCK @@ -33,7 +33,11 @@ Concurrency Kit (libck, \-lck) .Sh SYNOPSIS .In ck_cohort.h -.Fn CK_RWCOHORT_READ_LOCK "COHORT_NAME cohort_name" "LOCK *lock" "COHORT *cohort"\ +.Fn CK_RWCOHORT_NEUTRAL_WRITE_LOCK "COHORT_NAME cohort_name" "LOCK *lock" "COHORT *cohort"\ +"void *global_context" "void *local_context" +.Fn CK_RWCOHORT_RP_WRITE_LOCK "COHORT_NAME cohort_name" "LOCK *lock" "COHORT *cohort"\ +"void *global_context" "void *local_context" +.Fn CK_RWCOHORT_WP_WRITE_LOCK "COHORT_NAME cohort_name" "LOCK *lock" "COHORT *cohort"\ "void *global_context" "void *local_context" .Sh DESCRIPTION This call will acquire write permission for diff --git a/doc/CK_RWCOHORT_WRITE_UNLOCK b/doc/CK_RWCOHORT_WRITE_UNLOCK index 4d063f8..61cbcf6 100644 --- a/doc/CK_RWCOHORT_WRITE_UNLOCK +++ b/doc/CK_RWCOHORT_WRITE_UNLOCK @@ -33,7 +33,11 @@ Concurrency Kit (libck, \-lck) .Sh SYNOPSIS .In ck_cohort.h -.Fn CK_RWCOHORT_READ_LOCK "COHORT_NAME cohort_name" "LOCK *lock" "COHORT *cohort"\ +.Fn CK_RWCOHORT_NEUTRAL_WRITE_UNLOCK "COHORT_NAME cohort_name" "LOCK *lock" "COHORT *cohort"\ +"void *global_context" "void *local_context" +.Fn CK_RWCOHORT_RP_WRITE_UNLOCK "COHORT_NAME cohort_name" "LOCK *lock" "COHORT *cohort"\ +"void *global_context" "void *local_context" +.Fn CK_RWCOHORT_WP_WRITE_UNLOCK "COHORT_NAME cohort_name" "LOCK *lock" "COHORT *cohort"\ "void *global_context" "void *local_context" .Sh DESCRIPTION This call will relinquish write permission for diff --git a/doc/ck_rwcohort b/doc/ck_rwcohort index d948db6..8948287 100644 --- a/doc/ck_rwcohort +++ b/doc/ck_rwcohort @@ -24,66 +24,55 @@ .\" SUCH DAMAGE. .\" .\" -.Dd February 24, 2013. -.Dt ck_cohort 3 +.Dd April 23, 2013. +.Dt ck_rwcohort 3 .Sh NAME -.Nm ck_cohort -.Nd generalized interface for lock cohorts +.Nm ck_rwcohort +.Nd generalized interface for reader-writer locks using cohort locks .Sh LIBRARY Concurrency Kit (libck, \-lck) .Sh SYNOPSIS -.In ck_cohort.h -.Fn CK_COHORT_PROTOTYPE "COHORT_NAME cohort_name" "LOCK_FXN global_lock_method" \ -"LOCK_FXN global_unlock_method" "LOCK_FXN local_lock_method" "LOCK_FXN local_unlock_method" -.Fn CK_COHORT_TRYLOCK_PROTOTYPE "COHORT_NAME cohort_name" \ -"LOCK_FXN global_lock_method" "LOCK_FXN global_unlock_method" \ -"BOOL_LOCK_FXN global_locked_method" BOOL_LOCK_FXN global_trylock_method" \ -"LOCK_FXN local_lock_method" "LOCK_FXN local_unlock_method" \ -"BOOL_LOCK_FXN local_locked_method" BOOL_LOCK_FXN local_trylock_method" -.Fn CK_COHORT_INSTANCE "COHORT_NAME cohort_name" -.Fn CK_COHORT_INIT "COHORT_NAME cohort_name" "ck_cohort *cohort" \ -"void *global_lock" "void *local_lock" "unsigned int pass_limit" -.Fn CK_COHORT_LOCK "COHORT_NAME cohort_name" "ck_cohort *cohort" \ +.In ck_rwcohort.h +In each of the following macros, "STRATEGY" should be replaced with either "NEUTRAL", "RP", or "WP" +depending on which locking strategy the user prefers. RP and WP represent reader preference and +writer preference, respectively, while NEUTRAL represents a strategy neutral to reads vs. writes. +.Fn CK_RWCOHORT_STRATEGY_PROTOTYPE "COHORT_NAME cohort_name" +.Fn CK_RWCOHORT_STRATEGY_NAME "COHORT_NAME cohort_name" +.Fn CK_RWCOHORT_STRATEGY_INSTANCE "COHORT_NAME cohort_name" +.Fn CK_RWCOHORT_STRATEGY_INIT "COHORT_NAME cohort_name" "RWCOHORT lock" "unsigned int wait_limit" +Note: the wait_limit argument should be omitted for locks using the neutral strategy +.Fn CK_RWCOHORT_STRATEGY_READ_LOCK "COHORT_NAME cohort_name" "RWCOHORT lock" "COHORT cohort" \ "void *global_context" "void *local_context" -.Fn CK_COHORT_UNLOCK "COHORT_NAME cohort_name" "ck_cohort *cohort" \ +.Fn CK_RWCOHORT_STRATEGY_READ_UNLOCK "COHORT_NAME cohort_name" "RWCOHORT lock" "COHORT cohort" \ "void *global_context" "void *local_context" -.Pp -Where LOCK_FXN refers to a method with the signature -.br -void(void *lock, void *context) -.br -BOOL_LOCK_FXN refers to a method with the signature -.br -bool(void *lock, void *context) -.Pp -The -.Fa context -argument in each signature is used to pass along any additional information that -the lock might need for its lock, unlock and trylock methods. The values for this -argument are provided to each call to -.Xr CK_COHORT_LOCK 3 , -.Xr CK_COHORT_UNLOCK 3 , -.Xr CK_COHORT_LOCKED 3 , -and -.Xr CK_COHORT_TRYLOCK 3 -. +.Fn CK_RWCOHORT_STRATEGY_WRITE_LOCK "COHORT_NAME cohort_name" "RWCOHORT lock" "COHORT cohort" \ +"void *global_context" "void *local_context" +.Fn CK_RWCOHORT_STRATEGY_WRITE_UNLOCK "COHORT_NAME cohort_name" "RWCOHORT lock" "COHORT cohort" \ +"void *global_context" "void *local_context" + +Arguments of type RWCOHORT must be pointers to structs defined using the +.Xr CK_RWCOHORT_STRATEGY_PROTOTYPE 3 +macro with the same strategy and cohort name as the current call. + +Arguments of type COHORT must be pointers to structs defined using the +.Xr CK_COHORT_PROTOTYPE 3 +macro. + .Sh DESCRIPTION -ck_cohort.h provides an interface for defining lock cohorts with -arbitrary lock types. Cohorts are a mechanism for coordinating -threads on NUMA architectures in order to reduce the frequency -with which a lock is passed between threads on different clusters. +ck_rwcohort.h provides an interface for defining reader-writer locks +that use cohort locks internally to increase performance on NUMA +architectures. See +.Xr ck_cohort 3 +for more information about cohort locks. .Pp -Before using a cohort, the user must define a cohort type using +Before using a reader-writer cohort lock, the user must define a cohort type using either the -.Fn CK_COHORT_PROTOTYPE -or the -.Fn CK_COHORT_TRYLOCK_PROTOTYPE -macros. These macros allow the user to specify the lock methods that -they would like the cohort to use. See the .Xr CK_COHORT_PROTOTYPE 3 -and +or the .Xr CK_COHORT_TRYLOCK_PROTOTYPE 3 -man pages for more details. +macros, and define a reader-writer lock type using the +.Xr CK_RWCOHORT_PROTOTYPE 3 +macro. .Pp .Sh EXAMPLE .Bd -literal -offset indent diff --git a/include/ck_rwcohort.h b/include/ck_rwcohort.h index 76fb9cb..582b232 100644 --- a/include/ck_rwcohort.h +++ b/include/ck_rwcohort.h @@ -54,7 +54,6 @@ unsigned int write_barrier; \ unsigned int wait_limit; \ }; \ - \ CK_CC_INLINE static void \ ck_rwcohort_wp_##N##_init(CK_RWCOHORT_WP_INSTANCE(N) *rw_cohort, \ unsigned int wait_limit) \ @@ -65,7 +64,6 @@ ck_pr_barrier(); \ return; \ } \ - \ CK_CC_INLINE static void \ ck_rwcohort_wp_##N##_write_lock(CK_RWCOHORT_WP_INSTANCE(N) *rw_cohort, \ CK_COHORT_INSTANCE(N) *cohort, void *global_context, \ @@ -83,7 +81,6 @@ \ return; \ } \ - \ CK_CC_INLINE static void \ ck_rwcohort_wp_##N##_write_unlock(CK_RWCOHORT_WP_INSTANCE(N) *rw_cohort, \ CK_COHORT_INSTANCE(N) *cohort, void *global_context, \ @@ -91,8 +88,8 @@ { \ (void)rw_cohort; \ CK_COHORT_UNLOCK(N, cohort, global_context, local_context); \ + return; \ } \ - \ CK_CC_INLINE static void \ ck_rwcohort_wp_##N##_read_lock(CK_RWCOHORT_WP_INSTANCE(N) *rw_cohort, \ CK_COHORT_INSTANCE(N) *cohort, void *global_context, \ @@ -101,7 +98,7 @@ unsigned int wait_count = 0; \ bool raised = false; \ \ - while (true) { \ + for (;;) { \ ck_pr_inc_uint(&rw_cohort->read_counter); \ if (CK_COHORT_LOCKED(N, cohort, global_context, local_context) == false) {\ break; \ @@ -123,11 +120,11 @@ \ return; \ } \ - \ CK_CC_INLINE static void \ ck_rwcohort_wp_##N##_read_unlock(CK_RWCOHORT_WP_INSTANCE(N) *cohort) \ { \ ck_pr_dec_uint(&cohort->read_counter); \ + return; \ } #define CK_RWCOHORT_WP_INITIALIZER { \ @@ -152,7 +149,6 @@ unsigned int read_barrier; \ unsigned int wait_limit; \ }; \ - \ CK_CC_INLINE static void \ ck_rwcohort_rp_##N##_init(CK_RWCOHORT_RP_INSTANCE(N) *rw_cohort, \ unsigned int wait_limit) \ @@ -163,7 +159,6 @@ ck_pr_barrier(); \ return; \ } \ - \ CK_CC_INLINE static void \ ck_rwcohort_rp_##N##_write_lock(CK_RWCOHORT_RP_INSTANCE(N) *rw_cohort, \ CK_COHORT_INSTANCE(N) *cohort, void *global_context, \ @@ -172,7 +167,7 @@ unsigned int wait_count = 0; \ bool raised = false; \ \ - while (true) { \ + for (;;) { \ CK_COHORT_LOCK(N, cohort, global_context, local_context); \ if (ck_pr_load_uint(&rw_cohort->read_counter) == 0) { \ break; \ @@ -194,15 +189,14 @@ \ return; \ } \ - \ CK_CC_INLINE static void \ ck_rwcohort_rp_##N##_write_unlock(CK_RWCOHORT_RP_INSTANCE(N) *rw_cohort, \ CK_COHORT_INSTANCE(N) *cohort, void *global_context, void *local_context) \ { \ (void)rw_cohort; \ CK_COHORT_UNLOCK(N, cohort, global_context, local_context); \ + return; \ } \ - \ CK_CC_INLINE static void \ ck_rwcohort_rp_##N##_read_lock(CK_RWCOHORT_RP_INSTANCE(N) *rw_cohort, \ CK_COHORT_INSTANCE(N) *cohort, void *global_context, \ @@ -219,12 +213,11 @@ \ return; \ } \ - \ - \ CK_CC_INLINE static void \ ck_rwcohort_rp_##N##_read_unlock(CK_RWCOHORT_RP_INSTANCE(N) *cohort) \ { \ ck_pr_dec_uint(&cohort->read_counter); \ + return; \ } #define CK_RWCOHORT_RP_INITIALIZER { \ @@ -247,7 +240,6 @@ CK_RWCOHORT_NEUTRAL_INSTANCE(N) { \ unsigned int read_counter; \ }; \ - \ CK_CC_INLINE static void \ ck_rwcohort_neutral_##N##_init(CK_RWCOHORT_NEUTRAL_INSTANCE(N) *rw_cohort) \ { \ @@ -255,7 +247,6 @@ ck_pr_barrier(); \ return; \ } \ - \ CK_CC_INLINE static void \ ck_rwcohort_neutral_##N##_write_lock(CK_RWCOHORT_NEUTRAL_INSTANCE(N) *rw_cohort, \ CK_COHORT_INSTANCE(N) *cohort, void *global_context, \ @@ -267,15 +258,14 @@ } \ return; \ } \ - \ CK_CC_INLINE static void \ ck_rwcohort_neutral_##N##_write_unlock(CK_RWCOHORT_NEUTRAL_INSTANCE(N) *rw_cohort, \ CK_COHORT_INSTANCE(N) *cohort, void *global_context, void *local_context) \ { \ (void)rw_cohort; \ CK_COHORT_UNLOCK(N, cohort, global_context, local_context); \ + return; \ } \ - \ CK_CC_INLINE static void \ ck_rwcohort_neutral_##N##_read_lock(CK_RWCOHORT_NEUTRAL_INSTANCE(N) *rw_cohort, \ CK_COHORT_INSTANCE(N) *cohort, void *global_context, \ @@ -287,12 +277,11 @@ \ return; \ } \ - \ - \ CK_CC_INLINE static void \ ck_rwcohort_neutral_##N##_read_unlock(CK_RWCOHORT_NEUTRAL_INSTANCE(N) *cohort) \ { \ ck_pr_dec_uint(&cohort->read_counter); \ + return; \ } #define CK_RWCOHORT_NEUTRAL_INITIALIZER { \