Prevent SR0 owner from being stopped if host process is still using GateMP
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / ipc / hlos / knl / GateMP_daemon.c
1 /*
2  * Copyright (c) 2013-2014, 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  */
33 /*
34  *  ======== GateMP_daemon.c ========
35  */
38 /* Standard headers */
39 #include <ti/ipc/Std.h>
41 /* Qnx specific header files */
42 #include <pthread.h>
44 /* System headers */
45 #include <sys/mman.h>
46 #include <stdlib.h>
47 #include <assert.h>
49 /* Module level headers */
50 #include <ti/ipc/GateMP.h>
51 #include <ti/ipc/NameServer.h>
52 #include <ti/ipc/MultiProc.h>
53 #include <_MultiProc.h>
54 #include <GateMP_config.h>
55 #include <_GateMP.h>
57 #include <ti/syslink/utils/IGateProvider.h>
58 #include <ti/syslink/inc/_GateMP_daemon.h>
59 #include <_IpcLog.h>
61 #if defined (__cplusplus)
62 extern "C" {
63 #endif
65 /* Timeout of GateMP_setup in seconds */
66 #define SETUP_TIMEOUT         2
68 #define NUM_INFO_FIELDS       6    /* Number of fields in info entry */
70 /* Values used to populate the resource 'inUse' arrays */
71 #define UNUSED          ((UInt8)0)
72 #define USED            ((UInt8)1)
73 #define RESERVED        ((UInt8)-1)
75 /* Name of GateMP's nameserver */
76 #define GateMP_NAMESERVER  "GateMP"
78 /* =============================================================================
79  * Structures & Enums
80  * =============================================================================
81  */
83 /* structure for GateMP module state */
84 typedef struct {
85     Int                numRemoteSystem;
86     Int                numRemoteCustom1;
87     Int                numRemoteCustom2;
88     UInt8 *            remoteSystemInUse;
89     UInt8 *            remoteCustom1InUse;
90     UInt8 *            remoteCustom2InUse;
91     GateMP_Handle      defaultGate;
92     NameServer_Handle  nameServer;
93     Bool               isSetup;
94     UInt32             startCount;   /* number of times GateMP is started */
95     pthread_mutex_t    lock;
96 } GateMP_ModuleObject;
98 /* Internal functions */
99 static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr,
100     UInt16 * creatorProcId);
101 static Int GateMP_closeDefaultGate(GateMP_Handle *handlePtr);
103 /* =============================================================================
104  *  Globals
105  * =============================================================================
106  */
107 /*
108  * GateMP_state
109  */
110 static GateMP_ModuleObject GateMP_state = {
111     .numRemoteSystem                 = 0,
112     .numRemoteCustom1                = 0,
113     .numRemoteCustom2                = 0,
114     .remoteSystemInUse               = NULL,
115     .remoteCustom1InUse              = NULL,
116     .remoteCustom2InUse              = NULL,
117     .defaultGate                     = NULL,
118     .nameServer                      = NULL,
119     .isSetup                         = FALSE,
120     .startCount                      = 0,
121     .lock                            = PTHREAD_RMUTEX_INITIALIZER
122 };
124 static GateMP_ModuleObject * GateMP_module = &GateMP_state;
126 /* =============================================================================
127  * APIS
128  * =============================================================================
129  */
131 /* Function to setup the gatemp module. */
132 Int GateMP_setup(Int32 * sr0ProcId)
134     Int               status = GateMP_S_SUCCESS;
135     NameServer_Params params;
136     UInt32            nsValue[NUM_INFO_FIELDS];
137     UInt32            len;
138     UInt              timeout = SETUP_TIMEOUT;
139     UInt16            procId;
141     NameServer_Params_init(&params);
142     params.maxRuntimeEntries = MAX_RUNTIME_ENTRIES;
143     params.maxNameLen = MAX_NAME_LEN;
145     /* Assume info entry has more fields than other entries */
146     params.maxValueLen = NUM_INFO_FIELDS * sizeof(UInt32);
148     pthread_mutex_lock(&GateMP_module->lock);
150     if (GateMP_module->isSetup) {
151         pthread_mutex_unlock(&GateMP_module->lock);
152         return (GateMP_S_ALREADYSETUP);
153     }
155     GateMP_module->nameServer =
156                 NameServer_create(GateMP_NAMESERVER, &params);
158     if (GateMP_module->nameServer == NULL) {
159         status = GateMP_E_FAIL;
160         LOG0("GateMP_setup: NameServer_create failed\n");
161     }
163     if (status == GateMP_S_SUCCESS) {
164         /* The default gate creator is the owner of SR0 */
165         while (((status = GateMP_openDefaultGate(&GateMP_module->defaultGate,
166             &procId)) == GateMP_E_NOTFOUND) && (timeout > 0)) {
167             sleep(1);
168             timeout--;
169         }
171         if ((status < 0) && (status != GateMP_E_NOTFOUND)) {
172             LOG0("GateMP_setup: failed to open default gate\n");
173             status = GateMP_E_FAIL;
174         }
175         else if (status == GateMP_S_SUCCESS) {
176             *sr0ProcId = procId;
177         }
178         else {
179             /* If default gate is not found, return GateMP_E_NOTFOUND */
180         }
181     }
183     if (status == GateMP_S_SUCCESS) {
184         /* Process global info NameServer entry */
185         len = sizeof(nsValue);
187         status = NameServer_get(GateMP_module->nameServer, "_GateMP_TI_info",
188             &nsValue, &len, NULL);
190         if (status < 0) {
191             LOG0("GateMP_setup: failed to find info entry\n");
192             status = GateMP_E_NOTFOUND;
193         }
194         else {
195             GateMP_module->numRemoteSystem = nsValue[3];
196             GateMP_module->numRemoteCustom1 = nsValue[4];
197             GateMP_module->numRemoteCustom2 = nsValue[5];
199             /* Map InUse arrays to daemon's address space */
200             GateMP_module->remoteSystemInUse = mmap(NULL,
201                 GateMP_module->numRemoteSystem * sizeof (UInt8),
202                 (PROT_READ|PROT_WRITE|PROT_NOCACHE),
203                 (MAP_PHYS|MAP_SHARED), NOFD, (off_t)nsValue[0]);
204             if (GateMP_module->remoteSystemInUse == MAP_FAILED) {
205                  GateMP_module->remoteSystemInUse = NULL;
206                  status = GateMP_E_MEMORY;
207                  LOG0("Failed to map remoteSystemInUse to host address space!");
208             }
210             if (status == GateMP_S_SUCCESS) {
211                 GateMP_module->remoteCustom1InUse = mmap(NULL,
212                     GateMP_module->numRemoteCustom1 * sizeof (UInt8),
213                     (PROT_READ|PROT_WRITE|PROT_NOCACHE),
214                     (MAP_PHYS|MAP_SHARED), NOFD, (off_t)nsValue[1]);
215                 if (GateMP_module->remoteCustom1InUse == MAP_FAILED) {
216                     GateMP_module->remoteCustom1InUse = NULL;
217                     status = GateMP_E_MEMORY;
218                     LOG0("Failed to map remoteSystemInUse to host address" \
219                         " space!");
220                 }
221             }
223             if (status == GateMP_S_SUCCESS) {
224                 GateMP_module->remoteCustom2InUse = mmap(NULL,
225                     GateMP_module->numRemoteCustom2 * sizeof (UInt8),
226                     (PROT_READ|PROT_WRITE|PROT_NOCACHE),
227                     (MAP_PHYS|MAP_SHARED), NOFD, (off_t)nsValue[2]);
228                 if (GateMP_module->remoteCustom2InUse == MAP_FAILED) {
229                     GateMP_module->remoteCustom2InUse = NULL;
230                     status = GateMP_E_MEMORY;
231                     LOG0("Failed to map remoteSystemInUse to host address" \
232                         " space!");
233                 }
234             }
235         }
236     }
238     /* TODO: setup the proxy map */
240     /* clean up if error */
241     if (status < 0) {
242         GateMP_destroy(TRUE);
243     }
244     else {
245         GateMP_module->isSetup = TRUE;
246     }
248     pthread_mutex_unlock(&GateMP_module->lock);
250     return (status);
253 Int GateMP_destroy(Bool forced)
255     pthread_mutex_lock(&GateMP_module->lock);
257     if ((!forced) && (GateMP_module->startCount != 0)) {
258         /* Some process on the host is still using GateMP */
259         pthread_mutex_unlock(&GateMP_module->lock);
260         return (GateMP_E_FAIL);
261     }
263     if (GateMP_module->remoteSystemInUse) {
264         munmap((unsigned int *)GateMP_module->remoteSystemInUse,
265             GateMP_module->numRemoteSystem * sizeof (UInt8));
266         GateMP_module->remoteSystemInUse = NULL;
267     }
269     if (GateMP_module->remoteCustom1InUse) {
270         munmap((unsigned int *)GateMP_module->remoteCustom1InUse,
271             GateMP_module->numRemoteCustom1 * sizeof (UInt8));
272         GateMP_module->remoteCustom1InUse = NULL;
273     }
275     if (GateMP_module->remoteCustom2InUse) {
276         munmap((unsigned int *)GateMP_module->remoteCustom2InUse,
277             GateMP_module->numRemoteCustom2 * sizeof (UInt8));
278         GateMP_module->remoteCustom2InUse = NULL;
279     }
281     if (GateMP_module->defaultGate) {
282         GateMP_closeDefaultGate(&GateMP_module->defaultGate);
283     }
285     if (GateMP_module->nameServer) {
286         NameServer_delete(&GateMP_module->nameServer);
287         GateMP_module->nameServer = NULL;
288     }
290     GateMP_module->isSetup = FALSE;
292     pthread_mutex_unlock(&GateMP_module->lock);
294     return (GateMP_S_SUCCESS);
297 /* Open default gate during GateMP_setup. Should only be called once */
298 static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr,
299     UInt16 * creatorProcId)
301     Int             status = GateMP_S_SUCCESS;
302     UInt32          len;
303     UInt32          nsValue[4];
304     GateMP_Object * obj = NULL;
305     UInt32          arg;
306     UInt32          mask;
308     GateMP_RemoteSystemProxy_Params     systemParams;
310     /* assert that a valid pointer has been supplied */
311     if (handlePtr == NULL) {
312         LOG0("GateMP_open: argument cannot be null\n");
313         status = GateMP_E_INVALIDARG;
314     }
316     if (status == GateMP_S_SUCCESS) {
317         len = sizeof(nsValue);
319         status = NameServer_get(GateMP_module->nameServer, "_GateMP_TI_dGate",
320             &nsValue, &len, NULL);
322         if (status < 0) {
323             *handlePtr = NULL;
324             status = GateMP_E_NOTFOUND;
325         }
326         else {
327             arg = nsValue[2];
328             mask = nsValue[3];
329             *creatorProcId = nsValue[1] >> 16;
330         }
331     }
333     if (status == GateMP_S_SUCCESS) {
334         /* allocate the instance object */
335         obj = (GateMP_Object *)calloc(1, sizeof (GateMP_Object));
336         if (obj != NULL) {
337             obj->localGate  = NULL;  /* TODO: create the local gate instance */
338             obj->localProtect  = GETLOCAL(mask);
339             obj->remoteProtect = GETREMOTE(mask);
340             obj->nsKey         = 0;
341             obj->numOpens      = 1;
342             obj->objType       = Ipc_ObjType_OPENDYNAMIC;
343             obj->resourceId    = arg;
345             assert(obj->remoteProtect == GateMP_RemoteProtect_SYSTEM);
347             /* create the proxy object */
348             GateMP_RemoteSystemProxy_Params_init(&systemParams);
349             systemParams.resourceId = obj->resourceId;
350             systemParams.openFlag = TRUE;
352             /*
353              * TODO: Currently passing in localProtect instead of localGate,
354              * since GateHWSpinlock owns the local gate
355              */
356             obj->gateHandle = (IGateProvider_Handle)
357                 GateMP_RemoteSystemProxy_create(obj->localProtect,
358                     &systemParams);
360             if (obj->gateHandle == NULL) {
361                 LOG0("GateMP_openDefaultGate: failed to create proxy\n");
362                 free(obj);
363                 obj = NULL;
364             }
365         }
366         else {
367             LOG0("GateMP_openDefaultGate: Memory allocation failed")
368         }
370         if (obj == NULL) {
371             status = GateMP_E_FAIL;
372         }
373     }
375     /* Return the "opened" GateMP instance  */
376     *handlePtr = (GateMP_Handle)obj;
378     return status;
381 static Int GateMP_closeDefaultGate(GateMP_Handle *handlePtr)
383     Int status = GateMP_S_SUCCESS;
384     GateMP_Object * obj = *(GateMP_Object **)handlePtr;
386     if (obj->gateHandle != NULL) {
387         /* Default gate is always of type System when more than 1 processor */
388         GateMP_RemoteSystemProxy_delete(
389             (GateMP_RemoteSystemProxy_Handle *)&obj->gateHandle);
390     }
392     free(*handlePtr);
393     *handlePtr = NULL;
395     return(status);
398 Int GateMP_getFreeResource(GateMP_RemoteProtect type)
400     IArg   key;
401     Bool   flag = FALSE;
402     Int    resourceId = -1;
403     UInt8* inUse = NULL;
404     Int    num = 0;
406     /* Remote case */
407     switch (type) {
408         /* TODO: currently only support System proxy */
409         case GateMP_RemoteProtect_SYSTEM:
410         case GateMP_RemoteProtect_CUSTOM1:
411         case GateMP_RemoteProtect_CUSTOM2:
412             inUse = GateMP_module->remoteSystemInUse;
413             num = GateMP_module->numRemoteSystem;
414             break;
416         default:
417             LOG0("GateMP_getFreeResource: Invalid remote protection type\n");
418             break;
419     }
421     if (inUse != NULL) {
422         assert(GateMP_module->defaultGate != NULL);
423         key = GateMP_enter(GateMP_module->defaultGate);
425         /*
426          *  Find a free resource id. Note: zero is reserved on the
427          *  system proxy for the default gate.
428          */
429         for (resourceId = 0; resourceId < num; resourceId++) {
430             /*
431              *  If not in-use, set the inUse to TRUE to prevent other
432              *  creates from getting this one.
433              */
434             if (inUse[resourceId] == UNUSED) {
435                 flag = TRUE;
437                 /* Denote in shared memory that the resource is used */
438                 inUse[resourceId] = USED;
439                 break;
440             }
441         }
443         GateMP_leave(GateMP_module->defaultGate, key);
444     }
446     if (flag == FALSE) {
447         resourceId = -1;
448     }
450     return (resourceId);
453 Int GateMP_releaseResource(UInt id, GateMP_RemoteProtect type)
455     Int    status = GateMP_S_SUCCESS;
456     IArg   key;
457     UInt8* inUse = NULL;
458     Int    num = 0;
460     /* Remote case */
461     switch (type) {
462         /* TODO: currently only support System proxy */
463         case GateMP_RemoteProtect_SYSTEM:
464         case GateMP_RemoteProtect_CUSTOM1:
465         case GateMP_RemoteProtect_CUSTOM2:
466             inUse = GateMP_module->remoteSystemInUse;
467             num = GateMP_module->numRemoteSystem;
468             break;
470         default:
471             LOG0("GateMP_releaseResource: Invalid remote protection type\n");
472             status = GateMP_E_FAIL;
473             break;
474     }
476     if ((inUse != NULL) && (id < num)) {
477         assert(GateMP_module->defaultGate != NULL);
478         key = GateMP_enter(GateMP_module->defaultGate);
479         inUse[id] = UNUSED;
480         GateMP_leave(GateMP_module->defaultGate, key);
481     }
482     else {
483         /* Should not happen if module is properly setup */
484         status = GateMP_E_FAIL;
485     }
487     return (status);
490 Int GateMP_getNumResources(GateMP_RemoteProtect type)
492     Int   num = -1;
494     /* Remote case */
495     switch (type) {
496         /* TODO: currently only support System proxy */
497         case GateMP_RemoteProtect_SYSTEM:
498         case GateMP_RemoteProtect_CUSTOM1:
499         case GateMP_RemoteProtect_CUSTOM2:
500             num = GateMP_module->numRemoteSystem;
501             break;
503         default:
504             LOG0("GateMP_getNumResources: Invalid remote protection type\n");
505             break;
506     }
508     return (num);
511 NameServer_Handle GateMP_getNameServer(Void)
513     return (GateMP_module->nameServer);
516 Int GateMP_start(Void)
518     Int status = GateMP_S_SUCCESS;
520     pthread_mutex_lock(&GateMP_module->lock);
522     if (GateMP_isSetup()) {
523         GateMP_module->startCount++;
524     }
525     else {
526         /* Cannot start GateMP if it is not setup */
527         status = GateMP_E_FAIL;
528     }
530     pthread_mutex_unlock(&GateMP_module->lock);
532     return (status);
535 Int GateMP_stop(Void)
537     Int status = GateMP_S_SUCCESS;
539     pthread_mutex_lock(&GateMP_module->lock);
541     if (GateMP_isSetup()) {
542         GateMP_module->startCount--;
543     }
544     else {
545         /* Cannot stop GateMP if it is not setup */
546         status = GateMP_E_FAIL;
547     }
549     pthread_mutex_unlock(&GateMP_module->lock);
551     return (status);
554 Bool GateMP_isSetup(Void)
556     return (GateMP_module->isSetup);
559 IArg GateMP_enter(GateMP_Handle handle)
561     GateMP_Object * obj;
562     IArg            key;
564     obj = (GateMP_Object *)handle;
565     key = IGateProvider_enter(obj->gateHandle);
567     return(key);
570 Void GateMP_leave(GateMP_Handle handle, IArg key)
572     GateMP_Object *obj;
574     obj = (GateMP_Object *)handle;
575     IGateProvider_leave(obj->gateHandle, key);