You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
173 lines
3.2 KiB
173 lines
3.2 KiB
#include <setjmp.h>
|
|
#include <signal.h>
|
|
#include <time.h>
|
|
#include <errno.h>
|
|
|
|
#include <scot/thread.h>
|
|
#include <scot/exception.h>
|
|
#include <scot/scot_int.h>
|
|
#include <scot/memory.h>
|
|
|
|
struct join_cond_st
|
|
{
|
|
pthread_mutex_t join_alarm_mutex;
|
|
pthread_cond_t join_alarm_cond;
|
|
THREAD_T thread;
|
|
};
|
|
|
|
static
|
|
T_PROC_RET
|
|
join_thread (void * arg)
|
|
{
|
|
int status;
|
|
struct join_cond_st * join_cond = (struct join_cond_st *) arg;
|
|
|
|
THREAD_CANCEL_ENABLE;
|
|
THREAD_CANCEL_ASYNC;
|
|
|
|
pthread_join (join_cond->thread, NULL);
|
|
|
|
status = pthread_cond_signal (&(join_cond->join_alarm_cond));
|
|
if (status != 0)
|
|
{
|
|
perror ("problem with sending signal within join");
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
THREAD_T
|
|
thread_new (T_PROC_RET (*t_proc)(void *), void* arg)
|
|
{
|
|
THREAD_T handle;
|
|
|
|
if (pthread_create (&handle, NULL, t_proc, arg) != 0)
|
|
{
|
|
SCOT_MEM_ZERO (&handle, sizeof (THREAD_T));
|
|
}
|
|
|
|
return handle;
|
|
}
|
|
|
|
void
|
|
thread_end (THREAD_T thread, uint32_t timeout)
|
|
{
|
|
int err;
|
|
|
|
err = CANCEL_THREAD (thread);
|
|
if (err != 0)
|
|
THROW (EXC (EXC_ERROR,
|
|
err,
|
|
"[EVENT_SOURCE_THREAD]cancel request failed"));
|
|
|
|
err = JOIN_THREAD (thread, timeout);
|
|
if (err == JOIN_TIMEOUT)
|
|
THROW (EXC (EXC_ERROR,
|
|
err,
|
|
"[EVENT_SOURCE_THREAD]timeout exceeded while waiting "
|
|
"for threads end"));
|
|
if (err == JOIN_ERROR)
|
|
THROW (EXC (EXC_ERROR,
|
|
err,
|
|
"[EVENT_SOURCE_THREAD]failure on waiting for threads end"));
|
|
}
|
|
|
|
int
|
|
thread_join (THREAD_T thread, uint32_t timeout)
|
|
{
|
|
int status,
|
|
join_state = JOIN_OK;
|
|
struct timespec alarm;
|
|
pthread_t join_thr;
|
|
struct join_cond_st join_cond =
|
|
{
|
|
PTHREAD_MUTEX_INITIALIZER,
|
|
PTHREAD_COND_INITIALIZER,
|
|
thread
|
|
};
|
|
|
|
if (timeout == INFINITE)
|
|
{
|
|
if (pthread_join (thread, NULL) == 0)
|
|
{
|
|
return JOIN_OK;
|
|
}
|
|
else
|
|
{
|
|
return JOIN_ERROR;
|
|
}
|
|
}
|
|
|
|
alarm.tv_sec = time (NULL) + timeout;
|
|
alarm.tv_nsec = 0;
|
|
|
|
status = pthread_mutex_lock (&join_cond.join_alarm_mutex);
|
|
if (status != 0)
|
|
{
|
|
perror ("problem achiving mutex within join");
|
|
}
|
|
|
|
join_thr = NEW_THREAD (join_thread, (void *) &join_cond);
|
|
|
|
status = pthread_cond_timedwait (
|
|
&(join_cond.join_alarm_cond),
|
|
&(join_cond.join_alarm_mutex),
|
|
&alarm);
|
|
if (status != 0)
|
|
{
|
|
if (status == ETIMEDOUT)
|
|
{
|
|
join_state = JOIN_TIMEOUT;
|
|
|
|
pthread_cancel (join_thr);
|
|
pthread_join (join_thr, NULL);
|
|
}
|
|
else
|
|
{
|
|
perror ("problem with condition wait within join");
|
|
}
|
|
}
|
|
|
|
return join_state;
|
|
}
|
|
|
|
void
|
|
thread_mutex_new (THREAD_MUTEX_T * mutex)
|
|
{
|
|
pthread_mutex_init (mutex, NULL);
|
|
}
|
|
|
|
void
|
|
thread_cond_new (THREAD_COND_T * cond)
|
|
{
|
|
pthread_cond_init (cond, NULL);
|
|
}
|
|
|
|
int
|
|
thread_mutex_lock (THREAD_MUTEX_T * mutex)
|
|
{
|
|
if (pthread_mutex_lock (mutex) == 0)
|
|
{
|
|
return MUTEX_LOCK_OK;
|
|
}
|
|
else
|
|
{
|
|
return MUTEX_LOCK_ERROR;
|
|
}
|
|
}
|
|
|
|
int
|
|
thread_cond_wait (THREAD_COND_T * cond, THREAD_COND_CS_T * cs, uint32_t t)
|
|
{
|
|
if (t == INFINITE)
|
|
return pthread_cond_wait (cond, cs);
|
|
else
|
|
{
|
|
struct timespec tout;
|
|
|
|
tout.tv_sec = time (NULL) + t;
|
|
tout.tv_nsec = 0;
|
|
|
|
return pthread_cond_timedwait (cond, cs, &tout);
|
|
}
|
|
}
|