source: trunk/third/db/os_vxworks/os_map.c @ 17055

Revision 17055, 8.8 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r17054, which included commits to RCS files with non-trunk default branches.
Line 
1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 1998, 1999, 2000
5 *      Sleepycat Software.  All rights reserved.
6 *
7 * This code is derived from software contributed to Sleepycat Software by
8 * Frederick G.M. Roeber of Netscape Communications Corp.
9 */
10
11#include "db_config.h"
12
13#ifndef lint
14static const char revid[] = "$Id: os_map.c,v 1.1.1.1 2002-02-11 16:26:53 ghudson Exp $";
15#endif /* not lint */
16
17#ifndef NO_SYSTEM_INCLUDES
18#include <sys/types.h>
19#include <errno.h>
20#include <string.h>
21#endif
22
23#include "db_int.h"
24#include "common_ext.h"
25
26/*
27 * DB uses memory-mapped files for two things:
28 *      faster access of read-only databases, and
29 *      shared memory for process synchronization and locking.
30 * The code carefully does not mix the two uses.  The first-case uses are
31 * actually written such that memory-mapping isn't really required -- it's
32 * merely a convenience -- so we don't have to worry much about it.  In the
33 * second case, it's solely used as a shared memory mechanism, so that's
34 * all we have to replace.
35 *
36 * All memory in VxWorks is shared, and a task can allocate memory and keep
37 * notes.  So I merely have to allocate memory, remember the "filename" for
38 * that memory, and issue small-integer segment IDs which index the list of
39 * these shared-memory segments. Subsequent opens are checked against the
40 * list of already open segments.
41 */
42typedef struct {
43        void *segment;                  /* Segment address. */
44        u_int32_t size;                 /* Segment size. */
45        char *name;                     /* Segment name. */
46} os_segdata_t;
47
48static os_segdata_t *__os_segdata;      /* Segment table. */
49static int __os_segdata_size;           /* Segment table size. */
50
51#define OS_SEGDATA_STARTING_SIZE 16
52#define OS_SEGDATA_INCREMENT     16
53
54static int __os_segdata_allocate
55               __P((DB_ENV *, const char *, REGINFO *, REGION *));
56static int __os_segdata_find_byname
57               __P((DB_ENV *, const char *, REGINFO *, REGION *));
58static int __os_segdata_init __P((DB_ENV *));
59static int __os_segdata_new __P((DB_ENV *, int *));
60static int __os_segdata_release __P((DB_ENV *, int));
61
62/*
63 * __os_r_sysattach --
64 *      Create/join a shared memory region.
65 *
66 * PUBLIC: int __os_r_sysattach __P((DB_ENV *, REGINFO *, REGION *));
67 */
68int
69__os_r_sysattach(dbenv, infop, rp)
70        DB_ENV *dbenv;
71        REGINFO *infop;
72        REGION *rp;
73{
74        int ret;
75
76        if (__os_segdata == NULL)
77                __os_segdata_init(dbenv);
78
79        /* Try to find an already existing segment. */
80        DB_BEGIN_SINGLE_THREAD;
81        if (__os_segdata_find_byname(dbenv, infop->name, infop, rp) == 0) {
82                DB_END_SINGLE_THREAD;
83                return (0);
84        }
85
86        /*
87         * If we're trying to join the region and failing, assume
88         * that there was a reboot and the region no longer exists.
89         */
90        if (!F_ISSET(infop, REGION_CREATE)) {
91                __db_err(dbenv, "segment %s does not exist", infop->name);
92                DB_END_SINGLE_THREAD;
93                return (EAGAIN);
94        }
95
96        /* Create a new segment. */
97        ret = __os_segdata_allocate(dbenv, infop->name, infop, rp);
98        DB_END_SINGLE_THREAD;
99        return (ret);
100}
101
102/*
103 * __os_r_sysdetach --
104 *      Detach from a shared region.
105 *
106 * PUBLIC: int __os_r_sysdetach __P((DB_ENV *, REGINFO *, int));
107 */
108int
109__os_r_sysdetach(dbenv, infop, destroy)
110        DB_ENV *dbenv;
111        REGINFO *infop;
112        int destroy;
113{
114        REGION *rp;
115
116        rp = infop->rp;
117        /*
118         * If just detaching, there is no mapping to discard.
119         * If destroying, remove the region.
120         */
121        if (destroy)
122                return (__os_segdata_release(dbenv, rp->segid));
123        return(0);
124}
125
126/*
127 * __os_mapfile --
128 *      Map in a shared memory file.
129 *
130 * PUBLIC: int __os_mapfile __P((DB_ENV *,
131 * PUBLIC:    char *, DB_FH *, size_t, int, void **));
132 */
133int
134__os_mapfile(dbenv, path, fhp, len, is_rdonly, addrp)
135        DB_ENV *dbenv;
136        char *path;
137        DB_FH *fhp;
138        int is_rdonly;
139        size_t len;
140        void **addrp;
141{
142        /* We cannot map in regular files in VxWorks. */
143
144        COMPQUIET(path, NULL);
145        COMPQUIET(fhp, NULL);
146        COMPQUIET(is_rdonly, 0);
147        COMPQUIET(len, 0);
148        COMPQUIET(addrp, NULL);
149
150        __db_err(dbenv, "architecture doesn't support mapping in files");
151        return (__db_eopnotsup(dbenv));
152}
153
154/*
155 * __os_unmapfile --
156 *      Unmap the shared memory file.
157 *
158 * PUBLIC: int __os_unmapfile __P((DB_ENV *, void *, size_t));
159 */
160int
161__os_unmapfile(dbenv, addr, len)
162        DB_ENV *dbenv;
163        void *addr;
164        size_t len;
165{
166        /* We cannot map in regular files in VxWorks. */
167
168        COMPQUIET(addr, NULL);
169        COMPQUIET(len, 0);
170
171        __db_err(dbenv, "architecture doesn't support mapping in files");
172        return (__db_eopnotsup(dbenv));
173}
174
175/*
176 * __os_segdata_init --
177 *      Initializes the library's table of shared memory segments.
178 *      Called once on the first time through __os_segdata_new().
179 */
180static int
181__os_segdata_init(dbenv)
182        DB_ENV *dbenv;
183{
184        int ret;
185
186        if (__os_segdata != NULL) {
187                __db_err(dbenv, "shared memory segment already exists");
188                return (EEXIST);
189        }
190
191        /*
192         * The lock init call returns a locked lock
193         */
194        DB_BEGIN_SINGLE_THREAD;
195        __os_segdata_size = OS_SEGDATA_STARTING_SIZE;
196        if ((ret = __os_calloc(dbenv, __os_segdata_size,
197            sizeof(os_segdata_t), &__os_segdata)) != 0) {
198                DB_END_SINGLE_THREAD;
199                return (ret);
200        }
201        DB_END_SINGLE_THREAD;
202
203        return (0);
204}
205
206/*
207 * __os_segdata_destroy --
208 *      Destroys the library's table of shared memory segments.  It also
209 *      frees all linked data: the segments themselves, and their names.
210 *      Currently not called.  This function should be called if the
211 *      user creates a function to unload or shutdown.
212 *
213 * PUBLIC: int __os_segdata_destroy __P((void));
214 */
215int
216__os_segdata_destroy()
217{
218        os_segdata_t *p;
219        int i;
220
221        if (__os_segdata == NULL)
222                return (0);
223
224        DB_BEGIN_SINGLE_THREAD;
225        for (i = 0; i < __os_segdata_size; i++) {
226                p = &__os_segdata[i];
227                if (p->name != NULL) {
228                        __os_freestr(p->name);
229                        p->name = NULL;
230                }
231                if (p->segment != NULL) {
232                        __os_free(p->segment, p->size);
233                        p->segment = NULL;
234                }
235                p->size = 0;
236        }
237
238        __os_free(__os_segdata, __os_segdata_size * sizeof(os_segdata_t));
239        __os_segdata = NULL;
240        __os_segdata_size = 0;
241        DB_END_SINGLE_THREAD;
242
243        return (0);
244}
245
246/*
247 * __os_segdata_allocate --
248 *      Creates a new segment of the specified size, optionally with the
249 *      specified name.
250 *
251 * Assumes it is called with the SEGDATA lock taken.
252 */
253static int
254__os_segdata_allocate(dbenv, name, infop, rp)
255        DB_ENV *dbenv;
256        const char *name;
257        REGINFO *infop;
258        REGION *rp;
259{
260        os_segdata_t *p;
261        int segid, ret;
262
263        if ((ret = __os_segdata_new(dbenv, &segid)) != 0)
264                return (ret);
265
266        p = &__os_segdata[segid];
267        if ((ret = __os_calloc(dbenv, rp->size, 1, &p->segment)) != 0)
268                return (ret);
269        if ((ret = __os_strdup(dbenv, name, &p->name)) != 0) {
270                __os_free(p->segment, rp->size);
271                p->segment = NULL;
272                return (ret);
273        }
274        p->size = rp->size;
275
276        infop->addr = p->segment;
277        rp->segid = segid;
278
279        return (0);
280}
281
282/*
283 * __os_segdata_new --
284 *      Finds a new segdata slot.  Does not initialise it, so the fd returned
285 *      is only valid until you call this again.
286 *
287 * Assumes it is called with the SEGDATA lock taken.
288 */
289static int
290__os_segdata_new(dbenv, segidp)
291        DB_ENV *dbenv;
292        int *segidp;
293{
294        os_segdata_t *p;
295        int i, newsize, ret;
296
297        if (__os_segdata == NULL) {
298                __db_err(dbenv, "shared memory segment not initialized");
299                return (EAGAIN);
300        }
301
302        for (i = 0; i < __os_segdata_size; i++) {
303                p = &__os_segdata[i];
304                if (p->segment == NULL) {
305                        *segidp = i;
306                        return (0);
307                }
308        }
309
310        /*
311         * No more free slots, expand.
312         */
313        newsize = __os_segdata_size + OS_SEGDATA_INCREMENT;
314        if ((ret = __os_realloc(dbenv, newsize * sizeof(os_segdata_t),
315            NULL, &__os_segdata)) != 0)
316                return (ret);
317        memset(&__os_segdata[__os_segdata_size],
318            0, OS_SEGDATA_INCREMENT * sizeof(os_segdata_t));
319
320        *segidp = __os_segdata_size;
321        __os_segdata_size = newsize;
322
323        return (0);
324}
325
326/*
327 * __os_segdata_find_byname --
328 *      Finds a segment by its name.
329 *
330 * Assumes it is called with the SEGDATA lock taken.
331 *
332 * PUBLIC: __os_segdata_find_byname
333 * PUBLIC:     __P((DB_ENV *, const char *, REGINFO *, REGION *));
334 */
335static int
336__os_segdata_find_byname(dbenv, name, infop, rp)
337        DB_ENV *dbenv;
338        const char *name;
339        REGINFO *infop;
340        REGION *rp;
341{
342        os_segdata_t *p;
343        int i;
344
345        if (__os_segdata == NULL) {
346                __db_err(dbenv, "shared memory segment not initialized");
347                return (EAGAIN);
348        }
349
350        if (name == NULL) {
351                __db_err(dbenv, "no segment name given");
352                return (ENOENT);
353        }
354
355        for (i = 0; i < __os_segdata_size; i++) {
356                p = &__os_segdata[i];
357                if (p->name != NULL && strcmp(name, p->name) == 0) {
358                        infop->addr = p->segment;
359                        rp->segid = i;
360                        return (0);
361                }
362        }
363        return (ENOENT);
364}
365
366/*
367 * __os_segdata_release --
368 *      Free a segdata entry.
369 */
370static int
371__os_segdata_release(dbenv, segid)
372        DB_ENV *dbenv;
373        int segid;
374{
375        os_segdata_t *p;
376
377        if (__os_segdata == NULL) {
378                __db_err(dbenv, "shared memory segment not initialized");
379                return (EAGAIN);
380        }
381
382        if (segid < 0 || segid >= __os_segdata_size) {
383                __db_err(dbenv, "segment id %d out of range", segid);
384                return (EINVAL);
385        }
386
387        DB_BEGIN_SINGLE_THREAD;
388        p = &__os_segdata[segid];
389        if (p->name != NULL) {
390                __os_freestr(p->name);
391                p->name = NULL;
392        }
393        if (p->segment != NULL) {
394                __os_free(p->segment, p->size);
395                p->segment = NULL;
396        }
397        p->size = 0;
398        DB_END_SINGLE_THREAD;
399
400        /* Any shrink-table logic could go here */
401
402        return (0);
403}
Note: See TracBrowser for help on using the repository browser.