4
4
#include "storage/lwlock.h"
5
5
#include <stdint.h>
6
6
7
- static Table * table ;
7
+
8
8
static dsm_segment * segment = NULL ;
9
9
10
+ typedef struct DsmConfig
11
+ {
12
+ dsm_handle segment_handle ;
13
+ size_t block_size ;
14
+ size_t blocks_count ;
15
+ size_t first_free ;
16
+ } DsmConfig ;
17
+
18
+ static DsmConfig * dsm_cfg = NULL ;
19
+
20
+ typedef int BlockHeader ;
21
+ typedef BlockHeader * BlockHeaderPtr ;
22
+
23
+ #define FREE_BIT 0x80000000
24
+ #define is_free (header ) \
25
+ ((*header) & FREE_BIT)
26
+ #define set_free (header ) \
27
+ ((*header) | FREE_BIT)
28
+ #define set_used (header ) \
29
+ ((*header) & ~FREE_BIT)
30
+ #define get_length (header ) \
31
+ ((*header) & ~FREE_BIT)
32
+ #define set_length (header , length ) \
33
+ ((length) | ((*header) & FREE_BIT))
10
34
11
35
void
12
36
alloc_dsm_table ()
13
37
{
14
38
bool found ;
15
- table = ( Table * ) ShmemInitStruct ("dsm table " , sizeof (Table ), & found );
39
+ dsm_cfg = ShmemInitStruct ("dsm config " , sizeof (DsmConfig ), & found );
16
40
if (!found )
17
- table -> segment_handle = 0 ;
41
+ {
42
+ dsm_cfg -> segment_handle = 0 ;
43
+ dsm_cfg -> block_size = 0 ;
44
+ dsm_cfg -> blocks_count = INITIAL_BLOCKS_COUNT ;
45
+ dsm_cfg -> first_free = 0 ;
46
+ }
18
47
}
19
48
20
49
@@ -23,31 +52,33 @@ alloc_dsm_table()
23
52
* false if attached to existing segment
24
53
*/
25
54
bool
26
- init_dsm_segment (size_t block_size )
55
+ init_dsm_segment (size_t blocks_count , size_t block_size )
27
56
{
28
57
bool ret ;
29
- dsm_handle handle ;
30
58
31
59
/* lock here */
32
60
LWLockAcquire (dsm_init_lock , LW_EXCLUSIVE );
33
61
34
62
/* if there is already an existing segment then attach to it */
35
- if (table -> segment_handle != 0 )
63
+ if (dsm_cfg -> segment_handle != 0 )
36
64
{
37
65
ret = false;
38
- segment = dsm_attach (table -> segment_handle );
66
+ segment = dsm_attach (dsm_cfg -> segment_handle );
39
67
}
40
68
41
69
/*
42
70
* If segment hasn't been created yet or has already been destroyed
43
71
* (it happens when last session detaches segment) then create new one
44
72
*/
45
- if (table -> segment_handle == 0 || segment == NULL )
73
+ if (dsm_cfg -> segment_handle == 0 || segment == NULL )
46
74
{
47
75
/* create segment */
48
- segment = dsm_create (block_size * BLOCKS_COUNT , 0 );
49
- handle = dsm_segment_handle (segment );
50
- init_dsm_table (table , handle , block_size );
76
+ segment = dsm_create (block_size * blocks_count , 0 );
77
+ dsm_cfg -> segment_handle = dsm_segment_handle (segment );
78
+ dsm_cfg -> first_free = 0 ;
79
+ dsm_cfg -> block_size = block_size ;
80
+ dsm_cfg -> blocks_count = blocks_count ;
81
+ init_dsm_table (block_size , 0 , dsm_cfg -> blocks_count );
51
82
ret = true;
52
83
}
53
84
@@ -63,24 +94,22 @@ init_dsm_segment(size_t block_size)
63
94
return ret ;
64
95
}
65
96
97
+ /*
98
+ * Initialize allocated segment with block structure
99
+ */
66
100
void
67
- init_dsm_table (Table * tbl , dsm_handle h , size_t block_size )
101
+ init_dsm_table (size_t block_size , size_t start , size_t end )
68
102
{
69
103
int 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 ;
104
+ BlockHeaderPtr header ;
105
+ char * ptr = dsm_segment_address (segment );
76
106
77
107
/* create blocks */
78
- for (i = 0 ; i < BLOCKS_COUNT ; i ++ )
108
+ for (i = start ; i < end ; i ++ )
79
109
{
80
- block = & table -> blocks [i ];
81
- block -> segment = h ;
82
- block -> offset = i * block_size ;
83
- block -> is_free = true;
110
+ header = (BlockHeaderPtr ) & ptr [i * block_size ];
111
+ * header = set_free (header );
112
+ * header = set_length (header , 1 );
84
113
}
85
114
86
115
return ;
@@ -93,71 +122,115 @@ void
93
122
alloc_dsm_array (DsmArray * arr , size_t entry_size , size_t length )
94
123
{
95
124
int i = 0 ;
96
- Block * block = NULL ;
97
- int free_count = 0 ;
98
125
int size_requested = entry_size * length ;
99
126
int min_pos = 0 ;
100
127
int max_pos = 0 ;
101
-
102
- for (i = table -> first_free ; i < BLOCKS_COUNT ; i ++ )
128
+ bool found = false;
129
+ bool collecting_blocks = false;
130
+ size_t offset = -1 ;
131
+ size_t total_length = 0 ;
132
+ BlockHeaderPtr header ;
133
+ char * ptr = dsm_segment_address (segment );
134
+
135
+ for (i = dsm_cfg -> first_free ; i < dsm_cfg -> blocks_count ; )
103
136
{
104
- if (table -> blocks [i ].is_free )
137
+ header = (BlockHeaderPtr ) & ptr [i * dsm_cfg -> block_size ];
138
+ if (is_free (header ))
105
139
{
106
- if (!block )
140
+ if (!collecting_blocks )
107
141
{
108
- block = & table -> blocks [i ];
142
+ offset = i * dsm_cfg -> block_size ;
143
+ total_length = dsm_cfg -> block_size - sizeof (BlockHeader );
109
144
min_pos = i ;
145
+ collecting_blocks = true;
146
+ }
147
+ else
148
+ {
149
+ total_length += dsm_cfg -> block_size ;
110
150
}
111
- free_count ++ ;
151
+ i ++ ;
112
152
}
113
153
else
114
154
{
115
- free_count = 0 ;
116
- block = NULL ;
155
+ collecting_blocks = false;
156
+ offset = 0 ;
157
+ total_length = 0 ;
158
+ i += get_length (header );
117
159
}
118
160
119
- if (free_count * table -> block_size >= size_requested )
161
+ if (total_length >= size_requested )
120
162
{
121
- // return block->offset ;
122
- max_pos = i ;
163
+ max_pos = i - 1 ;
164
+ found = true ;
123
165
break ;
124
166
}
125
167
}
126
168
169
+ /*
170
+ * If dsm segment size is not enough then resize it (or allocate bigger
171
+ * for segment SysV and Windows, not implemented yet)
172
+ */
173
+ if (!found )
174
+ {
175
+ size_t new_blocks_count = dsm_cfg -> blocks_count * 2 ;
176
+
177
+ dsm_resize (segment , new_blocks_count * dsm_cfg -> block_size );
178
+ init_dsm_table (dsm_cfg -> block_size , dsm_cfg -> blocks_count , new_blocks_count );
179
+ dsm_cfg -> blocks_count = new_blocks_count ;
180
+
181
+ /* try again */
182
+ return alloc_dsm_array (arr , entry_size , length );
183
+ }
184
+
127
185
/* look up for first free block */
128
- for (i = i + 1 ; i < BLOCKS_COUNT ; i ++ )
129
- if (table -> blocks [i ].is_free == true)
186
+ if (dsm_cfg -> first_free == min_pos )
187
+ {
188
+ for (; i < dsm_cfg -> blocks_count ; )
130
189
{
131
- table -> first_free = i ;
132
- break ;
190
+ header = (BlockHeaderPtr ) & ptr [i * dsm_cfg -> block_size ];
191
+ if (is_free (header ))
192
+ {
193
+ dsm_cfg -> first_free = i ;
194
+ break ;
195
+ }
196
+ else
197
+ {
198
+ i += get_length (header );
199
+ }
133
200
}
201
+ }
134
202
135
203
/* if we found enough of space */
136
- if (free_count * table -> block_size >= size_requested )
204
+ if (total_length >= size_requested )
137
205
{
138
- for (i = min_pos ; i <=max_pos ; i ++ )
139
- table -> blocks [i ].is_free = false;
140
- arr -> offset = block -> offset ;
206
+ header = (BlockHeaderPtr ) & ptr [min_pos * dsm_cfg -> block_size ];
207
+ * header = set_used (header );
208
+ * header = set_length (header , max_pos - min_pos + 1 );
209
+
210
+ arr -> offset = offset ;
141
211
arr -> length = length ;
142
212
}
143
213
}
144
214
145
215
void
146
216
free_dsm_array (DsmArray * arr )
147
217
{
148
- int start = arr -> offset / table -> block_size ;
218
+ int start = arr -> offset / dsm_cfg -> block_size ;
149
219
int i = 0 ;
220
+ char * ptr = dsm_segment_address (segment );
221
+ BlockHeaderPtr header = (BlockHeaderPtr ) & ptr [start * dsm_cfg -> block_size ];
222
+ size_t blocks_count = get_length (header );
150
223
151
224
/* set blocks free */
152
- for (;; i ++ )
225
+ for (; i < blocks_count ; i ++ )
153
226
{
154
- table -> blocks [ start + i ]. is_free = true ;
155
- if ( i * table -> block_size >= arr -> length )
156
- break ;
227
+ header = ( BlockHeaderPtr ) & ptr [( start + i ) * dsm_cfg -> block_size ] ;
228
+ * header = set_free ( header );
229
+ * header = set_length ( header , 1 ) ;
157
230
}
158
231
159
- if (arr -> offset < table -> first_free )
160
- table -> first_free = arr -> offset ;
232
+ if (start < dsm_cfg -> first_free )
233
+ dsm_cfg -> first_free = start ;
161
234
162
235
arr -> offset = 0 ;
163
236
arr -> length = 0 ;
@@ -166,5 +239,5 @@ free_dsm_array(DsmArray *arr)
166
239
void *
167
240
dsm_array_get_pointer (const DsmArray * arr )
168
241
{
169
- return (uint8_t * ) dsm_segment_address (segment ) + arr -> offset ;
242
+ return (char * ) dsm_segment_address (segment ) + arr -> offset + sizeof ( BlockHeader ) ;
170
243
}
0 commit comments