Kernel - Start on SHM 'driver' (and common in-memory finddir/readdir)
[tpg/acess2.git] / KernelLand / Kernel / drv / shm.c
1 /* 
2  * Acess2 Kernel
3  * - By John Hodge (thePowersGang)
4  *
5  * drv/shm.c
6  * - Shared memory "device"
7  */
8 #define DEBUG   0
9 #include <acess.h>
10 #include <modules.h>
11 #include <fs_devfs.h>
12 #include <memfs_helpers.h> 
13 #include <semaphore.h>
14
15 // === TYPES ===
16 #define PAGES_PER_BLOCK 1024
17 typedef struct sSHM_BufferBlock
18 {
19         struct sSHM_BufferBlock *Next;
20         tPAddr  Pages[PAGES_PER_BLOCK];
21 } tSHM_BufferBlock;
22 typedef struct
23 {
24         tMemFS_FileHdr  FileHdr;
25         tVFS_Node       Node;
26         tSHM_BufferBlock        FirstBlock;
27 } tSHM_Buffer;
28
29 // === PROTOTYPES ===
30  int    SHM_Install(char **Arguments);
31  int    SHM_Uninstall(void);
32 tSHM_Buffer     *SHM_CreateBuffer(const char *Name);
33 void    SHM_DeleteBuffer(tSHM_Buffer *Buffer);
34 // - Root directory
35  int    SHM_ReadDir(tVFS_Node *Node, int Id, char Dest[FILENAME_MAX]);
36 tVFS_Node       *SHM_FindDir(tVFS_Node *Node, const char *Filename, Uint Flags);
37 tVFS_Node       *SHM_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
38  int    SHM_Unlink(tVFS_Node *Node, const char *OldName);
39 // - Buffers
40 void    SHM_Reference(tVFS_Node *Node);
41 void    SHM_Close(tVFS_Node *Node);
42 size_t  SHM_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags);
43 size_t  SHM_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags);
44  int    SHM_MMap(struct sVFS_Node *Node, off_t Offset, int Length, void *Dest);
45
46 // === GLOBALS ===
47 MODULE_DEFINE(0, 0x0100, SHM, SHM_Install, SHM_Uninstall, NULL);
48 tMemFS_DirHdr   gSHM_RootDir = {
49         .FileHdr = {.Name = "SHMRoot"}
50 };
51 tVFS_NodeType   gSHM_DirNodeType = {
52         .TypeName = "SHM Root",
53         .ReadDir = SHM_ReadDir,
54         .FindDir = SHM_FindDir,
55         .MkNod   = SHM_MkNod,
56         .Unlink  = SHM_Unlink,
57 };
58 tVFS_NodeType   gSHM_FileNodeType = {
59         .TypeName = "SHM Buffer",
60         .Read  = SHM_Read,
61         .Write = SHM_Write,
62         .Close = SHM_Close,
63         .MMap  = SHM_MMap,
64         .Reference = SHM_Reference,
65 };
66 tDevFS_Driver   gSHM_DriverInfo = {
67         .Name = "shm",
68         .RootNode = {
69                 .Size = 0,
70                 .NumACLs = 1,
71                 .ACLs = &gVFS_ACL_EveryoneRW,
72                 .Flags = VFS_FFLAG_DIRECTORY,
73                 .Type = &gSHM_DirNodeType
74         }
75 };
76
77 // === CODE ===
78 int SHM_Install(char **Arguments)
79 {
80         MemFS_InitDir(&gSHM_RootDir);
81         DevFS_AddDevice( &gSHM_DriverInfo );
82         return MODULE_ERR_OK;
83 }
84 int SHM_Uninstall(void)
85 {
86         return MODULE_ERR_OK;
87 }
88 tSHM_Buffer *SHM_CreateBuffer(const char *Name)
89 {
90         tSHM_Buffer *ret = calloc(1, sizeof(tSHM_Buffer) + strlen(Name) + 1);
91         MemFS_InitFile(&ret->FileHdr);
92         ret->FileHdr.Name = (const char*)(ret+1);
93         strcpy((char*)ret->FileHdr.Name, Name);
94         ret->Node.ImplPtr = ret;
95         ret->Node.Type = &gSHM_FileNodeType;
96         ret->Node.ReferenceCount = 1;
97         return ret;
98 }
99 void SHM_DeleteBuffer(tSHM_Buffer *Buffer)
100 {
101         ASSERTCR(Buffer->Node.ReferenceCount,==,0,);
102         
103         // TODO: Destroy multi-block nodes
104         ASSERT(Buffer->FirstBlock.Next == NULL);
105         
106         free(Buffer);
107 }
108 // - Root directory
109 int SHM_ReadDir(tVFS_Node *Node, int Id, char Dest[FILENAME_MAX])
110 {
111         return MemFS_ReadDir(&gSHM_RootDir, Id, Dest);
112 }
113
114 /**
115  * \brief Open a shared memory buffer
116  *
117  * \note Opening 'anon' will always succeed, and will create an anonymous mapping
118  */
119 tVFS_Node *SHM_FindDir(tVFS_Node *Node, const char *Filename, Uint Flags)
120 {
121         if( strcmp(Filename, "anon") == 0 )
122         {
123                 tSHM_Buffer *ret = SHM_CreateBuffer("");
124                 return &ret->Node;
125         }
126         
127         tMemFS_FileHdr  *file = MemFS_FindDir(&gSHM_RootDir, Filename);
128         if( !file )
129                 return NULL;
130         
131         return &((tSHM_Buffer*)file)->Node;
132 }
133
134
135 /**
136  * \brief Create a named shared memory file
137  */
138 tVFS_Node *SHM_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
139 {
140         if( MemFS_FindDir(&gSHM_RootDir, Name) )
141                 return NULL;
142         
143         tSHM_Buffer *ret = SHM_CreateBuffer(Name);
144         if( !MemFS_Insert(&gSHM_RootDir, &ret->FileHdr) )
145         {
146                 ret->Node.ReferenceCount = 0;
147                 SHM_DeleteBuffer(ret);
148                 return NULL;
149         }
150
151         return &ret->Node;
152 }
153
154 /**
155  * \breif Remove a named shared memory buffer (will be deleted when all references drop)
156  */
157 int SHM_Unlink(tVFS_Node *Node, const char *OldName)
158 {
159         tMemFS_FileHdr  *file = MemFS_Remove(&gSHM_RootDir, OldName);
160         if( !file )
161                 return 1;
162
163         tSHM_Buffer *buf = (tSHM_Buffer*)file;
164         if( buf->Node.ReferenceCount == 0 )
165         {
166                 SHM_DeleteBuffer(buf);
167         }
168         else
169         {
170                 // dangling references, let them clean themselves up later
171         }
172         return 0;
173 }
174 // - Buffers
175 void SHM_Reference(tVFS_Node *Node)
176 {
177         Node->ReferenceCount ++;
178 }
179 void SHM_Close(tVFS_Node *Node)
180 {
181         Node->ReferenceCount --;
182         if( Node->ReferenceCount == 0 )
183         {
184                 // TODO: How to tell if a buffer should be deleted here?
185                 UNIMPLEMENTED();
186         }
187 }
188 size_t SHM_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
189 {
190         UNIMPLEMENTED();
191         return -1;
192 }
193 size_t SHM_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags)
194 {
195         // TODO: Should first write determine the fixed size of the buffer?
196         UNIMPLEMENTED();
197         return -1;
198 }
199 int SHM_MMap(struct sVFS_Node *Node, off_t Offset, int Length, void *Dest)
200 {
201         UNIMPLEMENTED();
202         return 1;
203 }
204

UCC git Repository :: git.ucc.asn.au