]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - packages/ti/sdo/ipc/gates/GatePeterson.c
Rename: git mv src packages to complete application of ipc-j patches to ipcdev.
[ipc/ipcdev.git] / packages / ti / sdo / ipc / gates / GatePeterson.c
1 /*
2  * Copyright (c) 2012-2013, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 /*
33  *  ======== GatePeterson.c ========
34  */
36 #include <xdc/std.h>
37 #include <xdc/runtime/Error.h>
38 #include <xdc/runtime/Assert.h>
39 #include <xdc/runtime/IGateProvider.h>
40 #include <xdc/runtime/Gate.h>
41 #include <xdc/runtime/Log.h>
43 #include <ti/sdo/ipc/interfaces/IGateMPSupport.h>
45 #include <ti/sysbios/hal/Cache.h>
47 #include "package/internal/GatePeterson.xdc.h"
49 #include <ti/sdo/ipc/_Ipc.h>
50 #include <ti/sdo/utils/_MultiProc.h>
51 #include <ti/sdo/ipc/_SharedRegion.h>
53 /*
54  *************************************************************************
55  *                       Instance functions
56  *************************************************************************
57  */
59 /*
60  *  ======== GatePeterson_Instance_init ========
61  */
62 Int GatePeterson_Instance_init(GatePeterson_Object *obj,
63                                IGateProvider_Handle localGate,
64                                const GatePeterson_Params *params,
65                                Error_Block *eb)
66 {
67     Assert_isTrue(params->sharedAddr != NULL, ti_sdo_ipc_Ipc_A_invParam);
68     Assert_isTrue(GatePeterson_numInstances != NULL, ti_sdo_ipc_Ipc_A_invParam);
70     obj->localGate      = localGate;
71     obj->cacheEnabled   = SharedRegion_isCacheEnabled(params->regionId);
72     obj->cacheLineSize  = SharedRegion_getCacheLineSize(params->regionId);
74     /* Settings for both the creator and opener */
75     if (obj->cacheLineSize > sizeof(GatePeterson_Attrs)) {
76         obj->attrs   = params->sharedAddr;
77         obj->flag[0] = (Bits16 *)((UArg)(obj->attrs) + obj->cacheLineSize);
78         obj->flag[1] = (Bits16 *)((UArg)(obj->flag[0]) + obj->cacheLineSize);
79         obj->turn    = (Bits16 *)((UArg)(obj->flag[1]) + obj->cacheLineSize);
80     }
81     else {
82         obj->attrs   = params->sharedAddr;
83         obj->flag[0] = (Bits16 *)((UArg)(obj->attrs) +
84                         sizeof(GatePeterson_Attrs));
85         obj->flag[1] = (Bits16 *)((UArg)(obj->flag[0]) + sizeof(Bits16));
86         obj->turn    = (Bits16 *)((UArg)(obj->flag[1]) + sizeof(Bits16));
87     }
88     obj->nested  = 0;
90     if (!params->openFlag) {
91         /* Creating. */
92         obj->selfId = 0;
93         obj->otherId = 1;
94         obj->objType = ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC;
95         GatePeterson_postInit(obj);
96     }
97     else {
98         /* Opening. */
99         obj->objType = ti_sdo_ipc_Ipc_ObjType_OPENDYNAMIC;
101         Cache_inv((Ptr)obj->attrs, sizeof(GatePeterson_Attrs), Cache_Type_ALL,
102                   TRUE);
104         if (obj->attrs->creatorProcId == MultiProc_self()) {
105             /* Opening locally */
106             obj->selfId         = 0;
107             obj->otherId        = 1;
108         }
109         else {
110             /* Trying to open a gate remotely */
111             obj->selfId         = 1;
112             obj->otherId        = 0;
113             if (obj->attrs->openerProcId == MultiProc_INVALIDID) {
114                 /* Opening remotely for the first time */
115                 obj->attrs->openerProcId    = MultiProc_self();
116             }
117             else if (obj->attrs->openerProcId != MultiProc_self()) {
118                 Error_raise(eb, GatePeterson_E_gateRemotelyOpened,
119                             obj->attrs->creatorProcId,
120                             obj->attrs->openerProcId);
121             }
123             if (obj->cacheEnabled) {
124                 Cache_wbInv((Ptr)obj->attrs, sizeof(GatePeterson_Attrs),
125                             Cache_Type_ALL, TRUE);
126             }
127         }
128     }
130     return (0);
133 /*
134  *  ======== GatePeterson_Instance_finalize ========
135  */
136 Void GatePeterson_Instance_finalize(GatePeterson_Object *obj, Int status)
138     if (!status) {
139         /* Modify shared memory */
140         if (obj->objType == ti_sdo_ipc_Ipc_ObjType_OPENDYNAMIC) {
141             obj->attrs->openerProcId = MultiProc_INVALIDID;
142             Cache_wbInv(obj->attrs, sizeof(GatePeterson_Attrs), Cache_Type_ALL,
143                         TRUE);
144         }
145     }
148 /*
149  *  ======== GatePeterson_enter ========
150  */
151 IArg GatePeterson_enter(GatePeterson_Object *obj)
153     IArg key;
155     /* Enter local gate */
156     key = IGateProvider_enter(obj->localGate);
158     /* If the gate object has already been entered, return the key */
159     obj->nested++;
160     if (obj->nested > 1) {
161         return (key);
162     }
164     /* Indicate that we need to use the resource. */
165     *(obj->flag[obj->selfId]) = GatePeterson_BUSY ;
166     if (obj->cacheEnabled) {
167         Cache_wbInv((Ptr)obj->flag[obj->selfId], obj->cacheLineSize,
168             Cache_Type_ALL, TRUE);
169     }
171     /* Give away the turn. */
172     *(obj->turn) = obj->otherId;
174     if (obj->cacheEnabled) {
175         Cache_wbInv((Ptr)obj->turn, obj->cacheLineSize, Cache_Type_ALL, TRUE);
176         Cache_inv((Ptr)obj->flag[obj->otherId], obj->cacheLineSize,
177             Cache_Type_ALL, TRUE);
178     }
180     /* Wait while other process is using the resource and has the turn. */
181     while ((*(obj->flag[obj->otherId]) == GatePeterson_BUSY) &&
182         (*(obj->turn) == obj->otherId)) {
183         if (obj->cacheEnabled) {
184             Cache_inv((Ptr)obj->flag[obj->otherId], obj->cacheLineSize,
185                 Cache_Type_ALL, FALSE);
186             Cache_inv((Ptr)obj->turn, obj->cacheLineSize, Cache_Type_ALL, TRUE);
187         }
188     }
190     return (key);
193 /*
194  *  ======== GatePeterson_leave ========
195  */
196 Void GatePeterson_leave(GatePeterson_Object *obj, IArg key)
198     /* Release the resource and leave system gate. */
199     obj->nested--;
200     if (obj->nested == 0) {
201         *(obj->flag[obj->selfId]) = GatePeterson_FREE;
202         if (obj->cacheEnabled) {
203             Cache_wbInv((Ptr)obj->flag[obj->selfId], obj->cacheLineSize,
204                 Cache_Type_ALL, TRUE);
205         }
206     }
208     /* Leave local gate */
209     IGateProvider_leave(obj->localGate, key);
212 /*
213  *************************************************************************
214  *                       Module functions
215  *************************************************************************
216  */
218 /*
219  *  ======== GatePeterson_getReservedMask ========
220  */
221 Bits32 *GatePeterson_getReservedMask()
223     /* This gate doesn't allow reserving resources */
224     return (NULL);
227 /*
228  *  ======== GatePeterson_sharedMemReq ========
229  */
230 SizeT GatePeterson_sharedMemReq(const IGateMPSupport_Params *params)
232     SizeT memReq;
234     if (SharedRegion_getCacheLineSize(params->regionId) >=
235         sizeof(GatePeterson_Attrs)) {
236         /*! 4 Because shared of shared memory usage (see GatePeterson.xdc) */
237         memReq = 4 * SharedRegion_getCacheLineSize(params->regionId);
238     }
239     else {
240         memReq = sizeof(GatePeterson_Attrs) + sizeof(Bits16) * 3;
241     }
243     return(memReq);
246 /*
247  *  ======== GatePeterson_query ========
248  */
249 Bool GatePeterson_query(Int qual)
251     Bool rc;
253     switch (qual) {
254         case IGateProvider_Q_BLOCKING:
255             /* GatePeterson is never blocking */
256             rc = FALSE;
257             break;
258         case IGateProvider_Q_PREEMPTING:
259             /* Depends on gate proxy? */
260             rc = TRUE;
261             break;
262         default:
263             rc = FALSE;
264             break;
265     }
267     return (rc);
270 /*
271  *************************************************************************
272  *                       Internal functions
273  *************************************************************************
274  */
275 /*
276  *  ======== GatePeterson_postInit ========
277  *  Function to be called during
278  *  1. module startup to complete the initialization of all static instances
279  *  2. instance_init to complete the initialization of a dynamic instance
280  *
281  *  Main purpose is to set up shared memory
282  */
283 Void GatePeterson_postInit(GatePeterson_Object *obj)
285     /* Set up shared memory */
286     *(obj->turn)       = 0;
287     *(obj->flag[0])    = 0;
288     *(obj->flag[1])    = 0;
289     obj->attrs->creatorProcId  = MultiProc_self();
290     obj->attrs->openerProcId   = MultiProc_INVALIDID;
292     /*
293      * Write everything back to memory. This assumes that obj->attrs is equal
294      * to the shared memory base address
295      */
296     if (obj->cacheEnabled) {
297         Cache_wbInv((Ptr)obj->attrs, sizeof(GatePeterson_Attrs), Cache_Type_ALL,
298             FALSE);
299         Cache_wbInv((Ptr)(obj->flag[0]), obj->cacheLineSize * 3, Cache_Type_ALL,
300             TRUE);
301     }