Removing unused declarations
[barrelfish] / lib / posixcompat / shm.c
1 /*
2  * Copyright (c) 2011, ETH Zurich.
3  * All rights reserved.
4  *
5  * This file is distributed under the terms in the attached LICENSE file.
6  * If you do not find this file, copies can be found by writing to:
7  * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
8  */
9
10 #include <stdlib.h>
11 #include <sys/shm.h>
12 #include <assert.h>
13 #include <stdbool.h>
14 #include <errno.h>
15 #include <stdio.h>
16 #include <barrelfish/barrelfish.h>
17 #include <octopus/init.h>
18 #include <octopus/capability_storage.h>
19 #include <vfs/fdtab.h>
20 #include "posixcompat.h"
21
22 struct _shm {
23     struct shmid_ds ds;
24     bool used;
25     key_t key;
26     struct capref frame;
27 };
28
29 struct _shmap {
30     bool used;
31     void *mem;
32     int id;
33 };
34
35 #define MAX_SHMS        32
36
37 struct _shm shms[MAX_SHMS];
38 struct _shmap shmaps[MAX_SHMS];
39
40 void *shmat(int shmid, const void *shmaddr, int shmflg)
41 {
42     assert(shmid >= 0 && shmid < MAX_SHMS);
43     struct _shm *s = &shms[shmid];
44     errval_t err;
45
46     printf("%s:%s:%d: shmid = %d, shmaddr= %p, shmflg = %d\n",
47            __FILE__, __FUNCTION__, __LINE__, shmid, shmaddr, shmflg);
48
49     struct frame_identity id;
50     vregion_flags_t attr;
51
52     int i;
53
54     for(i = 0; i < MAX_SHMS; i++) {
55       if(!shmaps[i].used) {
56         break;
57       }
58     }
59
60     if(i == MAX_SHMS) {
61         // Out of space for mappings
62         errno = ENOSPC;
63         return NULL;
64     }
65
66     struct _shmap *m = &shmaps[i];
67
68     err = frame_identify(s->frame, &id);
69     if(err_is_fail(err)) {
70         USER_PANIC_ERR(err, "frame_identify");
71     }
72
73     if(shmflg & SHM_RDONLY) {
74         attr = VREGION_FLAGS_READ;
75     } else {
76         attr = VREGION_FLAGS_READ_WRITE;
77     }
78
79     if(shmaddr != NULL) {
80         err = vspace_map_one_frame_fixed_attr((lvaddr_t)shmaddr, id.bytes,
81                                               s->frame, attr, NULL, NULL);
82         m->mem = (void *)shmaddr;
83     } else {
84         err = vspace_map_one_frame_attr(&m->mem, id.bytes, s->frame,
85                                         attr, NULL, NULL);
86     }
87
88     if(err_is_fail(err)) {
89         DEBUG_ERR(err, "vspace_map_one_frame_(fixed_)attr");
90         // XXX: Probably cause it didn't fit the virtual address space
91         m->mem = NULL;
92         errno = ENOMEM;
93         return NULL;
94     }
95
96     s->ds.shm_nattch++;
97     m->used = true;
98     m->id   = shmid;
99
100     POSIXCOMPAT_DEBUG("shmat(%d, %p, %d) = %p\n",
101                       shmid, shmaddr, shmflg, m->mem);
102     return m->mem;
103 }
104
105 int shmget(key_t key, size_t size, int shmflg)
106 {
107     int i;
108     bool newkey = true;
109
110     // XXX: Private key not supported yet
111     assert(key != IPC_PRIVATE);
112
113     POSIXCOMPAT_DEBUG("key is not ipc_private\n");
114     for(i = 0; i < MAX_SHMS; i++) {
115         if(shms[i].used && shms[i].key == key) {
116             newkey = false;
117             break;
118         }
119     }
120
121     if(i == MAX_SHMS) {
122         // Allocate an SHM descriptor
123         for(i = 0; i < MAX_SHMS; i++) {
124             if(!shms[i].used && shms[i].ds.shm_nattch == 0) {
125                 break;
126             }
127         }
128     }
129
130     if(i == MAX_SHMS) {
131         // Out of descriptors
132         errno = ENOSPC;
133         return -1;
134     }
135
136     if (newkey) {
137         struct _shm *s = &shms[i];
138         char skey[128];
139         snprintf(skey, 128, "%lu", key);
140
141         POSIXCOMPAT_DEBUG("get capability %s\n", skey);
142         oct_init(); // XXX: do some posixcompat initialization
143         // XXX: Not multi-processing safe!
144         errval_t err = oct_get_capability(skey, &s->frame);
145         if(err_is_fail(err) && err_no(err) != OCT_ERR_CAP_NAME_UNKNOWN) {
146             USER_PANIC_ERR(err, "oct_get_capability");
147         }
148         if(err == OCT_ERR_CAP_NAME_UNKNOWN) {
149             if(!(shmflg & IPC_CREAT)) {
150                 errno = ENOENT;
151                 return -1;
152             }
153
154             // Allocate frame (don't map it yet)
155             err = frame_alloc(&s->frame, size, NULL);
156             if(err_is_fail(err)) {
157                 DEBUG_ERR(err, "frame_alloc");
158                 if(err_no(err) == LIB_ERR_RAM_ALLOC_MS_CONSTRAINTS) {
159                     errno = ENOMEM;
160                 }
161                 return -1;
162             }
163
164             char buffer[1024];
165             debug_print_cap_at_capref(buffer, 1024, s->frame);
166             POSIXCOMPAT_DEBUG("%s:%d: store cap skey=%s capability=%s\n",
167                               __FILE__, __LINE__, skey, buffer);
168             // XXX: This can fail if someone else won the race
169             err = oct_put_capability(skey, s->frame);
170             if(err_is_fail(err)) {
171                 USER_PANIC_ERR(err, "oct_put_capability");
172             }
173
174             s->ds.shm_nattch = 0;
175         }
176
177         // Assign to local cache
178         s->used = true;
179         s->key = key;
180     }
181
182     POSIXCOMPAT_DEBUG("shmget(%ld, %zu, %d) = %d\n",
183                       key, size, shmflg, i);
184
185     return i;
186 }
187
188 int shmctl(int shmid, int cmd, struct shmid_ds *buf)
189 {
190     char skey[128];
191
192     if(shmid < 0 || shmid >= MAX_SHMS) {
193         return -1;
194     }
195
196     struct _shm *s = &shms[shmid];
197
198     if(!s->used) {
199         return -1;
200     }
201
202     POSIXCOMPAT_DEBUG("shmctl(%d, %d, %p)\n", shmid, cmd, buf);
203
204     switch(cmd) {
205     case IPC_STAT:
206         assert(!"NYI");
207         break;
208
209     case IPC_SET:
210         assert(!"NYI");
211         break;
212
213     case IPC_RMID:
214         snprintf(skey, 128, "%lu", s->key);
215
216         // This can fail if someone else won the race, but
217         // we don't really care, the key has been removed anyway
218         oct_init();
219         oct_remove_capability(skey);
220         s->used = false;
221         break;
222
223     default:
224         return -1;
225     }
226
227     return 0;
228 }
229
230 int shmdt(const void *shmaddr)
231 {
232     struct _shm *s = NULL;
233     struct _shmap *m = NULL;
234     errval_t err;
235
236     int i;
237     for(i = 0; i < MAX_SHMS; i++) {
238         if(shmaps[i].used && shmaps[i].mem == shmaddr) {
239             m = &shmaps[i];
240             break;
241         }
242     }
243
244     if(m == NULL) {
245         errno = EINVAL;
246         return -1;
247     }
248
249     POSIXCOMPAT_DEBUG("shmdt(%p)\n", shmaddr);
250     s = &shms[i];
251
252     assert(s->ds.shm_nattch > 0);
253
254     err = vspace_unmap(shmaddr);
255     if(err_is_fail(err)) {
256         DEBUG_ERR(err, "vspace_unmap");
257         return -1;
258     }
259
260     s->ds.shm_nattch--;
261     m->used = false;
262
263     if(s->ds.shm_nattch==0)
264       s->used = false;
265
266     return 0;
267 }