root/headers/private/kernel/UserTimer.h
/*
 * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
 * Distributed under the terms of the MIT License.
 */
#ifndef _KERNEL_USER_TIMER_H
#define _KERNEL_USER_TIMER_H


#include <sys/cdefs.h>
#include <time.h>

#include <util/DoublyLinkedList.h>

#include <ksignal.h>
#include <timer.h>
#include <user_timer_defs.h>


struct thread_creation_attributes;


namespace BKernel {


struct UserEvent;
struct Team;


struct UserTimer : DoublyLinkedListLinkImpl<UserTimer> {
                                                                UserTimer();
        virtual                                         ~UserTimer();

                        int32                           ID() const
                                                                        { return fID; }
                        void                            SetID(int32 id)
                                                                        { fID = id; }

                        void                            SetEvent(UserEvent* event)
                                                                        { fEvent = event; }

        virtual void                            Schedule(bigtime_t nextTime, bigtime_t interval,
                                                                        uint32 flags, bigtime_t& _oldRemainingTime,
                                                                        bigtime_t& _oldInterval) = 0;
                        void                            Cancel();

        virtual void                            GetInfo(bigtime_t& _remainingTime,
                                                                        bigtime_t& _interval,
                                                                        uint32& _overrunCount) = 0;

protected:
        static  int32                           HandleTimerHook(struct timer* timer);
        virtual void                            HandleTimer();

        inline  void                            UpdatePeriodicStartTime();
        inline  void                            CheckPeriodicOverrun(bigtime_t now);

        inline  void                            CancelTimer();

protected:
                        int32                           fID;
                        timer                           fTimer;
                        UserEvent*                      fEvent;
                        bigtime_t                       fNextTime;
                        bigtime_t                       fInterval;
                        uint32                          fOverrunCount;
                        bool                            fScheduled;     // fTimer scheduled
                        int32                           fSkip;
};


struct SystemTimeUserTimer : public UserTimer {
        virtual void                            Schedule(bigtime_t nextTime, bigtime_t interval,
                                                                        uint32 flags, bigtime_t& _oldRemainingTime,
                                                                        bigtime_t& _oldInterval);
        virtual void                            GetInfo(bigtime_t& _remainingTime,
                                                                        bigtime_t& _interval,
                                                                        uint32& _overrunCount);

protected:
        virtual void                            HandleTimer();

                        void                            ScheduleKernelTimer(bigtime_t now,
                                                                        bool checkPeriodicOverrun);
};


struct RealTimeUserTimer : public SystemTimeUserTimer {
        virtual void                            Schedule(bigtime_t nextTime, bigtime_t interval,
                                                                        uint32 flags, bigtime_t& _oldRemainingTime,
                                                                        bigtime_t& _oldInterval);

                        void                            TimeWarped();

private:
                        bigtime_t                       fRealTimeOffset;
                        bool                            fAbsolute;

protected:
        virtual void                            HandleTimer();

public:
                        // conceptually package private
                        DoublyLinkedListLink<RealTimeUserTimer> fGlobalListLink;
};


struct TeamTimeUserTimer : public UserTimer {
                                                                TeamTimeUserTimer(team_id teamID);
                                                                ~TeamTimeUserTimer();

        virtual void                            Schedule(bigtime_t nextTime, bigtime_t interval,
                                                                        uint32 flags, bigtime_t& _oldRemainingTime,
                                                                        bigtime_t& _oldInterval);
        virtual void                            GetInfo(bigtime_t& _remainingTime,
                                                                        bigtime_t& _interval,
                                                                        uint32& _overrunCount);

                        void                            Deactivate();

                        void                            Update(Thread* unscheduledThread,
                                                                        Thread* lockedThread = NULL);
                        void                            TimeWarped(bigtime_t changedBy);

protected:
        virtual void                            HandleTimer();

private:
                        void                            _Update(bool unscheduling,
                                                                        Thread* lockedThread = NULL);

private:
                        team_id                         fTeamID;
                        Team*                           fTeam;
                        int32                           fRunningThreads;
                        bool                            fAbsolute;

public:
                        // conceptually package private
                        DoublyLinkedListLink<TeamTimeUserTimer> fCPUTimeListLink;
};


struct TeamUserTimeUserTimer : public UserTimer {
                                                                TeamUserTimeUserTimer(team_id teamID);
                                                                ~TeamUserTimeUserTimer();

        virtual void                            Schedule(bigtime_t nextTime, bigtime_t interval,
                                                                        uint32 flags, bigtime_t& _oldRemainingTime,
                                                                        bigtime_t& _oldInterval);
        virtual void                            GetInfo(bigtime_t& _remainingTime,
                                                                        bigtime_t& _interval,
                                                                        uint32& _overrunCount);

