예제 #1
0
파일: frame.c 프로젝트: jcheng95/libxbee3
xbee_err xbee_frameWait(struct xbee_frameBlock *fBlock, struct xbee_con *con, unsigned char *retVal, struct timespec *timeout) {
	xbee_err ret;
	struct xbee_frame *frame;
	int i, o;
	
	if (!fBlock || !con) return XBEE_EMISSINGPARAM;

	ret = XBEE_EINVAL;
	xbee_mutex_lock(&fBlock->mutex);
	frame = NULL;
	for (i = 0, o = fBlock->lastFrame; i < fBlock->numFrames; i++, o--) {
		if (o < 0) o = fBlock->numFrames - 1;
		if (fBlock->frame[o].id != con->frameId) continue;

		if (fBlock->frame[o].status == 0 || fBlock->frame[o].con != con) {
			ret = XBEE_ESTALE;
		} else {
			frame = &fBlock->frame[o];
			frame->status |= XBEE_FRAME_STATUS_WAITING;
		}
		break;
	}
	xbee_mutex_unlock(&fBlock->mutex);
	if (!frame) return ret;

	ret = XBEE_ENONE;
	if (timeout) {
		if (xsys_sem_timedwait(&frame->sem, timeout)) {
			if (errno == ETIMEDOUT) {
				ret = XBEE_ETIMEOUT;
			} else {
				ret = XBEE_ESEMAPHORE;
			}
		}
	} else {
		if (xsys_sem_wait(&frame->sem)) {
			ret = XBEE_ESEMAPHORE;
		}
	}
	
	xbee_mutex_lock(&fBlock->mutex);
	con->frameId = 0;
	frame->con = NULL;
	if (frame->status & XBEE_FRAME_STATUS_COMPLETE && ret == XBEE_ENONE) {
		if (retVal) *retVal = frame->retVal;
		frame->status = 0;
	} else {
		frame->status &= ~XBEE_FRAME_STATUS_WAITING;
	}
	xbee_mutex_unlock(&fBlock->mutex);
	
	return ret;
}
예제 #2
0
/* the thread monitoring thread... hmm */
void xbee_threadMonitor(struct xbee *xbee) {
	struct threadInfo *info;
	void *tRet;
	int ret;
	int count, joined, restarted;
	
	/* detach self, so that resources are free'd as soon as we return */
	xsys_thread_detach_self();
	
	while (xbee->running) {
		/* wait for 10 seconds, unless prodded */
		xsys_sem_timedwait(&xbee->semMonitor, 10, 0);
		
		xbee_log(15,"Scanning for dead threads...");
		
		/* keep track of some stats */
		count = 0;
		joined = 0;
		restarted = 0;
		
		/* iterate through each monitored thread */
		for (info = NULL; (info = ll_get_next(&xbee->threadList, info)) != NULL;) {
			/* if thread is supposed to be running */
			if (info->running) {
#warning TODO - find an alternative to pthread_tryjoin_np()
				/* try to join with the thread */
				if ((ret = xsys_thread_tryjoin(*info->thread, &tRet)) == 0) {
					/* apparently it died! mark it dead, and report it */
					info->running = 0;
					xbee_log(15,"Thread 0x%X died (%s), it returned 0x%X", info->thread, info->funcName, ret);
					joined++;
				} else {
					/* if the join failed, then find out why (to the best of our ability) and log the details */
					if (ret == EBUSY) {
						xbee_log(10,"xsys_thread_tryjoin(): 0x%X (%s) EBUSY", info->thread, info->funcName);
					} else if (ret == ETIMEDOUT) {
						xbee_log(10,"xsys_thread_tryjoin(): 0x%X (%s) ETIMEDOUT", info->thread, info->funcName);
					} else if (ret == EINVAL) {
						xbee_log(10,"xsys_thread_tryjoin(): 0x%X (%s) EINVAL", info->thread, info->funcName);
					} else {
						xbee_log(10,"xsys_thread_tryjoin(): 0x%X (%s) unknown (%d)", info->thread, info->funcName, ret);
					}
					count++;
				}
			}
			
			/* we need to re-test info->running, because it may have just been marked dead */
			if (!info->running) {
				/* try to restart the thread */
				if (xsys_thread_create(info->thread, info->start_routine, info->arg) == 0) {
					/* success! keep the stats */
					restarted++;
					info->restartCount++;
					info->running = 1;
				} else {
					/* otherwise log the info */
					xbee_log(10,"Failed to restart thread (%s)...\n", info->funcName);
				}
			}
		}
		
		/* log the stats */
		xbee_log(15,"Scan complete! joined/restarted/remain %d/%d/%d threads", joined, restarted, count);
	}
}