2 * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
13 #include <AutoDeleter.h>
14 #include <syscall_utils.h>
16 #include <errno_private.h>
18 #include <thread_defs.h>
19 #include <user_timer_defs.h>
21 #include <libroot_private.h>
22 #include <pthread_private.h>
23 #include <time_private.h>
24 #include <user_thread.h>
28 info_to_itimerspec(const user_timer_info
& info
, itimerspec
& spec
)
30 bigtime_to_timespec(info
.interval
, spec
.it_interval
);
32 // A remaining_time of B_INFINITE_TIMEOUT means the timer isn't scheduled.
33 if (info
.remaining_time
!= B_INFINITE_TIMEOUT
) {
34 bigtime_to_timespec(info
.remaining_time
, spec
.it_value
);
36 spec
.it_value
.tv_sec
= 0;
37 spec
.it_value
.tv_nsec
= 0;
43 itimerspec_to_bigtimes(const itimerspec
& spec
, bigtime_t
& _nextTime
,
46 if (!timespec_to_bigtime(spec
.it_interval
, _interval
)
47 || !timespec_to_bigtime(spec
.it_value
, _nextTime
)) {
52 _nextTime
= B_INFINITE_TIMEOUT
;
59 timer_thread_entry(void* _entry
, void* _value
)
62 pthread_thread thread
;
63 __init_pthread(&thread
, NULL
, NULL
);
64 thread
.flags
|= THREAD_DETACHED
;
66 get_user_thread()->pthread
= &thread
;
68 // we have been started with deferred signals -- undefer them
71 // prepare the arguments
73 value
.sival_ptr
= _value
;
74 void (*entry
)(union sigval
) = (void (*)(union sigval
))_entry
;
76 // call the entry function
87 timer_create(clockid_t clockID
, struct sigevent
* event
, timer_t
* _timer
)
89 // create a timer object
90 __timer_t
* timer
= new(std::nothrow
) __timer_t
;
92 RETURN_AND_SET_ERRNO(ENOMEM
);
93 ObjectDeleter
<__timer_t
> timerDeleter(timer
);
95 // If the notification method is SIGEV_THREAD, initialize thread creation
97 bool isThreadEvent
= event
!= NULL
&& event
->sigev_notify
== SIGEV_THREAD
;
98 thread_creation_attributes threadAttributes
;
100 status_t error
= __pthread_init_creation_attributes(
101 event
->sigev_notify_attributes
, NULL
, &timer_thread_entry
,
102 (void*)event
->sigev_notify_function
, event
->sigev_value
.sival_ptr
,
103 "timer notify", &threadAttributes
);
105 RETURN_AND_SET_ERRNO(error
);
107 threadAttributes
.flags
|= THREAD_CREATION_FLAG_DEFER_SIGNALS
;
111 int32 timerID
= _kern_create_timer(clockID
, -1, 0, event
,
112 isThreadEvent
? &threadAttributes
: NULL
);
114 RETURN_AND_SET_ERRNO(timerID
);
116 // init the object members
117 timer
->SetTo(timerID
, -1);
119 *_timer
= timerDeleter
.Detach();
125 timer_delete(timer_t timer
)
127 status_t error
= _kern_delete_timer(timer
->id
, timer
->thread
);
129 RETURN_AND_SET_ERRNO(error
);
137 timer_gettime(timer_t timer
, struct itimerspec
* value
)
139 user_timer_info info
;
140 status_t error
= _kern_get_timer(timer
->id
, timer
->thread
, &info
);
142 RETURN_AND_SET_ERRNO(error
);
144 info_to_itimerspec(info
, *value
);
151 timer_settime(timer_t timer
, int flags
, const struct itimerspec
* value
,
152 struct itimerspec
* oldValue
)
154 // translate new value
157 if (!itimerspec_to_bigtimes(*value
, nextTime
, interval
))
158 RETURN_AND_SET_ERRNO(EINVAL
);
160 uint32 timeoutFlags
= (flags
& TIMER_ABSTIME
) != 0
161 ? B_ABSOLUTE_TIMEOUT
: B_RELATIVE_TIMEOUT
;
164 user_timer_info oldInfo
;
165 status_t error
= _kern_set_timer(timer
->id
, timer
->thread
, nextTime
,
166 interval
, timeoutFlags
, oldValue
!= NULL
? &oldInfo
: NULL
);
168 RETURN_AND_SET_ERRNO(error
);
170 // translate old info back
171 if (oldValue
!= NULL
)
172 info_to_itimerspec(oldInfo
, *oldValue
);
179 timer_getoverrun(timer_t timer
)
181 user_timer_info info
;
182 status_t error
= _kern_get_timer(timer
->id
, timer
->thread
, &info
);
184 RETURN_AND_SET_ERRNO(error
);
186 return info
.overrun_count
;