Whamcloud - gitweb
LU-6142 lnet: SPDX for lnet/lnet/
[fs/lustre-release.git] / lnet / lnet / lock.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 /* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
4  * Copyright (c) 2012, 2015, Intel Corporation.
5  */
6
7 /* This file is part of Lustre, http://www.lustre.org/
8  *
9  * Author: liang@whamcloud.com
10  */
11
12 #define DEBUG_SUBSYSTEM S_LNET
13
14 #include <lnet/lib-lnet.h>
15
16 /** destroy cpu-partition lock, see libcfs_private.h for more detail */
17 void
18 cfs_percpt_lock_free(struct cfs_percpt_lock *pcl)
19 {
20         LASSERT(pcl->pcl_locks != NULL);
21         LASSERT(!pcl->pcl_locked);
22
23         cfs_percpt_free(pcl->pcl_locks);
24         LIBCFS_FREE(pcl, sizeof(*pcl));
25 }
26 EXPORT_SYMBOL(cfs_percpt_lock_free);
27
28 /**
29  * create cpu-partition lock, see libcfs_private.h for more detail.
30  *
31  * cpu-partition lock is designed for large-scale SMP system, so we need to
32  * reduce cacheline conflict as possible as we can, that's the
33  * reason we always allocate cacheline-aligned memory block.
34  */
35 struct cfs_percpt_lock *
36 cfs_percpt_lock_create(struct cfs_cpt_table *cptab,
37                        struct lock_class_key *keys)
38 {
39         struct cfs_percpt_lock  *pcl;
40         spinlock_t              *lock;
41         int                     i;
42
43         /* NB: cptab can be NULL, pcl will be for HW CPUs on that case */
44         LIBCFS_ALLOC(pcl, sizeof(*pcl));
45         if (pcl == NULL)
46                 return NULL;
47
48         pcl->pcl_cptab = cptab;
49         pcl->pcl_locks = cfs_percpt_alloc(cptab, sizeof(*lock));
50         if (pcl->pcl_locks == NULL) {
51                 LIBCFS_FREE(pcl, sizeof(*pcl));
52                 return NULL;
53         }
54
55         if (keys == NULL) {
56                 CWARN("Cannot setup class key for percpt lock, you may see recursive locking warnings which are actually fake.\n");
57         }
58
59         cfs_percpt_for_each(lock, i, pcl->pcl_locks) {
60                 spin_lock_init(lock);
61                 if (keys != NULL)
62                         lockdep_set_class(lock, &keys[i]);
63         }
64
65         return pcl;
66 }
67 EXPORT_SYMBOL(cfs_percpt_lock_create);
68
69 /**
70  * lock a CPU partition
71  *
72  * \a index != CFS_PERCPT_LOCK_EX
73  *     hold private lock indexed by \a index
74  *
75  * \a index == CFS_PERCPT_LOCK_EX
76  *     exclusively lock @pcl and nobody can take private lock
77  */
78 void
79 cfs_percpt_lock(struct cfs_percpt_lock *pcl, int index)
80 __acquires(pcl->pcl_locks)
81 {
82         int     ncpt = cfs_cpt_number(pcl->pcl_cptab);
83         int     i;
84
85         LASSERT(index >= CFS_PERCPT_LOCK_EX && index < ncpt);
86
87         if (ncpt == 1) {
88                 index = 0;
89         } else { /* serialize with exclusive lock */
90                 while (pcl->pcl_locked)
91                         cpu_relax();
92         }
93
94         if (likely(index != CFS_PERCPT_LOCK_EX)) {
95                 spin_lock(pcl->pcl_locks[index]);
96                 return;
97         }
98
99         /* exclusive lock request */
100         for (i = 0; i < ncpt; i++) {
101                 spin_lock(pcl->pcl_locks[i]);
102                 if (i == 0) {
103                         LASSERT(!pcl->pcl_locked);
104                         /* nobody should take private lock after this
105                          * so I wouldn't starve for too long time
106                          */
107                         pcl->pcl_locked = 1;
108                 }
109         }
110 }
111 EXPORT_SYMBOL(cfs_percpt_lock);
112
113 /** unlock a CPU partition */
114 void
115 cfs_percpt_unlock(struct cfs_percpt_lock *pcl, int index)
116 __releases(pcl->pcl_locks)
117 {
118         int     ncpt = cfs_cpt_number(pcl->pcl_cptab);
119         int     i;
120
121         index = ncpt == 1 ? 0 : index;
122
123         if (likely(index != CFS_PERCPT_LOCK_EX)) {
124                 spin_unlock(pcl->pcl_locks[index]);
125                 return;
126         }
127
128         for (i = ncpt - 1; i >= 0; i--) {
129                 if (i == 0) {
130                         LASSERT(pcl->pcl_locked);
131                         pcl->pcl_locked = 0;
132                 }
133                 spin_unlock(pcl->pcl_locks[i]);
134         }
135 }
136 EXPORT_SYMBOL(cfs_percpt_unlock);