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 )
79 tPage *pageptr = (void*)gaUserHandles;
80 size_t size = max_handles * sizeof(tVFS_Handle);
81 for( size_t ofs = 0; ofs < size; ofs ++)
83 if( !MM_Allocate( pageptr ) )
85 Warning("OOM - VFS_AllocHandle");
86 Threads_Exit(0, 0xFF); // Terminate user
90 memset( gaUserHandles, 0, size );
93 for( int i = 0; i < max_handles; i ++ )
95 if(gaUserHandles[i].Node) continue;
96 gaUserHandles[i].Node = Node;
97 gaUserHandles[i].Position = 0;
98 gaUserHandles[i].Mode = Mode;
104 // Allocate space if not already
105 if( MM_GetPhysAddr( gaKernelHandles ) == 0 )
107 tPage *pageptr = (void*)gaKernelHandles;
108 size_t size = MAX_KERNEL_FILES * sizeof(tVFS_Handle);
109 for(size_t ofs = 0; ofs < size; ofs += size)
111 if( !MM_Allocate( pageptr ) )
113 Panic("OOM - VFS_AllocHandle");
117 memset( gaKernelHandles, 0, size );
120 for(int i=0;i<MAX_KERNEL_FILES;i++)
122 if(gaKernelHandles[i].Node) continue;
123 gaKernelHandles[i].Node = Node;
124 gaKernelHandles[i].Position = 0;
125 gaKernelHandles[i].Mode = Mode;
126 return i|VFS_KERNEL_FLAG;
133 void VFS_ReferenceUserHandles(void)
136 int max_handles = *Threads_GetMaxFD();
138 // Check if this process has any handles
139 if( MM_GetPhysAddr( gaUserHandles ) == 0 )
142 for( i = 0; i < max_handles; i ++ )
145 h = &gaUserHandles[i];
148 _ReferenceNode(h->Node);
149 h->Mount->OpenHandleCount ++;
153 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( int 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 void *pg = (void*)( (tVAddr)h & ~(PAGE_SIZE-1) );
252 if( !MM_Allocate( pg ) )
257 memset(pg, 0, PAGE_SIZE);
259 // Safe to dereference, as Threads_CloneTCB references handles
266 h->Mount->OpenHandleCount --;
274 memcpy( gaUserHandles, handles, NumFDs * sizeof(tVFS_Handle) );
275 // Reference when copied
276 for( int i = 0; i < NumFDs; i ++ )
278 tVFS_Handle *h = &gaUserHandles[i];
282 // Debug("VFS_RestoreHandles: %i %p", i, h->Node);
283 _ReferenceNode(h->Node);
284 h->Mount->OpenHandleCount ++;
286 for( int i = NumFDs; i < max_handles; i ++ )
288 gaUserHandles[i].Node = NULL;
292 void VFS_FreeSavedHandles(int NumFDs, void *Handles)
294 tVFS_Handle *handles = Handles;
297 // NULL = nothing to do
301 // Dereference all saved nodes
302 for( i = 0; i < NumFDs; i ++ )
304 tVFS_Handle *h = &handles[i];
310 ASSERT(h->Mount->OpenHandleCount > 0);
311 LOG("dec. mntpt '%s' to %i", h->Mount->MountPoint, h->Mount->OpenHandleCount-1);
312 h->Mount->OpenHandleCount --;