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

NAME

4     ck_cohort — generalized interface for lock cohorts
5

LIBRARY

7     Concurrency Kit (libck, -lck)
8

SYNOPSIS

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

DESCRIPTION

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

EXAMPLE

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

SEE ALSO

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.
Impressum