Add support for IPC_DEBUG in QNX
[ipc/ipcdev.git] / qnx / src / api / gates / GateMP.c
1 /*
2  * Copyright (c) 2013-2015, 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;
76 /* traces in this file are controlled via _GateMP_verbose */
77 Bool _GateMP_verbose = FALSE;
78 #define verbose _GateMP_verbose
80 /* Internal structure defining parameters for GateMP_Instance_init */
81 typedef struct {
82     String name;                        /* Name of instance */
83     UInt16 regionId;                    /* not used on host*/
84     Ptr sharedAddr;                     /* not used on host*/
85     GateMP_LocalProtect localProtect;   /* Local protection level  */
86     GateMP_RemoteProtect remoteProtect; /* Remote protection level */
87     UInt32 resourceId;                  /* resource id */
88     Bool openFlag;                      /* Is this open or create? */
89 } _GateMP_Params;
91 static Int GateMP_getNumResources(GateMP_RemoteProtect type);
92 static Int GateMP_getFreeResource(GateMP_RemoteProtect type);
93 static Int GateMP_releaseResource(UInt id, GateMP_RemoteProtect type);
94 static GateMP_Handle _GateMP_create (const _GateMP_Params * params);
95 static Int GateMP_Instance_init(GateMP_Object *obj,
96     const _GateMP_Params *params);
97 static Void GateMP_Instance_finalize(GateMP_Object *obj, Int status);
99 /* -----------------------------------------------------------------------------
100  * Globals
101  * -----------------------------------------------------------------------------
102  */
103 static GateMP_ModuleObject GateMP_state =
105     .remoteSystemGates  = NULL,
106     .defaultGate        = NULL,
107     .nameServer         = NULL,
108     .mutex              = PTHREAD_MUTEX_INITIALIZER,
109 //    .gateMutex          = NULL,
110 //    .gateProcess        = NULL
111 };
113 static GateMP_ModuleObject *GateMP_module = &GateMP_state;
115 static GateMP_Params GateMP_defInstParams =
117     .name           = NULL,
118     .regionId       = 0,
119     .sharedAddr     = NULL,
120     .localProtect   = GateMP_LocalProtect_PROCESS,
121     .remoteProtect  = GateMP_RemoteProtect_SYSTEM
122 };
124 Int GateMP_start(Void)
126     Int status;
127     GateMPDrv_CmdArgs cmdArgs;
129     status = GateMPDrv_ioctl(CMD_GATEMP_START, &cmdArgs);
130     if (status < 0) {
131         PRINTVERBOSE1("GateMP_start: API (through IOCTL) failed, \
132             status=%d\n", status)
133     }
134     else {
135         /*
136          * Initialize module state. Note that Nameserver handles are compatible
137          * across processes.
138          */
139         GateMP_module->nameServer = cmdArgs.args.start.nameServerHandle;
140     }
142     /* allocate memory for remote system gate handles */
143     if (status == GateMP_S_SUCCESS) {
144         GateMP_module->numRemoteSystem =
145             GateMP_getNumResources(GateMP_RemoteProtect_SYSTEM);
146         if (GateMP_module->numRemoteSystem > 0) {
147             GateMP_module->remoteSystemGates = calloc(1,
148                 GateMP_module->numRemoteSystem *
149                 sizeof(IGateProvider_Handle));
151             if (GateMP_module->remoteSystemGates == NULL) {
152                 status = GateMP_E_MEMORY;
153                 PRINTVERBOSE0("GateMP_start: memory allocation failed")
154             }
155         }
156         else {
157             GateMP_module->remoteSystemGates = NULL;
158         }
159     }
161     if (status == GateMP_S_SUCCESS) {
162         /* Open default gate */
163         status = GateMP_open("_GateMP_TI_dGate", &GateMP_module->defaultGate);
164         if (status < 0) {
165             PRINTVERBOSE1("GateMP_start: could not open default gate, \
166                 status=%d\n", status)
167         }
168     }
170     /* in failure case, release acquired resources in reverse order */
171     if (status < 0) {
172         GateMP_stop();
173     }
175     GateMP_module->isStarted = TRUE;
177     return status;
180 Int GateMP_stop(Void)
182     Int status = GateMP_S_SUCCESS;
183     GateMPDrv_CmdArgs cmdArgs;
185     PRINTVERBOSE0("GateMP_stop: entered\n")
187     /* close the default gate */
188     if (GateMP_module->defaultGate) {
189         GateMP_close(&GateMP_module->defaultGate);
190         GateMP_module->defaultGate = NULL;
191     }
193     /* free system gate array */
194     if (GateMP_module->remoteSystemGates != NULL) {
195         free(GateMP_module->remoteSystemGates);
196         GateMP_module->remoteSystemGates = NULL;
197     }
199     /* Call stop in resource manager if necessary */
200     if (GateMP_module->nameServer != NULL) {
201         GateMP_module->nameServer = NULL;
202         status = GateMPDrv_ioctl(CMD_GATEMP_STOP, &cmdArgs);
203         if (status < 0) {
204             PRINTVERBOSE1("GateMP_stop: API (through IOCTL) failed, \
205                 status=%d\n", status)
206         }
207     }
209     GateMP_module->isStarted = FALSE;
211     return status;
214 Void GateMP_Params_init(GateMP_Params *params)
216     if (params != NULL) {
217         memcpy(params, &GateMP_defInstParams, sizeof(GateMP_Params));
218     }
219     else {
220         PRINTVERBOSE0("GateMP_Params_init: Params argument cannot be NULL")
221     }
223     return;
226 GateMP_Handle GateMP_create(const GateMP_Params *params)
228     _GateMP_Params      _params;
229     GateMP_Handle       handle = NULL;
231     if (GateMP_module->isStarted == FALSE) {
232         PRINTVERBOSE0("GateMP_create: GateMP module has not been started!")
233     }
234     else {
235         memset(&_params, 0, sizeof(_GateMP_Params));
236         memcpy(&_params, params, sizeof(GateMP_Params));
238         handle = _GateMP_create(&_params);
239     }
241     return(handle);
244 static GateMP_Handle _GateMP_create(const _GateMP_Params *params)
246     GateMP_Handle       handle = NULL;
247     GateMP_Object *     obj = NULL;
248     Int                 status;
250     /* allocate the instance object */
251     obj = (GateMP_Object *)calloc(1, sizeof(GateMP_Object));
253     if (obj != NULL) {
254         status = GateMP_Instance_init(obj, params);
255         if (status < 0) {
256             free(obj);
257         }
258         else {
259             handle = (GateMP_Handle)obj;
260         }
261     }
262     else {
263         PRINTVERBOSE0("GateMP_create: Memory allocation failed")
264     }
266     return(handle);
269 Int GateMP_open(String name, GateMP_Handle *handle)
271     Int             status = GateMP_S_SUCCESS;
272     UInt32          len;
273     UInt32          nsValue[4];
274     GateMP_Object * obj = NULL;
275     UInt32          arg;
276     UInt32          mask;
277     UInt32          creatorProcId;
278     _GateMP_Params  params;
280     /* assert that a valid pointer has been supplied */
281     if (handle == NULL) {
282         PRINTVERBOSE0("GateMP_open: handle cannot be null")
283         status = GateMP_E_INVALIDARG;
284     }
286     if (GateMP_module->nameServer == NULL) {
287         PRINTVERBOSE0("GateMP_open: NameServer handle is null")
288         PRINTVERBOSE0("GateMP_open: Make sure GateMP_start is called")
289         status = GateMP_E_INVALIDSTATE;
290     }
292     if (status == GateMP_S_SUCCESS) {
293         len = sizeof(nsValue);
295         status = NameServer_get(GateMP_module->nameServer, name, &nsValue,
296             &len, NULL);
298         if (status < 0) {
299             *handle = NULL;
300             status = GateMP_E_NOTFOUND;
301         }
302         else {
303             arg = nsValue[2];
304             mask = nsValue[3];
305             creatorProcId = nsValue[1] >> 16;
306         }
307     }
309     if (status == GateMP_S_SUCCESS) {
310         /*
311          * The least significant bit of nsValue[1] == 0 means its a
312          * local (private) GateMP, otherwise its a remote (shared) GateMP.
313          */
314         if ((nsValue[1] & 0x1) == 0) {
315             if ((nsValue[1] >> 16) != MultiProc_self()) {
316                 /* error: trying to open another processor's private gate */
317                 *handle = NULL;
318                 PRINTVERBOSE0("GateMP_open: cannot open private gate from \
319                     another processor")
320                 status = GateMP_E_FAIL;
321             }
322             else if (nsValue[0] != getpid()) {
323                 /* error: trying to open another process's private gate */
324                 *handle = NULL;
325                 PRINTVERBOSE0("GateMP_open: cannot open private gate from \
326                     another process")
327                 status = GateMP_E_FAIL;
328             }
329         }
330     }
332     if (status == GateMP_S_SUCCESS) {
333         /* local gate */
334         if (GETREMOTE(mask) == GateMP_RemoteProtect_NONE) {
335             if (creatorProcId != MultiProc_self()) {
336                 status = GateMP_E_FAIL;
337             }
338             else {
339                 *handle = (GateMP_Handle)arg;
340                 obj = (GateMP_Object *)(*handle);
341                 pthread_mutex_lock(&GateMP_module->mutex);
342                 obj->numOpens++;
343                 pthread_mutex_unlock(&GateMP_module->mutex);
344             }
345         }
346         else {
347             /* remote case */
348             switch (GETREMOTE(mask)) {
349                 case GateMP_RemoteProtect_SYSTEM:
350                 case GateMP_RemoteProtect_CUSTOM1:
351                 case GateMP_RemoteProtect_CUSTOM2:
352                     obj = GateMP_module->remoteSystemGates[arg];
353                     break;
355                 default:
356                     status = GateMP_E_FAIL;
357                     PRINTVERBOSE0("GateMP_open: unsupported remote protection \
358                         type")
359                     break;
360             }
362             /*  If the object is NULL, then it must have been created
363              *  on a remote processor or in another process on the
364              *  local processor. Need to create a local object. This is
365              *  accomplished by setting the openFlag to TRUE.
366              */
367             if (status == GateMP_S_SUCCESS) {
368                 if (obj == NULL) {
369                     /* create a GateMP object with the openFlag set to true */
370                     params.name = NULL;
371                     params.openFlag = TRUE;
372                     params.sharedAddr = NULL;
373                     params.resourceId = arg;
374                     params.localProtect = GETLOCAL(mask);
375                     params.remoteProtect = GETREMOTE(mask);
377                     obj = (GateMP_Object *)_GateMP_create(&params);
379                     if (obj == NULL) {
380                         status = GateMP_E_FAIL;
381                     }
382                 }
383                 else {
384                     pthread_mutex_lock(&GateMP_module->mutex);
385                     obj->numOpens++;
386                     pthread_mutex_unlock(&GateMP_module->mutex);
387                 }
388             }
390             /* Return the "opened" GateMP instance  */
391             *handle = (GateMP_Handle)obj;
392         }
393     }
395     return status;
398 GateMP_Handle GateMP_getDefaultRemote()
400     return (GateMP_module->defaultGate);
403 GateMP_LocalProtect GateMP_getLocalProtect(GateMP_Handle handle)
405     GateMP_Object *obj;
407     obj = (GateMP_Object *)handle;
408     return (obj->localProtect);
411 GateMP_RemoteProtect GateMP_getRemoteProtect(GateMP_Handle handle)
413     GateMP_Object *obj;
415     obj = (GateMP_Object *)handle;
416     return (obj->remoteProtect);
419 static Int GateMP_getNumResources(GateMP_RemoteProtect type)
421     Int status;
422     GateMPDrv_CmdArgs cmdArgs;
424     cmdArgs.args.getNumResources.type = type;
425     status = GateMPDrv_ioctl(CMD_GATEMP_GETNUMRES, &cmdArgs);
427     if (status < 0) {
428         PRINTVERBOSE1("GateMP_getNumResources: API (through IOCTL) failed, \
429             status=%d\n", status)
430         return -1;
431     }
433     return (cmdArgs.args.getNumResources.value);
436 static Int GateMP_getFreeResource(GateMP_RemoteProtect type)
438     Int status;
439     GateMPDrv_CmdArgs cmdArgs;
441     cmdArgs.args.getFreeResource.type = type;
442     status = GateMPDrv_ioctl(CMD_GATEMP_GETFREERES, &cmdArgs);
444     if (status < 0) {
445         PRINTVERBOSE1("GateMP_getFreeResource: API (through IOCTL) failed, \
446             status=%d\n", status)
447         return -1;
448     }
450     return (cmdArgs.args.getFreeResource.id);
453 static Int GateMP_releaseResource(UInt id, GateMP_RemoteProtect type)
455     Int status;
456     GateMPDrv_CmdArgs cmdArgs;
458     cmdArgs.args.releaseResource.type = type;
459     cmdArgs.args.releaseResource.id   = id;
460     status = GateMPDrv_ioctl(CMD_GATEMP_RELRES, &cmdArgs);
462     if (status < 0) {
463         PRINTVERBOSE1("GateMP_releaseResource: API (through IOCTL) failed, \
464             status=%d\n", status)
465     }
467     return (status);
470 Bool GateMP_isSetup(Void)
472     Int status;
473     GateMPDrv_CmdArgs cmdArgs;
475     cmdArgs.args.isSetup.result = FALSE;
476     status = GateMPDrv_ioctl(CMD_GATEMP_ISSETUP, &cmdArgs);
478     if (status < 0) {
479         PRINTVERBOSE1("GateMP_isSetup: API (through IOCTL) failed, \
480             status=%d\n", status)
481     }
483     assert(status == GateMP_S_SUCCESS);
485     return (cmdArgs.args.isSetup.result);
488 Int GateMP_close(GateMP_Handle *handle)
490     GateMP_Object * obj;
491     Int             status = GateMP_S_SUCCESS;
493     obj = (GateMP_Object *)(*handle);
495     pthread_mutex_lock(&GateMP_module->mutex);
497     /*  Cannot call with the numOpens equal to zero.  This is either
498      *  a created handle or been closed already.
499      */
500     if (obj->numOpens == 0) {
501         status = GateMP_E_INVALIDSTATE;
502     }
504     if (status == GateMP_S_SUCCESS) {
505         obj->numOpens--;
507         /*  If the count is zero and the gate is opened, then this
508          *  object was created in the open (i.e. the create happened
509          *  on a remote processor or another process).
510          */
511         if ((obj->numOpens == 0) && (obj->objType == Ipc_ObjType_OPENDYNAMIC)) {
512             GateMP_delete(handle);
513         }
514         else {
515             *handle = NULL;
516         }
517     }
519     pthread_mutex_unlock(&GateMP_module->mutex);
521     return(status);
524 Int GateMP_delete(GateMP_Handle *handlePtr)
526     Int               status = GateMP_S_SUCCESS;
528     if ((handlePtr == NULL) || (*handlePtr == NULL)) {
529         status =  GateMP_E_INVALIDARG;
530     }
531     else {
532         GateMP_Instance_finalize((GateMP_Object *)(*handlePtr), 0);
533         free(*handlePtr);
534         *handlePtr = NULL;
535     }
537     return status;
540 static Int GateMP_Instance_init(GateMP_Object *obj,
541     const _GateMP_Params *params)
543     GateMP_RemoteSystemProxy_Params     systemParams;
544     UInt32                              nsValue[4];
546     obj->resourceId = (UInt)-1;
548     /* TODO: create/open the local gate instance */
549     obj->localGate = NULL;
551     /* open GateMP instance */
552     if (params->openFlag == TRUE) {
553         /* all open work done here except for remote gateHandle */
554         obj->localProtect  = params->localProtect;
555         obj->remoteProtect = params->remoteProtect;
556         obj->nsKey         = 0;
557         obj->numOpens      = 1;
559         obj->objType       = Ipc_ObjType_OPENDYNAMIC;
560     }
562     /* create GateMP instance */
563     else {
564         obj->localProtect  = params->localProtect;
565         obj->remoteProtect = params->remoteProtect;
566         obj->nsKey         = 0;
567         obj->numOpens      = 0;
569         if (obj->remoteProtect == GateMP_RemoteProtect_NONE) {
570             /* TODO: create a local gate */
571             obj->gateHandle = obj->localGate;
573             /* create a local gate allocating from the local heap */
574             obj->objType = Ipc_ObjType_LOCAL;
575             obj->arg = (Bits32)obj;
576             obj->mask = SETMASK(obj->remoteProtect, obj->localProtect);
577             obj->creatorProcId = MultiProc_self();
579             if (params->name != NULL) {
580                 /*  nsv[0]       : creator process id
581                  *  nsv[1](31:16): creator procId
582                  *  nsv[1](15:0) : 0 = local gate, 1 = remote gate
583                  *  nsv[2]       : local gate object
584                  *  nsv[3]       : protection mask
585                  */
586                 nsValue[0] = getpid();
587                 nsValue[1] = MultiProc_self() << 16;
588                 nsValue[2] = obj->arg;
589                 nsValue[3] = obj->mask;
590                 obj->nsKey = NameServer_add(GateMP_module->nameServer,
591                         params->name, &nsValue, sizeof(nsValue));
592                 if (obj->nsKey == NULL) {
593                     PRINTVERBOSE0("GateMP_Instance_init: NameServer_add failed")
594                     return (GateMP_E_FAIL);
595                 }
596             }
598             /* nothing else to do for local gates */
599             return(0);
600         }
602         obj->objType = Ipc_ObjType_CREATEDYNAMIC;
603     }
605     /* proxy work for open and create done here */
606     switch (obj->remoteProtect) {
607         /* TODO: implement other types of remote protection */
608         case GateMP_RemoteProtect_SYSTEM:
609         case GateMP_RemoteProtect_CUSTOM1:
610         case GateMP_RemoteProtect_CUSTOM2:
611             if (obj->objType == Ipc_ObjType_OPENDYNAMIC) {
612                 /* resourceId set by open call */
613                 obj->resourceId = params->resourceId;
614             }
615             else {
616                 /* created instance */
617                 obj->resourceId = GateMP_getFreeResource(obj->remoteProtect);
618                 if (obj->resourceId == -1) {
619                     return (GateMP_E_RESOURCE);
620                 }
621             }
623             /* create the proxy object */
624             GateMP_RemoteSystemProxy_Params_init(&systemParams);
625             systemParams.resourceId = obj->resourceId;
626             systemParams.openFlag = (obj->objType == Ipc_ObjType_OPENDYNAMIC);
627             //systemParams.sharedAddr = obj->proxyAttrs;
629             /*
630              * TODO: Currently passing in localProtect instead of localGate,
631              * since existing GateHWSpinlock.h defines it this way
632              */
633             obj->gateHandle = (IGateProvider_Handle)
634                 GateMP_RemoteSystemProxy_create(obj->localProtect,
635                     &systemParams);
637             if (obj->gateHandle == NULL) {
638                 PRINTVERBOSE0("GateMP_Instance_init: failed to create proxy\n");
639                 return(GateMP_E_FAIL);
640             }
642             /* store the object handle in the gate array */
643             GateMP_module->remoteSystemGates[obj->resourceId] = obj;
644             break;
646         default:
647             break;
648     }
650     /* add name/attrs to NameServer table */
651     if (obj->objType != Ipc_ObjType_OPENDYNAMIC) {
652         obj->arg = obj->resourceId;
653         obj->mask = SETMASK(obj->remoteProtect, obj->localProtect);
655         if (params->name != NULL) {
656             /*  nsv[0]       : creator pid
657              *  nsv[1](31:16): creator procId
658              *  nsv[1](15:0) : 0 = local gate, 1 = remote gate
659              *  nsv[2]       : resource id
660              *  nsv[3]       : protection mask
661              */
662             nsValue[0] = getpid();
663             nsValue[1] = MultiProc_self() << 16 | 1;
664             nsValue[2] = obj->resourceId;
665             nsValue[3] = obj->mask;
666             obj->nsKey = NameServer_add(GateMP_module->nameServer,
667                     params->name, &nsValue, sizeof(nsValue));
669             if (obj->nsKey == NULL) {
670                 PRINTVERBOSE0("GateMP_Instance_init: NameServer_add failed")
671                 return (GateMP_E_FAIL);
672             }
673         }
674     }
676     return (GateMP_S_SUCCESS);
679 static Void GateMP_Instance_finalize(GateMP_Object *obj, Int status)
681     GateMP_Object ** remoteGates = NULL;
683     /* remove from NameServer */
684     if (obj->nsKey != 0) {
685         NameServer_removeEntry(GateMP_module->nameServer, obj->nsKey);
686         obj->nsKey = 0;
687     }
689     /* delete the remote gate */
690     switch (obj->remoteProtect) {
692         case GateMP_RemoteProtect_SYSTEM:
693         case GateMP_RemoteProtect_CUSTOM1:
694         case GateMP_RemoteProtect_CUSTOM2:
695             if (obj->gateHandle != NULL) {
696                 GateMP_RemoteSystemProxy_delete(
697                         (GateMP_RemoteSystemProxy_Handle *)&obj->gateHandle);
698             }
699             remoteGates = GateMP_module->remoteSystemGates;
700             break;
702         case GateMP_RemoteProtect_NONE:
703             /*  nothing else to finalize */
704             return;
706         default:
707             /* Nothing to do */
708             break;
709     }
711     /* TODO: close/delete local gate */
713     /* clear the handle array entry in local memory */
714     if (obj->resourceId != (UInt)-1) {
715         remoteGates[obj->resourceId] = NULL;
716     }
718     if ((obj->objType != Ipc_ObjType_OPENDYNAMIC)
719         && (obj->resourceId != (UInt)-1)) {
720         GateMP_releaseResource(obj->resourceId, obj->remoteProtect);
721     }
725 IArg GateMP_enter(GateMP_Handle handle)
727     GateMP_Object * obj;
728     IArg            key;
730     obj = (GateMP_Object *)handle;
731     key = IGateProvider_enter(obj->gateHandle);
733     return(key);
736 Void GateMP_leave(GateMP_Handle handle, IArg key)
738     GateMP_Object *obj;
740     obj = (GateMP_Object *)handle;
741     IGateProvider_leave(obj->gateHandle, key);