1/*
2 * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef _KERNEL_USER_TIMER_H
6#define _KERNEL_USER_TIMER_H
7
8
9#include <sys/cdefs.h>
10#include <time.h>
11
12#include <util/DoublyLinkedList.h>
13
14#include <ksignal.h>
15#include <timer.h>
16#include <user_timer_defs.h>
17
18
19struct thread_creation_attributes;
20
21
22namespace BKernel {
23
24
25struct UserEvent;
26struct Team;
27
28
29struct UserTimer : DoublyLinkedListLinkImpl<UserTimer> {
30								UserTimer();
31	virtual						~UserTimer();
32
33			int32				ID() const
34									{ return fID; }
35			void				SetID(int32 id)
36									{ fID = id; }
37
38			void				SetEvent(UserEvent* event)
39									{ fEvent = event; }
40
41	virtual	void				Schedule(bigtime_t nextTime, bigtime_t interval,
42									uint32 flags, bigtime_t& _oldRemainingTime,
43									bigtime_t& _oldInterval) = 0;
44			void				Cancel();
45
46	virtual	void				GetInfo(bigtime_t& _remainingTime,
47									bigtime_t& _interval,
48									uint32& _overrunCount) = 0;
49
50protected:
51	static	int32				HandleTimerHook(struct timer* timer);
52	virtual	void				HandleTimer();
53
54	inline	void				UpdatePeriodicStartTime();
55	inline	void				CheckPeriodicOverrun(bigtime_t now);
56
57protected:
58			int32				fID;
59			timer				fTimer;
60			UserEvent*			fEvent;
61			bigtime_t			fNextTime;
62			bigtime_t			fInterval;
63			uint32				fOverrunCount;
64			bool				fScheduled;	// fTimer scheduled
65};
66
67
68struct SystemTimeUserTimer : public UserTimer {
69	virtual	void				Schedule(bigtime_t nextTime, bigtime_t interval,
70									uint32 flags, bigtime_t& _oldRemainingTime,
71									bigtime_t& _oldInterval);
72	virtual	void				GetInfo(bigtime_t& _remainingTime,
73									bigtime_t& _interval,
74									uint32& _overrunCount);
75
76protected:
77	virtual	void				HandleTimer();
78
79			void				ScheduleKernelTimer(bigtime_t now,
80									bool checkPeriodicOverrun);
81};
82
83
84struct RealTimeUserTimer : public SystemTimeUserTimer {
85	virtual	void				Schedule(bigtime_t nextTime, bigtime_t interval,
86									uint32 flags, bigtime_t& _oldRemainingTime,
87									bigtime_t& _oldInterval);
88
89			void				TimeWarped();
90
91private:
92			bigtime_t			fRealTimeOffset;
93			bool				fAbsolute;
94
95protected:
96	virtual	void				HandleTimer();
97
98public:
99			// conceptually package private
100			DoublyLinkedListLink<RealTimeUserTimer> fGlobalListLink;
101};
102
103
104struct TeamTimeUserTimer : public UserTimer {
105								TeamTimeUserTimer(team_id teamID);
106								~TeamTimeUserTimer();
107
108	virtual	void				Schedule(bigtime_t nextTime, bigtime_t interval,
109									uint32 flags, bigtime_t& _oldRemainingTime,
110									bigtime_t& _oldInterval);
111	virtual	void				GetInfo(bigtime_t& _remainingTime,
112									bigtime_t& _interval,
113									uint32& _overrunCount);
114
115			void				Deactivate();
116
117			void				Update(Thread* unscheduledThread);
118			void				TimeWarped(bigtime_t changedBy);
119
120protected:
121	virtual	void				HandleTimer();
122
123private:
124			void				_Update(bool unscheduling);
125
126private:
127			team_id				fTeamID;
128			Team*				fTeam;
129			int32				fRunningThreads;
130			bool				fAbsolute;
131
132public:
133			// conceptually package private
134			DoublyLinkedListLink<TeamTimeUserTimer> fCPUTimeListLink;
135};
136
137
138struct TeamUserTimeUserTimer : public UserTimer {
139								TeamUserTimeUserTimer(team_id teamID);
140								~TeamUserTimeUserTimer();
141
142	virtual	void				Schedule(bigtime_t nextTime, bigtime_t interval,
143									uint32 flags, bigtime_t& _oldRemainingTime,
144									bigtime_t& _oldInterval);
145	virtual	void				GetInfo(bigtime_t& _remainingTime,
146									bigtime_t& _interval,
147									uint32& _overrunCount);
148
149			void				Deactivate();
150			void				Check();
151
152private:
153			team_id				fTeamID;
154			Team*				fTeam;
155
156public:
157			// conceptually package private
158			DoublyLinkedListLink<TeamUserTimeUserTimer> fCPUTimeListLink;
159};
160
161
162struct ThreadTimeUserTimer : public UserTimer {
163								ThreadTimeUserTimer(thread_id threadID);
164								~ThreadTimeUserTimer();
165
166	virtual	void				Schedule(bigtime_t nextTime, bigtime_t interval,
167									uint32 flags, bigtime_t& _oldRemainingTime,
168									bigtime_t& _oldInterval);
169	virtual	void				GetInfo(bigtime_t& _remainingTime,
170									bigtime_t& _interval,
171									uint32& _overrunCount);
172
173			void				Deactivate();
174
175			void				Start();
176			void				Stop();
177			void				TimeWarped(bigtime_t changedBy);
178
179protected:
180	virtual	void				HandleTimer();
181
182private:
183			thread_id			fThreadID;
184			Thread*				fThread;	// != NULL only when active
185			bool				fAbsolute;
186
187public:
188			// conceptually package private
189			DoublyLinkedListLink<ThreadTimeUserTimer> fCPUTimeListLink;
190};
191
192
193struct UserTimerList {
194								UserTimerList();
195								~UserTimerList();
196
197			UserTimer*			TimerFor(int32 id) const;
198			void				AddTimer(UserTimer* timer);
199			void				RemoveTimer(UserTimer* timer)
200									{ fTimers.Remove(timer); }
201			int32				DeleteTimers(bool userDefinedOnly);
202
203private:
204			typedef DoublyLinkedList<UserTimer> TimerList;
205
206private:
207			TimerList			fTimers;
208};
209
210
211typedef DoublyLinkedList<RealTimeUserTimer,
212	DoublyLinkedListMemberGetLink<RealTimeUserTimer,
213		&RealTimeUserTimer::fGlobalListLink> > RealTimeUserTimerList;
214
215typedef DoublyLinkedList<TeamTimeUserTimer,
216	DoublyLinkedListMemberGetLink<TeamTimeUserTimer,
217		&TeamTimeUserTimer::fCPUTimeListLink> > TeamTimeUserTimerList;
218
219typedef DoublyLinkedList<TeamUserTimeUserTimer,
220	DoublyLinkedListMemberGetLink<TeamUserTimeUserTimer,
221		&TeamUserTimeUserTimer::fCPUTimeListLink> > TeamUserTimeUserTimerList;
222
223typedef DoublyLinkedList<ThreadTimeUserTimer,
224	DoublyLinkedListMemberGetLink<ThreadTimeUserTimer,
225		&ThreadTimeUserTimer::fCPUTimeListLink> > ThreadTimeUserTimerList;
226
227
228}	// namespace BKernel
229
230
231using BKernel::RealTimeUserTimer;
232using BKernel::RealTimeUserTimerList;
233using BKernel::SystemTimeUserTimer;
234using BKernel::TeamUserTimeUserTimer;
235using BKernel::TeamUserTimeUserTimerList;
236using BKernel::TeamTimeUserTimer;
237using BKernel::TeamTimeUserTimerList;
238using BKernel::ThreadTimeUserTimer;
239using BKernel::ThreadTimeUserTimerList;
240using BKernel::UserTimer;
241using BKernel::UserTimerList;
242
243
244__BEGIN_DECLS
245
246status_t	user_timer_create_thread_timers(Team* team, Thread* thread);
247status_t	user_timer_create_team_timers(Team* team);
248
249status_t	user_timer_get_clock(clockid_t clockID, bigtime_t& _time);
250void		user_timer_real_time_clock_changed();
251
252void		user_timer_stop_cpu_timers(Thread* thread, Thread* nextThread);
253void		user_timer_continue_cpu_timers(Thread* thread,
254				Thread* previousThread);
255void		user_timer_check_team_user_timers(Team* team);
256
257status_t	_user_get_clock(clockid_t clockID, bigtime_t* _time);
258status_t	_user_set_clock(clockid_t clockID, bigtime_t time);
259
260int32		_user_create_timer(clockid_t clockID, thread_id threadID,
261				uint32 flags, const struct sigevent* event,
262				const thread_creation_attributes* threadAttributes);
263status_t	_user_delete_timer(int32 timerID, thread_id threadID);
264status_t	_user_get_timer(int32 timerID, thread_id threadID,
265				struct user_timer_info* info);
266status_t	_user_set_timer(int32 timerID, thread_id threadID,
267				bigtime_t startTime, bigtime_t interval, uint32 flags,
268				struct user_timer_info* oldInfo);
269
270__END_DECLS
271
272
273#endif	// _KERNEL_USER_TIMER_H
274