1 | /* |
---|
2 | * xhtab.c - Remote access embedded hash table implementation. |
---|
3 | * |
---|
4 | * Author Alain Greiner (2016,2017) |
---|
5 | * |
---|
6 | * Copyright (c) UPMC Sorbonne Universites |
---|
7 | * |
---|
8 | * This file is part of ALMOS-MKH. |
---|
9 | * |
---|
10 | * ALMOS-MKH is free software; you can redistribute it and/or modify it |
---|
11 | * under the terms of the GNU General Public License as published by |
---|
12 | * the Free Software Foundation; version 2.0 of the License. |
---|
13 | * |
---|
14 | * ALMOS-MKH is distributed in the hope that it will be useful, but |
---|
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
17 | * General Public License for more details. |
---|
18 | * |
---|
19 | * You should have received a copy of the GNU General Public License |
---|
20 | * along with ALMOS-MKH; if not, write to the Free Software Foundation, |
---|
21 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
---|
22 | */ |
---|
23 | |
---|
24 | #include <kernel_config.h> |
---|
25 | #include <hal_types.h> |
---|
26 | #include <hal_special.h> |
---|
27 | #include <hal_remote.h> |
---|
28 | #include <xlist.h> |
---|
29 | #include <remote_rwlock.h> |
---|
30 | #include <string.h> |
---|
31 | #include <printk.h> |
---|
32 | #include <xhtab.h> |
---|
33 | #include <vfs.h> |
---|
34 | |
---|
35 | |
---|
36 | /////////////////////////////////////////////////////////////////////////////////////////// |
---|
37 | // Item type specific (static) functions (two functions for each item type). |
---|
38 | // - for type <vfs_dentry_t>, identifier is the name field. |
---|
39 | /////////////////////////////////////////////////////////////////////////////////////////// |
---|
40 | |
---|
41 | /////////////////////////////////////////////////////////////////////////////////////////// |
---|
42 | // These static functions compute the hash index from the key. |
---|
43 | /////////////////////////////////////////////////////////////////////////////////////////// |
---|
44 | // @ key : local pointer on key. |
---|
45 | // @ return the index value, from 0 to (HASHTAB_SIZE - 1) |
---|
46 | /////////////////////////////////////////////////////////////////////////////////////////// |
---|
47 | |
---|
48 | ///////////////////////////////////////// |
---|
49 | uint32_t xhtab_dentry_index( void * key ) |
---|
50 | { |
---|
51 | char * name = key; |
---|
52 | uint32_t index = 0; |
---|
53 | while( *name ) |
---|
54 | { |
---|
55 | index = index + (*(name++) ^ index); |
---|
56 | } |
---|
57 | return index % HASHTAB_SIZE; |
---|
58 | } |
---|
59 | |
---|
60 | //////////////////////////////////////////////////////////////////////////////////////////// |
---|
61 | // These static function are used by xhtab_lookup(), xhtab_insert(), xhtab_remove(). |
---|
62 | // They scan one sub-list identified by <index> to find an item identified by <key>. |
---|
63 | // The sub-list is not modified, but the readlock must have been taken by the caller. |
---|
64 | //////////////////////////////////////////////////////////////////////////////////////////// |
---|
65 | // @ xhtab_xp : extended pointer on hash table. |
---|
66 | // @ index : index of sub-list to be scanned. |
---|
67 | // @ key : local pointer on item identifier. |
---|
68 | // return an extended pointer on item if found / return XPTR_NULL if not found. |
---|
69 | //////////////////////////////////////////////////////////////////////////////////////////// |
---|
70 | |
---|
71 | //////////////////////////////////////////////////// |
---|
72 | static xptr_t xhtab_dentry_scan( xptr_t xhtab_xp, |
---|
73 | uint32_t index, |
---|
74 | void * key ) |
---|
75 | { |
---|
76 | xptr_t xlist_xp; // xlist_entry_t (iterator) |
---|
77 | xhtab_t * xhtab_ptr; // hash table local pointer |
---|
78 | cxy_t xhtab_cxy; // hash table cluster |
---|
79 | char local_name[CONFIG_VFS_MAX_NAME_LENGTH]; // local copy of dentry name |
---|
80 | |
---|
81 | // get hash table cluster and local pointer |
---|
82 | xhtab_cxy = GET_CXY( xhtab_xp ); |
---|
83 | xhtab_ptr = (xhtab_t *)GET_PTR( xhtab_xp ); |
---|
84 | |
---|
85 | // scan sub-list[index] |
---|
86 | XLIST_FOREACH( XPTR( xhtab_cxy , &xhtab_ptr->roots[index] ) , xlist_xp ) |
---|
87 | { |
---|
88 | // get extended pointer on dentry containing the xlist_entry_t |
---|
89 | xptr_t dentry_xp = XLIST_ELEMENT( xlist_xp , vfs_dentry_t , xlist ); |
---|
90 | |
---|
91 | // get dentry cluster and local pointer |
---|
92 | cxy_t dentry_cxy = GET_CXY( dentry_xp ); |
---|
93 | vfs_dentry_t * dentry_ptr = (vfs_dentry_t *)GET_PTR( dentry_xp ); |
---|
94 | |
---|
95 | // make a local copy of dentry name |
---|
96 | hal_remote_memcpy( XPTR( local_cxy , local_name ) , |
---|
97 | XPTR( dentry_cxy , dentry_ptr->name ), |
---|
98 | CONFIG_VFS_MAX_NAME_LENGTH ); |
---|
99 | |
---|
100 | // check matching |
---|
101 | if( strcmp( local_name , (char *)key ) == 0 ) return dentry_xp; |
---|
102 | } |
---|
103 | |
---|
104 | // No matching item found |
---|
105 | return XPTR_NULL; |
---|
106 | } |
---|
107 | |
---|
108 | //////////////////////////////////////////////////////////////////////////////////////// |
---|
109 | // Generic access functions |
---|
110 | //////////////////////////////////////////////////////////////////////////////////////// |
---|
111 | |
---|
112 | ////////////////////////////////////////// |
---|
113 | void xhtab_init( xhtab_t * xhtab, |
---|
114 | xhtab_item_type_t type ) |
---|
115 | { |
---|
116 | uint32_t i; |
---|
117 | |
---|
118 | // initialize readlock |
---|
119 | remote_rwlock_init( XPTR( local_cxy , &xhtab->lock) ); |
---|
120 | |
---|
121 | xhtab->items = 0; |
---|
122 | |
---|
123 | if( type == XHTAB_DENTRY_TYPE ) |
---|
124 | { |
---|
125 | xhtab->scan = &xhtab_dentry_scan; |
---|
126 | xhtab->index = &xhtab_dentry_index; |
---|
127 | } |
---|
128 | else |
---|
129 | { |
---|
130 | printk("\n[PANIC] in %s : illegal item type\n", __FUNCTION__ ); |
---|
131 | hal_core_sleep(); |
---|
132 | } |
---|
133 | |
---|
134 | for( i=0 ; i < HASHTAB_SIZE ; i++ ) |
---|
135 | { |
---|
136 | xlist_root_init( XPTR( local_cxy , &xhtab->roots[i] ) ); |
---|
137 | } |
---|
138 | } |
---|
139 | |
---|
140 | /////////////////////////////////////// |
---|
141 | error_t xhtab_insert( xptr_t xhtab_xp, |
---|
142 | void * key, |
---|
143 | xptr_t xlist_xp ) |
---|
144 | { |
---|
145 | |
---|
146 | printk("\n @@@ xhtab_insert : 0 / name = %s / xhtab_xp = %l / xlist_xp = %l\n", |
---|
147 | key , xhtab_xp , xlist_xp ); |
---|
148 | |
---|
149 | // get xhtab cluster and local pointer |
---|
150 | cxy_t xhtab_cxy = GET_CXY( xhtab_xp ); |
---|
151 | xhtab_t * xhtab_ptr = (xhtab_t *)GET_PTR( xhtab_xp ); |
---|
152 | |
---|
153 | // compute index from key |
---|
154 | uint32_t index = xhtab_ptr->index( key ); |
---|
155 | |
---|
156 | printk("\n @@@ xhtab_insert : 1 / name = %s / index = %d\n", |
---|
157 | key , index ); |
---|
158 | |
---|
159 | // take the lock protecting hash table |
---|
160 | remote_rwlock_wr_lock( XPTR( xhtab_cxy , &xhtab_ptr->lock ) ); |
---|
161 | |
---|
162 | // search a matching item |
---|
163 | xptr_t item_xp = xhtab_ptr->scan( xhtab_xp , index , key ); |
---|
164 | |
---|
165 | if( item_xp != XPTR_NULL ) // error if found |
---|
166 | { |
---|
167 | // release the lock protecting hash table |
---|
168 | remote_rwlock_wr_unlock( XPTR( xhtab_cxy , &xhtab_ptr->lock ) ); |
---|
169 | |
---|
170 | printk("\n @@@ xhtab_insert : 2 / name = %s / item_xp = %l\n", |
---|
171 | key , item_xp ); |
---|
172 | |
---|
173 | return EINVAL; |
---|
174 | } |
---|
175 | else // insert item if not found |
---|
176 | { |
---|
177 | // register item in hash table |
---|
178 | xlist_add_last( XPTR( xhtab_cxy , &xhtab_ptr->roots[index] ) , xlist_xp ); |
---|
179 | |
---|
180 | // update number of registered items |
---|
181 | hal_remote_atomic_add( XPTR( xhtab_cxy , &xhtab_ptr->items ) , 1 ); |
---|
182 | |
---|
183 | // release the lock protecting hash table |
---|
184 | remote_rwlock_wr_unlock( XPTR( xhtab_cxy , &xhtab_ptr->lock ) ); |
---|
185 | |
---|
186 | printk("\n @@@ xhtab_insert : 3 / name = %s / item_xp = %l\n", |
---|
187 | key , xhtab_ptr->scan( xhtab_xp , index , key ) ); |
---|
188 | |
---|
189 | return 0; |
---|
190 | } |
---|
191 | } // end xhtab_insert() |
---|
192 | |
---|
193 | ///////////////////////////////////// |
---|
194 | error_t xhtab_remove( xptr_t xhtab_xp, |
---|
195 | void * key, |
---|
196 | xptr_t xlist_entry_xp ) |
---|
197 | { |
---|
198 | // get xhtab cluster and local pointer |
---|
199 | cxy_t xhtab_cxy = GET_CXY( xhtab_xp ); |
---|
200 | xhtab_t * xhtab_ptr = (xhtab_t *)GET_PTR( xhtab_xp ); |
---|
201 | |
---|
202 | // compute index from key |
---|
203 | uint32_t index = xhtab_ptr->index( key ); |
---|
204 | |
---|
205 | // take the lock protecting hash table |
---|
206 | remote_rwlock_wr_lock( XPTR( xhtab_cxy , &xhtab_ptr->lock ) ); |
---|
207 | |
---|
208 | // get extended pointer on item to remove |
---|
209 | xptr_t item_xp = xhtab_ptr->scan( xhtab_xp , index , key ); |
---|
210 | |
---|
211 | if( item_xp == XPTR_NULL ) // error if not found |
---|
212 | { |
---|
213 | // release the lock protecting hash table |
---|
214 | remote_rwlock_wr_unlock( XPTR( xhtab_cxy , &xhtab_ptr->lock ) ); |
---|
215 | |
---|
216 | return EINVAL; |
---|
217 | } |
---|
218 | else // remove item if found |
---|
219 | { |
---|
220 | // remove item from hash table <=> unlink xlist_entry_t |
---|
221 | xlist_unlink( xlist_entry_xp ); |
---|
222 | |
---|
223 | // update number of registered items |
---|
224 | hal_remote_atomic_add( XPTR( xhtab_cxy , &xhtab_ptr->items ) , -1 ); |
---|
225 | |
---|
226 | // release the lock protecting hash table |
---|
227 | remote_rwlock_wr_unlock( XPTR( xhtab_cxy , &xhtab_ptr->lock ) ); |
---|
228 | |
---|
229 | return 0; |
---|
230 | } |
---|
231 | } // end xhtab_remove() |
---|
232 | |
---|
233 | ///////////////////////////////////////// |
---|
234 | xptr_t xhtab_lookup( xptr_t xhtab_xp, |
---|
235 | void * key ) |
---|
236 | { |
---|
237 | xptr_t item_xp; |
---|
238 | |
---|
239 | // get xhtab cluster and local pointer |
---|
240 | cxy_t xhtab_cxy = GET_CXY( xhtab_xp ); |
---|
241 | xhtab_t * xhtab_ptr = (xhtab_t *)GET_PTR( xhtab_xp ); |
---|
242 | |
---|
243 | // compute index from key |
---|
244 | uint32_t index = xhtab_ptr->index( key ); |
---|
245 | |
---|
246 | // take the lock protecting hash table |
---|
247 | remote_rwlock_rd_lock( XPTR( xhtab_cxy , &xhtab_ptr->lock ) ); |
---|
248 | |
---|
249 | // scan sub-list |
---|
250 | item_xp = xhtab_ptr->scan( xhtab_xp , index , key ); |
---|
251 | |
---|
252 | // release the lock protecting hash table |
---|
253 | remote_rwlock_rd_unlock( XPTR( xhtab_cxy , &xhtab_ptr->lock ) ); |
---|
254 | |
---|
255 | return item_xp; |
---|
256 | |
---|
257 | } // end xhtab_lookup() |
---|
258 | |
---|
259 | |
---|