Implement setitimer() and sigaction().

The timer is implemented using a thread.

Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>
This commit is contained in:
Johannes Sixt
2007-11-13 10:14:45 +01:00
parent 73c1250e77
commit 6d305e3341
2 changed files with 134 additions and 1 deletions

View File

@@ -650,3 +650,119 @@ struct passwd *mingw_getpwuid(int uid)
p.pw_dir = NULL;
return &p;
}
static HANDLE timer_event;
static HANDLE timer_thread;
static int timer_interval;
static int one_shot;
static sig_handler_t timer_fn = SIG_DFL;
/* The timer works like this:
* The thread, ticktack(), is basically a trivial routine that most of the
* time only waits to receive the signal to terminate. The main thread
* tells the thread to terminate by setting the timer_event to the signalled
* state.
* But ticktack() does not wait indefinitely; instead, it interrupts the
* wait state every now and then, namely exactly after timer's interval
* length. At these opportunities it calls the signal handler.
*/
static __stdcall unsigned ticktack(void *dummy)
{
while (WaitForSingleObject(timer_event, timer_interval) == WAIT_TIMEOUT) {
if (timer_fn == SIG_DFL)
die("Alarm");
if (timer_fn != SIG_IGN)
timer_fn(SIGALRM);
if (one_shot)
break;
}
return 0;
}
static int start_timer_thread(void)
{
timer_event = CreateEvent(NULL, FALSE, FALSE, NULL);
if (timer_event) {
timer_thread = (HANDLE) _beginthreadex(NULL, 0, ticktack, NULL, 0, NULL);
if (!timer_thread )
return errno = ENOMEM,
error("cannot create progress indicator");
} else
return errno = ENOMEM,
error("cannot allocate resources for progress indicator");
return 0;
}
static void stop_timer_thread(void)
{
if (timer_event)
SetEvent(timer_event); /* tell thread to terminate */
if (timer_thread) {
int rc = WaitForSingleObject(timer_thread, 1000);
if (rc == WAIT_TIMEOUT)
error("timer thread did not terminate timely");
else if (rc != WAIT_OBJECT_0)
error("waiting for timer thread failed: %lu",
GetLastError());
CloseHandle(timer_thread);
}
if (timer_event)
CloseHandle(timer_event);
timer_event = NULL;
timer_thread = NULL;
}
static inline int is_timeval_eq(const struct timeval *i1, const struct timeval *i2)
{
return i1->tv_sec == i2->tv_sec && i1->tv_usec == i2->tv_usec;
}
int setitimer(int type, struct itimerval *in, struct itimerval *out)
{
static const struct timeval zero;
if (out != NULL)
return errno = EINVAL,
error("setitmer param 3 != NULL not implemented");
if (!is_timeval_eq(&in->it_interval, &zero) &&
!is_timeval_eq(&in->it_interval, &in->it_value))
return errno = EINVAL,
error("setitmer: it_interval must be zero or eq it_value");
if (timer_thread)
stop_timer_thread();
if (is_timeval_eq(&in->it_value, &zero) &&
is_timeval_eq(&in->it_interval, &zero))
return 0;
timer_interval = in->it_interval.tv_sec * 1000 + in->it_interval.tv_usec / 1000;
one_shot = is_timeval_eq(&in->it_value, &zero);
atexit(stop_timer_thread);
return start_timer_thread();
}
int sigaction(int sig, struct sigaction *in, struct sigaction *out)
{
if (sig != SIGALRM)
return errno = EINVAL,
error("sigaction only implemented for SIGALRM");
if (out != NULL)
return errno = EINVAL,
error("sigaction: param 3 != NULL not implemented");
timer_fn = in->sa_handler;
return 0;
}
#undef signal
sig_handler_t mingw_signal(int sig, sig_handler_t handler)
{
if (sig != SIGALRM)
return signal(sig, handler);
sig_handler_t old = timer_fn;
timer_fn = handler;
return old;
}

View File

@@ -454,7 +454,6 @@ typedef int pid_t;
#define WNOHANG 1
#define SIGKILL 0
#define SIGCHLD 0
#define SIGALRM 0
#define SIGPIPE 0
#define ECONNABORTED 0
@@ -548,6 +547,24 @@ struct passwd *mingw_getpwuid(int uid);
static inline int getuid() { return 1; }
static inline struct passwd *getpwnam(const char *name) { return NULL; }
struct itimerval {
struct timeval it_value, it_interval;
};
int setitimer(int type, struct itimerval *in, struct itimerval *out);
#define ITIMER_REAL 0
typedef void (__cdecl *sig_handler_t)(int);
struct sigaction {
sig_handler_t sa_handler;
unsigned sa_flags;
};
int sigaction(int sig, struct sigaction *in, struct sigaction *out);
#define sigemptyset(x) (void)0
#define SA_RESTART 0
#define SIGALRM 100
sig_handler_t mingw_signal(int sig, sig_handler_t handler);
#define signal mingw_signal
#endif /* __MINGW32__ */
#endif