1ck_rwcohort(3) BSD Library Functions Manual ck_rwcohort(3)
2
4 ck_rwcohort — generalized interface for reader-writer locks using cohort
5 locks
6
8 Concurrency Kit (libck, -lck)
9
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
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
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
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.