64e8faf6476d417303078a192a6ea0948169ee29
[profile/ivi/intel-emgd-kmod.git] / pvr / services4 / srvkm / common / perproc.c
1 /**********************************************************************
2  Copyright (c) Imagination Technologies Ltd.
3
4  Permission is hereby granted, free of charge, to any person obtaining a copy
5  of this software and associated documentation files (the "Software"), to deal
6  in the Software without restriction, including without limitation the rights
7  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  copies of the Software, and to permit persons to whom the Software is
9  furnished to do so, subject to the following conditions:
10
11  The above copyright notice and this permission notice shall be included in
12  all copies or substantial portions of the Software.
13
14  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  THE SOFTWARE.
21  ******************************************************************************/
22
23 #include "services_headers.h"
24 #include "resman.h"
25 #include "handle.h"
26 #include "perproc.h"
27 #include "osperproc.h"
28
29 #define HASH_TAB_INIT_SIZE 32
30
31 static HASH_TABLE *psHashTab = IMG_NULL;
32
33 static PVRSRV_ERROR FreePerProcessData(PVRSRV_PER_PROCESS_DATA *psPerProc)
34 {
35         PVRSRV_ERROR eError;
36         IMG_UINTPTR_T uiPerProc;
37
38         PVR_ASSERT(psPerProc != IMG_NULL);
39
40         if (psPerProc == IMG_NULL)
41         {
42                 PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: invalid parameter"));
43                 return PVRSRV_ERROR_INVALID_PARAMS;
44         }
45
46         uiPerProc = HASH_Remove(psHashTab, (IMG_UINTPTR_T)psPerProc->ui32PID);
47         if (uiPerProc == 0)
48         {
49                 PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't find process in per-process data hash table"));
50
51                 PVR_ASSERT(psPerProc->ui32PID == 0);
52         }
53         else
54         {
55                 PVR_ASSERT((PVRSRV_PER_PROCESS_DATA *)uiPerProc == psPerProc);
56                 PVR_ASSERT(((PVRSRV_PER_PROCESS_DATA *)uiPerProc)->ui32PID == psPerProc->ui32PID);
57         }
58
59
60         if (psPerProc->psHandleBase != IMG_NULL)
61         {
62                 eError = PVRSRVFreeHandleBase(psPerProc->psHandleBase);
63                 if (eError != PVRSRV_OK)
64                 {
65                         PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't free handle base for process (%d)", eError));
66                         return eError;
67                 }
68         }
69
70
71         if (psPerProc->hPerProcData != IMG_NULL)
72         {
73                 eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE, psPerProc->hPerProcData, PVRSRV_HANDLE_TYPE_PERPROC_DATA);
74
75                 if (eError != PVRSRV_OK)
76                 {
77                         PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't release per-process data handle (%d)", eError));
78                         return eError;
79                 }
80         }
81
82
83         eError = OSPerProcessPrivateDataDeInit(psPerProc->hOsPrivateData);
84         if (eError != PVRSRV_OK)
85         {
86                  PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: OSPerProcessPrivateDataDeInit failed (%d)", eError));
87                 return eError;
88         }
89
90         eError = OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
91                 sizeof(*psPerProc),
92                 psPerProc,
93                 psPerProc->hBlockAlloc);
94
95         if (eError != PVRSRV_OK)
96         {
97                 PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't free per-process data (%d)", eError));
98                 return eError;
99         }
100
101         return PVRSRV_OK;
102 }
103
104
105 PVRSRV_PER_PROCESS_DATA *PVRSRVPerProcessData(IMG_UINT32 ui32PID)
106 {
107         PVRSRV_PER_PROCESS_DATA *psPerProc;
108
109         PVR_ASSERT(psHashTab != IMG_NULL);
110
111
112         psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
113         return psPerProc;
114 }
115
116
117 PVRSRV_ERROR PVRSRVPerProcessDataConnect(IMG_UINT32     ui32PID)
118 {
119         PVRSRV_PER_PROCESS_DATA *psPerProc;
120         IMG_HANDLE hBlockAlloc;
121         PVRSRV_ERROR eError = PVRSRV_OK;
122
123         PVR_ASSERT(psHashTab != IMG_NULL);
124
125
126         psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
127
128         if (psPerProc == IMG_NULL)
129         {
130
131                 eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
132                                                         sizeof(*psPerProc),
133                                                         (IMG_PVOID *)&psPerProc,
134                                                         &hBlockAlloc,
135                                                         "Per Process Data");
136                 if (eError != PVRSRV_OK)
137                 {
138                         PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate per-process data (%d)", eError));
139                         return eError;
140                 }
141                 OSMemSet(psPerProc, 0, sizeof(*psPerProc));
142                 psPerProc->hBlockAlloc = hBlockAlloc;
143
144                 if (!HASH_Insert(psHashTab, (IMG_UINTPTR_T)ui32PID, (IMG_UINTPTR_T)psPerProc))
145                 {
146                         PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't insert per-process data into hash table"));
147                         eError = PVRSRV_ERROR_GENERIC;
148                         goto failure;
149                 }
150
151                 psPerProc->ui32PID = ui32PID;
152                 psPerProc->ui32RefCount = 0;
153
154
155                 eError = OSPerProcessPrivateDataInit(&psPerProc->hOsPrivateData);
156                 if (eError != PVRSRV_OK)
157                 {
158                          PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: OSPerProcessPrivateDataInit failed (%d)", eError));
159                         goto failure;
160                 }
161
162
163                 eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
164                                                                    &psPerProc->hPerProcData,
165                                                                    psPerProc,
166                                                                    PVRSRV_HANDLE_TYPE_PERPROC_DATA,
167                                                                    PVRSRV_HANDLE_ALLOC_FLAG_NONE);
168                 if (eError != PVRSRV_OK)
169                 {
170                         PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate handle for per-process data (%d)", eError));
171                         goto failure;
172                 }
173
174
175                 eError = PVRSRVAllocHandleBase(&psPerProc->psHandleBase);
176                 if (eError != PVRSRV_OK)
177                 {
178                         PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate handle base for process (%d)", eError));
179                         goto failure;
180                 }
181
182
183                 eError = OSPerProcessSetHandleOptions(psPerProc->psHandleBase);
184                 if (eError != PVRSRV_OK)
185                 {
186                         PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't set handle options (%d)", eError));
187                         goto failure;
188                 }
189
190
191                 eError = PVRSRVResManConnect(psPerProc, &psPerProc->hResManContext);
192                 if (eError != PVRSRV_OK)
193                 {
194                         PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't register with the resource manager"));
195                         goto failure;
196                 }
197         }
198
199         psPerProc->ui32RefCount++;
200         PVR_DPF((PVR_DBG_MESSAGE,
201                         "PVRSRVPerProcessDataConnect: Process 0x%x has ref-count %d",
202                         ui32PID, psPerProc->ui32RefCount));
203
204         return eError;
205
206 failure:
207         (IMG_VOID)FreePerProcessData(psPerProc);
208         return eError;
209 }
210
211
212 IMG_VOID PVRSRVPerProcessDataDisconnect(IMG_UINT32      ui32PID)
213 {
214         PVRSRV_ERROR eError;
215         PVRSRV_PER_PROCESS_DATA *psPerProc;
216
217         PVR_ASSERT(psHashTab != IMG_NULL);
218
219         psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
220         if (psPerProc == IMG_NULL)
221         {
222                 PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataDealloc: Couldn't locate per-process data for PID %u", ui32PID));
223         }
224         else
225         {
226                 psPerProc->ui32RefCount--;
227                 if (psPerProc->ui32RefCount == 0)
228                 {
229                         PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVPerProcessDataDisconnect: "
230                                         "Last close from process 0x%x received", ui32PID));
231
232
233                         PVRSRVResManDisconnect(psPerProc->hResManContext, IMG_FALSE);
234
235
236                         eError = FreePerProcessData(psPerProc);
237                         if (eError != PVRSRV_OK)
238                         {
239                                 PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataDisconnect: Error freeing per-process data"));
240                         }
241                 }
242         }
243
244         eError = PVRSRVPurgeHandles(KERNEL_HANDLE_BASE);
245         if (eError != PVRSRV_OK)
246         {
247                 PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataDisconnect: Purge of global handle pool failed (%d)", eError));
248         }
249 }
250
251
252 PVRSRV_ERROR PVRSRVPerProcessDataInit(IMG_VOID)
253 {
254         PVR_ASSERT(psHashTab == IMG_NULL);
255
256
257         psHashTab = HASH_Create(HASH_TAB_INIT_SIZE);
258         if (psHashTab == IMG_NULL)
259         {
260                 PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataInit: Couldn't create per-process data hash table"));
261                 return PVRSRV_ERROR_GENERIC;
262         }
263
264         return PVRSRV_OK;
265 }
266
267 PVRSRV_ERROR PVRSRVPerProcessDataDeInit(IMG_VOID)
268 {
269
270         if (psHashTab != IMG_NULL)
271         {
272
273                 HASH_Delete(psHashTab);
274                 psHashTab = IMG_NULL;
275         }
276
277         return PVRSRV_OK;
278 }
279