#include #include #include #include #include "bapp_task.h" #include "bapp_util.h" #include "genericlist.h" extern int pthread_kill (pthread_t THREAD, int SIGNO); struct bapp_task_event { LINKS_T links; bapp_task_event_t event; }; struct bapp_task_queue { LIST_T list; pthread_mutex_t mutex; }; struct bapp_task_mutex { pthread_mutex_t mutex; }; struct bapp_task { pthread_t thread; }; int g_ticks_per_ms = 1; int g_ticks_per_second = 1000; static pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER; static int lflag = 0; void bapp_task_init(void) { } void bapp_task_start(void) { } bapp_result_t bapp_task_start_task( bapp_task_t *handle, const bapp_task_params *params, bapp_task_func func, void *data ) { struct bapp_task *p_task = (struct bapp_task*)malloc(sizeof(struct bapp_task)); BAPP_UNUSED(params); if (!p_task) return eBAPP_RESULT_ALLOC_FAILURE; if (pthread_create((pthread_t*)&p_task->thread, NULL, (void *(*)(void*))func, data) == 0) { *handle = (bapp_task_t)p_task; return eBAPP_RESULT_OK; } free(p_task); return eBAPP_RESULT_ALLOC_FAILURE; } void bapp_task_stop_task(bapp_task_t handle) { struct bapp_task *p_task = (struct bapp_task *)handle; pthread_kill((pthread_t)p_task->thread,-9); free(p_task); } bapp_result_t bapp_task_create_queue( bapp_task_queue_t *handle, bapp_task_event_t *events, int num_events ) { struct bapp_task_queue *p_bq = (struct bapp_task_queue*)malloc(sizeof(struct bapp_task_queue)); BAPP_UNUSED(events); BAPP_UNUSED(num_events); if (!p_bq) return eBAPP_RESULT_ALLOC_FAILURE; if (pthread_mutex_init(&p_bq->mutex,NULL) != 0) { free(p_bq); return eBAPP_RESULT_ALLOC_FAILURE; } initl(&p_bq->list); *handle = (bapp_task_queue_t)p_bq; return eBAPP_RESULT_OK; } void bapp_task_delete_queue( bapp_task_queue_t handle ) { struct bapp_task_queue *p_bq = (struct bapp_task_queue*)handle; struct bapp_task_event *p_evt; for (p_evt = (struct bapp_task_event*)remlh(&p_bq->list); p_evt != NULL; p_evt = (struct bapp_task_event*)remlh(&p_bq->list)) { free(p_evt); } free(p_bq); } bapp_result_t bapp_task_post_event( bapp_task_queue_t handle, bapp_task_event_t event ) { struct bapp_task_queue *p_bq = (struct bapp_task_queue*)handle; struct bapp_task_event *p_evt = NULL; p_evt = (struct bapp_task_event*)malloc(sizeof(struct bapp_task_event)); if (!p_evt) return eBAPP_RESULT_ALLOC_FAILURE; if (pthread_mutex_lock((pthread_mutex_t *)&p_bq->mutex) != 0) goto error; p_evt->event = event; inslt(&p_bq->list,p_evt); pthread_mutex_unlock((pthread_mutex_t *)&p_bq->mutex); return eBAPP_RESULT_OK; error: if (p_evt) free(p_evt); return eBAPP_RESULT_FAILURE; } bapp_task_event_t bapp_task_pend_event( bapp_task_queue_t handle, int timeout_ms ) { struct bapp_task_queue *p_bq = (struct bapp_task_queue*)handle; struct bapp_task_event *p_evt = NULL; struct bapp_task_event *return_event = NULL; unsigned int timout_ticks = bapp_task_getticks() + timeout_ms * g_ticks_per_ms;; if (pthread_mutex_lock((pthread_mutex_t *)&p_bq->mutex) != 0) goto exit; while (LEMPTY(&p_bq->list)) { pthread_mutex_unlock((pthread_mutex_t *)&p_bq->mutex); bapp_task_sleep(1); if (timeout_ms >= 0) { if (timout_ticks < bapp_task_getticks()) goto exit; } if (pthread_mutex_lock((pthread_mutex_t *)&p_bq->mutex) != 0) goto exit; } p_evt = (struct bapp_task_event*)LHEAD(&p_bq->list); reml(&p_bq->list,p_evt); return_event = p_evt->event; free(p_evt); pthread_mutex_unlock((pthread_mutex_t *)&p_bq->mutex); exit: return (bapp_task_event_t)return_event; } void bapp_task_reset_queue( bapp_task_queue_t handle) { bapp_task_event_t event; do { event = bapp_task_pend_event(handle,0); }while(event != NULL); } bapp_result_t bapp_task_create_mutex( bapp_task_mutex_t *handle ) { struct bapp_task_mutex *p_mutex; p_mutex = (struct bapp_task_mutex*)malloc(sizeof(struct bapp_task_mutex)); if (!p_mutex) return eBAPP_RESULT_ALLOC_FAILURE; if (pthread_mutex_init((pthread_mutex_t *)&p_mutex->mutex,NULL) == 0) { *handle = (bapp_task_mutex_t)p_mutex; return eBAPP_RESULT_OK; } free(p_mutex); return eBAPP_RESULT_ALLOC_FAILURE; } void bapp_task_delete_mutex( bapp_task_mutex_t handle) { struct bapp_task_mutex *p_mutex = (struct bapp_task_mutex*)handle; pthread_mutex_destroy((pthread_mutex_t* )&p_mutex->mutex); free(p_mutex); } bapp_result_t bapp_task_acquire_mutex( bapp_task_mutex_t handle, int timeout_ms ) { struct bapp_task_mutex *p_mutex = (struct bapp_task_mutex*)handle; if (timeout_ms < 0) { if (pthread_mutex_lock((pthread_mutex_t *)&p_mutex->mutex) != 0) return eBAPP_RESULT_FAILURE; } else { unsigned int timout_ticks = bapp_task_getticks() + timeout_ms * g_ticks_per_ms; while (pthread_mutex_trylock((pthread_mutex_t *)&p_mutex->mutex) != 0) { bapp_task_sleep(1); if (timout_ticks < bapp_task_getticks()) return eBAPP_RESULT_TIMEOUT; } } return eBAPP_RESULT_OK; } bapp_result_t bapp_task_release_mutex( bapp_task_mutex_t handle ) { struct bapp_task_mutex *p_mutex = (struct bapp_task_mutex*)handle; pthread_mutex_unlock((pthread_mutex_t *)&p_mutex->mutex); return eBAPP_RESULT_OK; } void bapp_task_sleep( unsigned int sleep_ms ) { if (sleep_ms >=1000) { sleep(sleep_ms/1000); usleep((sleep_ms%1000) * 1000); } else { usleep(sleep_ms*1000); } } #if 0 static int timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y) { /* Perform the carry for the later subtraction by updating y. */ if (x->tv_usec < y->tv_usec) { int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; y->tv_usec -= 1000000 * nsec; y->tv_sec += nsec; } if (x->tv_usec - y->tv_usec > 1000000) { int nsec = (x->tv_usec - y->tv_usec) / 1000000; y->tv_usec += 1000000 * nsec; y->tv_sec -= nsec; } /* Compute the time remaining to wait. tv_usec is certainly positive. */ result->tv_sec = x->tv_sec - y->tv_sec; result->tv_usec = x->tv_usec - y->tv_usec; /* Return 1 if result is negative. */ return x->tv_sec < y->tv_sec; } #endif static struct timeval s_start_time = {0,0}; unsigned int bapp_task_getticks( void ) { struct timeval tv; struct timeval cur_tv; if ((s_start_time.tv_sec == 0) && (s_start_time.tv_usec == 0)) { gettimeofday(&s_start_time,NULL); } gettimeofday(&cur_tv,NULL); timeval_subtract(&tv,&cur_tv,&s_start_time); return (tv.tv_sec * 1000 + tv.tv_usec/1000); } unsigned int bapp_task_enter_critical(void) { pthread_mutex_lock((pthread_mutex_t *)&s_mutex); return lflag++; } void bapp_task_exit_critical(unsigned int flags) { BAPP_UNUSED(flags); pthread_mutex_unlock((pthread_mutex_t *)&s_mutex); }