static void rtems_aio_insert_prio (rtems_chain_control *chain, rtems_aio_request *req) { rtems_chain_node *node; AIO_printf ("FD exists \n"); node = rtems_chain_first (chain); if (rtems_chain_is_empty (chain)) { AIO_printf ("First in chain \n"); rtems_chain_prepend (chain, &req->next_prio); } else { AIO_printf ("Add by priority \n"); int prio = ((rtems_aio_request *) node)->aiocbp->aio_reqprio; while (req->aiocbp->aio_reqprio > prio && !rtems_chain_is_tail (chain, node)) { node = rtems_chain_next (node); prio = ((rtems_aio_request *) node)->aiocbp->aio_reqprio; } rtems_chain_insert (node->previous, &req->next_prio); } }
void ecg_algorithm_handler(void) { if (false == g_ecg_algo_sw) return; u32 u32Tick = 0; char pace = 0; s32 s32I = 0, s32II = 0, s32V = 0; #ifdef _ALG_ECG_RUN_TIME_ u32 u32curtick; #endif s32 s32Len = ECG_PopAlgoResult(&u32Tick, &s32I, &s32II, &s32V, &pace); if (s32Len)//有数据更新 { #ifdef _ALG_ECG_RUN_TIME_ u32curtick = SysTick_Get(); #endif g_Is_ecg_algo_run = true; l_ecg_PushAlgorithmData(&u32Tick, &s32I, &s32II, &s32V, &pace); ecg_algorithm_result(); g_Is_ecg_algo_run = false; #ifdef _ALG_ECG_RUN_TIME_ AIO_printf("\r\nECG ALGO RUN TICK =\t%d\tHR=%d", SysTick_Get()-u32curtick, (u16)p_ecg_algorithm_out->stResult.u32HeartRate); #endif } }
static void * rtems_aio_handle (void *arg) { rtems_aio_request_chain *r_chain = arg; rtems_aio_request *req; rtems_chain_control *chain; rtems_chain_node *node; int result, policy; struct sched_param param; AIO_printf ("Thread started\n"); while (1) { /* acquire the mutex of the current fd chain. we don't need to lock the queue mutex since we can add requests to idle fd chains or even active ones if the working request has been extracted from the chain */ result = pthread_mutex_lock (&r_chain->mutex); if (result != 0) return NULL; chain = &r_chain->perfd; /* If the locked chain is not empty, take the first request extract it, unlock the chain and process the request, in this way the user can supply more requests to this fd chain */ if (!rtems_chain_is_empty (chain)) { AIO_printf ("Get new request from not empty chain\n"); node = rtems_chain_first (chain); req = (rtems_aio_request *) node; /* See _POSIX_PRIORITIZE_IO and _POSIX_PRIORITY_SCHEDULING discussion in rtems_aio_enqueue () */ pthread_getschedparam (pthread_self(), &policy, ¶m); param.sched_priority = req->priority; pthread_setschedparam (pthread_self(), req->policy, ¶m); rtems_chain_extract (node); pthread_mutex_unlock (&r_chain->mutex); switch (req->aiocbp->aio_lio_opcode) { case LIO_READ: AIO_printf ("read\n"); result = pread (req->aiocbp->aio_fildes, (void *) req->aiocbp->aio_buf, req->aiocbp->aio_nbytes, req->aiocbp->aio_offset); break; case LIO_WRITE: AIO_printf ("write\n"); result = pwrite (req->aiocbp->aio_fildes, (void *) req->aiocbp->aio_buf, req->aiocbp->aio_nbytes, req->aiocbp->aio_offset); break; case LIO_SYNC: AIO_printf ("sync\n"); result = fsync (req->aiocbp->aio_fildes); break; default: result = -1; } if (result == -1) { req->aiocbp->return_value = -1; req->aiocbp->error_code = errno; } else { req->aiocbp->return_value = result; req->aiocbp->error_code = 0; } // notification needed for lio } else { /* If the fd chain is empty we unlock the fd chain and we lock the queue chain, this will ensure that we have at most one request comming to our fd chain when we check. If there was no request added sleep for 3 seconds and wait for a signal on chain, this will unlock the queue. The fd chain is already unlocked */ struct timespec timeout; AIO_printf ("Chain is empty [WQ], wait for work\n"); pthread_mutex_unlock (&r_chain->mutex); pthread_mutex_lock (&aio_request_queue.mutex); if (rtems_chain_is_empty (chain)) { clock_gettime (CLOCK_REALTIME, &timeout); timeout.tv_sec += 3; timeout.tv_nsec = 0; result = pthread_cond_timedwait (&r_chain->cond, &aio_request_queue.mutex, &timeout); /* If no requests were added to the chain we delete the fd chain from the queue and start working with idle fd chains */ if (result == ETIMEDOUT) { rtems_chain_extract (&r_chain->next_fd); pthread_mutex_destroy (&r_chain->mutex); pthread_cond_destroy (&r_chain->cond); free (r_chain); /* If the idle chain is empty sleep for 3 seconds and wait for a signal. The thread now becomes idle. */ if (rtems_chain_is_empty (&aio_request_queue.idle_req)) { AIO_printf ("Chain is empty [IQ], wait for work\n"); ++aio_request_queue.idle_threads; --aio_request_queue.active_threads; clock_gettime (CLOCK_REALTIME, &timeout); timeout.tv_sec += 3; timeout.tv_nsec = 0; result = pthread_cond_timedwait (&aio_request_queue.new_req, &aio_request_queue.mutex, &timeout); /* If no new fd chain was added in the idle requests then this thread is finished */ if (result == ETIMEDOUT) { AIO_printf ("Etimeout\n"); --aio_request_queue.idle_threads; pthread_mutex_unlock (&aio_request_queue.mutex); return NULL; } } /* Otherwise move this chain to the working chain and start the loop all over again */ AIO_printf ("Work on idle\n"); --aio_request_queue.idle_threads; ++aio_request_queue.active_threads; node = rtems_chain_first (&aio_request_queue.idle_req); rtems_chain_extract (node); r_chain = (rtems_aio_request_chain *) node; rtems_aio_move_to_work (r_chain); } } /* If there was a request added in the initial fd chain then release the mutex and process it */ pthread_mutex_unlock (&aio_request_queue.mutex); } } AIO_printf ("Thread finished\n"); return NULL; }
int rtems_aio_enqueue (rtems_aio_request *req) { rtems_aio_request_chain *r_chain; rtems_chain_control *chain; pthread_t thid; int result, policy; struct sched_param param; /* The queue should be initialized */ AIO_assert (aio_request_queue.initialized == AIO_QUEUE_INITIALIZED); result = pthread_mutex_lock (&aio_request_queue.mutex); if (result != 0) { free (req); return result; } /* _POSIX_PRIORITIZED_IO and _POSIX_PRIORITY_SCHEDULING are defined, we can use aio_reqprio to lower the priority of the request */ pthread_getschedparam (pthread_self(), &policy, ¶m); req->caller_thread = pthread_self (); req->priority = param.sched_priority - req->aiocbp->aio_reqprio; req->policy = policy; req->aiocbp->error_code = EINPROGRESS; req->aiocbp->return_value = 0; if ((aio_request_queue.idle_threads == 0) && aio_request_queue.active_threads < AIO_MAX_THREADS) /* we still have empty places on the active_threads chain */ { chain = &aio_request_queue.work_req; r_chain = rtems_aio_search_fd (chain, req->aiocbp->aio_fildes, 1); if (r_chain->new_fd == 1) { rtems_chain_prepend (&r_chain->perfd, &req->next_prio); r_chain->new_fd = 0; pthread_mutex_init (&r_chain->mutex, NULL); pthread_cond_init (&r_chain->cond, NULL); AIO_printf ("New thread \n"); result = pthread_create (&thid, &aio_request_queue.attr, rtems_aio_handle, (void *) r_chain); if (result != 0) { pthread_mutex_unlock (&aio_request_queue.mutex); return result; } ++aio_request_queue.active_threads; } else { /* put request in the fd chain it belongs to */ pthread_mutex_lock (&r_chain->mutex); rtems_aio_insert_prio (&r_chain->perfd, req); pthread_cond_signal (&r_chain->cond); pthread_mutex_unlock (&r_chain->mutex); } } else { /* the maximum number of threads has been already created even though some of them might be idle. The request belongs to one of the active fd chain */ r_chain = rtems_aio_search_fd (&aio_request_queue.work_req, req->aiocbp->aio_fildes, 0); if (r_chain != NULL) { pthread_mutex_lock (&r_chain->mutex); rtems_aio_insert_prio (&r_chain->perfd, req); pthread_cond_signal (&r_chain->cond); pthread_mutex_unlock (&r_chain->mutex); } else { /* or to the idle chain */ chain = &aio_request_queue.idle_req; r_chain = rtems_aio_search_fd (chain, req->aiocbp->aio_fildes, 1); if (r_chain->new_fd == 1) { /* If this is a new fd chain we signal the idle threads that might be waiting for requests */ AIO_printf (" New chain on waiting queue \n "); rtems_chain_prepend (&r_chain->perfd, &req->next_prio); r_chain->new_fd = 0; pthread_mutex_init (&r_chain->mutex, NULL); pthread_cond_init (&r_chain->cond, NULL); } else /* just insert the request in the existing fd chain */ rtems_aio_insert_prio (&r_chain->perfd, req); if (aio_request_queue.idle_threads > 0) pthread_cond_signal (&aio_request_queue.new_req); } } pthread_mutex_unlock (&aio_request_queue.mutex); return 0; }
int aio_cancel(int fildes, struct aiocb *aiocbp) { rtems_chain_control *idle_req_chain = &aio_request_queue.idle_req; rtems_chain_control *work_req_chain = &aio_request_queue.work_req; rtems_aio_request_chain *r_chain; int result; pthread_mutex_lock (&aio_request_queue.mutex); if (fcntl (fildes, F_GETFD) < 0) { pthread_mutex_unlock(&aio_request_queue.mutex); rtems_set_errno_and_return_minus_one (EBADF); } /* if aiocbp is NULL remove all request for given file descriptor */ if (aiocbp == NULL) { AIO_printf ("Cancel all requests\n"); r_chain = rtems_aio_search_fd (work_req_chain, fildes, 0); if (r_chain == NULL) { AIO_printf ("Request chain not on [WQ]\n"); if (!rtems_chain_is_empty (idle_req_chain)) { r_chain = rtems_aio_search_fd (idle_req_chain, fildes, 0); if (r_chain == NULL) { pthread_mutex_unlock(&aio_request_queue.mutex); return AIO_ALLDONE; } AIO_printf ("Request chain on [IQ]\n"); rtems_chain_extract (&r_chain->next_fd); rtems_aio_remove_fd (r_chain); pthread_mutex_destroy (&r_chain->mutex); pthread_cond_destroy (&r_chain->mutex); free (r_chain); pthread_mutex_unlock (&aio_request_queue.mutex); return AIO_CANCELED; } pthread_mutex_unlock (&aio_request_queue.mutex); return AIO_ALLDONE; } AIO_printf ("Request chain on [WQ]\n"); pthread_mutex_lock (&r_chain->mutex); rtems_chain_extract (&r_chain->next_fd); rtems_aio_remove_fd (r_chain); pthread_mutex_unlock (&r_chain->mutex); pthread_mutex_unlock (&aio_request_queue.mutex); return AIO_CANCELED; } else { AIO_printf ("Cancel request\n"); if (aiocbp->aio_fildes != fildes) { pthread_mutex_unlock (&aio_request_queue.mutex); rtems_set_errno_and_return_minus_one (EINVAL); } r_chain = rtems_aio_search_fd (work_req_chain, fildes, 0); if (r_chain == NULL) { if (!rtems_chain_is_empty (idle_req_chain)) { r_chain = rtems_aio_search_fd (idle_req_chain, fildes, 0); if (r_chain == NULL) { pthread_mutex_unlock (&aio_request_queue.mutex); rtems_set_errno_and_return_minus_one (EINVAL); } AIO_printf ("Request on [IQ]\n"); result = rtems_aio_remove_req (&r_chain->perfd, aiocbp); pthread_mutex_unlock (&aio_request_queue.mutex); return result; } else { pthread_mutex_unlock (&aio_request_queue.mutex); return AIO_ALLDONE; } } AIO_printf ("Request on [WQ]\n"); pthread_mutex_lock (&r_chain->mutex); result = rtems_aio_remove_req (&r_chain->perfd, aiocbp); pthread_mutex_unlock (&r_chain->mutex); pthread_mutex_unlock (&aio_request_queue.mutex); return result; } return AIO_ALLDONE; }