summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 66a45ee)
raw | patch | inline | side by side (parent: 66a45ee)
author | Justin Sobota <jsobota@ti.com> | |
Thu, 14 Mar 2013 21:50:40 +0000 (17:50 -0400) | ||
committer | Justin Sobota <jsobota@ti.com> | |
Thu, 14 Mar 2013 21:50:40 +0000 (17:50 -0400) |
26 files changed:
index d05570bd689588a5d21d83dbf80674520057f198..f7ae7f4dab9ebc86fd33569266c0c0b526b6ee44 100644 (file)
0xed,
0x00,
0x00,
-0x0a,
-0xe4,
+0x0b,
+0x20,
0x00,
0x00,
0x00,
0x38,
0x00,
0x00,
-0x0a,
-0xc8,
+0x0b,
+0x04,
0x00,
0x00,
0x00,
0x00,
0x00,
0x0a,
-0x90,
+0xcc,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
-0x27,
+0x62,
0x00,
0x00,
0x00,
0x65,
0x6e,
0x74,
+0x30,
+0x00,
+0x52,
+0x4d,
0x5f,
-0x44,
+0x43,
+0x6c,
+0x69,
0x65,
+0x6e,
+0x74,
+0x31,
+0x00,
+0x52,
+0x4d,
+0x5f,
+0x43,
0x6c,
+0x69,
0x65,
-0x67,
-0x61,
+0x6e,
0x74,
+0x32,
+0x00,
+0x52,
+0x4d,
+0x5f,
+0x43,
+0x6c,
+0x69,
0x65,
+0x6e,
+0x74,
+0x33,
+0x00,
+0x52,
+0x4d,
+0x5f,
+0x43,
+0x6c,
+0x69,
+0x65,
+0x6e,
+0x74,
+0x34,
+0x00,
+0x52,
+0x4d,
+0x5f,
+0x43,
+0x6c,
+0x69,
+0x65,
+0x6e,
+0x74,
+0x35,
+0x00,
+0x52,
+0x4d,
+0x5f,
+0x43,
+0x6c,
+0x69,
+0x65,
+0x6e,
+0x74,
+0x36,
0x00,
0x52,
0x4d,
0x65,
0x6e,
0x74,
+0x37,
+0x00,
0x00,
0x00,
0x00,
index 7ff0dc33579f71246e288d5a9ed868b25b1067cc..d36b14e568ba2b294a528379e6c820596c0e1ac7 100644 (file)
Binary files a/device/k2h/policy_dsp-only.dtb and b/device/k2h/policy_dsp-only.dtb differ
Binary files a/device/k2h/policy_dsp-only.dtb and b/device/k2h/policy_dsp-only.dtb differ
index e09c5e2fcdaeccdfa8ab2a7dc63d352eb9029f54..90f242c38163c2615f62d4bad90abfbddb8d697d 100644 (file)
* RM. For an RM instance to be given permissions the name used to initialize it
* must be present in this list */
valid-instances = "RM_Server",
- "RM_Client_Delegate",
- "RM_Client";
+ "RM_Client0",
+ "RM_Client1",
+ "RM_Client2",
+ "RM_Client3",
+ "RM_Client4",
+ "RM_Client5",
+ "RM_Client6",
+ "RM_Client7";
qmss {
linkram-control {
index 3523c1bfd85e2fbbeafb1be4e70ca57bc2dc6efb..5783f58bf96a2b07cb84312a03f343932a679d8f 100644 (file)
0x00,
0x00,
0x0b,
-0x90,
+0xcc,
0x00,
0x00,
0x00,
0x00,
0x00,
0x0b,
-0x74,
+0xb0,
0x00,
0x00,
0x00,
0x00,
0x00,
0x0b,
-0x3c,
+0x78,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
-0x27,
+0x62,
0x00,
0x00,
0x00,
0x65,
0x6e,
0x74,
+0x30,
+0x00,
+0x52,
+0x4d,
0x5f,
-0x44,
+0x43,
+0x6c,
+0x69,
0x65,
+0x6e,
+0x74,
+0x31,
+0x00,
+0x52,
+0x4d,
+0x5f,
+0x43,
0x6c,
+0x69,
0x65,
-0x67,
-0x61,
+0x6e,
0x74,
+0x32,
+0x00,
+0x52,
+0x4d,
+0x5f,
+0x43,
+0x6c,
+0x69,
0x65,
+0x6e,
+0x74,
+0x33,
0x00,
0x52,
0x4d,
0x65,
0x6e,
0x74,
+0x34,
+0x00,
+0x52,
+0x4d,
+0x5f,
+0x43,
+0x6c,
+0x69,
+0x65,
+0x6e,
+0x74,
+0x35,
+0x00,
+0x52,
+0x4d,
+0x5f,
+0x43,
+0x6c,
+0x69,
+0x65,
+0x6e,
+0x74,
+0x36,
+0x00,
+0x52,
+0x4d,
+0x5f,
+0x43,
+0x6c,
+0x69,
+0x65,
+0x6e,
+0x74,
+0x37,
+0x00,
0x00,
0x00,
0x00,
index a16d74d775d7c81570579ae4b6552b336e9ce1fe..98fdfe2cd7316443e0389858609bbe7ddca4333e 100644 (file)
Binary files a/device/k2h/policy_dsp_arm.dtb and b/device/k2h/policy_dsp_arm.dtb differ
Binary files a/device/k2h/policy_dsp_arm.dtb and b/device/k2h/policy_dsp_arm.dtb differ
index b071a3fb04a6f3272740e0d1477d0319369baaae..4eb3b64293150e812ce0009279d14cae9ab22130 100644 (file)
* RM. For an RM instance to be given permissions the name used to initialize it
* must be present in this list */
valid-instances = "RM_Server",
- "RM_Client_Delegate",
- "RM_Client";
+ "RM_Client0",
+ "RM_Client1",
+ "RM_Client2",
+ "RM_Client3",
+ "RM_Client4",
+ "RM_Client5",
+ "RM_Client6",
+ "RM_Client7";
qmss {
linkram-control {
index d05570bd689588a5d21d83dbf80674520057f198..f7ae7f4dab9ebc86fd33569266c0c0b526b6ee44 100644 (file)
0xed,
0x00,
0x00,
-0x0a,
-0xe4,
+0x0b,
+0x20,
0x00,
0x00,
0x00,
0x38,
0x00,
0x00,
-0x0a,
-0xc8,
+0x0b,
+0x04,
0x00,
0x00,
0x00,
0x00,
0x00,
0x0a,
-0x90,
+0xcc,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
-0x27,
+0x62,
0x00,
0x00,
0x00,
0x65,
0x6e,
0x74,
+0x30,
+0x00,
+0x52,
+0x4d,
0x5f,
-0x44,
+0x43,
+0x6c,
+0x69,
0x65,
+0x6e,
+0x74,
+0x31,
+0x00,
+0x52,
+0x4d,
+0x5f,
+0x43,
0x6c,
+0x69,
0x65,
-0x67,
-0x61,
+0x6e,
0x74,
+0x32,
+0x00,
+0x52,
+0x4d,
+0x5f,
+0x43,
+0x6c,
+0x69,
0x65,
+0x6e,
+0x74,
+0x33,
+0x00,
+0x52,
+0x4d,
+0x5f,
+0x43,
+0x6c,
+0x69,
+0x65,
+0x6e,
+0x74,
+0x34,
+0x00,
+0x52,
+0x4d,
+0x5f,
+0x43,
+0x6c,
+0x69,
+0x65,
+0x6e,
+0x74,
+0x35,
+0x00,
+0x52,
+0x4d,
+0x5f,
+0x43,
+0x6c,
+0x69,
+0x65,
+0x6e,
+0x74,
+0x36,
0x00,
0x52,
0x4d,
0x65,
0x6e,
0x74,
+0x37,
+0x00,
0x00,
0x00,
0x00,
index 7ff0dc33579f71246e288d5a9ed868b25b1067cc..d36b14e568ba2b294a528379e6c820596c0e1ac7 100644 (file)
Binary files a/device/k2k/policy_dsp-only.dtb and b/device/k2k/policy_dsp-only.dtb differ
Binary files a/device/k2k/policy_dsp-only.dtb and b/device/k2k/policy_dsp-only.dtb differ
index e09c5e2fcdaeccdfa8ab2a7dc63d352eb9029f54..90f242c38163c2615f62d4bad90abfbddb8d697d 100644 (file)
* RM. For an RM instance to be given permissions the name used to initialize it
* must be present in this list */
valid-instances = "RM_Server",
- "RM_Client_Delegate",
- "RM_Client";
+ "RM_Client0",
+ "RM_Client1",
+ "RM_Client2",
+ "RM_Client3",
+ "RM_Client4",
+ "RM_Client5",
+ "RM_Client6",
+ "RM_Client7";
qmss {
linkram-control {
index 3523c1bfd85e2fbbeafb1be4e70ca57bc2dc6efb..5783f58bf96a2b07cb84312a03f343932a679d8f 100644 (file)
0x00,
0x00,
0x0b,
-0x90,
+0xcc,
0x00,
0x00,
0x00,
0x00,
0x00,
0x0b,
-0x74,
+0xb0,
0x00,
0x00,
0x00,
0x00,
0x00,
0x0b,
-0x3c,
+0x78,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
-0x27,
+0x62,
0x00,
0x00,
0x00,
0x65,
0x6e,
0x74,
+0x30,
+0x00,
+0x52,
+0x4d,
0x5f,
-0x44,
+0x43,
+0x6c,
+0x69,
0x65,
+0x6e,
+0x74,
+0x31,
+0x00,
+0x52,
+0x4d,
+0x5f,
+0x43,
0x6c,
+0x69,
0x65,
-0x67,
-0x61,
+0x6e,
0x74,
+0x32,
+0x00,
+0x52,
+0x4d,
+0x5f,
+0x43,
+0x6c,
+0x69,
0x65,
+0x6e,
+0x74,
+0x33,
0x00,
0x52,
0x4d,
0x65,
0x6e,
0x74,
+0x34,
+0x00,
+0x52,
+0x4d,
+0x5f,
+0x43,
+0x6c,
+0x69,
+0x65,
+0x6e,
+0x74,
+0x35,
+0x00,
+0x52,
+0x4d,
+0x5f,
+0x43,
+0x6c,
+0x69,
+0x65,
+0x6e,
+0x74,
+0x36,
+0x00,
+0x52,
+0x4d,
+0x5f,
+0x43,
+0x6c,
+0x69,
+0x65,
+0x6e,
+0x74,
+0x37,
+0x00,
0x00,
0x00,
0x00,
index a16d74d775d7c81570579ae4b6552b336e9ce1fe..98fdfe2cd7316443e0389858609bbe7ddca4333e 100644 (file)
Binary files a/device/k2k/policy_dsp_arm.dtb and b/device/k2k/policy_dsp_arm.dtb differ
Binary files a/device/k2k/policy_dsp_arm.dtb and b/device/k2k/policy_dsp_arm.dtb differ
index b071a3fb04a6f3272740e0d1477d0319369baaae..4eb3b64293150e812ce0009279d14cae9ab22130 100644 (file)
* RM. For an RM instance to be given permissions the name used to initialize it
* must be present in this list */
valid-instances = "RM_Server",
- "RM_Client_Delegate",
- "RM_Client";
+ "RM_Client0",
+ "RM_Client1",
+ "RM_Client2",
+ "RM_Client3",
+ "RM_Client4",
+ "RM_Client5",
+ "RM_Client6",
+ "RM_Client7";
qmss {
linkram-control {
diff --git a/include/rm_internal.h b/include/rm_internal.h
index 9d27365a8a4ca82f68c780b8b9d529dd1a5b7028..5923cabaf69688d46bbf741b4d61d006de2dfccf 100644 (file)
--- a/include/rm_internal.h
+++ b/include/rm_internal.h
/* RM external includes */
#include <ti/drv/rm/rm.h>
+/* RM OSAL layer */
+#include <rm_osal.h>
+
/* RM true/false definitions */
#define RM_FALSE 0
#define RM_TRUE 1
+/* Shared server enter critical section macro */
+#define RM_SS_INST_INV_ENTER_CS(csKey) \
+ Rm_osalBeginMemAccess((void *)rmInst, sizeof(Rm_Inst)); \
+ if (rmInst->instType == Rm_instType_SHARED_SERVER) { \
+ csKey = Rm_osalCsEnter(); \
+ }
+
+/* Shared server exit critical section macro */
+#define RM_SS_INST_WB_EXIT_CS(csKey) \
+ if (rmInst->instType == Rm_instType_SHARED_SERVER) { \
+ Rm_osalEndMemAccess((void *)rmInst, sizeof(Rm_Inst)); \
+ Rm_osalCsExit(csKey); \
+ }
+
+/* Shared server invalidate macro */
+#define RM_SS_OBJ_INV(obj, objType) \
+ if (rmInst->instType == Rm_instType_SHARED_SERVER) { \
+ Rm_osalBeginMemAccess((void *)obj, sizeof(objType)); \
+ }
+
+/* Shared server writeback macro */
+#define RM_SS_OBJ_WB(obj, objType) \
+ if (rmInst->instType == Rm_instType_SHARED_SERVER) { \
+ Rm_osalEndMemAccess((void *)obj, sizeof(objType)); \
+ }
+
/* RM resource information */
typedef struct {
/* Resource name */
index d4d44182427e547cab8af91d7b1eff9124053091..04b83b89918aaa8f23581faf461a61c40c8a33ac 100644 (file)
extern "C" {
#endif
+/* RM external API includes */
+#include <ti/drv/rm/rm.h>
+
/* RM internal includes */
#include <ti/drv/rm/include/rm_treeloc.h>
int32_t rmNameServerAddObject(Rm_NameServerObjCfg *objCfg);
int32_t rmNameServerFindObject(Rm_NameServerObjCfg *objCfg);
int32_t rmNameServerDeleteObject(Rm_NameServerObjCfg *objCfg);
-void rmNameServerPrintObjects(Rm_NameServerTree *nameServerTree);
-Rm_NameServerTree *rmNameServerInit(void);
-void rmNameServerDelete(Rm_NameServerTree *nameServerTree);
+void rmNameServerPrintObjects(Rm_Handle rmHandle);
+void rmNameServerInit(Rm_Handle rmHandle);
+void rmNameServerDelete(Rm_Handle rmHandle);
#ifdef __cplusplus
}
diff --git a/include/rm_treeloc.h b/include/rm_treeloc.h
index 1fae8c8135602a499e58a4707c24aadb53c6e264..bc743703fb7a9445a74c481139a45f37cd5d07c8 100644 (file)
--- a/include/rm_treeloc.h
+++ b/include/rm_treeloc.h
****************** Tree Node Function Definitions ********************
**********************************************************************/
+void rmNameServerTreeInv(Rm_NameServerTree *treeRoot);
+void rmNameServerTreeWb(Rm_NameServerTree *treeRoot);
Rm_NameServerNode *rmNameServerNodeNew(Rm_NameServerNodeCfg *nodeCfg);
void rmNameServerNodeFree(Rm_NameServerNode *node);
int rmNameServerNodeCompare(Rm_NameServerNode *node1, Rm_NameServerNode *node2);
+void rmNameServerNodeInv(Rm_NameServerNode *node);
+void rmPolicyValidInstTreeInv(Rm_PolicyValidInstTree *treeRoot);
+void rmPolicyValidInstTreeWb(Rm_PolicyValidInstTree *treeRoot);
Rm_PolicyValidInstNode *rmPolicyValidInstNodeNew(char *instName);
void rmPolicyValidInstNodeFree(Rm_PolicyValidInstNode *node);
-int rmPolicyValidInstNodeCompare(Rm_PolicyValidInstNode *node1, Rm_PolicyValidInstNode *node2);
+int rmPolicyValidInstNodeCompare(Rm_PolicyValidInstNode *node1, Rm_PolicyValidInstNode *node2);
+void rmPolicyValidInstNodeInv(Rm_PolicyValidInstNode *node);
+void rmResourceTreeInv(Rm_ResourceTree *treeRoot);
+void rmResourceTreeWb(Rm_ResourceTree *treeRoot);
Rm_ResourceNode *rmResourceNodeNew(uint32_t resourceBase, uint32_t resourceLength);
void rmResourceNodeFree(Rm_ResourceNode *node);
-int rmResourceNodeCompare(Rm_ResourceNode *node1, Rm_ResourceNode *node2);
+int rmResourceNodeCompare(Rm_ResourceNode *node1, Rm_ResourceNode *node2);
+void rmResourceNodeInv(Rm_ResourceNode *node);
/**********************************************************************
******************** Tree Prototype Generation ***********************
**********************************************************************/
-RB_PROTOTYPE(_Rm_NameServerTree, _Rm_NameServerNode, linkage, rmNameServerNodeCompare)
-RB_PROTOTYPE(_Rm_PolicyValidInstTree, _Rm_PolicyValidInstNode, linkage, rmPolicyValidInstNodeCompare)
-RB_PROTOTYPE(_Rm_AllocatorResourceTree, _Rm_ResourceNode, linkage, rmResourceNodeCompare)
+RB_PROTOTYPE(_Rm_NameServerTree, _Rm_NameServerNode, linkage, rmNameServerNodeCompare, rmNameServerNodeInv)
+RB_PROTOTYPE(_Rm_PolicyValidInstTree, _Rm_PolicyValidInstNode, linkage, rmPolicyValidInstNodeCompare, rmPolicyValidInstNodeInv)
+RB_PROTOTYPE(_Rm_AllocatorResourceTree, _Rm_ResourceNode, linkage, rmResourceNodeCompare, rmResourceNodeInv)
#ifdef __cplusplus
}
index 3f85dbf7405b5a74537338f35618f3a61773d1d9..1fe43462859a01a4dd7ac26cf392c2e0f143902e 100644 (file)
--- a/rm.h
+++ b/rm.h
#define RM_ERROR_GRL_INVALID_LINUX_ALIAS_FORMAT RM_ERROR_BASE-14
/** Error allocating memory for the service handle */
#define RM_ERROR_SERVICE_HANDLE_MEM_ALLOC_FAILED RM_ERROR_BASE-15
-/** The RM instance service handle has already been opened */
-#define RM_ERROR_SERVICE_HANDLE_ALREADY_OPENED RM_ERROR_BASE-16
/** The RM instance service handle has already been closed */
-#define RM_ERROR_SERVICE_HANDLE_ALREADY_CLOSED RM_ERROR_BASE-17
+#define RM_ERROR_SERVICE_HANDLE_ALREADY_CLOSED RM_ERROR_BASE-16
/** Global Resource List (GRL) resource node contains an unknown property */
-#define RM_ERROR_GRL_UNKNOWN_RESOURCE_PROPERTY RM_ERROR_BASE-18
+#define RM_ERROR_GRL_UNKNOWN_RESOURCE_PROPERTY RM_ERROR_BASE-17
/** Could not find an allocator for the specified resource */
-#define RM_ERROR_RES_ALLOCATOR_DOES_NOT_EXIST RM_ERROR_BASE-19
+#define RM_ERROR_RES_ALLOCATOR_DOES_NOT_EXIST RM_ERROR_BASE-18
/** A resource node is specified more than once in the Global Resource List (GRL) */
-#define RM_ERROR_GRL_RES_SPECIFIED_MORE_THAN_ONCE RM_ERROR_BASE-20
+#define RM_ERROR_GRL_RES_SPECIFIED_MORE_THAN_ONCE RM_ERROR_BASE-19
/** No data was found at the GRL resource node's specified Linux alias path */
-#define RM_ERROR_DATA_NOT_FOUND_AT_LINUX_ALIAS RM_ERROR_BASE-21
+#define RM_ERROR_DATA_NOT_FOUND_AT_LINUX_ALIAS RM_ERROR_BASE-20
/** RM server was not provided a Global Resource List (GRL) and global policy at initialization */
-#define RM_ERROR_INVALID_SERVER_CONFIGURATION RM_ERROR_BASE-22
+#define RM_ERROR_INVALID_SERVER_CONFIGURATION RM_ERROR_BASE-21
/** Service request type not recognized */
-#define RM_ERROR_INVALID_SERVICE_TYPE RM_ERROR_BASE-23
+#define RM_ERROR_INVALID_SERVICE_TYPE RM_ERROR_BASE-22
/** rmAllocPkt transport callout returned NULL for rmPkt */
-#define RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR RM_ERROR_BASE-24
+#define RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR RM_ERROR_BASE-23
/** rmSendPkt transport callout returned error when attempting to send the rmPkt */
-#define RM_ERROR_TRANSPORT_SEND_ERROR RM_ERROR_BASE-25
+#define RM_ERROR_TRANSPORT_SEND_ERROR RM_ERROR_BASE-24
/** A RM service transaction could not be created for the service request */
-#define RM_ERROR_SERVICE_TRANS_NOT_CREATED RM_ERROR_BASE-26
+#define RM_ERROR_SERVICE_TRANS_NOT_CREATED RM_ERROR_BASE-25
/** RM service transaction could not be found in instance's transaction queue */
-#define RM_ERROR_SERVICE_TRANS_DOES_NOT_EXIST RM_ERROR_BASE-27
+#define RM_ERROR_SERVICE_TRANS_DOES_NOT_EXIST RM_ERROR_BASE-26
/** NameServer does not exist in instance, cannot satisfy NameServer service request */
-#define RM_ERROR_NAMESERVER_DOES_NOT_EXIST RM_ERROR_BASE-28
+#define RM_ERROR_NAMESERVER_DOES_NOT_EXIST RM_ERROR_BASE-27
/** Service request to add a name to the NameServer failed */
-#define RM_ERROR_NAMESERVER_NAME_ADD_FAILED RM_ERROR_BASE-29
+#define RM_ERROR_NAMESERVER_NAME_ADD_FAILED RM_ERROR_BASE-28
/** Could not find name specified in service request in NameServer */
-#define RM_ERROR_NAMESERVER_NAME_DOES_NOT_EXIST RM_ERROR_BASE-30
+#define RM_ERROR_NAMESERVER_NAME_DOES_NOT_EXIST RM_ERROR_BASE-29
/** Service request made on Client or CD when no transport established and no static policy registered */
-#define RM_ERROR_REQ_FAILED_NO_STATIC_POLICY RM_ERROR_BASE-31
+#define RM_ERROR_REQ_FAILED_NO_STATIC_POLICY RM_ERROR_BASE-30
/** RM transport handle has not been registered with the RM instance */
-#define RM_ERROR_TRANSPORT_HANDLE_DOES_NOT_EXIST RM_ERROR_BASE-32
+#define RM_ERROR_TRANSPORT_HANDLE_DOES_NOT_EXIST RM_ERROR_BASE-31
/** RM received a packet with an unknown RM packet type */
-#define RM_ERROR_RECEIVED_INVALID_PACKET_TYPE RM_ERROR_BASE-33
+#define RM_ERROR_RECEIVED_INVALID_PACKET_TYPE RM_ERROR_BASE-32
/** RM response packet does not match any requests sent from instance */
-#define RM_ERROR_PKT_RESP_DOES_NOT_MATCH_ANY_REQ RM_ERROR_BASE-34
+#define RM_ERROR_PKT_RESP_DOES_NOT_MATCH_ANY_REQ RM_ERROR_BASE-33
/** Server attempted to connect to another server or a CD attempted to connect to another CD or
* Client attempted to connect to another client */
-#define RM_ERROR_INVALID_REMOTE_INST_TYPE RM_ERROR_BASE-35
+#define RM_ERROR_INVALID_REMOTE_INST_TYPE RM_ERROR_BASE-34
/** RM client attempted to register with more than one Server or CD or a CD attempted to register
* with more than one Server */
-#define RM_ERROR_ALREADY_REGD_SERVER_OR_CD RM_ERROR_BASE-36
+#define RM_ERROR_ALREADY_REGD_SERVER_OR_CD RM_ERROR_BASE-35
/** Service has both a NameServer name and a base, length, or alignment specified */
-#define RM_ERROR_NS_NAME_AND_RES_VAL_CONFLICT RM_ERROR_BASE-37
+#define RM_ERROR_NS_NAME_AND_RES_VAL_CONFLICT RM_ERROR_BASE-36
/** Instance type not recognized */
-#define RM_ERROR_INVALID_INST_TYPE RM_ERROR_BASE-38
+#define RM_ERROR_INVALID_INST_TYPE RM_ERROR_BASE-37
/** Linux DTB alias properties specified in GRL but no Linux DTB provided during server instance init */
-#define RM_ERROR_GRL_LINUX_ALIAS_BUT_NO_DTB RM_ERROR_BASE-39
+#define RM_ERROR_GRL_LINUX_ALIAS_BUT_NO_DTB RM_ERROR_BASE-38
/** RM attempted to allocate a transport packet but the rmAllocPkt callout was not registered */
-#define RM_ERROR_TRANSPORT_ALLOC_PKT_NOT_REGD RM_ERROR_BASE-40
+#define RM_ERROR_TRANSPORT_ALLOC_PKT_NOT_REGD RM_ERROR_BASE-39
/** RM attempted to send a packet but the rmSendPkt callout was not registered */
-#define RM_ERROR_TRANSPORT_SEND_NOT_REGD RM_ERROR_BASE-41
+#define RM_ERROR_TRANSPORT_SEND_NOT_REGD RM_ERROR_BASE-40
/** RM attempted to send a response packet but the transport to the remote instance that sent
* the request packet is not registered */
-#define RM_ERROR_TRANSPORT_REMOTE_HNDL_NOT_REGD RM_ERROR_BASE-42
+#define RM_ERROR_TRANSPORT_REMOTE_HNDL_NOT_REGD RM_ERROR_BASE-41
/** RM instance cannot be deleted with transports still registered */
-#define RM_ERROR_CANT_DELETE_WITH_REGD_TRANSPORT RM_ERROR_BASE-43
+#define RM_ERROR_CANT_DELETE_WITH_REGD_TRANSPORT RM_ERROR_BASE-42
/** RM instance cannot be deleted with open service handle */
-#define RM_ERROR_CANT_DELETE_WITH_OPEN_SERV_HNDL RM_ERROR_BASE-44
+#define RM_ERROR_CANT_DELETE_WITH_OPEN_SERV_HNDL RM_ERROR_BASE-43
/** RM instance cannot be deleted when there are transactions pending and the
* ignorePendingServices parameter is set to false */
-#define RM_ERROR_CANT_DELETE_PENDING_TRANSACTIONS RM_ERROR_BASE-45
+#define RM_ERROR_CANT_DELETE_PENDING_TRANSACTIONS RM_ERROR_BASE-44
/** Only the Server instance can be used to return resource status via the
* Rm_resourceStatus API */
-#define RM_ERROR_INVALID_RES_STATUS_INSTANCE RM_ERROR_BASE-46
+#define RM_ERROR_INVALID_RES_STATUS_INSTANCE RM_ERROR_BASE-45
+/** RM Shared Server instances should always return a finished request since the instance has
+ * access to the resource structures no matter what core the service is requested from */
+#define RM_ERROR_SHARED_SERVER_UNFINISHED_REQ RM_ERROR_BASE-46
+/** RM Shared Server instances cannot register transports */
+#define RM_ERROR_SHARED_SERVER_CANNOT_REG_TRANS RM_ERROR_BASE-47
/**
* @brief Maximum number of characters allowed for RM instance, resource, and
Rm_instType_CLIENT_DELEGATE,
/** RM Client */
Rm_instType_CLIENT,
+ /** RM Shared Server - Server instance stored in shared memory that allows
+ * multiple DSP cores to request services without the need to configure
+ * and register transports. Allows requests to be fulfilled from any DSP
+ * core without blocking */
+ Rm_instType_SHARED_SERVER,
/** DO NOT USE: Last type */
Rm_instType_LAST
} Rm_InstType;
/**
- * @brief RM server initialization configurations
+ * @brief RM server (includes shared server) initialization configurations
*/
typedef struct {
/** Pointer to the device global resource list (GRL). The GRL contains
* result in a new RM instance. However, a network of RM instances
* can have only one RM Server. If an application has multiple RM
* Servers the resources managed by each server must be mutually
- * exclusive.
+ * exclusive. Additionally if an application has multiple RM shared
+ * servers the resources they manage must be mutually exclusive as well
*
* If any errors are encountered during the initialization process
* the Rm_Handle returned will be NULL.
diff --git a/rm_osal.h b/rm_osal.h
index 8825204def9eb63dd86ce62625397f2d58c34dd6..e9245768b3ba94c812cf0f339b554dd42d28c99d 100644 (file)
--- a/rm_osal.h
+++ b/rm_osal.h
extern void *Osal_rmMalloc (uint32_t num_bytes);
extern void Osal_rmFree (void *ptr, uint32_t size);
+extern void *Osal_rmCsEnter (void);
+extern void Osal_rmCsExit (void *CsHandle);
+extern void Osal_rmBeginMemAccess (void *ptr, uint32_t size);
+extern void Osal_rmEndMemAccess (void *ptr, uint32_t size);
extern void *Osal_rmTaskBlockCreate (void);
extern void Osal_rmTaskBlock (void *handle);
extern void Osal_rmTaskUnblock (void *handle);
*/
#define Rm_osalFree Osal_rmFree
+/**
+ * @brief The function is used to enter a critical section.
+ * Function protects against
+ *
+ * access from multiple cores
+ * and
+ * access from multiple threads on single core
+ *
+ * <b> Prototype: </b>
+ * The following is the C prototype for the expected OSAL API.
+ *
+ * @verbatim
+ void *Osal_rmCsEnter (void)
+ @endverbatim
+ *
+ * <b> Parameter </b>
+ * @n Not applicable.
+ *
+ * <b> Return Value </b>
+ * @n Handle used to lock critical section
+ */
+#define Rm_osalCsEnter Osal_rmCsEnter
+
+/**
+ * @brief The function is used to exit a critical section
+ * protected using Osal_rmCsEnter() API.
+ *
+ * <b> Prototype: </b>
+ * The following is the C prototype for the expected OSAL API.
+ *
+ * @verbatim
+ void Osal_rmCsExit (void *CsHandle)
+ @endverbatim
+ *
+ * <b> Parameter </b>
+ * @n Handle for unlocking critical section.
+ *
+ * <b> Return Value </b>
+ * @n Not applicable.
+ */
+#define Rm_osalCsExit Osal_rmCsExit
+
+/**
+ * @brief The function is used to indicate that a block of memory is
+ * about to be accessed. If the memory block is cached then this
+ * indicates that the application would need to ensure that the
+ * cache is updated with the data from the actual memory.
+ *
+ * <b> Prototype: </b>
+ * The following is the C prototype for the expected OSAL API.
+ *
+ * @verbatim
+ void Osal_rmBeginMemAccess (void *ptr, uint32_t size)
+ @endverbatim
+ *
+ * <b> Parameter </b>
+ * @n Address of memory block
+ * @n Size of memory block
+ *
+ * <b> Return Value </b>
+ * @n Not applicable.
+ */
+#define Rm_osalBeginMemAccess Osal_rmBeginMemAccess
+
+/**
+ * @brief The function is used to indicate that the block of memory has
+ * finished being accessed. If the memory block is cached then the
+ * application would need to ensure that the contents of the cache
+ * are updated immediately to the actual memory.
+ *
+ * <b> Prototype: </b>
+ * The following is the C prototype for the expected OSAL API.
+ *
+ * @verbatim
+ void Osal_rmEndMemAccess (void *ptr, uint32_t size)
+ @endverbatim
+ *
+ * <b> Parameter </b>
+ * @n Address of memory block
+ * @n Size of memory block
+ *
+ * <b> Return Value </b>
+ * @n Not applicable.
+ */
+#define Rm_osalEndMemAccess Osal_rmEndMemAccess
+
/**
* @brief The macro is used by RM to create a task blocking
* mechanism allowing a RM instance to block when it
diff --git a/src/rm.c b/src/rm.c
index 82441b0806334783d9c0179ddb69c189a8387745..f805f8cd359d46b75dce09cc67f2e7c2b120ae60 100644 (file)
--- a/src/rm.c
+++ b/src/rm.c
#include <ti/drv/rm/rm_transport.h>
/* RM internal includes */
+#include <ti/drv/rm/include/rm_internal.h>
#include <ti/drv/rm/include/rm_loc.h>
#include <ti/drv/rm/include/rm_allocatorloc.h>
#include <ti/drv/rm/include/rm_transportloc.h>
************************** Globals ***********************************
**********************************************************************/
-/** @brief Global Variable which describes the RM Version Information */
+/* Global Variable which describes the RM Version Information */
const char rmVersionStr[] = RM_VERSION_STR ":" __DATE__ ":" __TIME__;
/**********************************************************************
if ((transaction->resourceInfo.base == 0) &&
(transaction->resourceInfo.length == 0) &&
(transaction->resourceInfo.alignment == 0)) {
+ if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+ rmNameServerTreeInv(rmInst->u.server.nameServer);
+ }
memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
if ((transaction->resourceInfo.base == 0) &&
(transaction->resourceInfo.length == 0) &&
(transaction->resourceInfo.alignment == 0)) {
+ if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+ rmNameServerTreeInv(rmInst->u.server.nameServer);
+ }
memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
case Rm_service_RESOURCE_GET_BY_NAME:
case Rm_service_RESOURCE_UNMAP_NAME:
if (rmInst->u.server.nameServer) {
+ if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+ rmNameServerTreeInv(rmInst->u.server.nameServer);
+ }
memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {
transaction->state = rmNameServerDeleteObject(&nameServerObjCfg);
}
+
+ if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+ rmNameServerTreeWb(rmInst->u.server.nameServer);
+ }
}
else {
transaction->state = RM_ERROR_NAMESERVER_DOES_NOT_EXIST;
int32_t Rm_resourceStatus(Rm_Handle rmServerHandle, int printResources)
{
Rm_Inst *rmInst = (Rm_Inst *)rmServerHandle;
- Rm_Allocator *allocator = rmInst->u.server.allocators;
+ Rm_Allocator *allocator = NULL;
Rm_Owner *owners;
Rm_ResourceTree *treeRoot;
Rm_ResourceNode *treeNode;
int32_t totalResOwners = 0;
+ void *key;
- if (rmInst->instType == Rm_instType_SERVER) {
+ RM_SS_INST_INV_ENTER_CS(key);
+
+ if ((rmInst->instType == Rm_instType_SERVER) ||
+ (rmInst->instType == Rm_instType_SHARED_SERVER)) {
+ allocator = rmInst->u.server.allocators;
while (allocator) {
+ RM_SS_OBJ_INV(allocator, Rm_Allocator);
if (printResources) {
Rm_osalLog("Resource: %s\n", allocator->resourceName);
}
treeRoot = allocator->allocatorRootEntry;
-
+ RM_SS_OBJ_INV(treeRoot, Rm_ResourceTree);
+ if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+ rmResourceTreeInv(treeRoot);
+ }
RB_FOREACH(treeNode, _Rm_AllocatorResourceTree, treeRoot) {
if (printResources) {
if ((treeNode->base >= 65536) ||
else {
owners = treeNode->ownerList;
while (owners) {
+ RM_SS_OBJ_INV(owners, Rm_Owner);
if (printResources) {
Rm_osalLog("%s ", owners->instNameNode->name);
}
}
}
}
- allocator = allocator->nextAllocator;
+ allocator = allocator->nextAllocator;
}
if (printResources) {
- rmNameServerPrintObjects(rmInst->u.server.nameServer);
+ rmNameServerPrintObjects((Rm_Handle)rmInst);
}
}
else {
totalResOwners = RM_ERROR_INVALID_RES_STATUS_INSTANCE;
- }
+ }
+ RM_SS_INST_WB_EXIT_CS(key);
return(totalResOwners);
}
void Rm_instanceStatus(Rm_Handle rmHandle)
{
Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
- Rm_Transport *transportList = rmInst->transports;
- Rm_Transaction *transactionQ = rmInst->transactionQueue;
+ Rm_Transport *transportList = NULL;
+ Rm_Transaction *transactionQ = NULL;
+ void *key;
+
+ RM_SS_INST_INV_ENTER_CS(key);
Rm_osalLog("Instance name: %s\n", rmInst->instName);
Rm_osalLog("Handle: 0x%08x\n", rmHandle);
else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
Rm_osalLog("Type: Client Delegate\n");
}
- else {
+ else if (rmInst->instType == Rm_instType_CLIENT) {
Rm_osalLog("Type: Client\n");
}
-
+ else if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+ Rm_osalLog("Type: Shared Server\n");
+ }
+
+ transportList = rmInst->transports;
if (transportList) {
Rm_osalLog("\nRegistered Transports:\n");
while (transportList) {
+ RM_SS_OBJ_INV(transportList, Rm_Transport);
Rm_osalLog(" Remote instName: %s\n", transportList->remoteInstName);
if (transportList->remoteInstType == Rm_instType_SERVER) {
Rm_osalLog(" Remote instType: Server\n");
}
}
+ transactionQ = rmInst->transactionQueue;
if (transactionQ) {
Rm_osalLog("\nQueued Service Transactions:\n");
while (transactionQ) {
+ RM_SS_OBJ_INV(transactionQ, Rm_Transaction);
Rm_osalLog(" Service type: %d\n", transactionQ->type);
Rm_osalLog(" Service ID: %d\n", transactionQ->localId);
Rm_osalLog(" Service srcInstName %s\n", transactionQ->serviceSrcInstName);
transactionQ = transactionQ->nextTransaction;
}
}
+ RM_SS_INST_WB_EXIT_CS(key);
}
/* FUNCTION PURPOSE: RM instance creation and initialization
Rm_Inst *rmInst = NULL;
void *globalResourceDtb = NULL;
void *linuxResourceDtb = NULL;
- int addLinux = RM_FALSE;
+ int addLinux = RM_FALSE;
*result = RM_OK;
rmInst->instType = initCfg->instType;
strncpy (rmInst->instName, initCfg->instName, RM_NAME_MAX_CHARS);
- if (rmInst->instType == Rm_instType_SERVER) {
+ if ((rmInst->instType == Rm_instType_SERVER) ||
+ (rmInst->instType == Rm_instType_SHARED_SERVER)) {
if (!initCfg->instCfg.serverCfg.globalResourceList ||
!initCfg->instCfg.serverCfg.globalPolicy) {
*result = RM_ERROR_INVALID_SERVER_CONFIGURATION;
goto errorExit;
}
else {
- rmInst->u.server.nameServer = rmNameServerInit();
+ rmNameServerInit((Rm_Handle)rmInst);
globalResourceDtb = initCfg->instCfg.serverCfg.globalResourceList;
if (*result != RM_OK) {
rmAllocatorDeleteResources(rmInst->u.server.allocators);
- rmNameServerDelete(rmInst->u.server.nameServer);
+ rmNameServerDelete((Rm_Handle)rmInst);
goto errorExit;
}
}
}
}
- /* Create the instance's task blocking mechanism */
- rmInst->blockHandle = Rm_osalTaskBlockCreate();
-
+ if (initCfg->instType == Rm_instType_SHARED_SERVER) {
+ /* Invalidate the instance for other cores */
+ Rm_osalEndMemAccess ((void *)rmInst, sizeof(Rm_Inst));
+ }
+ else {
+ /* Create the instance's task blocking mechanism */
+ rmInst->blockHandle = Rm_osalTaskBlockCreate();
+ }
+
return ((Rm_Handle) rmInst);
errorExit:
if (rmInst) {
int32_t Rm_delete(Rm_Handle rmHandle, int ignorePendingServices)
{
Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
+ void *key;
+
+ RM_SS_INST_INV_ENTER_CS(key);
if (rmInst->serviceHandle) {
return (RM_ERROR_CANT_DELETE_WITH_OPEN_SERV_HNDL);
return (RM_ERROR_CANT_DELETE_PENDING_TRANSACTIONS);
}
- if (rmInst->instType == Rm_instType_SERVER) {
+ if ((rmInst->instType == Rm_instType_SERVER) ||
+ (rmInst->instType == Rm_instType_SHARED_SERVER)) {
rmAllocatorDeleteResources(rmInst->u.server.allocators);
rmPolicyFreeValidInstTree(rmInst->u.server.globalValidInstTree);
- rmNameServerDelete(rmInst->u.server.nameServer);
+ rmNameServerDelete(rmHandle);
}
else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
rmPolicyFreeValidInstTree(rmInst->u.cd.staticValidInstTree);
while(rmInst->transactionQueue) {
rmTransactionQueueDelete(rmInst, rmInst->transactionQueue->localId);
}
-
- /* Delete the instance's task blocking mechanism */
- Rm_osalTaskBlockDelete(rmInst->blockHandle);
- Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
+ if (rmInst->instType != Rm_instType_SHARED_SERVER) {
+ /* Delete the instance's task blocking mechanism */
+ Rm_osalTaskBlockDelete(rmInst->blockHandle);
+ }
+ else {
+ Rm_osalEndMemAccess((void *)rmInst, sizeof(Rm_Inst));
+ }
+
+ Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
+ if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+ Rm_osalCsExit(key);
+ }
return (RM_OK);
}
diff --git a/src/rm_allocator.c b/src/rm_allocator.c
index 230e646e4be562b90ac312941f31740ac27e3c3b..070e49b098c01d70cba98dd5846b2daa791aefdd 100644 (file)
--- a/src/rm_allocator.c
+++ b/src/rm_allocator.c
@@ -1130,6 +1130,9 @@ static int32_t allocatorExtractGrlResProps(Rm_Handle rmHandle, const char *resou
resourceProperties->nsAssignLen, &retVal);
if (nsAssignments) {
nsAssignmentBasePtr = nsAssignments;
+ if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+ rmNameServerTreeInv(rmInst->u.server.nameServer);
+ }
while (nsAssignments) {
memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
@@ -1140,6 +1143,9 @@ static int32_t allocatorExtractGrlResProps(Rm_Handle rmHandle, const char *resou
rmNameServerAddObject(&nameServerObjCfg);
nsAssignments = nsAssignments->nextNsAssignment;
}
+ if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+ rmNameServerTreeWb(rmInst->u.server.nameServer);
+ }
rmDtbUtilResFreeNsAssignmentList(nsAssignmentBasePtr);
}
}
diff --git a/src/rm_nameserver.c b/src/rm_nameserver.c
index ec6e4748afcfc376bff313b24648752f649403ba..401bf323b69362836fbf4c3971f9d8fd349c366e 100644 (file)
--- a/src/rm_nameserver.c
+++ b/src/rm_nameserver.c
#include <ti/drv/rm/rm.h>
/* RM internal API includes */
+#include <ti/drv/rm/include/rm_internal.h>
+#include <ti/drv/rm/include/rm_loc.h>
#include <ti/drv/rm/include/rm_nameserverloc.h>
#include <ti/drv/rm/include/rm_treeloc.h>
* DESCRIPTION: Prints the names and the resources they're mapped
* to for all objects stored in the NameServer tree.
*/
-void rmNameServerPrintObjects(Rm_NameServerTree *nameServerTree)
+void rmNameServerPrintObjects(Rm_Handle rmHandle)
{
+ Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
+ Rm_NameServerTree *root = rmInst->u.server.nameServer;
Rm_NameServerNode *node;
- RB_FOREACH(node, _Rm_NameServerTree, nameServerTree) {
+ if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+ rmNameServerTreeInv(root);
+ }
+ RB_FOREACH(node, _Rm_NameServerTree, root) {
Rm_osalLog("Name: %s resourceName: %s base: %d length: %d\n", node->objName, node->resourceName,
node->resourceBase, node->resourceLength);
}
* DESCRIPTION: Creates and initializes the NameServer tree
* root entry.
*/
-Rm_NameServerTree *rmNameServerInit(void)
+void rmNameServerInit(Rm_Handle rmHandle)
{
+ Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
Rm_NameServerTree *rootEntry = NULL;
rootEntry = Rm_osalMalloc(sizeof(Rm_NameServerTree));
RB_INIT(rootEntry);
-
- return(rootEntry);
+ RM_SS_OBJ_WB(rootEntry, Rm_NameServerTree);
+ rmInst->u.server.nameServer = rootEntry;
}
/* FUNCTION PURPOSE: Deletes the NameServer tree
* DESCRIPTION: Removes all objects from the NameServer tree
* and deletes the NameServer tree root node.
*/
-void rmNameServerDelete(Rm_NameServerTree *nameServerTree)
+void rmNameServerDelete(Rm_Handle rmHandle)
{
+ Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
+ Rm_NameServerTree *treeRoot = rmInst->u.server.nameServer;
Rm_NameServerNode *node;
Rm_NameServerNode *nextNode;
Rm_NameServerObjCfg objCfg;
+
+ if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+ rmNameServerTreeInv(treeRoot);
+ }
- for (node = RB_MIN(_Rm_NameServerTree, nameServerTree); node != NULL; node = nextNode) {
- nextNode = RB_NEXT(_Rm_NameServerTree, nameServerTree, node);
- objCfg.nameServerTree = nameServerTree;
+ for (node = RB_MIN(_Rm_NameServerTree, treeRoot); node != NULL; node = nextNode) {
+ nextNode = RB_NEXT(_Rm_NameServerTree, treeRoot, node);
+ objCfg.nameServerTree = treeRoot;
objCfg.nodeCfg.objName = node->objName;
rmNameServerDeleteObject(&objCfg);
- }
- if (RB_MIN(_Rm_NameServerTree, nameServerTree) == NULL) {
- Rm_osalFree((void *)nameServerTree, sizeof(Rm_NameServerTree));
- }
+ }
+
+ /* Don't need to writeback tree node changes since NameServer will be removed
+ * from instance */
+
+ if (RB_MIN(_Rm_NameServerTree, treeRoot) == NULL) {
+ Rm_osalFree((void *)treeRoot, sizeof(Rm_NameServerTree));
+ }
+ rmInst->u.server.nameServer = NULL;
}
diff --git a/src/rm_services.c b/src/rm_services.c
index c689ee4a3f5de036806755fdf61b543f0f84a38b..aa6b61331c71ecb9fc90392196c641dab7725930 100644 (file)
--- a/src/rm_services.c
+++ b/src/rm_services.c
{
Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
Rm_Transaction *transaction;
+ void *key;
+
+ RM_SS_INST_INV_ENTER_CS(key);
if (rmInst->isLocked) {
serviceResponse->serviceState = RM_SERVICE_DENIED_RM_INSTANCE_LOCKED;
@@ -126,68 +129,81 @@ void Rm_serviceHandler (void *rmHandle, const Rm_ServiceReqInfo *serviceRequest,
memset((void *)serviceResponse, 0, sizeof(Rm_ServiceRespInfo));
- if ((transaction->state == RM_SERVICE_PROCESSING) && (transaction->callback.serviceCallback == NULL)) {
- /* Block until response is received. Response will be received in transaction. */
- Rm_osalTaskBlock(rmInst->blockHandle);
- }
-
- serviceResponse->rmHandle = rmHandle;
- serviceResponse->serviceState = transaction->state;
- if ((serviceResponse->serviceState == RM_SERVICE_PROCESSING) ||
- (serviceResponse->serviceState == RM_SERVICE_APPROVED_STATIC)) {
- /* Service still being processed. Static requests will have their validation responses sent once
- * all transports have been established. Provide transaction ID back to component so it can sort
- * service responses received via callback function */
- serviceResponse->serviceId = transaction->localId;
- }
-
- if ((serviceResponse->serviceState == RM_SERVICE_APPROVED) ||
- (serviceResponse->serviceState == RM_SERVICE_APPROVED_STATIC)) {
- strncpy(serviceResponse->resourceName, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
- serviceResponse->resourceBase = transaction->resourceInfo.base;
- serviceResponse->resourceLength = transaction->resourceInfo.length;
- }
-
- /* Transactions still processing not deleted from queue. Includes static transactions which will be
- * verified once all transports are up */
- if ((serviceResponse->serviceState != RM_SERVICE_PROCESSING) &&
- (serviceResponse->serviceState != RM_SERVICE_APPROVED_STATIC)) {
+ if ((rmInst->instType == Rm_instType_SHARED_SERVER) &&
+ (transaction->state == RM_SERVICE_PROCESSING)) {
+ /* Shared Server should always return a fully processed transaction */
+ serviceResponse->serviceState = RM_ERROR_SHARED_SERVER_UNFINISHED_REQ;
rmTransactionQueueDelete(rmInst, transaction->localId);
}
+ else {
+ if ((transaction->state == RM_SERVICE_PROCESSING) &&
+ (transaction->callback.serviceCallback == NULL)) {
+ /* Block until response is received. Response will be received in transaction. */
+ Rm_osalTaskBlock(rmInst->blockHandle);
+ }
+
+ serviceResponse->rmHandle = rmHandle;
+ serviceResponse->serviceState = transaction->state;
+ if ((serviceResponse->serviceState == RM_SERVICE_PROCESSING) ||
+ (serviceResponse->serviceState == RM_SERVICE_APPROVED_STATIC)) {
+ /* Service still being processed. Static requests will have their validation responses sent once
+ * all transports have been established. Provide transaction ID back to component so it can sort
+ * service responses received via callback function */
+ serviceResponse->serviceId = transaction->localId;
+ }
+
+ if ((serviceResponse->serviceState == RM_SERVICE_APPROVED) ||
+ (serviceResponse->serviceState == RM_SERVICE_APPROVED_STATIC)) {
+ strncpy(serviceResponse->resourceName, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
+ serviceResponse->resourceBase = transaction->resourceInfo.base;
+ serviceResponse->resourceLength = transaction->resourceInfo.length;
+ }
+
+ /* Transactions still processing not deleted from queue including static transactions which will be
+ * verified once all transports are up */
+ if ((serviceResponse->serviceState != RM_SERVICE_PROCESSING) &&
+ (serviceResponse->serviceState != RM_SERVICE_APPROVED_STATIC)) {
+ rmTransactionQueueDelete(rmInst, transaction->localId);
+ }
+ }
}
else {
serviceResponse->serviceState = RM_ERROR_SERVICE_TRANS_NOT_CREATED;
}
+ RM_SS_INST_WB_EXIT_CS(key);
return;
}
/* FUNCTION PURPOSE: Opens the RM instance service handle
***********************************************************************
* DESCRIPTION: Returns the service handle for an RM instance. Only
- * one service handle can be opened per instance.
+ * one service handle is opened per instance.
*/
Rm_ServiceHandle *Rm_serviceOpenHandle(Rm_Handle rmHandle, int32_t *result)
{
Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
- Rm_ServiceHandle *newServiceHandle = NULL;
+ Rm_ServiceHandle *serviceHandle = NULL;
+ void *key;
+
+ RM_SS_INST_INV_ENTER_CS(key);
*result = RM_OK;
- if (rmInst->serviceHandle == NULL) {
- newServiceHandle = Rm_osalMalloc(sizeof(Rm_ServiceHandle));
- if (newServiceHandle) {
- newServiceHandle->rmHandle = rmHandle;
- newServiceHandle->Rm_serviceHandler = Rm_serviceHandler;
- rmInst->serviceHandle = newServiceHandle;
+ serviceHandle = rmInst->serviceHandle;
+ if (serviceHandle == NULL) {
+ serviceHandle = Rm_osalMalloc(sizeof(Rm_ServiceHandle));
+ if (serviceHandle) {
+ serviceHandle->rmHandle = rmHandle;
+ serviceHandle->Rm_serviceHandler = Rm_serviceHandler;
+ RM_SS_OBJ_WB(serviceHandle, Rm_ServiceHandle);
+ rmInst->serviceHandle = serviceHandle;
}
else {
*result = RM_ERROR_SERVICE_HANDLE_MEM_ALLOC_FAILED;
}
}
- else {
- *result = RM_ERROR_SERVICE_HANDLE_ALREADY_OPENED;
- }
- return (newServiceHandle);
+ RM_SS_INST_WB_EXIT_CS(key);
+ return (serviceHandle);
}
/* FUNCTION PURPOSE: Closes the RM instance service handle
{
Rm_Inst *rmInst = (Rm_Inst *)rmServiceHandle->rmHandle;
int32_t retVal = RM_OK;
+ void *key;
+
+ RM_SS_INST_INV_ENTER_CS(key);
if (rmInst->serviceHandle) {
Rm_osalFree((void *)rmServiceHandle, sizeof(Rm_ServiceHandle));
else {
retVal = RM_ERROR_SERVICE_HANDLE_ALREADY_CLOSED;
}
+ RM_SS_INST_WB_EXIT_CS(key);
return(retVal);
}
diff --git a/src/rm_transport.c b/src/rm_transport.c
index 6cd585e5d38c7c8adf9d074b9eba0cb0da561298..d2e192283ae967f33ae9a0f7428aeba1dc7a705b 100644 (file)
--- a/src/rm_transport.c
+++ b/src/rm_transport.c
@@ -203,19 +203,31 @@ Rm_TransportHandle Rm_transportRegister (const Rm_TransportCfg *transportCfg, in
{\r
Rm_Inst *rmInst = (Rm_Inst *) transportCfg->rmHandle;\r
Rm_Transport *transport = NULL;\r
+ void *key;\r
\r
*result = RM_OK;\r
\r
- /* RM Servers cannot connect to other Servers. \r
+ RM_SS_INST_INV_ENTER_CS(key);\r
+\r
+ /* Shared servers cannot connect to anyone */\r
+ if (rmInst->instType == Rm_instType_SHARED_SERVER) {\r
+ *result = RM_ERROR_SHARED_SERVER_CANNOT_REG_TRANS;\r
+ goto errorExit;\r
+ }\r
+\r
+ /* No one can connect to a shared server\r
+ * RM Servers cannot connect to other Servers. \r
* RM Client Delegates cannot connect to other Client Delegates.\r
* RM Clients cannot connect to other Clients */\r
- if (((rmInst->instType == Rm_instType_SERVER) &&\r
+ if ((transportCfg->remoteInstType == Rm_instType_SHARED_SERVER) ||\r
+ ((rmInst->instType == Rm_instType_SERVER) &&\r
(transportCfg->remoteInstType == Rm_instType_SERVER)) ||\r
((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
(transportCfg->remoteInstType == Rm_instType_CLIENT_DELEGATE)) ||\r
((rmInst->instType == Rm_instType_CLIENT) &&\r
(transportCfg->remoteInstType == Rm_instType_CLIENT))) {\r
*result = RM_ERROR_INVALID_REMOTE_INST_TYPE;\r
+ goto errorExit;\r
}\r
\r
/* Verify Clients are not registering with more than one Client Delegate or Server. And\r
@@ -226,23 +238,25 @@ Rm_TransportHandle Rm_transportRegister (const Rm_TransportCfg *transportCfg, in
((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
(transportCfg->remoteInstType == Rm_instType_SERVER)))) {\r
*result = RM_ERROR_ALREADY_REGD_SERVER_OR_CD;\r
+ goto errorExit;\r
} \r
\r
if (!transportCfg->transportCallouts.rmAllocPkt) {\r
*result = RM_ERROR_TRANSPORT_ALLOC_PKT_NOT_REGD;\r
+ goto errorExit;\r
}\r
else if (!transportCfg->transportCallouts.rmSendPkt) {\r
*result = RM_ERROR_TRANSPORT_SEND_NOT_REGD;\r
+ goto errorExit;\r
}\r
\r
- if (*result == RM_OK) {\r
- transport = transportAdd(transportCfg);\r
- if ((transport->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
- (transport->remoteInstType == Rm_instType_SERVER)) {\r
- rmInst->registeredWithDelegateOrServer = RM_TRUE;\r
- }\r
+ transport = transportAdd(transportCfg);\r
+ if ((transport->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
+ (transport->remoteInstType == Rm_instType_SERVER)) {\r
+ rmInst->registeredWithDelegateOrServer = RM_TRUE;\r
}\r
-\r
+errorExit:\r
+ RM_SS_INST_WB_EXIT_CS(key); \r
return ((Rm_TransportHandle) transport);\r
}\r
\r
{\r
Rm_Transport *transport = (Rm_Transport *)transportHandle;\r
Rm_Inst *rmInst = (Rm_Inst *)transport->rmHandle;\r
- int32_t retVal = RM_OK; \r
+ int32_t retVal = RM_OK;\r
\r
if (transportIsRegistered(transport->rmHandle, transport)) {\r
if ((transport->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
diff --git a/src/rm_tree.c b/src/rm_tree.c
index ee5c92468c4850a07d7cfad50b76de379953b959..a5e7ec2b76cb6e7096b0bc95d0fbe1b68474f767 100644 (file)
--- a/src/rm_tree.c
+++ b/src/rm_tree.c
********************* NameServer Tree Functions **********************
**********************************************************************/
+/* FUNCTION PURPOSE: Invalidates an entire NameServer tree
+ ***********************************************************************
+ * DESCRIPTION: Uses the cache handling versions of the RB tree
+ * macros to walk an entire NameServer tree and invalidate
+ * it.
+ */
+void rmNameServerTreeInv(Rm_NameServerTree *treeRoot)
+{
+ Rm_NameServerNode *node;
+
+ /* Invalidate the tree root */
+ Rm_osalBeginMemAccess((void *)treeRoot, sizeof(Rm_NameServerTree));
+ /* Walk the tree which will invalidate each element in the tree */
+ node = RB_MIN_CACHED(_Rm_NameServerTree, treeRoot);
+ while (node) {
+ node = RB_NEXT_CACHED(_Rm_NameServerTree, treeRoot, node);
+ }
+}
+
+/* FUNCTION PURPOSE: Writebacks an entire NameServer tree
+ ***********************************************************************
+ * DESCRIPTION: Walks the entire NameServer tree writing back
+ * each element to shared memory
+ */
+void rmNameServerTreeWb(Rm_NameServerTree *treeRoot)
+{
+ Rm_NameServerNode *node;
+
+ /* Writeback each element in the tree */
+ node = RB_MIN(_Rm_NameServerTree, treeRoot);
+ do {
+ Rm_osalEndMemAccess((void *)node, sizeof(Rm_NameServerNode));
+ node = RB_NEXT(_Rm_NameServerTree, treeRoot, node);
+ } while (node);
+
+ /* Writeback the tree root */
+ Rm_osalEndMemAccess((void *)treeRoot, sizeof(Rm_NameServerTree));
+}
+
/* FUNCTION PURPOSE: Creates a new NameServer tree node
***********************************************************************
* DESCRIPTION: Creates a new NameServer tree node with the
@@ -101,13 +140,62 @@ int rmNameServerNodeCompare(Rm_NameServerNode *node1, Rm_NameServerNode *node2)
return(strncmp(node1->objName, node2->objName, RM_NAME_MAX_CHARS));
}
+/* FUNCTION PURPOSE: Invalidates a NameServer tree node
+ ***********************************************************************
+ * DESCRIPTION: Uses RM OSAL layer to invalidate the specified
+ * NameServer tree node.
+ */
+void rmNameServerNodeInv(Rm_NameServerNode *node)
+{
+ Rm_osalBeginMemAccess((void *)node, sizeof(Rm_NameServerNode));
+}
+
/* Generate the NameServer tree manipulation functions */
-RB_GENERATE(_Rm_NameServerTree, _Rm_NameServerNode, linkage, rmNameServerNodeCompare);
+RB_GENERATE(_Rm_NameServerTree, _Rm_NameServerNode, linkage, rmNameServerNodeCompare, rmNameServerNodeInv);
/**********************************************************************
*************** Policy Valid Instance Tree Functions *****************
**********************************************************************/
+/* FUNCTION PURPOSE: Invalidates an entire valid instance tree
+ ***********************************************************************
+ * DESCRIPTION: Uses the cache handling versions of the RB tree
+ * macros to walk an entire valid instance tree and invalidate
+ * it.
+ */
+void rmPolicyValidInstTreeInv(Rm_PolicyValidInstTree *treeRoot)
+{
+ Rm_PolicyValidInstNode *node;
+
+ /* Invalidate the tree root */
+ Rm_osalBeginMemAccess((void *)treeRoot, sizeof(Rm_PolicyValidInstTree));
+ /* Walk the tree which will invalidate each element in the tree */
+ node = RB_MIN_CACHED(_Rm_PolicyValidInstTree, treeRoot);
+ while (node) {
+ node = RB_NEXT_CACHED(_Rm_PolicyValidInstTree, treeRoot, node);
+ }
+}
+
+/* FUNCTION PURPOSE: Writebacks an entire valid instance tree
+ ***********************************************************************
+ * DESCRIPTION: Walks the entire valid instance tree writing back
+ * each element to shared memory
+ */
+void rmPolicyValidInstTreeWb(Rm_PolicyValidInstTree *treeRoot)
+{
+ Rm_PolicyValidInstNode *node;
+
+ /* Writeback each element in the tree */
+ node = RB_MIN(_Rm_PolicyValidInstTree, treeRoot);
+ do {
+ Rm_osalEndMemAccess((void *)node, sizeof(Rm_PolicyValidInstNode));
+ node = RB_NEXT(_Rm_PolicyValidInstTree, treeRoot, node);
+ } while (node);
+
+ /* Writeback the tree root */
+ Rm_osalEndMemAccess((void *)treeRoot, sizeof(Rm_PolicyValidInstTree));
+}
+
/* FUNCTION PURPOSE: Creates a new valid instance tree node
***********************************************************************
* DESCRIPTION: Creates a new valid instance tree node with the
@@ -153,13 +241,62 @@ int rmPolicyValidInstNodeCompare(Rm_PolicyValidInstNode *node1, Rm_PolicyValidIn
return(strncmp(node1->name, node2->name, RM_NAME_MAX_CHARS));
}
+/* FUNCTION PURPOSE: Invalidates a valid instance tree node
+ ***********************************************************************
+ * DESCRIPTION: Uses RM OSAL layer to invalidate the specified
+ * valid instance tree node.
+ */
+void rmPolicyValidInstNodeInv(Rm_PolicyValidInstNode *node)
+{
+ Rm_osalBeginMemAccess((void *)node, sizeof(Rm_PolicyValidInstNode));
+}
+
/* Generate the valid instance tree manipulation functions */
-RB_GENERATE(_Rm_PolicyValidInstTree, _Rm_PolicyValidInstNode, linkage, rmPolicyValidInstNodeCompare);
+RB_GENERATE(_Rm_PolicyValidInstTree, _Rm_PolicyValidInstNode, linkage, rmPolicyValidInstNodeCompare, rmPolicyValidInstNodeInv);
/**********************************************************************
***************** Allocator Resource Tree Functions ******************
**********************************************************************/
+/* FUNCTION PURPOSE: Invalidates an entire resource tree
+ ***********************************************************************
+ * DESCRIPTION: Uses the cache handling versions of the RB tree
+ * macros to walk an entire resource tree and invalidate
+ * it.
+ */
+void rmResourceTreeInv(Rm_ResourceTree *treeRoot)
+{
+ Rm_ResourceNode *node;
+
+ /* Invalidate the tree root */
+ Rm_osalBeginMemAccess((void *)treeRoot, sizeof(Rm_ResourceTree));
+ /* Walk the tree which will invalidate each element in the tree */
+ node = RB_MIN_CACHED(_Rm_AllocatorResourceTree, treeRoot);
+ while (node) {
+ node = RB_NEXT_CACHED(_Rm_AllocatorResourceTree, treeRoot, node);
+ }
+}
+
+/* FUNCTION PURPOSE: Writebacks an entire resource tree
+ ***********************************************************************
+ * DESCRIPTION: Walks the entire resource tree writing back
+ * each element to shared memory
+ */
+void rmResourceTreeWb(Rm_ResourceTree *treeRoot)
+{
+ Rm_ResourceNode *node;
+
+ /* Writeback each element in the tree */
+ node = RB_MIN(_Rm_AllocatorResourceTree, treeRoot);
+ do {
+ Rm_osalEndMemAccess((void *)node, sizeof(Rm_ResourceNode));
+ node = RB_NEXT(_Rm_AllocatorResourceTree, treeRoot, node);
+ } while (node);
+
+ /* Writeback the tree root */
+ Rm_osalEndMemAccess((void *)treeRoot, sizeof(Rm_ResourceTree));
+}
+
/* FUNCTION PURPOSE: Creates a new resource tree node
***********************************************************************
* DESCRIPTION: Creates a new resource tree node with the
}
}
+/* FUNCTION PURPOSE: Invalidates a resource tree node
+ ***********************************************************************
+ * DESCRIPTION: Uses RM OSAL layer to invalidate the specified
+ * resource tree node.
+ */
+void rmResourceNodeInv(Rm_ResourceNode *node)
+{
+ Rm_osalBeginMemAccess((void *)node, sizeof(Rm_ResourceNode));
+}
+
/* Generate the resource tree manipulation functions */
-RB_GENERATE(_Rm_AllocatorResourceTree, _Rm_ResourceNode, linkage, rmResourceNodeCompare)
+RB_GENERATE(_Rm_AllocatorResourceTree, _Rm_ResourceNode, linkage, rmResourceNodeCompare, rmResourceNodeInv)
diff --git a/test/rm_osal.c b/test/rm_osal.c
index 291608c4a47f1b119339432a1929447eb5438bac..7302871081d0dfb1a004ee624edb0735e86592f8 100644 (file)
--- a/test/rm_osal.c
+++ b/test/rm_osal.c
Memory_free(NULL, ptr, size);
}
+/* FUNCTION PURPOSE: Critical section enter
+ ***********************************************************************
+ * DESCRIPTION: The function is used to enter a critical section.
+ * Function protects against
+ *
+ * access from multiple cores
+ * and
+ * access from multiple threads on single core
+ */
+void *Osal_rmCsEnter(void)
+{
+
+ return NULL;
+}
+
+/* FUNCTION PURPOSE: Critical section exit
+ ***********************************************************************
+ * DESCRIPTION: The function is used to exit a critical section
+ * protected using Osal_cppiCsEnter() API.
+ */
+void Osal_rmCsExit(void *CsHandle)
+{
+
+}
+
+/* FUNCTION PURPOSE: Critical section exit
+ ***********************************************************************
+ * DESCRIPTION: The function is used to indicate that a block of memory is
+ * about to be accessed. If the memory block is cached then this
+ * indicates that the application would need to ensure that the
+ * cache is updated with the data from the actual memory.
+ */
+void Osal_rmBeginMemAccess(void *ptr, uint32_t size)
+{
+
+}
+
+/* FUNCTION PURPOSE: Critical section exit
+ ***********************************************************************
+ * DESCRIPTION: The function is used to indicate that the block of memory has
+ * finished being accessed. If the memory block is cached then the
+ * application would need to ensure that the contents of the cache
+ * are updated immediately to the actual memory.
+ */
+void Osal_rmEndMemAccess(void *ptr, uint32_t size)
+{
+
+}
+
/* FUNCTION PURPOSE: Creates a task blocking object
***********************************************************************
* DESCRIPTION: The function is used to create a task blocking object
diff --git a/test/rm_test.c b/test/rm_test.c
index 5f9fafc1a58ee789701cb3757165d7b376319f71..bd8becc408e700e3cff07eeb30f465c832c2a772 100644 (file)
--- a/test/rm_test.c
+++ b/test/rm_test.c
#include <ti/sysbios/family/c64p/Hwi.h>
/* CSL Includes */
-#include <ti/csl/csl_semAux.h>
#include <ti/csl/csl_cacheAux.h>
#include <ti/csl/csl_xmcAux.h>
/* RM test Static Policy provided to RM Client Delegate and Client */
extern const char rmStaticPolicy[];
-/* OSAL RM Local Gate Initialization. */
-extern void Osal_rmLocalGateInit (void);
-
/**********************************************************************
********************** Global Variables ******************************
**********************************************************************/
diff --git a/util/tree.h b/util/tree.h
index 80d0f53813442514d8861d9a152c34f6c7708c65..8ada42d2f9c1082b1676b652a9d9233583ef0fbf 100644 (file)
--- a/util/tree.h
+++ b/util/tree.h
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ * ALL RIGHTS RESERVED
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Every operation on a red-black tree is bounded as O(lg n).
* The maximum height of a red-black tree is 2lg (n+1).
*/
+/* Change Log
+ * TI - Added versions of some RB macros that handle caching
+ */
#define SPLAY_HEAD(name, type) \
struct name { \
} while (0)
/* Generates prototypes and inline functions */
-#define RB_PROTOTYPE(name, type, field, cmp) \
- RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
-#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
- RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static)
-#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
+#define RB_PROTOTYPE(name, type, field, cmp, inv) \
+ RB_PROTOTYPE_INTERNAL(name, type, field, cmp, inv,)
+#define RB_PROTOTYPE_STATIC(name, type, field, cmp, inv) \
+ RB_PROTOTYPE_INTERNAL(name, type, field, cmp, inv, __attribute__((__unused__)) static)
+#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, inv, attr) \
attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \
attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
attr struct type *name##_RB_REMOVE(struct name *, struct type *); \
attr struct type *name##_RB_NEXT(struct type *); \
attr struct type *name##_RB_PREV(struct type *); \
attr struct type *name##_RB_MINMAX(struct name *, int); \
+attr struct type *name##_RB_NEXT_CACHED(struct type *); \
+attr struct type *name##_RB_MINMAX_CACHED(struct name *, int); \
\
/* Main rb operation.
* Moves node close to the key of elm to top
*/
-#define RB_GENERATE(name, type, field, cmp) \
- RB_GENERATE_INTERNAL(name, type, field, cmp,)
-#define RB_GENERATE_STATIC(name, type, field, cmp) \
- RB_GENERATE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static)
-#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \
+#define RB_GENERATE(name, type, field, cmp, inv) \
+ RB_GENERATE_INTERNAL(name, type, field, cmp, inv,)
+#define RB_GENERATE_STATIC(name, type, field, cmp, inv) \
+ RB_GENERATE_INTERNAL(name, type, field, cmp, inv, __attribute__((__unused__)) static)
+#define RB_GENERATE_INTERNAL(name, type, field, cmp, inv, attr) \
attr void \
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
{ \
tmp = RB_RIGHT(tmp, field); \
} \
return (parent); \
-}
+} \
+ \
+/* ARGSUSED */ \
+attr struct type * \
+name##_RB_NEXT_CACHED(struct type *elm) \
+{ \
+ inv(elm); \
+ if (RB_RIGHT(elm, field)) { \
+ elm = RB_RIGHT(elm, field); \
+ inv(elm); \
+ while (RB_LEFT(elm, field)) { \
+ elm = RB_LEFT(elm, field); \
+ inv(elm); \
+ } \
+ } else { \
+ inv(RB_PARENT(elm, field)); \
+ if (RB_PARENT(elm, field) && \
+ (elm == RB_LEFT(RB_PARENT(elm, field), field))) \
+ elm = RB_PARENT(elm, field); \
+ else { \
+ while (RB_PARENT(elm, field) && \
+ (elm == RB_RIGHT(RB_PARENT(elm, field), field))) {\
+ elm = RB_PARENT(elm, field); \
+ inv(RB_PARENT(elm, field)); \
+ } \
+ elm = RB_PARENT(elm, field); \
+ } \
+ } \
+ return (elm); \
+} \
+ \
+attr struct type * \
+name##_RB_MINMAX_CACHED(struct name *head, int val) \
+{ \
+ struct type *tmp = RB_ROOT(head); \
+ struct type *parent = NULL; \
+ while (tmp) { \
+ parent = tmp; \
+ inv(tmp); \
+ if (val < 0) \
+ tmp = RB_LEFT(tmp, field); \
+ else \
+ tmp = RB_RIGHT(tmp, field); \
+ } \
+ return (parent); \
+}
#define RB_NEGINF -1
#define RB_INF 1
#define RB_PREV(name, x, y) name##_RB_PREV(y)
#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
+/* Cache versions */
+#define RB_NEXT_CACHED(name, x, y) name##_RB_NEXT_CACHED(y)
+#define RB_MIN_CACHED(name, x) name##_RB_MINMAX_CACHED(x, RB_NEGINF)
#define RB_FOREACH(x, name, head) \
for ((x) = RB_MIN(name, head); \