]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - qnx/src/api/gates/GateMP.c
GateMP: Introduce support for GateMP on QNX
[ipc/ipcdev.git] / qnx / src / api / gates / GateMP.c
1 /*
2  * Copyright (c) 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  *  ======== GateMP.c ========
34  */
35 #include <ti/ipc/Std.h>
37 #include <stdlib.h>
38 #include <string.h>
40 #include <pthread.h>
41 #include <assert.h>
43 #include <ti/ipc/GateMP.h>
44 #include <ti/ipc/NameServer.h>
45 #include <ti/ipc/MultiProc.h>
47 #include <GateMP_config.h>
49 #include <_GateMP.h>
50 #include <_IpcLog.h>
52 #include <_GateMP_usr.h>
54 #include <ti/syslink/inc/IoctlDefs.h>
55 #include <ti/syslink/inc/usr/Qnx/GateMPDrv.h>
56 #include <ti/syslink/inc/GateMPDrvDefs.h>
58 /* structure for GateMP module state */
59 typedef struct {
60     GateMP_Params       defaultInstParams;
61     /* Default instance creation parameters */
62     GateMP_Handle       defaultGate;
63     /* Handle to default gate */
64     NameServer_Handle   nameServer;
65     /* NameServer for GateMP instances */
66     Bool                isStarted;
67     /* Has GateMP been started */
68     pthread_mutex_t     mutex;
69     /* Mutex for use on local process to serialize access to gate obj */
70     GateMP_Object **    remoteSystemGates;
71     /* Remote system gates */
72     Int                 numRemoteSystem;
73     /* Number of remote system gates */
74 } GateMP_ModuleObject;
77 static Bool verbose = FALSE;
79 /* Internal structure defining parameters for GateMP_Instance_init */
80 typedef struct {
81     String name;                        /* Name of instance */
82     UInt16 regionId;                    /* not used on host*/
83     Ptr sharedAddr;                     /* not used on host*/
84     GateMP_LocalProtect localProtect;   /* Local protection level  */
85     GateMP_RemoteProtect remoteProtect; /* Remote protection level */
86     UInt32 resourceId;                  /* resource id */
87     Bool openFlag;                      /* Is this open or create? */
88 } _GateMP_Params;
90 static Int GateMP_getNumResources(GateMP_RemoteProtect type);
91 static Int GateMP_getFreeResource(GateMP_RemoteProtect type);
92 static Int GateMP_releaseResource(UInt id, GateMP_RemoteProtect type);
93 static GateMP_Handle _GateMP_create (const _GateMP_Params * params);
94 static Int GateMP_Instance_init(GateMP_Object *obj,
95     const _GateMP_Params *params);
96 static Void GateMP_Instance_finalize(GateMP_Object *obj, Int status);
98 /* -----------------------------------------------------------------------------
99  * Globals
100  * -----------------------------------------------------------------------------
101  */
102 static GateMP_ModuleObject GateMP_state =
104     .remoteSystemGates  = NULL,
105     .defaultGate        = NULL,
106     .nameServer         = NULL,
107     .mutex              = PTHREAD_MUTEX_INITIALIZER,
108 //    .gateMutex          = NULL,
109 //    .gateProcess        = NULL
110 };
112 static GateMP_ModuleObject *GateMP_module = &GateMP_state;
114 static GateMP_Params GateMP_defInstParams =
116     .name           = NULL,
117     .regionId       = 0,
118     .sharedAddr     = NULL,
119     .localProtect   = GateMP_LocalProtect_PROCESS,
120     .remoteProtect  = GateMP_RemoteProtect_SYSTEM
121 };
123 Int GateMP_start(Void)
125     Int status;
126     GateMPDrv_CmdArgs cmdArgs;
128     status = GateMPDrv_ioctl(CMD_GATEMP_START, &cmdArgs);
129     if (status < 0) {
130         PRINTVERBOSE1("GateMP_start: API (through IOCTL) failed, \
131             status=%d\n", status)
132     }
133     else {
134         /*
135          * Initialize module state. Note that Nameserver handles are compatible
136          * across processes.
137          */
138         GateMP_module->nameServer = cmdArgs.args.start.nameServerHandle;
139     }
141     /* allocate memory for remote system gate handles */
142     if (status == GateMP_S_SUCCESS) {
143         GateMP_module->numRemoteSystem =
144             GateMP_getNumResources(GateMP_RemoteProtect_SYSTEM);
145         if (GateMP_module->numRemoteSystem > 0) {
146             GateMP_module->remoteSystemGates = calloc(1,
147                 GateMP_module->numRemoteSystem *
148                 sizeof(IGateProvider_Handle));
150             if (GateMP_module->remoteSystemGates == NULL) {
151                 status = GateMP_E_MEMORY;
152                 PRINTVERBOSE0("GateMP_start: memory allocation failed")
153             }
154         }
155         else {
156             GateMP_module->remoteSystemGates = NULL;
157         }
158     }
160     if (status == GateMP_S_SUCCESS) {
161         /* Open default gate */
162         status = GateMP_open("_GateMP_TI_dGate", &GateMP_module->defaultGate);
163         if (status < 0) {
164             PRINTVERBOSE1("GateMP_start: could not open default gate, \
165                 status=%d\n", status)
166         }
167     }
169     /* in failure case, release acquired resources in reverse order */
170     if (status < 0) {
171         GateMP_stop();
172     }
174     GateMP_module->isStarted = TRUE;
176     return status;
179 Int GateMP_stop(Void)
181     Int status = GateMP_S_SUCCESS;
183     PRINTVERBOSE0("GateMP_stop: entered\n")
185     /* close the default gate */
186     if (GateMP_module->defaultGate) {
187         GateMP_close(&GateMP_module->defaultGate);
188         GateMP_module->defaultGate = NULL;
189     }
191     /* free system gate array */
192     if (GateMP_module->remoteSystemGates != NULL) {
193         free(GateMP_module->remoteSystemGates);
194         GateMP_module->remoteSystemGates = NULL;
195     }
197     GateMP_module->isStarted = FALSE;
199     return status;
202 Void GateMP_Params_init(GateMP_Params *params)
204     if (params != NULL) {
205         memcpy(params, &GateMP_defInstParams, sizeof(GateMP_Params));
206     }
207     else {
208         PRINTVERBOSE0("GateMP_Params_init: Params argument cannot be NULL")
209     }
211     return;
214 GateMP_Handle GateMP_create(const GateMP_Params *params)
216     _GateMP_Params      _params;
217     GateMP_Handle       handle = NULL;
219     if (GateMP_module->isStarted == FALSE) {
220         PRINTVERBOSE0("GateMP_create: GateMP module has not been started!")
221     }
222     else {
223         memset(&_params, 0, sizeof(_GateMP_Params));
224         memcpy(&_params, params, sizeof(GateMP_Params));
226         handle = _GateMP_create(&_params);
227     }
229     return(handle);
232 static GateMP_Handle _GateMP_create(const _GateMP_Params *params)
234     GateMP_Handle       handle = NULL;
235     GateMP_Object *     obj = NULL;
236     Int                 status;
238     /* allocate the instance object */
239     obj = (GateMP_Object *)calloc(1, sizeof(GateMP_Object));
241     if (obj != NULL) {
242         status = GateMP_Instance_init(obj, params);
243         if (status < 0) {
244             free(obj);
245         }
246         else {
247             handle = (GateMP_Handle)obj;
248         }
249     }
250     else {
251         PRINTVERBOSE0("GateMP_create: Memory allocation failed")
252     }
254     return(handle);
257 Int GateMP_open(String name, GateMP_Handle *handle)
259     Int             status = GateMP_S_SUCCESS;
260     UInt32          len;
261     UInt32          nsValue[4];
262     GateMP_Object * obj = NULL;
263     UInt32          arg;
264     UInt32          mask;
265     UInt32          creatorProcId;
266     _GateMP_Params  params;
268     /* assert that a valid pointer has been supplied */
269     if (handle == NULL) {
270         PRINTVERBOSE0("GateMP_open: handle cannot be null")
271         status = GateMP_E_INVALIDARG;
272     }
274     if (status == GateMP_S_SUCCESS) {
275         len = sizeof(nsValue);
277         status = NameServer_get(GateMP_module->nameServer, name, &nsValue,
278             &len, NULL);
280         if (status < 0) {
281             *handle = NULL;
282             status = GateMP_E_NOTFOUND;
283         }
284         else {
285             arg = nsValue[2];
286             mask = nsValue[3];
287             creatorProcId = nsValue[1] >> 16;
288         }
289     }
291     if (status == GateMP_S_SUCCESS) {
292         /*
293          * The least significant bit of nsValue[1] == 0 means its a
294          * local (private) GateMP, otherwise its a remote (shared) GateMP.
295          */
296         if ((nsValue[1] & 0x1) == 0) {
297             if ((nsValue[1] >> 16) != MultiProc_self()) {
298                 /* error: trying to open another processor's private gate */
299                 *handle = NULL;
300                 PRINTVERBOSE0("GateMP_open: cannot open private gate from \
301                     another processor")
302                 status = GateMP_E_FAIL;
303             }
304             else if (nsValue[0] != getpid()) {
305                 /* error: trying to open another process's private gate */
306                 *handle = NULL;
307                 PRINTVERBOSE0("GateMP_open: cannot open private gate from \
308                     another process")
309                 status = GateMP_E_FAIL;
310             }
311         }
312     }
314     if (status == GateMP_S_SUCCESS) {
315         /* local gate */
316         if (GETREMOTE(mask) == GateMP_RemoteProtect_NONE) {
317             if (creatorProcId != MultiProc_self()) {
318                 status = GateMP_E_FAIL;
319             }
320             else {
321                 *handle = (GateMP_Handle)arg;
322                 obj = (GateMP_Object *)(*handle);
323                 pthread_mutex_lock(&GateMP_module->mutex);
324                 obj->numOpens++;
325                 pthread_mutex_unlock(&GateMP_module->mutex);
326             }
327         }
328         else {
329             /* remote case */
330             switch (GETREMOTE(mask)) {
331                 case GateMP_RemoteProtect_SYSTEM:
332                 case GateMP_RemoteProtect_CUSTOM1:
333                 case GateMP_RemoteProtect_CUSTOM2:
334                     obj = GateMP_module->remoteSystemGates[arg];
335                     break;
337                 default:
338                     status = GateMP_E_FAIL;
339                     PRINTVERBOSE0("GateMP_open: unsupported remote protection \
340                         type")
341                     break;
342             }
344             /*  If the object is NULL, then it must have been created
345              *  on a remote processor or in another process on the
346              *  local processor. Need to create a local object. This is
347              *  accomplished by setting the openFlag to TRUE.
348              */
349             if (status == GateMP_S_SUCCESS) {
350                 if (obj == NULL) {
351                     /* create a GateMP object with the openFlag set to true */
352                     params.name = NULL;
353                     params.openFlag = TRUE;
354                     params.sharedAddr = NULL;
355                     params.resourceId = arg;
356                     params.localProtect = GETLOCAL(mask);
357                     params.remoteProtect = GETREMOTE(mask);
359                     obj = (GateMP_Object *)_GateMP_create(&params);
361                     if (obj == NULL) {
362                         status = GateMP_E_FAIL;
363                     }
364                 }
365                 else {
366                     pthread_mutex_lock(&GateMP_module->mutex);
367                     obj->numOpens++;
368                     pthread_mutex_unlock(&GateMP_module->mutex);
369                 }
370             }
372             /* Return the "opened" GateMP instance  */
373             *handle = (GateMP_Handle)obj;
374         }
375     }
377     return status;
380 GateMP_Handle GateMP_getDefaultRemote()
382     return(GateMP_module->defaultGate);
385 GateMP_LocalProtect GateMP_getLocalProtect(GateMP_Handle handle)
387     GateMP_Object *obj;
389     obj = (GateMP_Object *)handle;
390     return(obj->localProtect);
393 GateMP_RemoteProtect GateMP_getRemoteProtect(GateMP_Handle handle)
395     GateMP_Object *obj;
397     obj = (GateMP_Object *)handle;
398     return (obj->remoteProtect);
401 static Int GateMP_getNumResources(GateMP_RemoteProtect type)
403     Int status;
404     GateMPDrv_CmdArgs cmdArgs;
406     cmdArgs.args.getNumResources.type = type;
407     status = GateMPDrv_ioctl(CMD_GATEMP_GETNUMRES, &cmdArgs);
409     if (status < 0) {
410         PRINTVERBOSE1("GateMP_getNumResources: API (through IOCTL) failed, \
411             status=%d\n", status)
412         return -1;
413     }
415     return (cmdArgs.args.getNumResources.value);
418 static Int GateMP_getFreeResource(GateMP_RemoteProtect type)
420     Int status;
421     GateMPDrv_CmdArgs cmdArgs;
423     cmdArgs.args.getFreeResource.type = type;
424     status = GateMPDrv_ioctl(CMD_GATEMP_GETFREERES, &cmdArgs);
426     if (status < 0) {
427         PRINTVERBOSE1("GateMP_getFreeResource: API (through IOCTL) failed, \
428             status=%d\n", status)
429         return -1;
430     }
432     return (cmdArgs.args.getFreeResource.id);
435 static Int GateMP_releaseResource(UInt id, GateMP_RemoteProtect type)
437     Int status;
438     GateMPDrv_CmdArgs cmdArgs;
440     cmdArgs.args.releaseResource.type = type;
441     cmdArgs.args.releaseResource.id   = id;
442     status = GateMPDrv_ioctl(CMD_GATEMP_RELRES, &cmdArgs);
444     if (status < 0) {
445         PRINTVERBOSE1("GateMP_releaseResource: API (through IOCTL) failed, \
446             status=%d\n", status)
447     }
449     return (status);
452 Bool GateMP_isSetup(Void)
454     Int status;
455     GateMPDrv_CmdArgs cmdArgs;
457     cmdArgs.args.isSetup.result = FALSE;
458     status = GateMPDrv_ioctl(CMD_GATEMP_ISSETUP, &cmdArgs);
460     if (status < 0) {
461         PRINTVERBOSE1("GateMP_isSetup: API (through IOCTL) failed, \
462             status=%d\n", status)
463     }
465     assert(status == GateMP_S_SUCCESS);
467     return (cmdArgs.args.isSetup.result);
470 Int GateMP_close(GateMP_Handle *handle)
472     GateMP_Object * obj;
473     Int             status = GateMP_S_SUCCESS;
475     obj = (GateMP_Object *)(*handle);
477     pthread_mutex_lock(&GateMP_module->mutex);
479     /*  Cannot call with the numOpens equal to zero.  This is either
480      *  a created handle or been closed already.
481      */
482     if (obj->numOpens == 0) {
483         status = GateMP_E_INVALIDSTATE;
484     }
486     if (status == GateMP_S_SUCCESS) {
487         obj->numOpens--;
489         /*  If the count is zero and the gate is opened, then this
490          *  object was created in the open (i.e. the create happened
491          *  on a remote processor or another process).
492          */
493         if ((obj->numOpens == 0) && (obj->objType == Ipc_ObjType_OPENDYNAMIC)) {
494             GateMP_delete(handle);
495         }
496         else {
497             *handle = NULL;
498         }
499     }
501     pthread_mutex_unlock(&GateMP_module->mutex);
503     return(status);
506 Int GateMP_delete(GateMP_Handle *handlePtr)
508     Int               status = GateMP_S_SUCCESS;
510     if ((handlePtr == NULL) || (*handlePtr == NULL)) {
511         status =  GateMP_E_INVALIDARG;
512     }
513     else {
514         GateMP_Instance_finalize((GateMP_Object *)(*handlePtr), 0);
515         free(*handlePtr);
516         *handlePtr = NULL;
517     }
519     return status;
522 static Int GateMP_Instance_init(GateMP_Object *obj,
523     const _GateMP_Params *params)
525     GateMP_RemoteSystemProxy_Params     systemParams;
526     UInt32                              nsValue[4];
527     Int                                 status;
529     status = 0;
531     obj->resourceId = (UInt)-1;
533     /* TODO: create/open the local gate instance */
534     obj->localGate = NULL;
536     /* open GateMP instance */
537     if (params->openFlag == TRUE) {
538         /* all open work done here except for remote gateHandle */
539         obj->localProtect  = params->localProtect;
540         obj->remoteProtect = params->remoteProtect;
541         obj->nsKey         = 0;
542         obj->numOpens      = 1;
544         obj->objType       = Ipc_ObjType_OPENDYNAMIC;
545     }
547     /* create GateMP instance */
548     else {
549         obj->localProtect  = params->localProtect;
550         obj->remoteProtect = params->remoteProtect;
551         obj->nsKey         = 0;
552         obj->numOpens      = 0;
554         if (obj->remoteProtect == GateMP_RemoteProtect_NONE) {
555             /* TODO: create a local gate */
556             obj->gateHandle = obj->localGate;
558             /* create a local gate allocating from the local heap */
559             obj->objType = Ipc_ObjType_LOCAL;
560             obj->arg = (Bits32)obj;
561             obj->mask = SETMASK(obj->remoteProtect, obj->localProtect);
562             obj->creatorProcId = MultiProc_self();
564             if (params->name != NULL) {
565                 /*  nsv[0]       : creator process id
566                  *  nsv[1](31:16): creator procId
567                  *  nsv[1](15:0) : 0 = local gate, 1 = remote gate
568                  *  nsv[2]       : local gate object
569                  *  nsv[3]       : protection mask
570                  */
571                 nsValue[0] = getpid();
572                 nsValue[1] = MultiProc_self() << 16;
573                 nsValue[2] = obj->arg;
574                 nsValue[3] = obj->mask;
575                 obj->nsKey = NameServer_add(GateMP_module->nameServer,
576                         params->name, &nsValue, sizeof(nsValue));
577                 if (obj->nsKey == NULL) {
578                     PRINTVERBOSE0("GateMP_Instance_init: NameServer_add failed")
579                     return (GateMP_E_FAIL);
580                 }
581             }
583             /* nothing else to do for local gates */
584             return(0);
585         }
587         obj->objType = Ipc_ObjType_CREATEDYNAMIC;
588     }
590     /* proxy work for open and create done here */
591     switch (obj->remoteProtect) {
592         /* TODO: implement other types of remote protection */
593         case GateMP_RemoteProtect_SYSTEM:
594         case GateMP_RemoteProtect_CUSTOM1:
595         case GateMP_RemoteProtect_CUSTOM2:
596             if (obj->objType == Ipc_ObjType_OPENDYNAMIC) {
597                 /* resourceId set by open call */
598                 obj->resourceId = params->resourceId;
599             }
600             else {
601                 /* created instance */
602                 obj->resourceId = GateMP_getFreeResource(obj->remoteProtect);
603                 if (obj->resourceId == -1) {
604                     return (GateMP_E_RESOURCE);
605                 }
606             }
608             /* create the proxy object */
609             GateMP_RemoteSystemProxy_Params_init(&systemParams);
610             systemParams.resourceId = obj->resourceId;
611             systemParams.openFlag = (obj->objType == Ipc_ObjType_OPENDYNAMIC);
612             //systemParams.sharedAddr = obj->proxyAttrs;
614             /*
615              * TODO: Currently passing in localProtect instead of localGate,
616              * since existing GateHWSpinlock.h defines it this way
617              */
618             obj->gateHandle = (IGateProvider_Handle)
619                 GateMP_RemoteSystemProxy_create(obj->localProtect,
620                     &systemParams);
622             if (obj->gateHandle == NULL) {
623                 PRINTVERBOSE0("GateMP_Instance_init: failed to create proxy\n");
624                 return(GateMP_E_FAIL);
625             }
627             /* store the object handle in the gate array */
628             GateMP_module->remoteSystemGates[obj->resourceId] = obj;
629             break;
631         default:
632             break;
633     }
635     /* add name/attrs to NameServer table */
636     if (obj->objType != Ipc_ObjType_OPENDYNAMIC) {
637         obj->arg = obj->resourceId;
638         obj->mask = SETMASK(obj->remoteProtect, obj->localProtect);
640         if (params->name != NULL) {
641             /*  nsv[0]       : creator pid
642              *  nsv[1](31:16): creator procId
643              *  nsv[1](15:0) : 0 = local gate, 1 = remote gate
644              *  nsv[2]       : resource id
645              *  nsv[3]       : protection mask
646              */
647             nsValue[0] = getpid();
648             nsValue[1] = MultiProc_self() << 16 | 1;
649             nsValue[2] = obj->resourceId;
650             nsValue[3] = obj->mask;
651             obj->nsKey = NameServer_add(GateMP_module->nameServer,
652                     params->name, &nsValue, sizeof(nsValue));
654             if (obj->nsKey == NULL) {
655                 PRINTVERBOSE0("GateMP_Instance_init: NameServer_add failed")
656                 return (GateMP_E_FAIL);
657             }
658         }
659     }
661     return (GateMP_S_SUCCESS);
664 static Void GateMP_Instance_finalize(GateMP_Object *obj, Int status)
666     GateMP_Object ** remoteGates = NULL;
668     /* remove from NameServer */
669     if (obj->nsKey != 0) {
670         NameServer_removeEntry(GateMP_module->nameServer, obj->nsKey);
671         obj->nsKey = 0;
672     }
674     /* delete the remote gate */
675     switch (obj->remoteProtect) {
677         case GateMP_RemoteProtect_SYSTEM:
678         case GateMP_RemoteProtect_CUSTOM1:
679         case GateMP_RemoteProtect_CUSTOM2:
680             if (obj->gateHandle != NULL) {
681                 GateMP_RemoteSystemProxy_delete(
682                         (GateMP_RemoteSystemProxy_Handle *)&obj->gateHandle);
683             }
684             remoteGates = GateMP_module->remoteSystemGates;
685             break;
687         case GateMP_RemoteProtect_NONE:
688             /*  nothing else to finalize */
689             return;
691         default:
692             /* Nothing to do */
693             break;
694     }
696     /* TODO: close/delete local gate */
698     /* clear the handle array entry in local memory */
699     if (obj->resourceId != (UInt)-1) {
700         remoteGates[obj->resourceId] = NULL;
701     }
703     if ((obj->objType != Ipc_ObjType_OPENDYNAMIC)
704         && (obj->resourceId != (UInt)-1)) {
705         GateMP_releaseResource(obj->resourceId, obj->remoteProtect);
706     }
710 IArg GateMP_enter(GateMP_Handle handle)
712     GateMP_Object * obj;
713     IArg            key;
715     obj = (GateMP_Object *)handle;
716     key = IGateProvider_enter(obj->gateHandle);
718     return(key);
721 Void GateMP_leave(GateMP_Handle handle, IArg key)
723     GateMP_Object *obj;
725     obj = (GateMP_Object *)handle;
726     IGateProvider_leave(obj->gateHandle, key);