source: trunk/kernel/libk/xhtab.c @ 563

Last change on this file since 563 was 563, checked in by alain, 5 years ago

Complete restructuration of kernel spinlocks.

File size: 17.5 KB
Line 
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_kernel_types.h>
26#include <hal_special.h>
27#include <hal_remote.h>
28#include <xlist.h>
29#include <remote_busylock.h>
30#include <string.h>
31#include <printk.h>
32#include <xhtab.h>
33#include <vfs.h>
34
35
36///////////////////////////////////////////////////////////////////////////////////////////
37// Item type specific functions (four functions for each item type).
38// Example below is for <vfs_dentry_t> where the identifier is the dentry name.
39///////////////////////////////////////////////////////////////////////////////////////////
40
41///////////////////////////////////////////////////////////////////////////////////////////
42// vfs_dentry_t
43// This functions compute the hash index from the key, that is the directory entry name.
44///////////////////////////////////////////////////////////////////////////////////////////
45// @ key      : local pointer on name.
46// @ return the index value, from 0 to (HASHTAB_SIZE - 1)
47///////////////////////////////////////////////////////////////////////////////////////////
48static uint32_t xhtab_dentry_index_from_key( void * key )
49{
50        char     * name  = key;
51        uint32_t   index = 0;
52        while( *name )
53    {
54        index = index + (*(name++) ^ index);
55    }
56        return index % XHASHTAB_SIZE;
57} 
58
59///////////////////////////////////////////////////////////////////////////////////////////
60// vfs_dentry_t
61// This functions returns the extended pointer on the item, from the extended pointer
62// on xlist contained in the item.
63///////////////////////////////////////////////////////////////////////////////////////////
64// @ xlist_xp      : extended pointer on embedded xlist entry.
65// @ return the extended pointer on the dentry containing this xlist entry.
66///////////////////////////////////////////////////////////////////////////////////////////
67static xptr_t xhtab_dentry_item_from_xlist( xptr_t xlist_xp )
68{
69    return XLIST_ELEMENT( xlist_xp , vfs_dentry_t , list );
70}
71
72////////////////////////////////////////////////////////////////////////////////////////////
73// vfs_dentry_t
74// This function compares the identifier of an item to a given <key>.
75// it returns true when the directory name matches the name pointed by the <key> argument.
76////////////////////////////////////////////////////////////////////////////////////////////
77// @ item_xp   : extended pointer on item.
78// @ key       : pointer on searched item identifier.
79// returns true if given name matches directory entry name.
80////////////////////////////////////////////////////////////////////////////////////////////
81static bool_t xhtab_dentry_item_match_key( xptr_t    item_xp,
82                                           void    * key )
83{
84    char name[CONFIG_VFS_MAX_NAME_LENGTH];
85
86    // get dentry cluster and local pointer
87    cxy_t          dentry_cxy = GET_CXY( item_xp );
88    vfs_dentry_t * dentry_ptr = GET_PTR( item_xp );
89
90    // make a local copy of directory entry name
91    hal_remote_strcpy( XPTR( local_cxy , name ) ,
92                       XPTR( dentry_cxy , &dentry_ptr->name ) );
93
94    return( strcmp( name , (char*)key ) == 0 );
95}
96
97////////////////////////////////////////////////////////////////////////////////////////////
98// vfs_dentry_t
99// This function print the item key, that is the name for a vfs_dentry_t.
100////////////////////////////////////////////////////////////////////////////////////////////
101// @ item_xp   : extended pointer on item.
102////////////////////////////////////////////////////////////////////////////////////////////
103static void xhtab_dentry_item_print_key( xptr_t item_xp )
104{
105    char name[CONFIG_VFS_MAX_NAME_LENGTH];
106
107    // get dentry cluster and local pointer
108    cxy_t          dentry_cxy = GET_CXY( item_xp );
109    vfs_dentry_t * dentry_ptr = GET_PTR( item_xp );
110   
111    // make a local copy of directory entry name
112    hal_remote_strcpy( XPTR( local_cxy , name ) ,
113                       XPTR( dentry_cxy , &dentry_ptr->name ) );
114
115    // print dentry name
116    printk("%s , ", name );
117}                       
118
119////////////////////////////////////////////////////////////////////////////////////////
120//         Generic access functions
121////////////////////////////////////////////////////////////////////////////////////////
122
123//////////////////////////////////////////
124void xhtab_init( xhtab_t          * xhtab,
125                 xhtab_item_type_t  type )
126{
127        uint32_t i;
128
129    // initialize readlock
130    remote_busylock_init( XPTR( local_cxy , &xhtab->lock), LOCK_XHTAB_STATE );
131
132    xhtab->items            = 0;
133    xhtab->current_index    = 0;
134    xhtab->current_xlist_xp = XPTR_NULL;
135
136    if( type == XHTAB_DENTRY_TYPE )
137    {
138        xhtab->item_match_key  = &xhtab_dentry_item_match_key;
139        xhtab->index_from_key  = &xhtab_dentry_index_from_key;
140        xhtab->item_from_xlist = &xhtab_dentry_item_from_xlist;
141        xhtab->item_print_key  = &xhtab_dentry_item_print_key;
142    }
143    else
144    {
145        assert( false , "illegal item type\n" );
146    }
147
148        for( i=0 ; i < XHASHTAB_SIZE ; i++ )
149    {
150                xlist_root_init( XPTR( local_cxy , &xhtab->roots[i] ) );
151    } 
152
153}  // end xhtab_init()
154
155//////////////////////////////////////
156xptr_t xhtab_scan( xptr_t    xhtab_xp,
157                   uint32_t  index,
158                   void    * key )
159{
160    xptr_t              xlist_xp;           // xlist_entry_t (iterator)
161    xptr_t              item_xp;            // associated item
162    xhtab_t           * xhtab_ptr;          // hash table local pointer
163    cxy_t               xhtab_cxy;          // hash table cluster
164    item_from_xlist_t * item_from_xlist;    // function pointer
165    item_match_key_t  * item_match_key;     // function pointer
166
167    // get hash table cluster and local pointer
168    xhtab_cxy = GET_CXY( xhtab_xp );
169    xhtab_ptr = GET_PTR( xhtab_xp );
170
171    // get pointer on "item_from_xlist" function
172    item_from_xlist = (item_from_xlist_t *)hal_remote_lpt( XPTR( xhtab_cxy , 
173                                                           &xhtab_ptr->item_from_xlist ) );
174    // get pointer on "item_match_key" function
175    item_match_key = (item_match_key_t *)hal_remote_lpt( XPTR( xhtab_cxy , 
176                                                         &xhtab_ptr->item_match_key ) );
177
178    // scan sub-list[index]
179    XLIST_FOREACH( XPTR( xhtab_cxy , &xhtab_ptr->roots[index] ) , xlist_xp )
180    {
181        // get extended pointer on item containing the xlist entry
182            item_xp = item_from_xlist( xlist_xp );
183
184        // check matching
185        if( item_match_key( item_xp , key ) ) return item_xp;
186    }
187
188    // No matching item found
189    return XPTR_NULL;
190
191}  // end xhtab_scan()
192
193///////////////////////////////////////
194error_t xhtab_insert( xptr_t   xhtab_xp,
195                      void   * key,
196                      xptr_t   xlist_xp )
197{
198    xptr_t             item_xp;
199    uint32_t           index;
200    cxy_t              xhtab_cxy;
201    xhtab_t          * xhtab_ptr;
202    index_from_key_t * index_from_key;     // function pointer
203   
204#if DEBUG_XHTAB
205printk("\n[DBG] %s : enter / %s\n", __FUNCTION__, key );
206#endif
207
208    // get xhtab cluster and local pointer
209    xhtab_cxy = GET_CXY( xhtab_xp );
210    xhtab_ptr = GET_PTR( xhtab_xp );
211
212    // get pointer on "index_from_key" function
213    index_from_key = (index_from_key_t *)hal_remote_lpt( XPTR( xhtab_cxy , 
214                                                         &xhtab_ptr->index_from_key ) );
215    // compute index from key
216        index = index_from_key( key );
217
218    // take the lock protecting hash table
219    remote_busylock_acquire( XPTR( xhtab_cxy , &xhtab_ptr->lock ) );
220
221    // search a matching item
222    item_xp = xhtab_scan( xhtab_xp , index , key );
223
224    if( item_xp != XPTR_NULL )    // error if found
225    {
226        // release the lock protecting hash table
227        remote_busylock_release( XPTR( xhtab_cxy , &xhtab_ptr->lock ) );
228
229        return EINVAL;
230    }
231    else                          // insert item if not found
232    {
233        // register item in hash table
234            xlist_add_last( XPTR( xhtab_cxy , &xhtab_ptr->roots[index] ) , xlist_xp );
235
236        // update number of registered items
237        hal_remote_atomic_add( XPTR( xhtab_cxy , &xhtab_ptr->items ) , 1 );
238
239        // release the lock protecting hash table
240        remote_busylock_release( XPTR( xhtab_cxy , &xhtab_ptr->lock ) );
241   
242#if DEBUG_XHTAB
243printk("\n[DBG] %s : success / %s\n", __FUNCTION__, key );
244#endif
245
246        return 0;
247    }
248}  // end xhtab_insert()
249
250/////////////////////////////////////
251error_t xhtab_remove( xptr_t   xhtab_xp,
252                      void   * key,
253                      xptr_t   xlist_entry_xp )
254{
255    xptr_t             item_xp;
256    uint32_t           index;
257    cxy_t              xhtab_cxy;
258    xhtab_t          * xhtab_ptr;
259    index_from_key_t * index_from_key;     // function pointer
260
261    // get xhtab cluster and local pointer
262    xhtab_cxy = GET_CXY( xhtab_xp );
263    xhtab_ptr = GET_PTR( xhtab_xp );
264
265    // get pointer on "index_from_key" function
266    index_from_key = (index_from_key_t *)hal_remote_lpt( XPTR( xhtab_cxy , 
267                                                         &xhtab_ptr->index_from_key ) );
268    // compute index from key
269        index = index_from_key( key );
270
271    // take the lock protecting hash table
272    remote_busylock_acquire( XPTR( xhtab_cxy , &xhtab_ptr->lock ) );
273
274    // get extended pointer on item to remove
275    item_xp = xhtab_scan( xhtab_xp , index , key );
276
277    if( item_xp == XPTR_NULL )    // error if not found
278    {
279        // release the lock protecting hash table
280        remote_busylock_release( XPTR( xhtab_cxy , &xhtab_ptr->lock ) );
281
282        return EINVAL;
283    }
284    else                          // remove item if found
285    {
286        // remove item from hash table <=> unlink xlist_entry_t
287        xlist_unlink( xlist_entry_xp );
288
289        // update number of registered items
290        hal_remote_atomic_add( XPTR( xhtab_cxy , &xhtab_ptr->items ) , -1 );
291
292        // release the lock protecting hash table
293        remote_busylock_release( XPTR( xhtab_cxy , &xhtab_ptr->lock ) );
294
295        return 0;
296    }
297}  // end xhtab_remove()
298
299/////////////////////////////////////////
300xptr_t  xhtab_lookup( xptr_t    xhtab_xp,
301                      void    * key )
302{
303    xptr_t             item_xp;
304    uint32_t           index;
305    cxy_t              xhtab_cxy;
306    xhtab_t          * xhtab_ptr;
307    index_from_key_t * index_from_key;     // function pointer
308
309    // get xhtab cluster and local pointer
310    xhtab_cxy = GET_CXY( xhtab_xp );
311    xhtab_ptr = GET_PTR( xhtab_xp );
312
313    // get pointer on "index_from_key" function
314    index_from_key = (index_from_key_t *)hal_remote_lpt( XPTR( xhtab_cxy , 
315                                                         &xhtab_ptr->index_from_key ) );
316    // compute index from key
317        index = index_from_key( key );
318   
319#if DEBUG_XHTAB
320printk("\n[DBG] %s : enter / %s\n", __FUNCTION__, key );
321#endif
322
323    // take the lock protecting hash table
324    remote_busylock_acquire( XPTR( xhtab_cxy , &xhtab_ptr->lock ) );
325   
326#if DEBUG_XHTAB
327printk("\n[DBG] %s : after lock acquire / %s\n", __FUNCTION__, key );
328#endif
329
330    // scan sub-list
331    item_xp = xhtab_scan( xhtab_xp , index , key );
332
333#if DEBUG_XHTAB
334printk("\n[DBG] %s : after xhtab scan / %s\n", __FUNCTION__, key );
335#endif
336
337    // release the lock protecting hash table
338    remote_busylock_release( XPTR( xhtab_cxy , &xhtab_ptr->lock ) );
339
340#if DEBUG_XHTAB
341printk("\n[DBG] %s : after lock release / %s\n", __FUNCTION__, key );
342#endif
343
344    return item_xp;
345
346}  // end xhtab_lookup()
347
348//////////////////////////////////
349void xhtab_lock( xptr_t xhtab_xp )
350{
351    // get xhtab cluster and local pointer
352    cxy_t     xhtab_cxy = GET_CXY( xhtab_xp );
353    xhtab_t * xhtab_ptr = GET_PTR( xhtab_xp );
354
355    // take the lock protecting hash table
356    remote_busylock_acquire( XPTR( xhtab_cxy , &xhtab_ptr->lock ) );
357}
358
359////////////////////////////////////
360void xhtab_unlock( xptr_t xhtab_xp )
361{
362    // get xhtab cluster and local pointer
363    cxy_t     xhtab_cxy = GET_CXY( xhtab_xp );
364    xhtab_t * xhtab_ptr = GET_PTR( xhtab_xp );
365
366    // release the lock protecting hash table
367    remote_busylock_release( XPTR( xhtab_cxy , &xhtab_ptr->lock ) );
368}
369
370/////////////////////////////////////////
371xptr_t xhtab_get_first( xptr_t xhtab_xp )
372{
373    uint32_t            index;
374    cxy_t               xhtab_cxy;
375    xhtab_t           * xhtab_ptr;
376    xptr_t              xlist_xp;
377    xptr_t              item_xp;
378    xptr_t              root_xp;
379    item_from_xlist_t * item_from_xlist;   // function pointer
380
381    // get xhtab cluster and local pointer
382    xhtab_cxy = GET_CXY( xhtab_xp );
383    xhtab_ptr = GET_PTR( xhtab_xp );
384
385    // get pointer on "item_from_xlist" function
386    item_from_xlist = (item_from_xlist_t *)hal_remote_lpt( XPTR( xhtab_cxy , 
387                                                           &xhtab_ptr->item_from_xlist ) );
388    //loop on subsets
389    for( index = 0 ; index < XHASHTAB_SIZE ; index++ )
390    {
391        // get root of subset
392        root_xp = XPTR( xhtab_cxy , &xhtab_ptr->roots[index] );
393
394        // get first item
395        xlist_xp = xlist_next( root_xp , root_xp );
396
397        if( xlist_xp != XPTR_NULL )  // first item found
398        {
399            // get extended pointer on item containing the xlist entry
400                item_xp = item_from_xlist( xlist_xp );
401
402            // register item in hash table header
403            hal_remote_s32 ( XPTR( xhtab_cxy , &xhtab_ptr->current_index ) , index );
404            hal_remote_s64( XPTR( xhtab_cxy , &xhtab_ptr->current_xlist_xp ) , xlist_xp );
405
406            return item_xp;
407        }
408    }
409           
410    // item not found
411    return XPTR_NULL;
412
413} // end xhtab_get_first()
414   
415////////////////////////////////////////
416xptr_t xhtab_get_next( xptr_t xhtab_xp )
417{
418    uint32_t            index;
419    cxy_t               xhtab_cxy;
420    xhtab_t           * xhtab_ptr;
421    xptr_t              xlist_xp;
422    xptr_t              item_xp;
423    xptr_t              root_xp;
424    item_from_xlist_t * item_from_xlist;   // function pointer
425
426    uint32_t current_index;
427    xptr_t   current_xlist_xp;
428
429    // get xhtab cluster and local pointer
430    xhtab_cxy = GET_CXY( xhtab_xp );
431    xhtab_ptr = GET_PTR( xhtab_xp );
432
433    // get current item pointers
434    current_index    = hal_remote_l32 ( XPTR( xhtab_cxy , &xhtab_ptr->current_index ) ); 
435    current_xlist_xp = hal_remote_l64( XPTR( xhtab_cxy , &xhtab_ptr->current_xlist_xp ) ); 
436
437    // get pointer on "item_from_xlist" function
438    item_from_xlist = (item_from_xlist_t *)hal_remote_lpt( XPTR( xhtab_cxy , 
439                                                           &xhtab_ptr->item_from_xlist ) );
440    //loop on subsets
441    for( index = current_index ; index < XHASHTAB_SIZE ; index++ )
442    {
443        // get root of subset
444        root_xp = XPTR( xhtab_cxy , &xhtab_ptr->roots[index] );
445
446        // get next item
447        if( index == current_index ) xlist_xp = xlist_next( root_xp , current_xlist_xp );
448        else                         xlist_xp = xlist_next( root_xp , root_xp );
449
450        if( xlist_xp != XPTR_NULL )  // next item found
451        {
452            // get extended pointer on item containing the xlist entry
453                item_xp = item_from_xlist( xlist_xp );
454
455            // register item in hash table header
456            hal_remote_s32 ( XPTR( xhtab_cxy , &xhtab_ptr->current_index ) , index );
457            hal_remote_s64( XPTR( xhtab_cxy , &xhtab_ptr->current_xlist_xp ) , xlist_xp );
458
459            return item_xp;
460        }
461    }
462           
463    // item not found
464    return XPTR_NULL;
465
466} // end xhtab_get_next()
467
468/////////////////////////////////////
469void xhtab_display( xptr_t xhtab_xp )
470{
471    uint32_t            index;
472    cxy_t               xhtab_cxy;
473    xhtab_t           * xhtab_ptr;
474    xptr_t              root_xp;
475    xptr_t              iter_xp;
476    xptr_t              item_xp;
477    item_from_xlist_t * item_from_xlist;   // function pointer
478    item_print_key_t  * item_print_key;    // function pointer
479
480    // get xhtab cluster and local pointer
481    xhtab_cxy = GET_CXY( xhtab_xp );
482    xhtab_ptr = GET_PTR( xhtab_xp );
483
484    // get pointer on "item_from_xlist" function
485    item_from_xlist = (item_from_xlist_t *)hal_remote_lpt( XPTR( xhtab_cxy , 
486                                                           &xhtab_ptr->item_from_xlist ) );
487    // get pointer on "item_print_key" function
488    item_print_key = (item_print_key_t *)hal_remote_lpt( XPTR( xhtab_cxy , 
489                                                         &xhtab_ptr->item_print_key ) );
490    //loop on subsets
491    for( index = 0 ; index < XHASHTAB_SIZE ; index++ )
492    {
493        printk(" index = %d : ", index );
494
495        // get root of subset
496        root_xp = XPTR( xhtab_cxy , &xhtab_ptr->roots[index] );
497
498        // loop on xlist
499        XLIST_FOREACH( root_xp , iter_xp )
500        {
501            // get item from xlist
502            item_xp = item_from_xlist( iter_xp );
503           
504            // print item identifier
505            item_print_key( item_xp );
506        }
507
508        printk("\n");
509    }
510}  // end xhtab_display()
Note: See TracBrowser for help on using the repository browser.