3 * - AllocHandle, GetHandle
12 #include <threads.h> // GetMaxFD
13 #include <vfs_threads.h> // Handle maintainance
16 #define MAX_KERNEL_FILES 128
21 tVFS_Handle *gaUserHandles = (void*)MM_PPD_HANDLES;
22 tVFS_Handle *gaKernelHandles = (void*)MM_KERNEL_VFS;
26 * \fn tVFS_Handle *VFS_GetHandle(int FD)
27 * \brief Gets a pointer to the handle information structure
29 tVFS_Handle *VFS_GetHandle(int FD)
33 //Log_Debug("VFS", "VFS_GetHandle: (FD=0x%x)", FD);
35 if(FD < 0) return NULL;
37 if(FD & VFS_KERNEL_FLAG) {
38 FD &= (VFS_KERNEL_FLAG - 1);
39 if(FD >= MAX_KERNEL_FILES) return NULL;
40 h = &gaKernelHandles[ FD ];
42 if(FD >= *Threads_GetMaxFD()) return NULL;
43 h = &gaUserHandles[ FD ];
46 if(h->Node == NULL) return NULL;
47 //Log_Debug("VFS", "VFS_GetHandle: RETURN %p", h);
51 int VFS_SetHandle(int FD, tVFS_Node *Node, int Mode)
56 if( FD & VFS_KERNEL_FLAG ) {
57 FD &= (VFS_KERNEL_FLAG -1);
58 if( FD >= MAX_KERNEL_FILES ) return -1;
59 h = &gaKernelHandles[FD];
62 if( FD >= *Threads_GetMaxFD()) return -1;
63 h = &gaUserHandles[FD];
70 int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode)
72 // Check for a user open
75 int max_handles = *Threads_GetMaxFD();
77 if( MM_GetPhysAddr( gaUserHandles ) == 0 )
80 size = max_handles * sizeof(tVFS_Handle);
81 for(addr = 0; addr < size; addr += 0x1000)
83 if( !MM_Allocate( (tVAddr)gaUserHandles + addr ) )
85 Warning("OOM - VFS_AllocHandle");
86 Threads_Exit(0, 0xFF); // Terminate user
89 memset( gaUserHandles, 0, size );
92 for( int i = 0; i < max_handles; i ++ )
94 if(gaUserHandles[i].Node) continue;
95 gaUserHandles[i].Node = Node;
96 gaUserHandles[i].Position = 0;
97 gaUserHandles[i].Mode = Mode;
103 // Allocate space if not already
104 if( MM_GetPhysAddr( gaKernelHandles ) == 0 )
107 size = MAX_KERNEL_FILES * sizeof(tVFS_Handle);
108 for(addr = 0; addr < size; addr += 0x1000)
110 if( !MM_Allocate( (tVAddr)gaKernelHandles + addr ) )
112 Panic("OOM - VFS_AllocHandle");
113 Threads_Exit(0, 0xFF); // Terminate application (get some space back)
116 memset( gaKernelHandles, 0, size );
119 for(int i=0;i<MAX_KERNEL_FILES;i++)
121 if(gaKernelHandles[i].Node) continue;
122 gaKernelHandles[i].Node = Node;
123 gaKernelHandles[i].Position = 0;
124 gaKernelHandles[i].Mode = Mode;
125 return i|VFS_KERNEL_FLAG;
132 void VFS_ReferenceUserHandles(void)
135 int max_handles = *Threads_GetMaxFD();
137 // Check if this process has any handles
138 if( MM_GetPhysAddr( gaUserHandles ) == 0 )
141 for( i = 0; i < max_handles; i ++ )
144 h = &gaUserHandles[i];
147 _ReferenceNode(h->Node);
148 h->Mount->OpenHandleCount ++;
152 void VFS_CloseAllUserHandles(void)
155 int max_handles = *Threads_GetMaxFD();
157 // Check if this process has any handles
158 if( MM_GetPhysAddr( gaUserHandles ) == 0 )
161 for( i = 0; i < max_handles; i ++ )
164 h = &gaUserHandles[i];
172 * \brief Take a backup of a set of file descriptors
174 void *VFS_SaveHandles(int NumFDs, int *FDs)
177 int max_handles = *Threads_GetMaxFD();
179 // Check if this process has any handles
180 if( MM_GetPhysAddr( gaUserHandles ) == 0 )
184 ret = malloc( NumFDs * sizeof(tVFS_Handle) );
188 if( NumFDs > max_handles )
189 NumFDs = max_handles;
191 // Take copies of the handles
193 memcpy(ret, gaUserHandles, NumFDs * sizeof(tVFS_Handle));
197 for( int i = 0; i < NumFDs; i ++ )
201 Log_Warning("VFS", "VFS_SaveHandles - Slot %i error FD (%i<0), ignorning",
203 memset(&ret[i], 0, sizeof(tVFS_Handle));
207 int fd = FDs[i] & (VFS_KERNEL_FLAG - 1);
208 tVFS_Handle *h = VFS_GetHandle(fd);
210 Log_Warning("VFS", "VFS_SaveHandles - Invalid FD 0x%x (%i) in slot %i",
215 // Log("%i: Duplicate FD %i (%p)", i, fd, h->Node);
216 memcpy( &ret[i], h, sizeof(tVFS_Handle) );
220 // Reference nodes/mounts
221 for( int i = 0; i < NumFDs; i ++ )
223 tVFS_Handle *h = &ret[i];
227 // Debug("VFS_SaveHandles: %i %p", i, h->Node);
228 _ReferenceNode(h->Node);
229 h->Mount->OpenHandleCount ++;
235 void VFS_RestoreHandles(int NumFDs, void *Handles)
237 tVFS_Handle *handles = Handles;
238 int max_handles = *Threads_GetMaxFD();
240 // NULL = nothing to do
244 // Allocate user handle area (and dereference existing handles)
245 for( int i = 0; i < NumFDs; i ++ )
247 tVFS_Handle *h = &gaUserHandles[i];
249 if( !MM_GetPhysAddr(h) )
251 if( !MM_Allocate( (tVAddr)h & ~(PAGE_SIZE-1) ) )
256 // Safe to dereference, as Threads_CloneTCB references handles
263 h->Mount->OpenHandleCount --;
271 memcpy( gaUserHandles, handles, NumFDs * sizeof(tVFS_Handle) );
272 // Reference when copied
273 for( int i = 0; i < NumFDs; i ++ )
275 tVFS_Handle *h = &gaUserHandles[i];
279 // Debug("VFS_RestoreHandles: %i %p", i, h->Node);
280 _ReferenceNode(h->Node);
281 h->Mount->OpenHandleCount ++;
283 for( int i = NumFDs; i < max_handles; i ++ )
285 gaUserHandles[i].Node = NULL;
289 void VFS_FreeSavedHandles(int NumFDs, void *Handles)
291 tVFS_Handle *handles = Handles;
294 // NULL = nothing to do
298 // Dereference all saved nodes
299 for( i = 0; i < NumFDs; i ++ )
301 tVFS_Handle *h = &handles[i];
307 ASSERT(h->Mount->OpenHandleCount > 0);
308 LOG("dec. mntpt '%s' to %i", h->Mount->MountPoint, h->Mount->OpenHandleCount-1);
309 h->Mount->OpenHandleCount --;