1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements.  See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License.  You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "apr_general.h"
18#include "apr_shm.h"
19#include "apr_errno.h"
20#include "apr_lib.h"
21#include "apr_strings.h"
22#include <stdio.h>
23#include <stdlib.h>
24#include <kernel/OS.h>
25#include "apr_portable.h"
26
27struct apr_shm_t {
28    apr_pool_t *pool;
29    void *memblock;
30    void *ptr;
31    apr_size_t reqsize;
32    apr_size_t avail;
33    area_id aid;
34};
35
36APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m,
37                                         apr_size_t reqsize,
38                                         const char *filename,
39                                         apr_pool_t *p)
40{
41    apr_size_t pagesize;
42    area_id newid;
43    char *addr;
44    char shname[B_OS_NAME_LENGTH];
45
46    (*m) = (apr_shm_t *)apr_pcalloc(p, sizeof(apr_shm_t));
47    /* we MUST allocate in pages, so calculate how big an area we need... */
48    pagesize = ((reqsize + B_PAGE_SIZE - 1) / B_PAGE_SIZE) * B_PAGE_SIZE;
49
50    if (!filename) {
51        int num = 0;
52        snprintf(shname, B_OS_NAME_LENGTH, "apr_shmem_%ld", find_thread(NULL));
53        while (find_area(shname) >= 0)
54            snprintf(shname, B_OS_NAME_LENGTH, "apr_shmem_%ld_%d",
55                     find_thread(NULL), num++);
56    }
57    newid = create_area(filename ? filename : shname,
58                        (void*)&addr, B_ANY_ADDRESS,
59                        pagesize, B_LAZY_LOCK, B_READ_AREA|B_WRITE_AREA);
60
61    if (newid < 0)
62        return errno;
63
64    (*m)->pool = p;
65    (*m)->aid = newid;
66    (*m)->memblock = addr;
67    (*m)->ptr = (void*)addr;
68    (*m)->avail = pagesize; /* record how big an area we actually created... */
69    (*m)->reqsize = reqsize;
70
71    return APR_SUCCESS;
72}
73
74APR_DECLARE(apr_status_t) apr_shm_destroy(apr_shm_t *m)
75{
76    delete_area(m->aid);
77    m->avail = 0;
78    m->memblock = NULL;
79    return APR_SUCCESS;
80}
81
82APR_DECLARE(apr_status_t) apr_shm_remove(const char *filename,
83                                         apr_pool_t *pool)
84{
85    area_id deleteme = find_area(filename);
86
87    if (deleteme == B_NAME_NOT_FOUND)
88        return APR_EINVAL;
89
90    delete_area(deleteme);
91    return APR_SUCCESS;
92}
93
94APR_DECLARE(apr_status_t) apr_shm_attach(apr_shm_t **m,
95                                         const char *filename,
96                                         apr_pool_t *pool)
97{
98    area_info ai;
99    thread_info ti;
100    apr_shm_t *new_m;
101    area_id deleteme = find_area(filename);
102
103    if (deleteme == B_NAME_NOT_FOUND)
104        return APR_EINVAL;
105
106    new_m = (apr_shm_t*)apr_palloc(pool, sizeof(apr_shm_t*));
107    if (new_m == NULL)
108        return APR_ENOMEM;
109    new_m->pool = pool;
110
111    get_area_info(deleteme, &ai);
112    get_thread_info(find_thread(NULL), &ti);
113
114    if (ti.team != ai.team) {
115        area_id narea;
116
117        narea = clone_area(ai.name, &(ai.address), B_CLONE_ADDRESS,
118                           B_READ_AREA|B_WRITE_AREA, ai.area);
119
120        if (narea < B_OK)
121            return narea;
122
123        get_area_info(narea, &ai);
124        new_m->aid = narea;
125        new_m->memblock = ai.address;
126        new_m->ptr = (void*)ai.address;
127        new_m->avail = ai.size;
128        new_m->reqsize = ai.size;
129    }
130
131    (*m) = new_m;
132
133    return APR_SUCCESS;
134}
135
136APR_DECLARE(apr_status_t) apr_shm_detach(apr_shm_t *m)
137{
138    delete_area(m->aid);
139    return APR_SUCCESS;
140}
141
142APR_DECLARE(void *) apr_shm_baseaddr_get(const apr_shm_t *m)
143{
144    return m->memblock;
145}
146
147APR_DECLARE(apr_size_t) apr_shm_size_get(const apr_shm_t *m)
148{
149    return m->reqsize;
150}
151
152APR_POOL_IMPLEMENT_ACCESSOR(shm)
153
154APR_DECLARE(apr_status_t) apr_os_shm_get(apr_os_shm_t *osshm,
155                                         apr_shm_t *shm)
156{
157    return APR_ENOTIMPL;
158}
159
160APR_DECLARE(apr_status_t) apr_os_shm_put(apr_shm_t **m,
161                                         apr_os_shm_t *osshm,
162                                         apr_pool_t *pool)
163{
164    return APR_ENOTIMPL;
165}
166
167