summaryrefslogtreecommitdiffstats
path: root/lib/base/shmem.cpp
blob: 1ddd76d33712e49122feac67a6977378f8503fae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/** BEGIN COPYRIGHT BLOCK
 * Copyright 2001 Sun Microsystems, Inc.
 * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
 * All rights reserved.
 * END COPYRIGHT BLOCK **/
/*
 * shmem.h: Portable abstraction for memory shared among a server's workers
 * 
 * Rob McCool
 */


#include "shmem.h"

#if defined (SHMEM_UNIX_MMAP)

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <private/pprio.h>  /* for nspr20 binary release */

NSPR_BEGIN_EXTERN_C
#include <sys/mman.h>
NSPR_END_EXTERN_C

NSAPI_PUBLIC shmem_s *shmem_alloc(char *name, int size, int expose)
{
    shmem_s *ret = (shmem_s *) PERM_MALLOC(sizeof(shmem_s));
    char *growme;

    if( (ret->fd = PR_Open(name, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE, 0666)) == NULL) {
        PERM_FREE(ret);
        return NULL;
    }
    growme = (char *) PERM_MALLOC(size);
    ZERO(growme, size);
    if(PR_Write(ret->fd, (char *)growme, size) < 0) {
        PR_Close(ret->fd);
        PERM_FREE(growme);
        PERM_FREE(ret);
        return NULL;
    }
    PERM_FREE(growme);
    PR_Seek(ret->fd, 0, PR_SEEK_SET);
    if( (ret->data = (char *)mmap(NULL, size, PROT_READ | PROT_WRITE,
                          SHMEM_MMAP_FLAGS, PR_FileDesc2NativeHandle(ret->fd), 0)) == (caddr_t) -1)
    {
        PR_Close(ret->fd);
        PERM_FREE(ret);
        return NULL;
    }
    if(!expose) {
        ret->name = NULL;
        unlink(name);
    }
    else
        ret->name = STRDUP(name);
    ret->size = size;
    return ret;
}


NSAPI_PUBLIC void shmem_free(shmem_s *region)
{
    if(region->name) {
        unlink(region->name);
        PERM_FREE(region->name);
    }
    munmap((char *)region->data, region->size);  /* CLEARLY, C++ SUCKS */
    PR_Close(region->fd);
    PERM_FREE(region);
}

#elif defined (SHMEM_WIN32_MMAP)

#define PAGE_SIZE	(1024*8)
#define ALIGN(x)	( (x+PAGE_SIZE-1) & (~(PAGE_SIZE-1)) )
NSAPI_PUBLIC shmem_s *shmem_alloc(char *name, int size, int expose)
{
    shmem_s *ret = (shmem_s *) PERM_MALLOC(sizeof(shmem_s));
    HANDLE fHandle;

    ret->fd = 0; /* not used on NT */
  
    size = ALIGN(size);
    if( !(ret->fdmap = CreateFileMapping(
                           (HANDLE)0xffffffff,
                           NULL, 
                           PAGE_READWRITE,
                           0, 
                           size, 
                           name)) )
    {
        int err = GetLastError();
        PERM_FREE(ret);
        return NULL;
    }
    if( !(ret->data = (char *)MapViewOfFile (
                               ret->fdmap, 
                               FILE_MAP_ALL_ACCESS,
                               0, 
                               0, 
                               0)) )
    {
        CloseHandle(ret->fdmap);
        PERM_FREE(ret);
        return NULL;
    }
    ret->size = size;
    ret->name = NULL;

    return ret;
}


NSAPI_PUBLIC void shmem_free(shmem_s *region)
{
    if(region->name) {
        DeleteFile(region->name);
        PERM_FREE(region->name);
    }
    UnmapViewOfFile(region->data);
    CloseHandle(region->fdmap);
    PERM_FREE(region);
}

#endif /* SHMEM_WIN32_MMAP */