00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "db_config.h"
00011
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014
00015 #include <stdlib.h>
00016 #include <string.h>
00017 #endif
00018
00019 #include "db_int.h"
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 SH_LIST_HEAD(__head);
00032 struct __data {
00033 size_t len;
00034 SH_LIST_ENTRY links;
00035 };
00036
00037 #define ILLEGAL_SIZE 1
00038
00039
00040
00041
00042
00043
00044
00045 void
00046 __db_shalloc_init(infop, size)
00047 REGINFO *infop;
00048 size_t size;
00049 {
00050 struct __data *elp;
00051 struct __head *hp;
00052
00053
00054 if (F_ISSET(infop->dbenv, DB_ENV_PRIVATE))
00055 return;
00056
00057 hp = infop->addr;
00058 SH_LIST_INIT(hp);
00059
00060 elp = (struct __data *)(hp + 1);
00061 elp->len = (size - sizeof(struct __head)) - sizeof(elp->len);
00062 SH_LIST_INSERT_HEAD(hp, elp, links, __data);
00063 }
00064
00065
00066
00067
00068
00069
00070
00071 size_t
00072 __db_shalloc_size(len, align)
00073 size_t len, align;
00074 {
00075
00076 if (len < sizeof(struct __data))
00077 len = sizeof(struct __data);
00078
00079 #ifdef DIAGNOSTIC
00080
00081 ++len;
00082 #endif
00083
00084
00085 if (align <= sizeof(uintmax_t))
00086 align = sizeof(uintmax_t);
00087
00088 return ((size_t)DB_ALIGN(len, align) + sizeof(struct __data));
00089 }
00090
00091
00092
00093
00094
00095
00096
00097 int
00098 __db_shalloc(infop, len, align, retp)
00099 REGINFO *infop;
00100 size_t len, align;
00101 void *retp;
00102 {
00103 DB_ENV *dbenv;
00104 struct __data *elp;
00105 size_t *sp;
00106 int ret;
00107 void *p, *rp;
00108
00109 dbenv = infop->dbenv;
00110
00111
00112 if (align <= sizeof(uintmax_t))
00113 align = sizeof(uintmax_t);
00114
00115
00116 if (F_ISSET(dbenv, DB_ENV_PRIVATE)) {
00117
00118 if (infop->allocated >= infop->max_alloc)
00119 return (ENOMEM);
00120
00121
00122 len += sizeof(size_t);
00123
00124
00125 len += align - 1;
00126
00127
00128 if ((ret = __os_malloc(dbenv, len, &p)) != 0)
00129 return (ret);
00130 infop->allocated += len;
00131
00132
00133 sp = p;
00134 *sp++ = len;
00135
00136
00137 *(void **)retp = rp = ALIGNP_INC(sp, align);
00138
00139
00140 for (; (void *)sp < rp; ++sp)
00141 *sp = ILLEGAL_SIZE;
00142
00143 return (0);
00144 }
00145
00146
00147 if (len < sizeof(struct __data))
00148 len = sizeof(struct __data);
00149
00150 #ifdef DIAGNOSTIC
00151
00152 ++len;
00153 #endif
00154
00155 p = infop->addr;
00156
00157
00158 for (elp = SH_LIST_FIRST((struct __head *)p, __data);
00159 elp != NULL;
00160 elp = SH_LIST_NEXT(elp, links, __data)) {
00161
00162
00163
00164
00165
00166 if (elp->len < len)
00167 continue;
00168
00169
00170
00171
00172
00173
00174
00175
00176 rp = (u_int8_t *)elp + sizeof(size_t) + elp->len;
00177 rp = (u_int8_t *)rp - len;
00178 rp = ALIGNP_DEC(rp, align);
00179
00180
00181
00182
00183
00184 if ((u_int8_t *)rp < (u_int8_t *)&elp->links)
00185 continue;
00186
00187 *(void **)retp = rp;
00188 #ifdef DIAGNOSTIC
00189
00190
00191
00192
00193
00194
00195
00196 *((u_int8_t *)elp + sizeof(size_t) + elp->len - 1) = GUARD_BYTE;
00197 #endif
00198
00199 #define SHALLOC_FRAGMENT 32
00200
00201
00202
00203
00204 if ((u_int8_t *)rp >=
00205 (u_int8_t *)&elp->links + SHALLOC_FRAGMENT) {
00206 sp = rp;
00207 *--sp = elp->len -
00208 ((u_int8_t *)rp - (u_int8_t *)&elp->links);
00209 elp->len -= *sp + sizeof(size_t);
00210 return (0);
00211 }
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 SH_LIST_REMOVE(elp, links, __data);
00222 for (sp = rp; (u_int8_t *)--sp >= (u_int8_t *)&elp->links;)
00223 *sp = ILLEGAL_SIZE;
00224 return (0);
00225 }
00226
00227 return (ENOMEM);
00228 }
00229
00230
00231
00232
00233
00234
00235
00236 void
00237 __db_shalloc_free(infop, ptr)
00238 REGINFO *infop;
00239 void *ptr;
00240 {
00241 DB_ENV *dbenv;
00242 struct __data *elp, *lastp, *newp;
00243 struct __head *hp;
00244 size_t free_size, *sp;
00245 int merged;
00246
00247 dbenv = infop->dbenv;
00248
00249
00250
00251
00252
00253 for (sp = (size_t *)ptr; sp[-1] == ILLEGAL_SIZE; --sp)
00254 ;
00255 ptr = sp;
00256
00257 newp = (struct __data *)((u_int8_t *)ptr - sizeof(size_t));
00258 free_size = newp->len;
00259
00260
00261 if (F_ISSET(dbenv, DB_ENV_PRIVATE)) {
00262 DB_ASSERT(infop->allocated >= free_size);
00263 infop->allocated -= free_size;
00264
00265 __os_free(dbenv, newp);
00266 return;
00267 }
00268
00269 #ifdef DIAGNOSTIC
00270
00271
00272
00273
00274
00275
00276 if (*((u_int8_t *)ptr + free_size - 1) != GUARD_BYTE) {
00277
00278
00279
00280
00281 fprintf(stderr,
00282 "Guard byte incorrect during shared memory free.\n");
00283 abort();
00284
00285 }
00286
00287
00288 memset(ptr, CLEAR_BYTE, free_size);
00289 #endif
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 hp = (struct __head *)(infop->addr);
00300 for (elp = SH_LIST_FIRST(hp, __data), lastp = NULL;
00301 elp != NULL && (void *)elp < (void *)ptr;
00302 lastp = elp, elp = SH_LIST_NEXT(elp, links, __data))
00303 ;
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 merged = 0;
00314 if ((u_int8_t *)ptr + free_size == (u_int8_t *)elp) {
00315 newp->len += elp->len + sizeof(size_t);
00316 SH_LIST_REMOVE(elp, links, __data);
00317 if (lastp != NULL)
00318 SH_LIST_INSERT_AFTER(lastp, newp, links, __data);
00319 else
00320 SH_LIST_INSERT_HEAD(hp, newp, links, __data);
00321 merged = 1;
00322 }
00323
00324
00325 if (lastp != NULL && (u_int8_t *)lastp +
00326 lastp->len + sizeof(size_t) == (u_int8_t *)newp) {
00327 lastp->len += newp->len + sizeof(size_t);
00328
00329
00330
00331
00332
00333
00334 if (merged)
00335 SH_LIST_REMOVE(newp, links, __data);
00336 merged = 1;
00337 }
00338
00339 if (!merged) {
00340 if (lastp == NULL)
00341 SH_LIST_INSERT_HEAD(hp, newp, links, __data);
00342 else
00343 SH_LIST_INSERT_AFTER(lastp, newp, links, __data);
00344 }
00345 }
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358 size_t
00359 __db_shalloc_sizeof(ptr)
00360 void *ptr;
00361 {
00362 struct __data *elp;
00363 size_t *sp;
00364
00365
00366
00367
00368
00369 for (sp = (size_t *)ptr; sp[-1] == ILLEGAL_SIZE; --sp)
00370 ;
00371
00372 elp = (struct __data *)((u_int8_t *)sp - sizeof(size_t));
00373 return (elp->len);
00374 }