1 /**********************************************************************
3 * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful but, except
10 * as otherwise stated in writing, without any warranty; without even the
11 * implied warranty of merchantability or fitness for a particular purpose.
12 * See the GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18 * The full GNU General Public License is included in this distribution in
19 * the file called "COPYING".
21 * Contact Information:
22 * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23 * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
25 ******************************************************************************/
27 #include "services_headers.h"
31 #include "osperproc.h"
33 #define HASH_TAB_INIT_SIZE 32
35 static struct HASH_TABLE *psHashTab;
37 static enum PVRSRV_ERROR FreePerProcessData(
38 struct PVRSRV_PER_PROCESS_DATA *psPerProc)
40 enum PVRSRV_ERROR eError;
43 PVR_ASSERT(psPerProc != NULL);
45 if (psPerProc == NULL) {
46 PVR_DPF(PVR_DBG_ERROR,
47 "FreePerProcessData: invalid parameter");
48 return PVRSRV_ERROR_INVALID_PARAMS;
51 uiPerProc = HASH_Remove(psHashTab, (u32)psPerProc->ui32PID);
53 PVR_DPF(PVR_DBG_ERROR, "FreePerProcessData: "
54 "Couldn't find process in per-process data hash table");
56 PVR_ASSERT(psPerProc->ui32PID == 0);
58 PVR_ASSERT((struct PVRSRV_PER_PROCESS_DATA *)
59 uiPerProc == psPerProc);
60 PVR_ASSERT(((struct PVRSRV_PER_PROCESS_DATA *)uiPerProc)->
61 ui32PID == psPerProc->ui32PID);
64 if (psPerProc->psHandleBase != NULL) {
65 eError = PVRSRVFreeHandleBase(psPerProc->psHandleBase);
66 if (eError != PVRSRV_OK) {
67 PVR_DPF(PVR_DBG_ERROR, "FreePerProcessData: "
68 "Couldn't free handle base for process (%d)",
74 if (psPerProc->hPerProcData != NULL) {
76 PVRSRVReleaseHandle(KERNEL_HANDLE_BASE,
77 psPerProc->hPerProcData,
78 PVRSRV_HANDLE_TYPE_PERPROC_DATA);
80 if (eError != PVRSRV_OK) {
81 PVR_DPF(PVR_DBG_ERROR, "FreePerProcessData: "
82 "Couldn't release per-process data handle (%d)",
88 eError = OSPerProcessPrivateDataDeInit(psPerProc->hOsPrivateData);
89 if (eError != PVRSRV_OK) {
90 PVR_DPF(PVR_DBG_ERROR, "FreePerProcessData: "
91 "OSPerProcessPrivateDataDeInit failed (%d)",
96 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(*psPerProc), psPerProc,
97 psPerProc->hBlockAlloc);
102 struct PVRSRV_PER_PROCESS_DATA *PVRSRVPerProcessData(u32 ui32PID)
104 struct PVRSRV_PER_PROCESS_DATA *psPerProc;
106 PVR_ASSERT(psHashTab != NULL);
109 (struct PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab,
114 enum PVRSRV_ERROR PVRSRVPerProcessDataConnect(u32 ui32PID)
116 struct PVRSRV_PER_PROCESS_DATA *psPerProc;
118 enum PVRSRV_ERROR eError = PVRSRV_OK;
120 PVR_ASSERT(psHashTab != NULL);
122 psPerProc = (struct PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab,
124 if (psPerProc == NULL) {
125 eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
126 sizeof(*psPerProc), (void **)&psPerProc,
128 if (eError != PVRSRV_OK) {
129 PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: "
130 "Couldn't allocate per-process data (%d)",
134 OSMemSet(psPerProc, 0, sizeof(*psPerProc));
135 psPerProc->hBlockAlloc = hBlockAlloc;
137 if (!HASH_Insert(psHashTab, (u32) ui32PID, (u32)psPerProc)) {
138 PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: "
139 "Couldn't insert per-process data into hash table");
140 eError = PVRSRV_ERROR_GENERIC;
144 psPerProc->ui32PID = ui32PID;
145 psPerProc->ui32RefCount = 0;
148 OSPerProcessPrivateDataInit(&psPerProc->hOsPrivateData);
149 if (eError != PVRSRV_OK) {
150 PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: "
151 "OSPerProcessPrivateDataInit failed (%d)",
156 eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
157 &psPerProc->hPerProcData,
159 PVRSRV_HANDLE_TYPE_PERPROC_DATA,
160 PVRSRV_HANDLE_ALLOC_FLAG_NONE);
161 if (eError != PVRSRV_OK) {
162 PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: "
163 "Couldn't allocate handle for per-process data (%d)",
168 eError = PVRSRVAllocHandleBase(&psPerProc->psHandleBase);
169 if (eError != PVRSRV_OK) {
170 PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: "
171 "Couldn't allocate handle base for process (%d)",
176 eError = OSPerProcessSetHandleOptions(psPerProc->psHandleBase);
177 if (eError != PVRSRV_OK) {
178 PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: "
179 "Couldn't set handle options (%d)",
185 PVRSRVResManConnect(psPerProc, &psPerProc->hResManContext);
186 if (eError != PVRSRV_OK) {
187 PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: "
188 "Couldn't register with the resource manager");
193 psPerProc->ui32RefCount++;
194 PVR_DPF(PVR_DBG_MESSAGE,
195 "PVRSRVPerProcessDataConnect: Process 0x%x has ref-count %d",
196 ui32PID, psPerProc->ui32RefCount);
201 (void)FreePerProcessData(psPerProc);
205 void PVRSRVPerProcessDataDisconnect(u32 ui32PID)
207 enum PVRSRV_ERROR eError;
208 struct PVRSRV_PER_PROCESS_DATA *psPerProc;
210 PVR_ASSERT(psHashTab != NULL);
212 psPerProc = (struct PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab,
214 if (psPerProc == NULL) {
215 PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataDealloc: "
216 "Couldn't locate per-process data for PID %u",
219 psPerProc->ui32RefCount--;
220 if (psPerProc->ui32RefCount == 0) {
221 PVR_DPF(PVR_DBG_MESSAGE,
222 "PVRSRVPerProcessDataDisconnect: "
223 "Last close from process 0x%x received",
226 PVRSRVResManDisconnect(psPerProc->hResManContext,
229 eError = FreePerProcessData(psPerProc);
230 if (eError != PVRSRV_OK)
231 PVR_DPF(PVR_DBG_ERROR,
232 "PVRSRVPerProcessDataDisconnect: "
233 "Error freeing per-process data");
237 eError = PVRSRVPurgeHandles(KERNEL_HANDLE_BASE);
238 if (eError != PVRSRV_OK)
239 PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataDisconnect: "
240 "Purge of global handle pool failed (%d)",
244 enum PVRSRV_ERROR PVRSRVPerProcessDataInit(void)
246 PVR_ASSERT(psHashTab == NULL);
248 psHashTab = HASH_Create(HASH_TAB_INIT_SIZE);
249 if (psHashTab == NULL) {
250 PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataInit: "
251 "Couldn't create per-process data hash table");
252 return PVRSRV_ERROR_GENERIC;
258 enum PVRSRV_ERROR PVRSRVPerProcessDataDeInit(void)
260 if (psHashTab != NULL) {
261 HASH_Delete(psHashTab);