1ck_rwcohort(3)           BSD Library Functions Manual           ck_rwcohort(3)
2

NAME

4     ck_rwcohort — generalized interface for reader-writer locks using cohort
5     locks
6

LIBRARY

8     Concurrency Kit (libck, -lck)
9

SYNOPSIS

11     #include <ck_rwcohort.h>
12     In each of the following macros, "STRATEGY" should be replaced with
13     either "NEUTRAL", "RP", or "WP" depending on which locking strategy the
14     user prefers.  RP and WP represent reader preference and writer prefer‐
15     ence, respectively, while NEUTRAL represents a strategy neutral to reads
16     vs. writes.
17
18     CK_RWCOHORT_STRATEGY_PROTOTYPE(COHORT_NAME cohort_name);
19
20     CK_RWCOHORT_STRATEGY_NAME(COHORT_NAME cohort_name);
21
22     CK_RWCOHORT_STRATEGY_INSTANCE(COHORT_NAME cohort_name);
23
24     CK_RWCOHORT_STRATEGY_INIT(COHORT_NAME cohort_name, RWCOHORT lock,
25         unsigned int wait_limit);
26     Note: the wait_limit argument should be omitted for locks using the neu‐
27     tral strategy
28
29     CK_RWCOHORT_STRATEGY_READ_LOCK(COHORT_NAME cohort_name, RWCOHORT lock,
30         COHORT cohort, void *global_context, void *local_context);
31
32     CK_RWCOHORT_STRATEGY_READ_UNLOCK(COHORT_NAME cohort_name, RWCOHORT lock,
33         COHORT cohort, void *global_context, void *local_context);
34
35     CK_RWCOHORT_STRATEGY_WRITE_LOCK(COHORT_NAME cohort_name, RWCOHORT lock,
36         COHORT cohort, void *global_context, void *local_context);
37
38     CK_RWCOHORT_STRATEGY_WRITE_UNLOCK(COHORT_NAME cohort_name, RWCOHORT lock,
39         COHORT cohort, void *global_context, void *local_context);
40
41     Arguments of type RWCOHORT must be pointers to structs defined using the
42     CK_RWCOHORT_STRATEGY_PROTOTYPE(3) macro with the same strategy and cohort
43     name as the current call.
44
45     Arguments of type COHORT must be pointers to structs defined using the
46     CK_COHORT_PROTOTYPE(3) macro.
47

DESCRIPTION

49     ck_rwcohort.h provides an interface for defining reader-writer locks that
50     use cohort locks internally to increase performance on NUMA architec‐
51     tures.  See ck_cohort(3) for more information about cohort locks.
52
53     Before using a reader-writer cohort lock, the user must define a cohort
54     type using either the CK_COHORT_PROTOTYPE(3) or the
55     CK_COHORT_TRYLOCK_PROTOTYPE(3) macros, and define a reader-writer lock
56     type using the CK_RWCOHORT_PROTOTYPE(3) macro.
57

EXAMPLE

59           #include <stdlib.h>
60           #include <pthread.h>
61
62           #include <ck_pr.h>
63           #include <ck_cohort.h>
64           #include <ck_rwcohort.h>
65           #include <ck_spinlock.h>
66
67           /* Create cohort methods with signatures that match the required signature */
68
69           static void
70           ck_spinlock_lock_with_context(ck_spinlock_t *lock, void *context)
71           {
72                   (void)context;
73                   ck_spinlock_lock(lock);
74                   return;
75           }
76
77           static void
78           ck_spinlock_unlock_with_context(ck_spinlock_t *lock, void *context)
79           {
80                   (void)context;
81                   ck_spinlock_unlock(lock);
82                   return;
83           }
84
85           static bool
86           ck_spinlock_locked_with_context(ck_spinlock_t *lock, void *context)
87           {
88                   (void)context;
89                   return ck_spinlock_locked(lock);
90           }
91
92           /*
93            * define a cohort type named "test_cohort" that will use
94            * the above methods for both its global and local locks
95            */
96           CK_COHORT_PROTOTYPE(test_cohort,
97                   ck_spinlock_lock_with_context, ck_spinlock_unlock_with_context, ck_spinlock_locked_with_context,
98                   ck_spinlock_lock_with_context, ck_spinlock_unlock_with_context, ck_spinlock_locked_with_context)
99
100           /* define a reader-writer type using the same cohort type */
101           CK_RWCOHORT_WP_PROTOTYPE(test_cohort)
102
103           static ck_spinlock_t global_lock = CK_SPINLOCK_INITIALIZER;
104           static CK_COHORT_INSTANCE(test_cohort) *cohorts;
105           static CK_RWCOHORT_WP_INSTANCE(test_cohort) rw_cohort = CK_RWCOHORT_WP_INITIALIZER;
106           static unsigned int ready;
107
108           static void *
109           function(void *context)
110           {
111                   CK_COHORT_INSTANCE(test_cohort) *cohort = context;
112
113                   while (ck_pr_load_uint(&ready) == 0);
114
115                   while (ck_pr_load_uint(&ready) > 0) {
116                           /*
117                            * acquire the cohort lock before performing critical section.
118                            * note that we pass NULL for both the global and local context
119                            * arguments because neither the lock nor unlock functions
120                            * will use them.
121                            */
122                           CK_COHORT_LOCK(test_cohort, cohort, NULL, NULL);
123
124                           /* perform critical section */
125
126                           /* relinquish cohort lock */
127                           CK_COHORT_UNLOCK(test_cohort, cohort, NULL, NULL);
128                   }
129
130                   return NULL;
131           }
132
133           int
134           main(void)
135           {
136                   unsigned int nthr = 4;
137                   unsigned int n_cohorts = 2;
138                   unsigned int i;
139
140                   /* allocate 2 cohorts of the defined type */
141                   CK_COHORT_INSTANCE(test_cohort) *cohorts =
142                       calloc(n_cohorts, sizeof(CK_COHORT_INSTANCE(test_cohort)));
143
144                   /* create local locks to use with each cohort */
145                   ck_spinlock_t *local_locks =
146                           calloc(n_cohorts, sizeof(ck_spinlock_t));
147
148                   pthread_t *threads =
149                           calloc(nthr, sizeof(pthread_t));
150
151                   /* initialize each of the cohorts before using them */
152                   for (i = 0 ; i < n_cohorts ; ++i) {
153                           CK_COHORT_INIT(test_cohort, cohorts + i, &global_lock, local_locks + i,
154                                   CK_COHORT_DEFAULT_LOCAL_PASS_LIMIT);
155                   }
156
157                   /* start each thread and assign cohorts equally */
158                   for (i = 0 ; i < nthr ; ++i) {
159                           pthread_create(threads + i, NULL, function, cohorts + (i % n_cohorts));
160                   }
161
162                   ck_pr_store_uint(&ready, 1);
163                   sleep(10);
164                   ck_pr_store_uint(&ready, 0);
165
166                   for (i = 0 ; i < nthr ; ++i) {
167                           pthread_join(threads[i], NULL);
168                   }
169
170                   return 0;
171           }
172

SEE ALSO

174     CK_COHORT_PROTOTYPE(3), CK_COHORT_TRYLOCK_PROTOTYPE(3),
175     CK_COHORT_INSTANCE(3), CK_COHORT_INITIALIZER(3), CK_COHORT_INIT(3),
176     CK_COHORT_LOCK(3), CK_COHORT_UNLOCK(3), CK_COHORT_LOCKED(3),
177     CK_COHORT_TRYLOCK(3),
178
179     Additional information available at http://concurrencykit.org/
180
181                                April 23, 2013.
Impressum