                        void                            Deactivate();
                        void                            Check();

private:
                        team_id                         fTeamID;
                        Team*                           fTeam;

public:
                        // conceptually package private
                        DoublyLinkedListLink<TeamUserTimeUserTimer> fCPUTimeListLink;
};


struct ThreadTimeUserTimer : public UserTimer {
                                                                ThreadTimeUserTimer(thread_id threadID);
                                                                ~ThreadTimeUserTimer();

        virtual void                            Schedule(bigtime_t nextTime, bigtime_t interval,
                                                                        uint32 flags, bigtime_t& _oldRemainingTime,
                                                                        bigtime_t& _oldInterval);
        virtual void                            GetInfo(bigtime_t& _remainingTime,
                                                                        bigtime_t& _interval,
                                                                        uint32& _overrunCount);

                        void                            Deactivate();

                        void                            Start();
                        void                            Stop();
                        void                            TimeWarped(bigtime_t changedBy);

protected:
        virtual void                            HandleTimer();

private:
                        thread_id                       fThreadID;
                        Thread*                         fThread;        // != NULL only when active
                        bool                            fAbsolute;

public:
                        // conceptually package private
                        DoublyLinkedListLink<ThreadTimeUserTimer> fCPUTimeListLink;
};


struct UserTimerList {
                                                                UserTimerList();
                                                                ~UserTimerList();

                        UserTimer*                      TimerFor(int32 id) const;
                        void                            AddTimer(UserTimer* timer);
                        void                            RemoveTimer(UserTimer* timer)
                                                                        { fTimers.Remove(timer); }
                        int32                           DeleteTimers(bool userDefinedOnly);

private:
                        typedef DoublyLinkedList<UserTimer> TimerList;

private:
                        TimerList                       fTimers;
};


typedef DoublyLinkedList<RealTimeUserTimer,
        DoublyLinkedListMemberGetLink<RealTimeUserTimer,
                &RealTimeUserTimer::fGlobalListLink> > RealTimeUserTimerList;

typedef DoublyLinkedList<TeamTimeUserTimer,
        DoublyLinkedListMemberGetLink<TeamTimeUserTimer,
                &TeamTimeUserTimer::fCPUTimeListLink> > TeamTimeUserTimerList;

typedef DoublyLinkedList<TeamUserTimeUserTimer,
        DoublyLinkedListMemberGetLink<TeamUserTimeUserTimer,
                &TeamUserTimeUserTimer::fCPUTimeListLink> > TeamUserTimeUserTimerList;

typedef DoublyLinkedList<ThreadTimeUserTimer,
        DoublyLinkedListMemberGetLink<ThreadTimeUserTimer,
                &ThreadTimeUserTimer::fCPUTimeListLink> > ThreadTimeUserTimerList;


}       // namespace BKernel


using BKernel::RealTimeUserTimer;
using BKernel::RealTimeUserTimerList;
using BKernel::SystemTimeUserTimer;
using BKernel::TeamUserTimeUserTimer;
using BKernel::TeamUserTimeUserTimerList;
using BKernel::TeamTimeUserTimer;
using BKernel::TeamTimeUserTimerList;
using BKernel::ThreadTimeUserTimer;
using BKernel::ThreadTimeUserTimerList;
using BKernel::UserTimer;
using BKernel::UserTimerList;


__BEGIN_DECLS

status_t        user_timer_create_thread_timers(Team* team, Thread* thread);
status_t        user_timer_create_team_timers(Team* team);

status_t        user_timer_get_clock(clockid_t clockID, bigtime_t& _time);
void            user_timer_real_time_clock_changed();

void            user_timer_stop_cpu_timers(Thread* thread, Thread* nextThread);
void            user_timer_continue_cpu_timers(Thread* thread,
                                Thread* previousThread);
void            user_timer_check_team_user_timers(Team* team);

status_t        _user_get_clock(clockid_t clockID, bigtime_t* _time);
status_t        _user_set_clock(clockid_t clockID, bigtime_t time);
status_t        _user_get_cpuclockid(thread_id id, int32 which, clockid_t* _clockID);

int32           _user_create_timer(clockid_t clockID, thread_id threadID,
                                uint32 flags, const struct sigevent* event,
                                const thread_creation_attributes* threadAttributes);
status_t        _user_delete_timer(int32 timerID, thread_id threadID);
status_t        _user_get_timer(int32 timerID, thread_id threadID,
                                struct user_timer_info* info);
status_t        _user_set_timer(int32 timerID, thread_id threadID,
                                bigtime_t startTime, bigtime_t interval, uint32 flags,
                                struct user_timer_info* oldInfo);

__END_DECLS


#endif  // _KERNEL_USER_TIMER_H