1 /*
2 Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are
6 met:
7 		* Redistributions of source code must retain the above copyright
8 			notice, this list of conditions and the following disclaimer.
9 		* Redistributions in binary form must reproduce the above
10 			copyright notice, this list of conditions and the following
11 			disclaimer in the documentation and/or other materials provided
12 			with the distribution.
13 		* Neither the name of The Linux Foundation nor the names of its
14 			contributors may be used to endorse or promote products derived
15 			from this software without specific prior written permission.
16 
17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 /*!
30 	@file
31 	IPACM_EvtDispatcher.cpp
32 
33 	@brief
34 	This file implements the IPAM event dispatcher functionality
35 
36 	@Author
37 
38 */
39 #include <string.h>
40 #include <pthread.h>
41 #include <IPACM_EvtDispatcher.h>
42 #include <IPACM_Neighbor.h>
43 #include "IPACM_CmdQueue.h"
44 #include "IPACM_Defs.h"
45 
46 
47 extern pthread_mutex_t mutex;
48 extern pthread_cond_t  cond_var;
49 
50 cmd_evts *IPACM_EvtDispatcher::head = NULL;
51 extern uint32_t ipacm_event_stats[IPACM_EVENT_MAX];
52 
PostEvt(ipacm_cmd_q_data * data)53 int IPACM_EvtDispatcher::PostEvt
54 (
55 	 ipacm_cmd_q_data *data
56 )
57 {
58 	Message *item = NULL;
59 	MessageQueue *MsgQueue = NULL;
60 
61 	if(data->event < IPA_EXTERNAL_EVENT_MAX)
62 	{
63 		IPACMDBG("Insert event into external queue.\n");
64 		MsgQueue = MessageQueue::getInstanceExternal();
65 	}
66 	else
67 	{
68 		IPACMDBG("Insert event into internal queue.\n");
69 		MsgQueue = MessageQueue::getInstanceInternal();
70 	}
71 	if(MsgQueue == NULL)
72 	{
73 		IPACMERR("unable to retrieve MsgQueue instance\n");
74 		return IPACM_FAILURE;
75 	}
76 
77 	item = new Message();
78 	if(item == NULL)
79 	{
80 		IPACMERR("unable to create new message item\n");
81 		return IPACM_FAILURE;
82 	}
83 
84 	item->evt.callback_ptr = IPACM_EvtDispatcher::ProcessEvt;
85 	memcpy(&item->evt.data, data, sizeof(ipacm_cmd_q_data));
86 
87 	if(pthread_mutex_lock(&mutex) != 0)
88 	{
89 		IPACMERR("unable to lock the mutex\n");
90 		return IPACM_FAILURE;
91 	}
92 
93 	IPACMDBG("Enqueing item\n");
94 	MsgQueue->enqueue(item);
95 	IPACMDBG("Enqueued item %pK\n", item);
96 
97 	if(pthread_cond_signal(&cond_var) != 0)
98 	{
99 		IPACMDBG("unable to lock the mutex\n");
100 		/* Release the mutex before you return failure */
101 		if(pthread_mutex_unlock(&mutex) != 0)
102 		{
103 			IPACMERR("unable to unlock the mutex\n");
104 			return IPACM_FAILURE;
105 		}
106 		return IPACM_FAILURE;
107 	}
108 
109 	if(pthread_mutex_unlock(&mutex) != 0)
110 	{
111 		IPACMERR("unable to unlock the mutex\n");
112 		return IPACM_FAILURE;
113 	}
114 
115 	return IPACM_SUCCESS;
116 }
117 
ProcessEvt(ipacm_cmd_q_data * data)118 void IPACM_EvtDispatcher::ProcessEvt(ipacm_cmd_q_data *data)
119 {
120 
121 	cmd_evts *tmp = head, tmp1;
122 
123 	if(head == NULL)
124 	{
125 		IPACMDBG("Queue is empty\n");
126 	}
127 
128 	while(tmp != NULL)
129 	{
130 	        memcpy(&tmp1, tmp, sizeof(tmp1));
131 		if(data->event == tmp1.event)
132 		{
133 			ipacm_event_stats[data->event]++;
134 			tmp1.obj->event_callback(data->event, data->evt_data);
135 			IPACMDBG(" Find matched registered events\n");
136 		}
137 	        tmp = tmp1.next;
138 	}
139 
140 	IPACMDBG(" Finished process events\n");
141 
142 	if(data->evt_data != NULL)
143 	{
144 		IPACMDBG("free the event:%d data: %pK\n", data->event, data->evt_data);
145 		free(data->evt_data);
146 	}
147 	return;
148 }
149 
registr(ipa_cm_event_id event,IPACM_Listener * obj)150 int IPACM_EvtDispatcher::registr(ipa_cm_event_id event, IPACM_Listener *obj)
151 {
152 	cmd_evts *tmp = head,*nw;
153 
154 	nw = (cmd_evts *)malloc(sizeof(cmd_evts));
155 	if(nw != NULL)
156 	{
157 		nw->event = event;
158 		nw->obj = obj;
159 		nw->next = NULL;
160 	}
161 	else
162 	{
163 		return IPACM_FAILURE;
164 	}
165 
166 	if(head == NULL)
167 	{
168 		head = nw;
169 	}
170 	else
171 	{
172 		while(tmp->next)
173 		{
174 			tmp = tmp->next;
175 		}
176 		tmp->next = nw;
177 	}
178 	return IPACM_SUCCESS;
179 }
180 
181 
deregistr(IPACM_Listener * param)182 int IPACM_EvtDispatcher::deregistr(IPACM_Listener *param)
183 {
184 	cmd_evts *tmp = head,*tmp1,*prev = head;
185 
186 	while(tmp != NULL)
187 	{
188 		if(tmp->obj == param)
189 		{
190 			tmp1 = tmp;
191 			if(tmp == head)
192 			{
193 				head = head->next;
194 			}
195 			else if(tmp->next == NULL)
196 			{
197 				prev->next = NULL;
198 			}
199 			else
200 			{
201 				prev->next = tmp->next;
202 			}
203 
204 			tmp = tmp->next;
205 			free(tmp1);
206 		}
207 		else
208 		{
209 			prev = tmp;
210 			tmp = tmp->next;
211 		}
212 	}
213 	return IPACM_SUCCESS;
214 }
215