1ck_cohort(3) BSD Library Functions Manual ck_cohort(3)
2
4 ck_cohort — generalized interface for lock cohorts
5
7 Concurrency Kit (libck, -lck)
8
10 #include <ck_cohort.h>
11
12 CK_COHORT_PROTOTYPE(COHORT_NAME cohort_name, LOCK_FXN global_lock_method,
13 LOCK_FXN global_unlock_method, LOCK_FXN local_lock_method,
14 LOCK_FXN local_unlock_method);
15
16 CK_COHORT_TRYLOCK_PROTOTYPE(COHORT_NAME cohort_name,
17 LOCK_FXN global_lock_method, LOCK_FXN global_unlock_method,
18 BOOL_LOCK_FXN global_locked_method,
19 BOOL_LOCK_FXN global_trylock_method, LOCK_FXN local_lock_method,
20 LOCK_FXN local_unlock_method, BOOL_LOCK_FXN local_locked_method,
21 BOOL_LOCK_FXN local_trylock_method);
22
23 CK_COHORT_INSTANCE(COHORT_NAME cohort_name);
24
25 CK_COHORT_INIT(COHORT_NAME cohort_name, ck_cohort *cohort,
26 void *global_lock, void *local_lock, unsigned int pass_limit);
27
28 CK_COHORT_LOCK(COHORT_NAME cohort_name, ck_cohort *cohort,
29 void *global_context, void *local_context);
30
31 CK_COHORT_UNLOCK(COHORT_NAME cohort_name, ck_cohort *cohort,
32 void *global_context, void *local_context);
33
34 Where LOCK_FXN refers to a method with the signature
35 void(void *lock, void *context)
36 BOOL_LOCK_FXN refers to a method with the signature
37 bool(void *lock, void *context)
38
39 The context
40 argument in each signature is used to pass along any additional informa‐
41 tion that the lock might need for its lock, unlock and trylock methods.
42 The values for this argument are provided to each call to
43 CK_COHORT_LOCK(3), CK_COHORT_UNLOCK(3), CK_COHORT_LOCKED(3), and
44 CK_COHORT_TRYLOCK(3)
45
47 ck_cohort.h provides an interface for defining lock cohorts with arbi‐
48 trary lock types. Cohorts are a mechanism for coordinating threads on
49 NUMA architectures in order to reduce the frequency with which a lock is
50 passed between threads on different clusters.
51
52 Before using a cohort, the user must define a cohort type using either
53 the CK_COHORT_PROTOTYPE() or the CK_COHORT_TRYLOCK_PROTOTYPE() macros.
54 These macros allow the user to specify the lock methods that they would
55 like the cohort to use. See the CK_COHORT_PROTOTYPE(3) and
56 CK_COHORT_TRYLOCK_PROTOTYPE(3) man pages for more details.
57
59 #include <stdlib.h>
60 #include <pthread.h>
61
62 #include <ck_pr.h>
63 #include <ck_cohort.h>
64 #include <ck_spinlock.h>
65
66 /*
67 * Create cohort methods with signatures that match
68 * the required signature
69 */
70 static void
71 ck_spinlock_lock_with_context(ck_spinlock_t *lock, void *context)
72 {
73 (void)context;
74 ck_spinlock_lock(lock);
75 return;
76 }
77
78 static void
79 ck_spinlock_unlock_with_context(ck_spinlock_t *lock, void *context)
80 {
81 (void)context;
82 ck_spinlock_unlock(lock);
83 return;
84 }
85
86 static bool
87 ck_spinlock_locked_with_context(ck_spinlock_t *lock, void *context)
88 {
89 (void)context;
90 return ck_spinlock_locked(lock);
91 }
92
93 /*
94 * define a cohort type named "test_cohort" that will use
95 * the above methods for both its global and local locks
96 */
97 CK_COHORT_PROTOTYPE(test_cohort,
98 ck_spinlock_lock_with_context, ck_spinlock_unlock_with_context, ck_spinlock_locked_with_context,
99 ck_spinlock_lock_with_context, ck_spinlock_unlock_with_context, ck_spinlock_locked_with_context)
100
101 static ck_spinlock_t global_lock = CK_SPINLOCK_INITIALIZER;
102 static unsigned int ready;
103
104 static void *
105 function(void *context)
106 {
107 CK_COHORT_INSTANCE(test_cohort) *cohort = context;
108
109 while (ready == 0);
110
111 while (ready > 0) {
112 /*
113 * acquire the cohort lock before performing critical section.
114 * note that we pass NULL for both the global and local context
115 * arguments because neither the lock nor unlock functions
116 * will use them.
117 */
118 CK_COHORT_LOCK(test_cohort, cohort, NULL, NULL);
119
120 /* perform critical section */
121
122 /* relinquish cohort lock */
123 CK_COHORT_UNLOCK(test_cohort, cohort, NULL, NULL);
124 }
125
126 return NULL;
127 }
128
129 int
130 main(void)
131 {
132 unsigned int nthr = 4;
133 unsigned int n_cohorts = 2;
134 unsigned int i;
135
136 /* allocate 2 cohorts of the defined type */
137 CK_COHORT_INSTANCE(test_cohort) *cohorts =
138 calloc(n_cohorts, sizeof(CK_COHORT_INSTANCE(test_cohort)));
139
140 /* create local locks to use with each cohort */
141 ck_spinlock_t *local_locks =
142 calloc(n_cohorts, sizeof(ck_spinlock_t));
143
144 pthread_t *threads =
145 calloc(nthr, sizeof(pthread_t));
146
147 /* initialize each of the cohorts before using them */
148 for (i = 0 ; i < n_cohorts ; ++i) {
149 CK_COHORT_INIT(test_cohort, cohorts + i, &global_lock, local_locks + i,
150 CK_COHORT_DEFAULT_LOCAL_PASS_LIMIT);
151 }
152
153 /* start each thread and assign cohorts equally */
154 for (i = 0 ; i < nthr ; ++i) {
155 pthread_create(threads + i, NULL, function, cohorts + (i % n_cohorts));
156 }
157
158 ck_pr_store_uint(&ready, 1);
159 sleep(10);
160 ck_pr_store_uint(&ready, 0);
161
162 for (i = 0 ; i < nthr ; ++i) {
163 pthread_join(threads[i], NULL);
164 }
165
166 return 0;
167 }
168
170 CK_COHORT_PROTOTYPE(3), CK_COHORT_TRYLOCK_PROTOTYPE(3),
171 CK_COHORT_INSTANCE(3), CK_COHORT_INITIALIZER(3), CK_COHORT_INIT(3),
172 CK_COHORT_LOCK(3), CK_COHORT_UNLOCK(3), CK_COHORT_LOCKED(3),
173 CK_COHORT_TRYLOCK(3),
174
175 Additional information available at http://concurrencykit.org/
176
177 February 24, 2013.