2 meinOS - A unix-like x86 microkernel operating system
3 Copyright (C) 2008 Janosch Gräf <janosch.graef@gmx.net>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <sys/types.h>
35 #define ipc_shm_permcheck(shm,op) (perm_check((shm)->ipc.owner->pid,(shm)->ipc.owner->gid,proc_current->uid,proc_current->gid,(shm)->ipc.mode,op) || proc_current->uid==(shm)->ipc.creator->uid)
36 #define ipc_shm_find(key,id) ipc_find(key,id,IPC_SHM)
39 * Intitializes Shared Memory
43 if (syscall_create(SYSCALL_IPC_SHM_GET
,ipc_shm_get
,1)==-1) return -1;
44 if (syscall_create(SYSCALL_IPC_SHM_CREATE
,ipc_shm_create
,4)==-1) return -1;
45 if (syscall_create(SYSCALL_IPC_SHM_ATTACH
,ipc_shm_attach
,4)==-1) return -1;
46 if (syscall_create(SYSCALL_IPC_SHM_DETACH
,ipc_shm_detach
,2)==-1) return -1;
47 if (syscall_create(SYSCALL_IPC_SHM_STAT
,ipc_shm_stat
,13)==-1) return -1;
48 if (syscall_create(SYSCALL_IPC_SHM_SET
,ipc_shm_set
,7)==-1) return -1;
49 if (syscall_create(SYSCALL_IPC_SHM_DESTROY
,ipc_shm_destroy
,1)==-1) return -1;
54 * Gets a shared memory object (Syscall)
58 id_t
ipc_shm_get(key_t key
) {
59 ipc_shm_t
*shm
= ipc_shm_find(key
,-1);
60 if (shm
==NULL
) return -EINVAL
;
61 else return shm
->ipc
.id
;
65 * Creates a shared memory object (Syscall)
69 * @param time Current time
72 id_t
ipc_shm_create(key_t key
,size_t size
,int flags
,time_t time
) {
73 ipc_shm_t
*shm
= key
!=IPC_PRIVATE
?ipc_shm_find(key
,-1):NULL
;
75 ipc_shm_t
*new = malloc(sizeof(ipc_shm_t
));
78 memset(new,0,sizeof(ipc_shm_t
));
79 new->ipc
.type
= IPC_SHM
;
80 new->ipc
.id
= ipc_lastid
++;
82 new->ipc
.owner
= proc_current
;
83 new->ipc
.creator
= proc_current
;
84 new->ipc
.mode
= flags
&0777;
86 new->num_pages
= ADDR2PAGE(PAGEUP(new->size
));
87 new->phys
= malloc(sizeof(void*)*new->num_pages
);
88 for (i
=0;i
<new->num_pages
;i
++) new->phys
[i
] = memphys_alloc();
89 new->atts
= llist_create();
90 new->lopid
= proc_current
->pid
;
91 llist_push(ipc_objects
,new);
100 * Attaches process to shared memory object (Syscall)
102 * @param virt Virtual address to attatch to
106 int ipc_shm_attach(id_t id
,const void **addr
,int flags
,time_t time
) {
107 void *virt
= (void*)*addr
;
108 if (virt
>=(void*)USERDATA_ADDRESS
|| virt
==NULL
) {
109 ipc_shm_t
*shm
= ipc_shm_find(-1,id
);
111 ipc_shm_att_t
*new = malloc(sizeof(ipc_shm_att_t
));
115 new->proc
= proc_current
;
116 new->virt
= virt
==NULL
?memuser_findvirt(proc_current
->addrspace
,shm
->num_pages
):(void*)virt
;
117 new->readonly
= flags
&SHM_RDONLY
;
118 if (virt
==NULL
) virt
= memuser_findvirt(proc_current
->addrspace
,shm
->num_pages
);
119 for (i
=0;i
<shm
->num_pages
;i
++) paging_map(new->virt
+i
*PAGE_SIZE
,shm
->phys
[i
],1,!new->readonly
);
120 llist_push(shm
->atts
,new);
122 shm
->lopid
= proc_current
->pid
;
133 * Detaches process form shared memory object (Syscall)
134 * @param virt Virtual address to detach from
137 int ipc_shm_detach(const void *virt
,time_t time
) {
141 if (virt
<(void*)USERDATA_ADDRESS
) return -1;
142 for (i
=0;(shm
= llist_get(ipc_objects
,i
));i
++) {
143 if (shm
->ipc
.type
==IPC_SHM
) {
144 for (j
=0;(att
= llist_get(shm
->atts
,j
));j
++) {
145 if (att
->proc
==proc_current
&& att
->virt
==virt
) {
146 for (k
=0;k
<shm
->num_pages
;k
++) paging_unmap(att
->virt
+k
*PAGE_SIZE
);
147 llist_remove(shm
->atts
,j
);
150 shm
->lopid
= proc_current
->pid
;
159 int ipc_shm_stat(id_t id
,uid_t
*uid
,gid_t
*gid
,uid_t
*cuid
,gid_t
*cgid
,mode_t
*mode
,size_t *segsz
,pid_t
*lpid
,pid_t
*cpid
,size_t *nattch
,time_t *atime
,time_t *dtime
,time_t *ctime
) {
160 ipc_shm_t
*shm
= ipc_shm_find(-1,id
);
162 if (ipc_shm_permcheck(shm
,PERM_R
)) {
163 *uid
= shm
->ipc
.owner
->uid
;
164 *gid
= shm
->ipc
.owner
->gid
;
165 *cuid
= shm
->ipc
.creator
->uid
;
166 *cgid
= shm
->ipc
.creator
->gid
;
167 *cpid
= shm
->ipc
.creator
->pid
;
168 *mode
= shm
->ipc
.mode
;
171 *nattch
= llist_size(shm
->atts
);
182 int ipc_shm_set(id_t id
,uid_t uid
,gid_t gid
,mode_t mode
,time_t time
) {
183 ipc_shm_t
*shm
= ipc_shm_find(-1,id
);
185 if (ipc_shm_permcheck(shm
,PERM_W
)) {
186 shm
->ipc
.mode
= mode
;
196 * Destroys a shared memory object
200 int ipc_shm_destroy(id_t id
) {
201 ipc_shm_t
*shm
= ipc_shm_find(-1,id
);
205 while ((att
= llist_pop(shm
->atts
))) {
206 for (i
=0;i
<shm
->num_pages
;i
++) paging_unmap(att
->virt
+i
*PAGE_SIZE
);
209 for (i
=0;i
<shm
->num_pages
;i
++) memphys_free(shm
->phys
[i
]);
212 llist_remove(ipc_objects
,llist_find(ipc_objects
,shm
));