Whamcloud - gitweb
LU-9859 libcfs: move percpt_lock into lnet
[fs/lustre-release.git] / lnet / include / lnet / lock.h
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * GPL HEADER END
17  */
18
19 /* percpu partition lock
20  *
21  * There are some use-cases like this in Lustre:
22  * . each CPU partition has it's own private data which is frequently changed,
23  *   and mostly by the local CPU partition.
24  * . all CPU partitions share some global data, these data are rarely changed.
25  *
26  * LNet is typical example.
27  * CPU partition lock is designed for this kind of use-cases:
28  * . each CPU partition has it's own private lock
29  * . change on private data just needs to take the private lock
30  * . read on shared data just needs to take _any_ of private locks
31  * . change on shared data needs to take _all_ private locks,
32  *   which is slow and should be really rare.
33  */
34 enum {
35         CFS_PERCPT_LOCK_EX      = -1,   /* negative */
36 };
37
38 struct cfs_percpt_lock {
39         /* cpu-partition-table for this lock */
40         struct cfs_cpt_table     *pcl_cptab;
41         /* exclusively locked */
42         unsigned int              pcl_locked;
43         /* private lock table */
44         spinlock_t              **pcl_locks;
45 };
46
47 /* return number of private locks */
48 #define cfs_percpt_lock_num(pcl)        cfs_cpt_number(pcl->pcl_cptab)
49
50 /* create a cpu-partition lock based on CPU partition table \a cptab,
51  * each private lock has extra \a psize bytes padding data
52  */
53 struct cfs_percpt_lock *cfs_percpt_lock_create(struct cfs_cpt_table *cptab,
54                                                struct lock_class_key *keys);
55 /* destroy a cpu-partition lock */
56 void cfs_percpt_lock_free(struct cfs_percpt_lock *pcl);
57
58 /* lock private lock \a index of \a pcl */
59 void cfs_percpt_lock(struct cfs_percpt_lock *pcl, int index);
60
61 /* unlock private lock \a index of \a pcl */
62 void cfs_percpt_unlock(struct cfs_percpt_lock *pcl, int index);
63
64 #define CFS_PERCPT_LOCK_KEYS    256
65
66 /* NB: don't allocate keys dynamically, lockdep needs them to be in ".data" */
67 #define cfs_percpt_lock_alloc(cptab)                                    \
68 ({                                                                      \
69         static struct lock_class_key ___keys[CFS_PERCPT_LOCK_KEYS];     \
70         struct cfs_percpt_lock *___lk;                                  \
71                                                                         \
72         if (cfs_cpt_number(cptab) > CFS_PERCPT_LOCK_KEYS)               \
73                 ___lk = cfs_percpt_lock_create(cptab, NULL);            \
74         else                                                            \
75                 ___lk = cfs_percpt_lock_create(cptab, ___keys);         \
76         ___lk;                                                          \
77 })