28
28
#include < my_bit.h>
29
29
#include < lf.h>
30
30
#include " my_cpu.h"
31
+ #include " assume_aligned.h"
31
32
32
33
/* An element of the list */
33
34
typedef struct {
34
- intptr volatile link ; /* a pointer to the next element in a list and a flag */
35
- uint32 hashnr ; /* reversed hash number, for sorting */
35
+ intptr link; /* a pointer to the next element in a list and a flag */
36
36
const uchar *key;
37
37
size_t keylen;
38
+ uint32 hashnr; /* reversed hash number, for sorting */
38
39
/*
39
40
data is stored here, directly after the keylen.
40
41
thus the pointer to data is (void*)(slist_element_ptr+1)
@@ -48,7 +49,7 @@ const int LF_HASH_OVERHEAD= sizeof(LF_SLIST);
48
49
in a list) from l_find to l_insert/l_delete
49
50
*/
50
51
typedef struct {
51
- intptr volatile * prev ;
52
+ intptr *prev;
52
53
LF_SLIST *curr, *next;
53
54
} CURSOR;
54
55
@@ -85,7 +86,7 @@ typedef struct {
85
86
0 - ok
86
87
1 - error (callbck returned 1)
87
88
*/
88
- static int l_find (LF_SLIST * volatile * head , CHARSET_INFO * cs , uint32 hashnr ,
89
+ static int l_find (LF_SLIST **head, CHARSET_INFO *cs, uint32 hashnr,
89
90
const uchar *key, size_t keylen, CURSOR *cursor, LF_PINS *pins,
90
91
my_hash_walk_action callback)
91
92
{
@@ -98,11 +99,11 @@ static int l_find(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr,
98
99
DBUG_ASSERT (!keylen || !callback); /* should not be set both */
99
100
100
101
retry:
101
- cursor -> prev = (intptr * )head ;
102
+ cursor->prev = (intptr *) my_assume_aligned< sizeof (intptr)>( head) ;
102
103
do { /* PTR() isn't necessary below, head is a dummy node */
103
- cursor -> curr = (LF_SLIST * )( * cursor -> prev );
104
+ cursor->curr = my_assume_aligned< sizeof (LF_SLIST *)>((LF_SLIST *)(* cursor->prev ) );
104
105
lf_pin (pins, 1 , cursor->curr );
105
- } while (my_atomic_loadptr ((void * * )cursor -> prev ) != cursor -> curr &&
106
+ } while (my_atomic_loadptr ((void **)my_assume_aligned< sizeof (LF_SLIST *)>( cursor->prev ) ) != cursor->curr &&
106
107
LF_BACKOFF ());
107
108
for (;;)
108
109
{
@@ -111,11 +112,14 @@ static int l_find(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr,
111
112
112
113
cur_hashnr= cursor->curr ->hashnr ;
113
114
cur_keylen= cursor->curr ->keylen ;
115
+ /* The key element needs to be aligned, not necessary what it points to */
116
+ my_assume_aligned<sizeof (const uchar *)>(&cursor->curr ->key );
114
117
cur_key= cursor->curr ->key ;
115
118
116
119
do {
120
+ /* attempting to my_assume_aligned onlink below broke the implementation */
117
121
link= cursor->curr ->link ;
118
- cursor -> next = PTR (link );
122
+ cursor->next = my_assume_aligned< sizeof (LF_SLIST *)>( PTR (link) );
119
123
lf_pin (pins, 0 , cursor->next );
120
124
} while (link != cursor->curr ->link && LF_BACKOFF ());
121
125
@@ -155,6 +159,10 @@ static int l_find(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr,
155
159
}
156
160
}
157
161
162
+
163
+ /* static l_find is the only user my_assume_aligned, keep the rest as c scoped */
164
+ C_MODE_START
165
+
158
166
/*
159
167
DESCRIPTION
160
168
insert a 'node' in the list that starts from 'head' in the correct
@@ -168,7 +176,7 @@ static int l_find(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr,
168
176
it uses pins[0..2], on return all pins are removed.
169
177
if there're nodes with the same key value, a new node is added before them.
170
178
*/
171
- static LF_SLIST * l_insert (LF_SLIST * volatile * head , CHARSET_INFO * cs ,
179
+ static LF_SLIST *l_insert (LF_SLIST **head, CHARSET_INFO *cs,
172
180
LF_SLIST *node, LF_PINS *pins, uint flags)
173
181
{
174
182
CURSOR cursor;
@@ -220,7 +228,7 @@ static LF_SLIST *l_insert(LF_SLIST * volatile *head, CHARSET_INFO *cs,
220
228
NOTE
221
229
it uses pins[0..2], on return all pins are removed.
222
230
*/
223
- static int l_delete (LF_SLIST * volatile * head , CHARSET_INFO * cs , uint32 hashnr ,
231
+ static int l_delete (LF_SLIST **head, CHARSET_INFO *cs, uint32 hashnr,
224
232
const uchar *key, uint keylen, LF_PINS *pins)
225
233
{
226
234
CURSOR cursor;
@@ -278,7 +286,7 @@ static int l_delete(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr,
278
286
it uses pins[0..2], on return the pin[2] keeps the node found
279
287
all other pins are removed.
280
288
*/
281
- static LF_SLIST * l_search (LF_SLIST * volatile * head , CHARSET_INFO * cs ,
289
+ static LF_SLIST *l_search (LF_SLIST **head, CHARSET_INFO *cs,
282
290
uint32 hashnr, const uchar *key, uint keylen,
283
291
LF_PINS *pins)
284
292
{
@@ -319,13 +327,14 @@ static inline my_hash_value_type calc_hash(CHARSET_INFO *cs,
319
327
320
328
#define MAX_LOAD 1.0 /* average number of elements in a bucket */
321
329
322
- static int initialize_bucket (LF_HASH * , LF_SLIST * volatile * , uint , LF_PINS * );
330
+ static int initialize_bucket (LF_HASH *, LF_SLIST **, uint, LF_PINS *);
323
331
324
332
static void default_initializer (LF_HASH *hash, void *dst, const void *src)
325
333
{
326
334
memcpy (dst, src, hash->element_size );
327
335
}
328
336
337
+
329
338
/*
330
339
Initializes lf_hash, the arguments are compatible with hash_init
331
340
@@ -398,7 +407,7 @@ void lf_hash_destroy(LF_HASH *hash)
398
407
int lf_hash_insert (LF_HASH *hash, LF_PINS *pins, const void *data)
399
408
{
400
409
int csize, bucket, hashnr;
401
- LF_SLIST * node , * volatile * el ;
410
+ LF_SLIST *node, **el;
402
411
403
412
node= (LF_SLIST *)lf_alloc_new (pins);
404
413
if (unlikely (!node))
@@ -407,7 +416,7 @@ int lf_hash_insert(LF_HASH *hash, LF_PINS *pins, const void *data)
407
416
node->key = hash_key (hash, (uchar *)(node+1 ), &node->keylen );
408
417
hashnr= hash->hash_function (hash->charset , node->key , node->keylen ) & INT_MAX32;
409
418
bucket= hashnr % hash->size ;
410
- el = lf_dynarray_lvalue (& hash -> array , bucket );
419
+ el= (LF_SLIST **) lf_dynarray_lvalue (&hash->array , bucket);
411
420
if (unlikely (!el))
412
421
return -1 ;
413
422
if (*el == NULL && unlikely (initialize_bucket (hash, el, bucket, pins)))
@@ -437,15 +446,15 @@ int lf_hash_insert(LF_HASH *hash, LF_PINS *pins, const void *data)
437
446
*/
438
447
int lf_hash_delete (LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen)
439
448
{
440
- LF_SLIST * volatile * el ;
449
+ LF_SLIST **el;
441
450
uint bucket, hashnr;
442
451
443
452
hashnr= hash->hash_function (hash->charset , (uchar *)key, keylen) & INT_MAX32;
444
453
445
454
/* hide OOM errors - if we cannot initialize a bucket, try the previous one */
446
455
for (bucket= hashnr % hash->size ; ;bucket= my_clear_highest_bit (bucket))
447
456
{
448
- el = lf_dynarray_lvalue (& hash -> array , bucket );
457
+ el= (LF_SLIST **) lf_dynarray_lvalue (&hash->array , bucket);
449
458
if (el && (*el || initialize_bucket (hash, el, bucket, pins) == 0 ))
450
459
break ;
451
460
if (unlikely (bucket == 0 ))
@@ -473,13 +482,13 @@ void *lf_hash_search_using_hash_value(LF_HASH *hash, LF_PINS *pins,
473
482
my_hash_value_type hashnr,
474
483
const void *key, uint keylen)
475
484
{
476
- LF_SLIST * volatile * el , * found ;
485
+ LF_SLIST **el, *found;
477
486
uint bucket;
478
487
479
488
/* hide OOM errors - if we cannot initialize a bucket, try the previous one */
480
489
for (bucket= hashnr % hash->size ; ;bucket= my_clear_highest_bit (bucket))
481
490
{
482
- el = lf_dynarray_lvalue (& hash -> array , bucket );
491
+ el= (LF_SLIST **) lf_dynarray_lvalue (&hash->array , bucket);
483
492
if (el && (*el || initialize_bucket (hash, el, bucket, pins) == 0 ))
484
493
break ;
485
494
if (unlikely (bucket == 0 ))
@@ -507,9 +516,9 @@ int lf_hash_iterate(LF_HASH *hash, LF_PINS *pins,
507
516
CURSOR cursor;
508
517
uint bucket= 0 ;
509
518
int res;
510
- LF_SLIST * volatile * el ;
519
+ LF_SLIST **el;
511
520
512
- el = lf_dynarray_lvalue (& hash -> array , bucket );
521
+ el= (LF_SLIST **) lf_dynarray_lvalue (&hash->array , bucket);
513
522
if (unlikely (!el))
514
523
return 0 ; /* if there's no bucket==0, the hash is empty */
515
524
if (*el == NULL && unlikely (initialize_bucket (hash, el, bucket, pins)))
@@ -539,14 +548,14 @@ static const uchar *dummy_key= (uchar*)"";
539
548
0 - ok
540
549
-1 - out of memory
541
550
*/
542
- static int initialize_bucket (LF_HASH * hash , LF_SLIST * volatile * node ,
551
+ static int initialize_bucket (LF_HASH *hash, LF_SLIST **node,
543
552
uint bucket, LF_PINS *pins)
544
553
{
545
554
uint parent= my_clear_highest_bit (bucket);
546
555
LF_SLIST *dummy= (LF_SLIST *)my_malloc (key_memory_lf_slist,
547
556
sizeof (LF_SLIST), MYF (MY_WME));
548
557
LF_SLIST **tmp= 0 , *cur;
549
- LF_SLIST * volatile * el = lf_dynarray_lvalue (& hash -> array , parent );
558
+ LF_SLIST **el= (LF_SLIST **) lf_dynarray_lvalue (&hash->array , parent);
550
559
if (unlikely (!el || !dummy))
551
560
return -1 ;
552
561
if (*el == NULL && bucket &&
@@ -574,3 +583,5 @@ static int initialize_bucket(LF_HASH *hash, LF_SLIST * volatile *node,
574
583
*/
575
584
return 0 ;
576
585
}
586
+
587
+ C_MODE_END
0 commit comments