3 * - By John Hodge (thePowersGang)
6 * - Shared memory "device"
12 #include <memfs_helpers.h>
13 #include <semaphore.h>
16 #define PAGES_PER_BLOCK 1024
17 typedef struct sSHM_BufferBlock
19 struct sSHM_BufferBlock *Next;
20 tPAddr Pages[PAGES_PER_BLOCK];
24 tMemFS_FileHdr FileHdr;
26 tSHM_BufferBlock FirstBlock;
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);
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);
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);
47 MODULE_DEFINE(0, 0x0100, SHM, SHM_Install, SHM_Uninstall, NULL);
48 tMemFS_DirHdr gSHM_RootDir = {
49 .FileHdr = {.Name = "SHMRoot"}
51 tVFS_NodeType gSHM_DirNodeType = {
52 .TypeName = "SHM Root",
53 .ReadDir = SHM_ReadDir,
54 .FindDir = SHM_FindDir,
58 tVFS_NodeType gSHM_FileNodeType = {
59 .TypeName = "SHM Buffer",
64 .Reference = SHM_Reference,
66 tDevFS_Driver gSHM_DriverInfo = {
71 .ACLs = &gVFS_ACL_EveryoneRW,
72 .Flags = VFS_FFLAG_DIRECTORY,
73 .Type = &gSHM_DirNodeType
78 int SHM_Install(char **Arguments)
80 MemFS_InitDir(&gSHM_RootDir);
81 DevFS_AddDevice( &gSHM_DriverInfo );
84 int SHM_Uninstall(void)
88 tSHM_Buffer *SHM_CreateBuffer(const char *Name)
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;
99 void SHM_DeleteBuffer(tSHM_Buffer *Buffer)
101 ASSERTCR(Buffer->Node.ReferenceCount,==,0,);
103 // TODO: Destroy multi-block nodes
104 ASSERT(Buffer->FirstBlock.Next == NULL);
109 int SHM_ReadDir(tVFS_Node *Node, int Id, char Dest[FILENAME_MAX])
111 return MemFS_ReadDir(&gSHM_RootDir, Id, Dest);
115 * \brief Open a shared memory buffer
117 * \note Opening 'anon' will always succeed, and will create an anonymous mapping
119 tVFS_Node *SHM_FindDir(tVFS_Node *Node, const char *Filename, Uint Flags)
121 if( strcmp(Filename, "anon") == 0 )
123 tSHM_Buffer *ret = SHM_CreateBuffer("");
127 tMemFS_FileHdr *file = MemFS_FindDir(&gSHM_RootDir, Filename);
131 return &((tSHM_Buffer*)file)->Node;
136 * \brief Create a named shared memory file
138 tVFS_Node *SHM_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
140 if( MemFS_FindDir(&gSHM_RootDir, Name) )
143 tSHM_Buffer *ret = SHM_CreateBuffer(Name);
144 if( !MemFS_Insert(&gSHM_RootDir, &ret->FileHdr) )
146 ret->Node.ReferenceCount = 0;
147 SHM_DeleteBuffer(ret);
155 * \breif Remove a named shared memory buffer (will be deleted when all references drop)
157 int SHM_Unlink(tVFS_Node *Node, const char *OldName)
159 tMemFS_FileHdr *file = MemFS_Remove(&gSHM_RootDir, OldName);
163 tSHM_Buffer *buf = (tSHM_Buffer*)file;
164 if( buf->Node.ReferenceCount == 0 )
166 SHM_DeleteBuffer(buf);
170 // dangling references, let them clean themselves up later
175 void SHM_Reference(tVFS_Node *Node)
177 Node->ReferenceCount ++;
179 void SHM_Close(tVFS_Node *Node)
181 Node->ReferenceCount --;
182 if( Node->ReferenceCount == 0 )
184 // TODO: How to tell if a buffer should be deleted here?
188 size_t SHM_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
193 size_t SHM_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags)
195 // TODO: Should first write determine the fixed size of the buffer?
199 int SHM_MMap(struct sVFS_Node *Node, off_t Offset, int Length, void *Dest)