44#include "storage/lwlock.h"
55
66
7- static Table * table ;
7+ // static Table *table;
88static dsm_segment * segment = NULL ;
9-
9+ static dsm_handle * segment_handle = 0 ;
10+ static size_t _first_free = 0 ;
11+ static size_t _block_size = 0 ;
12+
13+ typedef int BlockHeader ;
14+ typedef BlockHeader * BlockHeaderPtr ;
15+
16+ #define FREE_BIT 0x80000000
17+ #define is_free (header ) \
18+ ((*header) & FREE_BIT)
19+ #define set_free (header ) \
20+ ((*header) | FREE_BIT)
21+ #define set_used (header ) \
22+ ((*header) & ~FREE_BIT)
23+ #define get_length (header ) \
24+ ((*header) & ~FREE_BIT)
25+ #define set_length (header ,length ) \
26+ ((length) | ((*header) & FREE_BIT))
1027
1128void
1229alloc_dsm_table ()
1330{
1431bool found ;
15- table = ( Table * ) ShmemInitStruct ("dsm table" ,sizeof (Table ),& found );
32+ segment_handle = ShmemInitStruct ("dsm table" ,sizeof (dsm_handle ),& found );
1633if (!found )
17- table -> segment_handle = 0 ;
34+ * segment_handle = 0 ;
1835}
1936
2037
2643init_dsm_segment (size_t block_size )
2744{
2845bool ret ;
29- dsm_handle handle ;
3046
3147/* lock here */
3248LWLockAcquire (dsm_init_lock ,LW_EXCLUSIVE );
3349
3450/* if there is already an existing segment then attach to it */
35- if (table -> segment_handle != 0 )
51+ if (* segment_handle != 0 )
3652{
3753ret = false;
38- segment = dsm_attach (table -> segment_handle );
54+ segment = dsm_attach (* segment_handle );
3955}
4056
4157/*
4258 * If segment hasn't been created yet or has already been destroyed
4359 * (it happens when last session detaches segment) then create new one
4460 */
45- if (table -> segment_handle == 0 || segment == NULL )
61+ if (* segment_handle == 0 || segment == NULL )
4662{
4763/* create segment */
4864segment = dsm_create (block_size * BLOCKS_COUNT ,0 );
49- handle = dsm_segment_handle (segment );
50- init_dsm_table (table , handle , block_size );
65+ * segment_handle = dsm_segment_handle (segment );
66+ init_dsm_table (block_size );
5167ret = true;
5268}
69+ _block_size = block_size ;
5370
5471/*
5572 * Keep mapping till the end of the session. Otherwise it would be
@@ -63,25 +80,24 @@ init_dsm_segment(size_t block_size)
6380return ret ;
6481}
6582
83+ /*
84+ * Initialize allocated segment with block structure
85+ */
6686void
67- init_dsm_table (Table * tbl , dsm_handle h , size_t block_size )
87+ init_dsm_table (size_t block_size )
6888{
6989int i ;
70- Block * block ;
71-
72- memset (table ,0 ,sizeof (Table ));
73- table -> segment_handle = h ;
74- table -> block_size = block_size ;
75- table -> first_free = 0 ;
90+ BlockHeaderPtr header ;
91+ char * ptr = dsm_segment_address (segment );
7692
7793/* create blocks */
7894for (i = 0 ;i < BLOCKS_COUNT ;i ++ )
7995{
80- block = & table -> blocks [i ];
81- block -> segment = h ;
82- block -> offset = i * block_size ;
83- block -> is_free = true;
96+ header = (BlockHeaderPtr )& ptr [i * block_size ];
97+ * header = set_free (header );
98+ * header = set_length (header ,1 );
8499}
100+ _first_free = 0 ;
85101
86102return ;
87103}
@@ -93,71 +109,91 @@ void
93109alloc_dsm_array (DsmArray * arr ,size_t entry_size ,size_t length )
94110{
95111int i = 0 ;
96- Block * block = NULL ;
97- int free_count = 0 ;
98112int size_requested = entry_size * length ;
99113int min_pos = 0 ;
100114int max_pos = 0 ;
115+ size_t offset = 0 ;
116+ size_t total_length = 0 ;
117+ char * ptr = dsm_segment_address (segment );
118+ BlockHeaderPtr header ;
101119
102- for (i = table -> first_free ;i < BLOCKS_COUNT ;i ++ )
120+ for (i = _first_free ;i < BLOCKS_COUNT ; )
103121{
104- if (table -> blocks [i ].is_free )
122+ header = (BlockHeaderPtr )& ptr [i * _block_size ];
123+ if (is_free (header ))
105124{
106- if (!block )
125+ if (!offset )
107126{
108- block = & table -> blocks [i ];
127+ offset = i * _block_size ;
128+ total_length = _block_size - sizeof (BlockHeader );
109129min_pos = i ;
110130}
111- free_count ++ ;
131+ else
132+ {
133+ total_length += _block_size ;
134+ }
135+ i ++ ;
112136}
113137else
114138{
115- free_count = 0 ;
116- block = NULL ;
139+ offset = 0 ;
140+ total_length = 0 ;
141+ i += get_length (header );
117142}
118143
119- if (free_count * table -> block_size >=size_requested )
144+ if (total_length >=size_requested )
120145{
121- // return block->offset;
122- max_pos = i ;
146+ max_pos = i - 1 ;
123147break ;
124148}
125149}
126150
127151/* look up for first free block */
128- for (i = i + 1 ;i < BLOCKS_COUNT ;i ++ )
129- if (table -> blocks [i ].is_free == true)
152+ for (;i < BLOCKS_COUNT ; )
153+ {
154+ header = (BlockHeaderPtr )& ptr [i * _block_size ];
155+ if (is_free (header ))
130156{
131- table -> first_free = i ;
157+ _first_free = i ;
132158break ;
133159}
160+ else
161+ {
162+ i += get_length (header );
163+ }
164+ }
134165
135166/* if we found enough of space */
136- if (free_count * table -> block_size >=size_requested )
167+ if (total_length >=size_requested )
137168{
138- for (i = min_pos ;i <=max_pos ;i ++ )
139- table -> blocks [i ].is_free = false;
140- arr -> offset = block -> offset ;
169+ header = (BlockHeaderPtr )& ptr [min_pos * _block_size ];
170+ * header = set_used (header );
171+ * header = set_length (header ,max_pos - min_pos + 1 );
172+
173+ arr -> offset = offset ;
141174arr -> length = length ;
142175}
143176}
144177
145178void
146179free_dsm_array (DsmArray * arr )
147180{
148- int start = arr -> offset /table -> block_size ;
181+ int start = arr -> offset /_block_size ;
149182int i = 0 ;
183+ char * ptr = dsm_segment_address (segment );
184+ BlockHeaderPtr header = (BlockHeaderPtr )& ptr [start * _block_size ];
185+ size_t blocks_count = get_length (header );
150186
151187/* set blocks free */
152- for (;;i ++ )
188+ for (;i < blocks_count ;i ++ )
153189{
154- table -> blocks [ start + i ]. is_free = true ;
155- if ( i * table -> block_size >= arr -> length )
156- break ;
190+ header = ( BlockHeaderPtr ) & ptr [( start + i ) * _block_size ] ;
191+ * header = set_free ( header );
192+ * header = set_length ( header , 1 ) ;
157193}
158194
159- if (arr -> offset < table -> first_free )
160- table -> first_free = arr -> offset ;
195+ if (start < _first_free )
196+ _first_free = start ;
161197
162198arr -> offset = 0 ;
163199arr -> length = 0 ;
@@ -166,5 +202,5 @@ free_dsm_array(DsmArray *arr)
166202void *
167203dsm_array_get_pointer (const DsmArray * arr )
168204{
169- return (uint8_t * )dsm_segment_address (segment )+ arr -> offset ;
205+ return (char * )dsm_segment_address (segment )+ arr -> offset + sizeof ( BlockHeader ) ;
170206}