• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2 
3   (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4       www.systec-electronic.com
5 
6   Project:      openPOWERLINK
7 
8   Description:  source file for Epl Userspace-Timermodule for Win32
9 
10   License:
11 
12     Redistribution and use in source and binary forms, with or without
13     modification, are permitted provided that the following conditions
14     are met:
15 
16     1. Redistributions of source code must retain the above copyright
17        notice, this list of conditions and the following disclaimer.
18 
19     2. Redistributions in binary form must reproduce the above copyright
20        notice, this list of conditions and the following disclaimer in the
21        documentation and/or other materials provided with the distribution.
22 
23     3. Neither the name of SYSTEC electronic GmbH nor the names of its
24        contributors may be used to endorse or promote products derived
25        from this software without prior written permission. For written
26        permission, please contact info@systec-electronic.com.
27 
28     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32     COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
36     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
38     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39     POSSIBILITY OF SUCH DAMAGE.
40 
41     Severability Clause:
42 
43         If a provision of this License is or becomes illegal, invalid or
44         unenforceable in any jurisdiction, that shall not affect:
45         1. the validity or enforceability in that jurisdiction of any other
46            provision of this License; or
47         2. the validity or enforceability in other jurisdictions of that or
48            any other provision of this License.
49 
50   -------------------------------------------------------------------------
51 
52                 $RCSfile: EplTimeruWin32.c,v $
53 
54                 $Author: D.Krueger $
55 
56                 $Revision: 1.4 $  $Date: 2008/04/17 21:36:32 $
57 
58                 $State: Exp $
59 
60                 Build Environment:
61                     GCC V3.4
62 
63   -------------------------------------------------------------------------
64 
65   Revision History:
66 
67   2006/07/06 k.t.:   start of the implementation
68 
69 ****************************************************************************/
70 
71 #include "user/EplTimeru.h"
72 
73 /***************************************************************************/
74 /*                                                                         */
75 /*                                                                         */
76 /*          G L O B A L   D E F I N I T I O N S                            */
77 /*                                                                         */
78 /*                                                                         */
79 /***************************************************************************/
80 
81 //---------------------------------------------------------------------------
82 // const defines
83 //---------------------------------------------------------------------------
84 
85 //---------------------------------------------------------------------------
86 // local types
87 //---------------------------------------------------------------------------
88 typedef struct {
89 	tEplTimerArg TimerArgument;
90 	HANDLE DelteHandle;
91 	unsigned long ulTimeout;
92 
93 } tEplTimeruThread;
94 
95 typedef struct {
96 	LPCRITICAL_SECTION m_pCriticalSection;
97 	CRITICAL_SECTION m_CriticalSection;
98 } tEplTimeruInstance;
99 //---------------------------------------------------------------------------
100 // modul globale vars
101 //---------------------------------------------------------------------------
102 static tEplTimeruInstance EplTimeruInstance_g;
103 static tEplTimeruThread ThreadData_l;
104 //---------------------------------------------------------------------------
105 // local function prototypes
106 //---------------------------------------------------------------------------
107 DWORD PUBLIC EplSdoTimeruThreadms(LPVOID lpParameter);
108 
109 /***************************************************************************/
110 /*                                                                         */
111 /*                                                                         */
112 /*          C L A S S  <Epl Userspace-Timermodule for Win32>               */
113 /*                                                                         */
114 /*                                                                         */
115 /***************************************************************************/
116 //
117 // Description: Epl Userspace-Timermodule for Win32
118 //
119 //
120 /***************************************************************************/
121 
122 //=========================================================================//
123 //                                                                         //
124 //          P U B L I C   F U N C T I O N S                                //
125 //                                                                         //
126 //=========================================================================//
127 
128 //---------------------------------------------------------------------------
129 //
130 // Function:    EplTimeruInit
131 //
132 // Description: function init first instance
133 //
134 //
135 //
136 // Parameters:
137 //
138 //
139 // Returns:     tEplKernel  = errorcode
140 //
141 //
142 // State:
143 //
144 //---------------------------------------------------------------------------
EplTimeruInit()145 tEplKernel PUBLIC EplTimeruInit()
146 {
147 	tEplKernel Ret;
148 
149 	Ret = EplTimeruAddInstance();
150 
151 	return Ret;
152 }
153 
154 //---------------------------------------------------------------------------
155 //
156 // Function:    EplTimeruAddInstance
157 //
158 // Description: function init additional instance
159 //
160 //
161 //
162 // Parameters:
163 //
164 //
165 // Returns:     tEplKernel  = errorcode
166 //
167 //
168 // State:
169 //
170 //---------------------------------------------------------------------------
EplTimeruAddInstance()171 tEplKernel PUBLIC EplTimeruAddInstance()
172 {
173 	tEplKernel Ret;
174 
175 	Ret = kEplSuccessful;
176 
177 	// create critical section
178 	EplTimeruInstance_g.m_pCriticalSection =
179 	    &EplTimeruInstance_g.m_CriticalSection;
180 	InitializeCriticalSection(EplTimeruInstance_g.m_pCriticalSection);
181 
182 	return Ret;
183 }
184 
185 //---------------------------------------------------------------------------
186 //
187 // Function:    EplTimeruDelInstance
188 //
189 // Description: function delte instance
190 //              -> under Win32 nothing to do
191 //              -> no instnace table needed
192 //
193 //
194 //
195 // Parameters:
196 //
197 //
198 // Returns:     tEplKernel  = errorcode
199 //
200 //
201 // State:
202 //
203 //---------------------------------------------------------------------------
EplTimeruDelInstance()204 tEplKernel PUBLIC EplTimeruDelInstance()
205 {
206 	tEplKernel Ret;
207 
208 	Ret = kEplSuccessful;
209 
210 	return Ret;
211 }
212 
213 //---------------------------------------------------------------------------
214 //
215 // Function:    EplTimeruSetTimerMs
216 //
217 // Description: function create a timer and return a handle to the pointer
218 //
219 //
220 //
221 // Parameters:  pTimerHdl_p = pointer to a buffer to fill in the handle
222 //              ulTime_p    = time for timer in ms
223 //              Argument_p  = argument for timer
224 //
225 //
226 // Returns:     tEplKernel  = errorcode
227 //
228 //
229 // State:
230 //
231 //---------------------------------------------------------------------------
EplTimeruSetTimerMs(tEplTimerHdl * pTimerHdl_p,unsigned long ulTime_p,tEplTimerArg Argument_p)232 tEplKernel PUBLIC EplTimeruSetTimerMs(tEplTimerHdl * pTimerHdl_p,
233 				      unsigned long ulTime_p,
234 				      tEplTimerArg Argument_p)
235 {
236 	tEplKernel Ret;
237 	HANDLE DeleteHandle;
238 	HANDLE ThreadHandle;
239 	DWORD ThreadId;
240 
241 	Ret = kEplSuccessful;
242 
243 	// check handle
244 	if (pTimerHdl_p == NULL) {
245 		Ret = kEplTimerInvalidHandle;
246 		goto Exit;
247 	}
248 	// enter  critical section
249 	EnterCriticalSection(EplTimeruInstance_g.m_pCriticalSection);
250 
251 	// first create event to delete timer
252 	DeleteHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
253 	if (DeleteHandle == NULL) {
254 		Ret = kEplTimerNoTimerCreated;
255 		goto Exit;
256 	}
257 	// set handle for caller
258 	*pTimerHdl_p = (tEplTimerHdl) DeleteHandle;
259 
260 	// fill data for thread
261 	ThreadData_l.DelteHandle = DeleteHandle;
262 	EPL_MEMCPY(&ThreadData_l.TimerArgument, &Argument_p,
263 		   sizeof(tEplTimerArg));
264 	ThreadData_l.ulTimeout = ulTime_p;
265 
266 	// create thread to create waitable timer and wait for timer
267 	ThreadHandle = CreateThread(NULL,
268 				    0,
269 				    EplSdoTimeruThreadms,
270 				    &ThreadData_l, 0, &ThreadId);
271 	if (ThreadHandle == NULL) {
272 		// leave critical section
273 		LeaveCriticalSection(EplTimeruInstance_g.m_pCriticalSection);
274 
275 		// delte handle
276 		CloseHandle(DeleteHandle);
277 
278 		Ret = kEplTimerNoTimerCreated;
279 		goto Exit;
280 	}
281 
282       Exit:
283 	return Ret;
284 }
285 
286  //---------------------------------------------------------------------------
287 //
288 // Function:    EplTimeruModifyTimerMs
289 //
290 // Description: function change a timer and return a handle to the pointer
291 //
292 //
293 //
294 // Parameters:  pTimerHdl_p = pointer to a buffer to fill in the handle
295 //              ulTime_p    = time for timer in ms
296 //              Argument_p  = argument for timer
297 //
298 //
299 // Returns:     tEplKernel  = errorcode
300 //
301 //
302 // State:
303 //
304 //---------------------------------------------------------------------------
EplTimeruModifyTimerMs(tEplTimerHdl * pTimerHdl_p,unsigned long ulTime_p,tEplTimerArg Argument_p)305 tEplKernel PUBLIC EplTimeruModifyTimerMs(tEplTimerHdl * pTimerHdl_p,
306 					 unsigned long ulTime_p,
307 					 tEplTimerArg Argument_p)
308 {
309 	tEplKernel Ret;
310 	HANDLE DeleteHandle;
311 	HANDLE ThreadHandle;
312 	DWORD ThreadId;
313 
314 	Ret = kEplSuccessful;
315 
316 	// check parameter
317 	if (pTimerHdl_p == NULL) {
318 		Ret = kEplTimerInvalidHandle;
319 		goto Exit;
320 	}
321 
322 	DeleteHandle = (HANDLE) (*pTimerHdl_p);
323 
324 	// set event to end timer task for this timer
325 	SetEvent(DeleteHandle);
326 
327 	// create new timer
328 	// first create event to delete timer
329 	DeleteHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
330 	if (DeleteHandle == NULL) {
331 		Ret = kEplTimerNoTimerCreated;
332 		goto Exit;
333 	}
334 	// set handle for caller
335 	*pTimerHdl_p = (tEplTimerHdl) DeleteHandle;
336 
337 	// enter  critical section
338 	EnterCriticalSection(EplTimeruInstance_g.m_pCriticalSection);
339 
340 	// fill data for thread
341 	ThreadData_l.DelteHandle = DeleteHandle;
342 	EPL_MEMCPY(&ThreadData_l.TimerArgument, &Argument_p,
343 		   sizeof(tEplTimerArg));
344 	ThreadData_l.ulTimeout = ulTime_p;
345 
346 	// create thread to create waitable timer and wait for timer
347 	ThreadHandle = CreateThread(NULL,
348 				    0,
349 				    EplSdoTimeruThreadms,
350 				    &ThreadData_l, 0, &ThreadId);
351 	if (ThreadHandle == NULL) {
352 		// leave critical section
353 		LeaveCriticalSection(EplTimeruInstance_g.m_pCriticalSection);
354 
355 		// delte handle
356 
357 		Ret = kEplTimerNoTimerCreated;
358 		goto Exit;
359 	}
360 
361       Exit:
362 	return Ret;
363 }
364 
365  //---------------------------------------------------------------------------
366 //
367 // Function:    EplTimeruDeleteTimer
368 //
369 // Description: function delte a timer
370 //
371 //
372 //
373 // Parameters:  pTimerHdl_p = pointer to a buffer to fill in the handle
374 //
375 //
376 // Returns:     tEplKernel  = errorcode
377 //
378 //
379 // State:
380 //
381 //---------------------------------------------------------------------------
EplTimeruDeleteTimer(tEplTimerHdl * pTimerHdl_p)382 tEplKernel PUBLIC EplTimeruDeleteTimer(tEplTimerHdl * pTimerHdl_p)
383 {
384 	tEplKernel Ret;
385 	HANDLE DeleteHandle;
386 
387 	Ret = kEplSuccessful;
388 
389 	// check parameter
390 	if (pTimerHdl_p == NULL) {
391 		Ret = kEplTimerInvalidHandle;
392 		goto Exit;
393 	}
394 
395 	DeleteHandle = (HANDLE) (*pTimerHdl_p);
396 
397 	// set event to end timer task for this timer
398 	SetEvent(DeleteHandle);
399 
400 	// set handle invalide
401 	*pTimerHdl_p = 0;
402 
403       Exit:
404 	return Ret;
405 
406 }
407 
408 //=========================================================================//
409 //                                                                         //
410 //          P R I V A T E   F U N C T I O N S                              //
411 //                                                                         //
412 //=========================================================================//
413 
414 //---------------------------------------------------------------------------
415 //
416 // Function:    EplSdoTimeruThreadms
417 //
418 // Description: function to process timer as thread
419 //
420 //
421 //
422 // Parameters:  lpParameter = pointer to structur of type tEplTimeruThread
423 //
424 //
425 // Returns:     DWORD = Errorcode
426 //
427 //
428 // State:
429 //
430 //---------------------------------------------------------------------------
EplSdoTimeruThreadms(LPVOID lpParameter)431 DWORD PUBLIC EplSdoTimeruThreadms(LPVOID lpParameter)
432 {
433 	tEplKernel Ret;
434 	tEplTimeruThread *pThreadData;
435 	HANDLE aHandles[2];
436 	BOOL fReturn;
437 	LARGE_INTEGER TimeoutTime;
438 	unsigned long ulEvent;
439 	tEplEvent EplEvent;
440 	tEplTimeruThread ThreadData;
441 	tEplTimerEventArg TimerEventArg;
442 
443 	Ret = kEplSuccessful;
444 
445 	// get pointer to data
446 	pThreadData = (tEplTimeruThread *) lpParameter;
447 	// copy thread data
448 	EPL_MEMCPY(&ThreadData, pThreadData, sizeof(ThreadData));
449 	pThreadData = &ThreadData;
450 
451 	// leave critical section
452 	LeaveCriticalSection(EplTimeruInstance_g.m_pCriticalSection);
453 
454 	// create waitable timer
455 	aHandles[1] = CreateWaitableTimer(NULL, FALSE, NULL);
456 	if (aHandles[1] == NULL) {
457 		Ret = kEplTimerNoTimerCreated;
458 		goto Exit;
459 	}
460 	// set timer
461 	// set timeout interval -> needed to be negativ
462 	// -> because relative timeout
463 	// -> multiply by 10000 for 100 ns timebase of function
464 	TimeoutTime.QuadPart = (((long long)pThreadData->ulTimeout) * -10000);
465 	fReturn = SetWaitableTimer(aHandles[1],
466 				   &TimeoutTime, 0, NULL, NULL, FALSE);
467 	if (fReturn == 0) {
468 		Ret = kEplTimerNoTimerCreated;
469 		goto Exit;
470 	}
471 	// save delte event handle in handle array
472 	aHandles[0] = pThreadData->DelteHandle;
473 
474 	// wait for one of the events
475 	ulEvent = WaitForMultipleObjects(2, &aHandles[0], FALSE, INFINITE);
476 	if (ulEvent == WAIT_OBJECT_0) {	// delte event
477 
478 		// close handels
479 		CloseHandle(aHandles[1]);
480 		// terminate thread
481 		goto Exit;
482 	} else if (ulEvent == (WAIT_OBJECT_0 + 1)) {	// timer event
483 		// call event function
484 		TimerEventArg.m_TimerHdl =
485 		    (tEplTimerHdl) pThreadData->DelteHandle;
486 		TimerEventArg.m_ulArg = pThreadData->TimerArgument.m_ulArg;
487 
488 		EplEvent.m_EventSink = pThreadData->TimerArgument.m_EventSink;
489 		EplEvent.m_EventType = kEplEventTypeTimer;
490 		EPL_MEMSET(&EplEvent.m_NetTime, 0x00, sizeof(tEplNetTime));
491 		EplEvent.m_pArg = &TimerEventArg;
492 		EplEvent.m_uiSize = sizeof(TimerEventArg);
493 
494 		Ret = EplEventuPost(&EplEvent);
495 
496 		// close handels
497 		CloseHandle(aHandles[1]);
498 		// terminate thread
499 		goto Exit;
500 
501 	} else {		// error
502 		ulEvent = GetLastError();
503 		TRACE1("Error in WaitForMultipleObjects Errorcode: 0x%x\n",
504 		       ulEvent);
505 		// terminate thread
506 		goto Exit;
507 	}
508 
509       Exit:
510 	return Ret;
511 }
512 
513 // EOF
514