Kernel - Implementing SysSpawn
[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         for( i = 0; i < max_handles; i ++ )
124         {
125                 tVFS_Handle     *h;
126                 h = &gaUserHandles[i];
127                 if( h->Node->Type && h->Node->Type->Reference )
128                         h->Node->Type->Reference( h->Node );
129         }
130 }
131
132 void VFS_CloseAllUserHandles(void)
133 {
134          int    i;
135          int    max_handles = *Threads_GetMaxFD();
136         
137         for( i = 0; i < max_handles; i ++ )
138         {
139                 tVFS_Handle     *h;
140                 h = &gaUserHandles[i];
141                 if( h->Node->Type && h->Node->Type->Close )
142                         h->Node->Type->Close( h->Node );
143         }
144 }
145
146 /**
147  * \brief Take a backup of a set of file descriptors
148  */
149 void *VFS_SaveHandles(int NumFDs, int *FDs)
150 {
151         tVFS_Handle     *ret;
152          int    i;
153         
154         // Check if this process has any handles
155         if( MM_GetPhysAddr( (tVAddr)gaUserHandles ) == 0 )
156                 return NULL;
157
158         // Allocate
159         ret = malloc( NumFDs * sizeof(tVFS_Handle) );
160         if( !ret )
161                 return NULL;    
162
163         // Take copies of the handles
164         for( i = 0; i < NumFDs; i ++ )
165         {
166                 tVFS_Handle     *h;
167                 h = VFS_GetHandle(FDs[i] & (VFS_KERNEL_FLAG - 1));
168                 if(!h) {
169                         Log_Warning("VFS", "VFS_SaveHandles - Invalid FD %i",
170                                 FDs[i] & (VFS_KERNEL_FLAG - 1) );
171                         free(ret);
172                         return NULL;
173                 }
174                 memcpy( &ret[i], h, sizeof(tVFS_Handle) );
175                 
176                 // Reference node
177                 if( h->Node->Type && h->Node->Type->Reference )
178                         h->Node->Type->Reference( h->Node );
179         }       
180
181         return ret;
182 }
183
184 void VFS_RestoreHandles(int NumFDs, void *Handles)
185 {
186         tVFS_Handle     *handles = Handles;
187          int    i;
188
189         // NULL = nothing to do
190         if( !Handles )
191                 return ;        
192
193         // Check if there is already a set of handles
194         if( MM_GetPhysAddr( (tVAddr)gaUserHandles ) != 0 )
195                 return ;
196         
197         
198         // Allocate user handle area
199         {
200                 Uint    addr, size;
201                  int    max_handles = *Threads_GetMaxFD();
202                 size = max_handles * sizeof(tVFS_Handle);
203                 for(addr = 0; addr < size; addr += 0x1000)
204                 {
205                         if( !MM_Allocate( (tVAddr)gaUserHandles + addr ) )
206                         {
207                                 Warning("OOM - VFS_AllocHandle");
208                                 Threads_Exit(0, 0xFF);  // Terminate user
209                         }
210                 }
211                 memset( gaUserHandles, 0, size );
212         }
213         
214         // Restore handles
215         memcpy( gaUserHandles, handles, NumFDs * sizeof(tVFS_Handle) );
216         // Reference when copied
217         for( i = 0; i < NumFDs; i ++ )
218         {
219                 tVFS_Handle     *h = &handles[i];
220         
221                 if( h->Node->Type && h->Node->Type->Reference )
222                         h->Node->Type->Reference( h->Node );
223         }
224 }
225
226 void VFS_FreeSavedHandles(int NumFDs, void *Handles)
227 {
228         tVFS_Handle     *handles = Handles;
229          int    i;
230         
231         // Dereference all saved nodes
232         for( i = 0; i < NumFDs; i ++ )
233         {
234                 tVFS_Handle     *h = &handles[i];
235         
236                 if( h->Node->Type && h->Node->Type->Close )
237                         h->Node->Type->Close( h->Node );
238         }
239         free( Handles );
240 }

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