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 get_proc_name(ui32PID, psPerProc->name,
138 sizeof(psPerProc->name));
140 if (!HASH_Insert(psHashTab, (u32) ui32PID, (u32)psPerProc)) {
141 PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: "
142 "Couldn't insert per-process data into hash table");
143 eError = PVRSRV_ERROR_GENERIC;
147 psPerProc->ui32PID = ui32PID;
148 psPerProc->ui32RefCount = 0;
151 OSPerProcessPrivateDataInit(&psPerProc->hOsPrivateData);
152 if (eError != PVRSRV_OK) {
153 PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: "
154 "OSPerProcessPrivateDataInit failed (%d)",
159 eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
160 &psPerProc->hPerProcData,
162 PVRSRV_HANDLE_TYPE_PERPROC_DATA,
163 PVRSRV_HANDLE_ALLOC_FLAG_NONE);
164 if (eError != PVRSRV_OK) {
165 PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: "
166 "Couldn't allocate handle for per-process data (%d)",
171 eError = PVRSRVAllocHandleBase(&psPerProc->psHandleBase);
172 if (eError != PVRSRV_OK) {
173 PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: "
174 "Couldn't allocate handle base for process (%d)",
179 eError = OSPerProcessSetHandleOptions(psPerProc->psHandleBase);
180 if (eError != PVRSRV_OK) {
181 PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: "
182 "Couldn't set handle options (%d)",
188 PVRSRVResManConnect(psPerProc, &psPerProc->hResManContext);
189 if (eError != PVRSRV_OK) {
190 PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: "
191 "Couldn't register with the resource manager");
196 psPerProc->ui32RefCount++;
197 PVR_DPF(PVR_DBG_MESSAGE,
198 "PVRSRVPerProcessDataConnect: Process 0x%x has ref-count %d",
199 ui32PID, psPerProc->ui32RefCount);
204 (void)FreePerProcessData(psPerProc);
208 void PVRSRVPerProcessDataDisconnect(u32 ui32PID)
210 enum PVRSRV_ERROR eError;
211 struct PVRSRV_PER_PROCESS_DATA *psPerProc;
213 PVR_ASSERT(psHashTab != NULL);
215 psPerProc = (struct PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab,
217 if (psPerProc == NULL) {
218 PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataDealloc: "
219 "Couldn't locate per-process data for PID %u",
222 psPerProc->ui32RefCount--;
223 if (psPerProc->ui32RefCount == 0) {
224 PVR_DPF(PVR_DBG_MESSAGE,
225 "PVRSRVPerProcessDataDisconnect: "
226 "Last close from process 0x%x received",
229 PVRSRVResManDisconnect(psPerProc->hResManContext,
232 eError = FreePerProcessData(psPerProc);
233 if (eError != PVRSRV_OK)
234 PVR_DPF(PVR_DBG_ERROR,
235 "PVRSRVPerProcessDataDisconnect: "
236 "Error freeing per-process data");
240 eError = PVRSRVPurgeHandles(KERNEL_HANDLE_BASE);
241 if (eError != PVRSRV_OK)
242 PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataDisconnect: "
243 "Purge of global handle pool failed (%d)",
247 enum PVRSRV_ERROR PVRSRVPerProcessDataInit(void)
249 PVR_ASSERT(psHashTab == NULL);
251 psHashTab = HASH_Create(HASH_TAB_INIT_SIZE);
252 if (psHashTab == NULL) {
253 PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataInit: "
254 "Couldn't create per-process data hash table");
255 return PVRSRV_ERROR_GENERIC;
261 enum PVRSRV_ERROR PVRSRVPerProcessDataDeInit(void)
263 if (psHashTab != NULL) {
264 HASH_Delete(psHashTab);