heaps: Avoid possible divide by zero error
[ipc/ipcdev.git] / packages / ti / sdo / ipc / nsremote / NameServerRemoteNotify.c
1 /*
2  * Copyright (c) 2012-2019, 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  *  ======== NameServerRemoteNotify.c ========
34  */
36 /* Remove Windows strncpy warning */
37 #define _CRT_SECURE_NO_DEPRECATE 1
39 #include <xdc/std.h>
40 #include <string.h>
41 #include <stdlib.h>
43 #include <xdc/runtime/Assert.h>
44 #include <xdc/runtime/Error.h>
45 #include <xdc/runtime/knl/ISync.h>
47 #include <ti/sysbios/BIOS.h>
48 #include <ti/sysbios/hal/Cache.h>
49 #include <ti/sysbios/knl/Swi.h>
50 #include <ti/sysbios/knl/Semaphore.h>
52 #include "package/internal/NameServerRemoteNotify.xdc.h"
54 #include <ti/sdo/ipc/Ipc.h>
55 #include <ti/sdo/ipc/_Notify.h>
56 #include <ti/sdo/ipc/_GateMP.h>
57 #include <ti/sdo/ipc/_SharedRegion.h>
58 #include <ti/sdo/utils/_MultiProc.h>
59 #include <ti/sdo/utils/_NameServer.h>
61 /* Need to use reserved notify events */
62 #undef NameServerRemoteNotify_notifyEventId
63 #define NameServerRemoteNotify_notifyEventId \
64         ti_sdo_ipc_nsremote_NameServerRemoteNotify_notifyEventId + \
65                     (UInt32)((UInt32)Notify_SYSTEMKEY << 16)
67 /* private constant values */
68 #define NameServerRemoteNotify_RequestMsg       1
69 #define NameServerRemoteNotify_ResponseMsg      2
71 /*
72  *************************************************************************
73  *                       Instance functions
74  *************************************************************************
75  */
76 Int NameServerRemoteNotify_Instance_init(NameServerRemoteNotify_Object *obj,
77         UInt16 remoteProcId, const NameServerRemoteNotify_Params *params,
78         Error_Block *eb)
79 {
80     Int               offset = 0;
81     Int               status;
82     Semaphore_Params  semParams;
83     Semaphore_Handle  semHandle;
84     Swi_Params        swiParams;
85     Swi_Handle        swiHandle;
87     /* Assert that a NameServerRemoteNotify_Params has been supplied */
88     Assert_isTrue(params != NULL, Ipc_A_nullArgument);
90     /* Assert that remoteProcId is valid */
91     Assert_isTrue(remoteProcId != MultiProc_self() &&
92                   remoteProcId != MultiProc_INVALIDID,
93                   Ipc_A_invParam);
95     /* determine the offset based upon own id and remote's id */
96     if (MultiProc_self() > remoteProcId) {
97         offset = 1;
98     }
100     obj->regionId = SharedRegion_getId(params->sharedAddr);
101     obj->localState = NameServerRemoteNotify_IDLE;
102     obj->remoteState = NameServerRemoteNotify_IDLE;
104     /* assert that sharedAddr is cache aligned */
105     Assert_isTrue(SharedRegion_getCacheLineSize(obj->regionId) == 0 ||
106             ((UArg)params->sharedAddr %
107             SharedRegion_getCacheLineSize(obj->regionId) == 0),
108             Ipc_A_addrNotCacheAligned);
110     /* asset message structure size is cache aligned */
111     Assert_isTrue(SharedRegion_getCacheLineSize(obj->regionId) == 0 ||
112             (sizeof(NameServerRemoteNotify_Message) %
113             SharedRegion_getCacheLineSize(obj->regionId)) == 0,
114             NameServerRemoteNotify_A_messageSize);
116     obj->msg[0] = (NameServerRemoteNotify_Message *)(params->sharedAddr);
117     obj->msg[1] = (NameServerRemoteNotify_Message *)((UArg)obj->msg[0] +
118                           sizeof(NameServerRemoteNotify_Message));
119     obj->gate = params->gate;
120     obj->remoteProcId = remoteProcId;
122     /* construct the remoteWait semaphore */
123     semHandle = NameServerRemoteNotify_Instance_State_semRemoteWait(obj);
124     Semaphore_Params_init(&semParams);
125     Semaphore_construct(Semaphore_struct(semHandle), 0, &semParams);
127     /* construct the multiBlock semaphore */
128     semHandle = NameServerRemoteNotify_Instance_State_semMultiBlock(obj);
129     Semaphore_Params_init(&semParams);
130     Semaphore_construct(Semaphore_struct(semHandle), 1, &semParams);
132     /* construct swi which handles the request message */
133     swiHandle = NameServerRemoteNotify_Instance_State_swiRequest(obj);
134     Swi_Params_init(&swiParams);
135     swiParams.arg0 = (UArg)obj;
136     swiParams.priority = 0; /* lowest priority */
137     Swi_construct(Swi_struct(swiHandle),
138              (ti_sysbios_knl_Swi_FuncPtr)NameServerRemoteNotify_swiFxnRequest,
139              &swiParams, eb);
141     /* construct swi which handles the response message */
142     swiHandle = NameServerRemoteNotify_Instance_State_swiResponse(obj);
143     Swi_Params_init(&swiParams);
144     swiParams.arg0 = (UArg)obj;
145     swiParams.priority = 0; /* lowest priority */
146     Swi_construct(Swi_struct(swiHandle),
147              (ti_sysbios_knl_Swi_FuncPtr)NameServerRemoteNotify_swiFxnResponse,
148              &swiParams, eb);
150     /* initialize own side of message struct only */
151     obj->msg[offset]->requestStatus = 0;
152     obj->msg[offset]->value = 0;
153     obj->msg[offset]->valueLen = 0;
155     memset(obj->msg[offset]->instanceName, 0,
156                sizeof(obj->msg[offset]->instanceName));
157     memset(obj->msg[offset]->name, 0,
158                sizeof(obj->msg[offset]->name));
160     /* determine cacheability of the object from the regionId */
161     obj->cacheEnable = SharedRegion_isCacheEnabled(obj->regionId);
162     if (obj->cacheEnable) {
163         /* write back shared memory that was modified */
164         Cache_wbInv(obj->msg[offset], sizeof(NameServerRemoteNotify_Message),
165                     Cache_Type_ALL, TRUE);
166     }
168     /* register notify callback function to handle message notifications */
169     status = Notify_registerEventSingle(remoteProcId, 0,
170             NameServerRemoteNotify_notifyEventId,
171             (Notify_FnNotifyCbck)NameServerRemoteNotify_cbFxn, (UArg)obj);
173     /* if not successful return */
174     if (status < 0) {
175         Error_raise(eb, ti_sdo_ipc_Ipc_E_internal, 0, 0);
176         return (1);
177     }
179     /* register the remote driver with NameServer */
180     ti_sdo_utils_NameServer_registerRemoteDriver(
181             NameServerRemoteNotify_Handle_upCast(obj), remoteProcId);
183     return (0);
186 /*
187  *  ======== NameServerRemoteNotify_Instance_finalize ========
188  */
189 Void NameServerRemoteNotify_Instance_finalize(
190         NameServerRemoteNotify_Object *obj, Int status)
192     Semaphore_Handle  semHandle;
193     Swi_Handle        swiHandle;
195     if (status == 0) {
196         /* unregister remote driver from NameServer module */
197         ti_sdo_utils_NameServer_unregisterRemoteDriver(obj->remoteProcId);
199         /* unregister event from Notify module */
200         Notify_unregisterEventSingle(obj->remoteProcId, 0,
201                 NameServerRemoteNotify_notifyEventId);
202     }
204     semHandle = NameServerRemoteNotify_Instance_State_semRemoteWait(obj);
205     if (semHandle != NULL) {
206         Semaphore_destruct(Semaphore_struct(semHandle));
207     }
209     semHandle = NameServerRemoteNotify_Instance_State_semMultiBlock(obj);
210     if (semHandle != NULL) {
211         Semaphore_destruct(Semaphore_struct(semHandle));
212     }
214     swiHandle = NameServerRemoteNotify_Instance_State_swiRequest(obj);
215     if (swiHandle != NULL) {
216         Swi_destruct(Swi_struct(swiHandle));
217     }
219     swiHandle = NameServerRemoteNotify_Instance_State_swiResponse(obj);
220     if (swiHandle != NULL) {
221         Swi_destruct(Swi_struct(swiHandle));
222     }
225 /*
226  *************************************************************************
227  *                       Module functions
228  *************************************************************************
229  */
231 /*
232  *  ======== NameServerRemoteNotify_attach ========
233  */
234 Int NameServerRemoteNotify_attach(UInt16 remoteProcId, Ptr sharedAddr)
236     NameServerRemoteNotify_Params nsrParams;
237     NameServerRemoteNotify_Handle handle;
238     Int status = NameServerRemoteNotify_E_FAIL;
239     Error_Block eb;
241     /* Assert that the default GateMP is not NULL */
242     Assert_isTrue(GateMP_getDefaultRemote() != NULL, Ipc_A_internal);
244     Error_init(&eb);
246     /* Use default GateMP */
247     NameServerRemoteNotify_Params_init(&nsrParams);
248     nsrParams.gate = (ti_sdo_ipc_GateMP_Handle)GateMP_getDefaultRemote();
250     /* determine the address */
251     nsrParams.sharedAddr = sharedAddr;
253     /* create only if notify driver has been created to remote proc */
254     if (Notify_intLineRegistered(remoteProcId, 0)) {
255         handle = NameServerRemoteNotify_create(remoteProcId,
256                                                &nsrParams,
257                                                &eb);
258         if (handle != NULL) {
259             status = NameServerRemoteNotify_S_SUCCESS;
260         }
261     }
263     return (status);
266 /*
267  *  ======== NameServerRemoteNotify_cbFxn ========
268  */
269 Void NameServerRemoteNotify_cbFxn(UInt16 procId, UInt16 lineId, UInt32 eventId,
270         UArg arg, UInt32 payload)
272     NameServerRemoteNotify_Object *obj;
273     Swi_Handle swiHandle = NULL;
275     obj = (NameServerRemoteNotify_Object *)arg;
278     switch (payload)
279     {
280         case NameServerRemoteNotify_RequestMsg:
281             swiHandle = NameServerRemoteNotify_Instance_State_swiRequest(obj);
283             /* set object state (used by ROV) */
284             obj->remoteState = NameServerRemoteNotify_RECEIVE_REQUEST;
285             break;
287         case NameServerRemoteNotify_ResponseMsg:
288             swiHandle = NameServerRemoteNotify_Instance_State_swiResponse(obj);
290             /* set object state (used by ROV) */
291             obj->localState = NameServerRemoteNotify_RECEIVE_RESPONSE;
292             break;
294         default:
295             /* We should never get here but assert if we do */
296             Assert_isTrue(swiHandle != NULL, Ipc_A_internal);
297     }
298     if (swiHandle == NULL) {
299         return;
300     }
302     Swi_post(swiHandle);
305 /*
306  *  ======== NameServerRemoteNotify_detach ========
307  */
308 Int NameServerRemoteNotify_detach(UInt16 remoteProcId)
310     NameServerRemoteNotify_Handle handle;
311     Int status = NameServerRemoteNotify_S_SUCCESS;
313     for (handle = NameServerRemoteNotify_Object_first(); handle != NULL;
314         handle = NameServerRemoteNotify_Object_next(handle)) {
315         if (handle->remoteProcId == remoteProcId) {
316             break;
317         }
318     }
320     if (handle == NULL) {
321         status = NameServerRemoteNotify_E_FAIL;
322     }
323     else {
324         NameServerRemoteNotify_delete(&handle);
325     }
327     return (status);
330 /*
331  *  ======== NameServerRemoteNotify_get ========
332  */
333 Int NameServerRemoteNotify_get(NameServerRemoteNotify_Object *obj,
334         String instanceName, String name, Ptr value, UInt32 *valueLen,
335         ISync_Handle syncHandle, Error_Block *eb)
337     Int len;
338     Int retval = NameServer_E_NOTFOUND;
339     Int offset = 0;
340     Int status;
341     Int notifyStatus;
342     Semaphore_Handle semRemoteWait;
343     Semaphore_Handle semMultiBlock;
345     Assert_isTrue(*valueLen <= 300, NameServerRemoteNotify_A_invalidValueLen);
347     semRemoteWait = NameServerRemoteNotify_Instance_State_semRemoteWait(obj);
348     semMultiBlock = NameServerRemoteNotify_Instance_State_semMultiBlock(obj);
350     /* prevent multiple threads from entering */
351     Semaphore_pend(semMultiBlock, BIOS_WAIT_FOREVER);
353     if (MultiProc_self() > obj->remoteProcId) {
354         offset = 1;
355     }
357     if (obj->cacheEnable) {
358         /* Make sure there's no outstanding message */
359         Cache_inv(obj->msg[offset], sizeof(NameServerRemoteNotify_Message),
360                   Cache_Type_ALL, TRUE);
361     }
363     /* this is a request message */
364     obj->msg[offset]->requestStatus = 0;
365     obj->msg[offset]->valueLen = *valueLen;
367     /* copy the name of instance into shared memory */
368     len = strlen(instanceName);
369     strncpy((Char *)obj->msg[offset]->instanceName, instanceName, len + 1);
371     /* copy the name of nameserver entry into shared memory */
372     len = strlen(name);
373     strncpy((Char *)obj->msg[offset]->name, name, len + 1);
375     /* set object state (used by ROV) */
376     obj->localState = NameServerRemoteNotify_SEND_REQUEST;
378     if (obj->cacheEnable) {
379         Cache_wbInv(obj->msg[offset], sizeof(NameServerRemoteNotify_Message),
380                     Cache_Type_ALL, TRUE);
381     }
383     /*
384      *  Send the notification to remote processor. Do not wait here since
385      *  we hold the GateMP.
386      */
387     notifyStatus = Notify_sendEvent(obj->remoteProcId, 0,
388             NameServerRemoteNotify_notifyEventId,
389             NameServerRemoteNotify_RequestMsg, TRUE);
391     if (notifyStatus < 0) {
392         /* undo previous options */
393         obj->msg[offset]->valueLen = 0;
395         /* post the semaphore to make sure it doesn't block */
396         Semaphore_post(semMultiBlock);
398         return (retval);
399     }
401     /* pend here until we get a notification back from remote processor */
402     status = Semaphore_pend(semRemoteWait, NameServerRemoteNotify_timeout);
404     if (status == FALSE) {
405         retval = NameServer_E_TIMEOUT;
406     }
407     else {
408         /* getting here means we got the notification back */
410         if (obj->cacheEnable) {
411             Cache_inv(obj->msg[offset], sizeof(NameServerRemoteNotify_Message),
412                     Cache_Type_ALL, TRUE);
413         }
415         /* if successful request then copy to value */
416         if (obj->msg[offset]->requestStatus == TRUE) {
418             /* copy to value */
419             if (obj->msg[offset]->valueLen == sizeof(UInt32)) {
420                 memcpy(value, &(obj->msg[offset]->value), sizeof(UInt32));
421             }
422             else {
423                 memcpy(value, &(obj->msg[offset]->valueBuf),
424                        obj->msg[offset]->valueLen);
425             }
427             /* set length to amount of data that was copied */
428             *valueLen = obj->msg[offset]->valueLen;
430             /* set the status */
431             retval = NameServer_S_SUCCESS;
432         }
434         /* set object state (used by ROV) */
435         obj->localState = NameServerRemoteNotify_IDLE;
436     }
438     Semaphore_post(semMultiBlock);
440     return (retval);
443 /*
444  *  ======== NameServerRemoteNotify_sharedMemReq ========
445  */
446 SizeT NameServerRemoteNotify_sharedMemReq(Ptr sharedAddr)
448     /*
449      *  Two Message structs are required.
450      *  One for sending request and one for sending response.
451      */
452     if (ti_sdo_utils_MultiProc_numProcessors > 1) {
453         return (2 * sizeof(NameServerRemoteNotify_Message));
454     }
456     return (0);
459 /*
460  *  ======== NameServerRemoteNotify_swiFxnRequest ========
461  */
462 Void NameServerRemoteNotify_swiFxnRequest(UArg arg)
464     Int count = NameServer_E_FAIL;
465     Int remoteId;
466     UInt32 valueLen;
467     NameServer_Handle handle;
468     NameServerRemoteNotify_Object *obj;
469 #ifndef xdc_runtime_Assert_DISABLE_ALL
470     Int status;
471 #endif
473     obj = (NameServerRemoteNotify_Object *)arg;
475     /* compute index to remote message */
476     remoteId = (MultiProc_self() > obj->remoteProcId) ? 0 : 1;
478     if (obj->cacheEnable) {
479         Cache_inv(obj->msg[remoteId], sizeof(NameServerRemoteNotify_Message),
480                 Cache_Type_ALL, TRUE);
481     }
483     /* get the NameServer handle */
484     handle = NameServer_getHandle((String)obj->msg[remoteId]->instanceName);
485     valueLen = obj->msg[remoteId]->valueLen;
487     if (handle != NULL) {
488         /* Search for the NameServer entry */
489         if (valueLen == sizeof(UInt32)) {
490             count = NameServer_getLocalUInt32(handle,
491                 (String)obj->msg[remoteId]->name, &obj->msg[remoteId]->value);
492         }
493         else {
494             count = NameServer_getLocal(handle,
495                 (String)obj->msg[remoteId]->name,
496                 &obj->msg[remoteId]->valueBuf, &valueLen);
497         }
498     }
500     /*
501      *  If an entry was found, set requestStatus to TRUE
502      *  and valueLen to the size of data that was copied.
503      */
504     if (count == NameServer_S_SUCCESS) {
505         obj->msg[remoteId]->requestStatus = TRUE;
506         obj->msg[remoteId]->valueLen = valueLen;
507     }
509     /* set object state (used by ROV) */
510     obj->remoteState = NameServerRemoteNotify_SEND_RESPONSE;
512     if (obj->cacheEnable) {
513         Cache_wbInv(obj->msg[remoteId], sizeof(NameServerRemoteNotify_Message),
514                 Cache_Type_ALL, TRUE);
515     }
517     /* must wait to prevent dropped events, even though this is a swi */
518 #ifndef xdc_runtime_Assert_DISABLE_ALL
519     status =
520 #endif
521     Notify_sendEvent(obj->remoteProcId, 0,
522             NameServerRemoteNotify_notifyEventId,
523             NameServerRemoteNotify_ResponseMsg, TRUE);
525     /* The NS query could fail, but the reply should never fail */
526     Assert_isTrue(status >= 0, Ipc_A_internal);
528     /* set object state (used by ROV) */
529     obj->remoteState = NameServerRemoteNotify_IDLE;
532 /*
533  *  ======== NameServerRemoteNotify_swiFxnResponse ========
534  */
535 Void NameServerRemoteNotify_swiFxnResponse(UArg arg)
537     NameServerRemoteNotify_Object *obj;
538     Semaphore_Handle  sem;
540     obj = (NameServerRemoteNotify_Object *)arg;
542     /* post the semaphore to unblock waiting task */
543     sem = NameServerRemoteNotify_Instance_State_semRemoteWait(obj);
544     Semaphore_post(sem);
547 /*
548  *  ======== NameServerRemoteNotify_getHandle ========
549  */
550 NameServerRemoteNotify_Handle NameServerRemoteNotify_getHandle(
551     UInt16 remoteProcId)
553     NameServerRemoteNotify_Handle obj;
555     for (obj = NameServerRemoteNotify_Object_first(); obj != NULL;
556         obj = NameServerRemoteNotify_Object_next(obj)) {
557         if (obj->remoteProcId == remoteProcId) {
558             break;
559         }
560     }
562     return (obj);