Kernel - Slight reworks to timer code
[tpg/acess2.git] / Kernel / vfs / handle.c
1 /*
2  * Acess2 VFS
3  * - AllocHandle, GetHandle
4  */
5 #define DEBUG   0
6 #include <acess.h>
7 #include <mm_virt.h>
8 #include "vfs.h"
9 #include "vfs_int.h"
10 #include "vfs_ext.h"
11 #include <threads.h>    // GetMaxFD
12 #include <vfs_threads.h>        // Handle maintainance
13
14 // === CONSTANTS ===
15 #define MAX_KERNEL_FILES        128
16
17 // === PROTOTYPES ===
18 #if 0
19 tVFS_Handle     *VFS_GetHandle(int FD);
20 #endif
21  int    VFS_AllocHandle(int FD, tVFS_Node *Node, int Mode);
22
23 // === GLOBALS ===
24 tVFS_Handle     *gaUserHandles = (void*)MM_PPD_HANDLES;
25 tVFS_Handle     *gaKernelHandles = (void*)MM_KERNEL_VFS;
26
27 // === CODE ===
28 /**
29  * \fn tVFS_Handle *VFS_GetHandle(int FD)
30  * \brief Gets a pointer to the handle information structure
31  */
32 tVFS_Handle *VFS_GetHandle(int FD)
33 {
34         tVFS_Handle     *h;
35         
36         //Log_Debug("VFS", "VFS_GetHandle: (FD=0x%x)", FD);
37         
38         if(FD < 0)      return NULL;
39         
40         if(FD & VFS_KERNEL_FLAG) {
41                 FD &= (VFS_KERNEL_FLAG - 1);
42                 if(FD >= MAX_KERNEL_FILES)      return NULL;
43                 h = &gaKernelHandles[ FD ];
44         } else {
45                 if(FD >= *Threads_GetMaxFD())   return NULL;
46                 h = &gaUserHandles[ FD ];
47         }
48         
49         if(h->Node == NULL)     return NULL;
50         //Log_Debug("VFS", "VFS_GetHandle: RETURN %p", h);
51         return h;
52 }
53
54 int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode)
55 {
56          int    i;
57         
58         // Check for a user open
59         if(bIsUser)
60         {
61                  int    max_handles = *Threads_GetMaxFD();
62                 // Allocate Buffer
63                 if( MM_GetPhysAddr( (tVAddr)gaUserHandles ) == 0 )
64                 {
65                         Uint    addr, size;
66                         size = max_handles * sizeof(tVFS_Handle);
67                         for(addr = 0; addr < size; addr += 0x1000)
68                         {
69                                 if( !MM_Allocate( (tVAddr)gaUserHandles + addr ) )
70                                 {
71                                         Warning("OOM - VFS_AllocHandle");
72                                         Threads_Exit(0, 0xFF);  // Terminate user
73                                 }
74                         }
75                         memset( gaUserHandles, 0, size );
76                 }
77                 // Get a handle
78                 for( i = 0; i < max_handles; i ++ )
79                 {
80                         if(gaUserHandles[i].Node)       continue;
81                         gaUserHandles[i].Node = Node;
82                         gaUserHandles[i].Position = 0;
83                         gaUserHandles[i].Mode = Mode;
84                         return i;
85                 }
86         }
87         else
88         {
89                 // Allocate space if not already
90                 if( MM_GetPhysAddr( (tVAddr)gaKernelHandles ) == 0 )
91                 {
92                         Uint    addr, size;
93                         size = MAX_KERNEL_FILES * sizeof(tVFS_Handle);
94                         for(addr = 0; addr < size; addr += 0x1000)
95                         {
96                                 if( !MM_Allocate( (tVAddr)gaKernelHandles + addr ) )
97                                 {
98                                         Panic("OOM - VFS_AllocHandle");
99                                         Threads_Exit(0, 0xFF);  // Terminate application (get some space back)
100                                 }
101                         }
102                         memset( gaKernelHandles, 0, size );
103                 }
104                 // Get a handle
105                 for(i=0;i<MAX_KERNEL_FILES;i++)
106                 {
107                         if(gaKernelHandles[i].Node)     continue;
108                         gaKernelHandles[i].Node = Node;
109                         gaKernelHandles[i].Position = 0;
110                         gaKernelHandles[i].Mode = Mode;
111                         return i|VFS_KERNEL_FLAG;
112                 }
113         }
114         
115         return -1;
116 }
117
118 void VFS_ReferenceUserHandles(void)
119 {
120          int    i;
121          int    max_handles = *Threads_GetMaxFD();
122
123         // Check if this process has any handles
124         if( MM_GetPhysAddr( (tVAddr)gaUserHandles ) == 0 )
125                 return ;
126         
127         for( i = 0; i < max_handles; i ++ )
128         {
129                 tVFS_Handle     *h;
130                 h = &gaUserHandles[i];
131                 if( !h->Node )
132                         continue ;
133                 if( h->Node->Type && h->Node->Type->Reference )
134                         h->Node->Type->Reference( h->Node );
135         }
136 }
137
138 void VFS_CloseAllUserHandles(void)
139 {
140          int    i;
141          int    max_handles = *Threads_GetMaxFD();
142
143         // Check if this process has any handles
144         if( MM_GetPhysAddr( (tVAddr)gaUserHandles ) == 0 )
145                 return ;
146         
147         for( i = 0; i < max_handles; i ++ )
148         {
149                 tVFS_Handle     *h;
150                 h = &gaUserHandles[i];
151                 if( !h->Node )
152                         continue ;
153                 if( h->Node->Type && h->Node->Type->Close )
154                         h->Node->Type->Close( h->Node );
155         }
156 }
157
158 /**
159  * \brief Take a backup of a set of file descriptors
160  */
161 void *VFS_SaveHandles(int NumFDs, int *FDs)
162 {
163         tVFS_Handle     *ret;
164          int    i;
165          int    max_handles = *Threads_GetMaxFD();
166         
167         // Check if this process has any handles
168         if( MM_GetPhysAddr( (tVAddr)gaUserHandles ) == 0 )
169                 return NULL;
170
171         // Allocate
172         ret = malloc( NumFDs * sizeof(tVFS_Handle) );
173         if( !ret )
174                 return NULL;    
175
176         if( NumFDs > max_handles )
177                 NumFDs = max_handles;
178
179         // Take copies of the handles
180         for( i = 0; i < NumFDs; i ++ )
181         {
182                 tVFS_Handle     *h;
183                 if( FDs == NULL )
184                         h = &gaUserHandles[i];
185                 else {
186                         h = VFS_GetHandle(FDs[i] & (VFS_KERNEL_FLAG - 1));
187                         if(!h) {
188                                 Log_Warning("VFS", "VFS_SaveHandles - Invalid FD %i",
189                                         FDs[i] & (VFS_KERNEL_FLAG - 1) );
190                                 free(ret);
191                                 return NULL;
192                         }
193                 }
194                 memcpy( &ret[i], h, sizeof(tVFS_Handle) );
195                 
196                 // Reference node
197                 if( !h->Node )
198                         continue ;
199                 if( h->Node->Type && h->Node->Type->Reference )
200                         h->Node->Type->Reference( h->Node );
201         }       
202
203         return ret;
204 }
205
206 void VFS_RestoreHandles(int NumFDs, void *Handles)
207 {
208         tVFS_Handle     *handles = Handles;
209          int    i;
210
211         // NULL = nothing to do
212         if( !Handles )
213                 return ;        
214
215         // Check if there is already a set of handles
216         if( MM_GetPhysAddr( (tVAddr)gaUserHandles ) != 0 )
217                 return ;
218         
219         
220         // Allocate user handle area
221         {
222                 Uint    addr, size;
223                  int    max_handles = *Threads_GetMaxFD();
224                 size = max_handles * sizeof(tVFS_Handle);
225                 for(addr = 0; addr < size; addr += 0x1000)
226                 {
227                         if( !MM_Allocate( (tVAddr)gaUserHandles + addr ) )
228                         {
229                                 Warning("OOM - VFS_AllocHandle");
230                                 Threads_Exit(0, 0xFF);  // Terminate user
231                         }
232                 }
233                 memset( gaUserHandles, 0, size );
234         }
235         
236         // Restore handles
237         memcpy( gaUserHandles, handles, NumFDs * sizeof(tVFS_Handle) );
238         // Reference when copied
239         for( i = 0; i < NumFDs; i ++ )
240         {
241                 tVFS_Handle     *h = &handles[i];
242         
243                 if( !h->Node )
244                         continue ;
245                 if( h->Node->Type && h->Node->Type->Reference )
246                         h->Node->Type->Reference( h->Node );
247         }
248 }
249
250 void VFS_FreeSavedHandles(int NumFDs, void *Handles)
251 {
252         tVFS_Handle     *handles = Handles;
253          int    i;
254
255         // NULL = nothing to do
256         if( !Handles )
257                 return ;        
258         
259         // Dereference all saved nodes
260         for( i = 0; i < NumFDs; i ++ )
261         {
262                 tVFS_Handle     *h = &handles[i];
263         
264                 if( !h->Node )
265                         continue ;
266                 if( h->Node->Type && h->Node->Type->Close )
267                         h->Node->Type->Close( h->Node );
268         }
269         free( Handles );
270 }

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