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