Browse Source

Implement a generic cgsem_mswait similar to sem_timedwait

Con Kolivas 12 years ago
parent
commit
c75ce853a9
2 changed files with 51 additions and 0 deletions
  1. 50 0
      util.c
  2. 1 0
      util.h

+ 50 - 0
util.c

@@ -881,6 +881,14 @@ void ms_to_timespec(struct timespec *spec, int64_t ms)
 	spec->tv_nsec = tvdiv.rem * 1000000;
 	spec->tv_nsec = tvdiv.rem * 1000000;
 }
 }
 
 
+void ms_to_timeval(struct timeval *val, int64_t ms)
+{
+	lldiv_t tvdiv = lldiv(ms, 1000);
+
+	val->tv_sec = tvdiv.quot;
+	val->tv_usec = tvdiv.rem * 1000;
+}
+
 void timeraddspec(struct timespec *a, const struct timespec *b)
 void timeraddspec(struct timespec *a, const struct timespec *b)
 {
 {
 	a->tv_sec += b->tv_sec;
 	a->tv_sec += b->tv_sec;
@@ -2407,6 +2415,31 @@ void _cgsem_destroy(cgsem_t *cgsem)
 	close(cgsem->pipefd[1]);
 	close(cgsem->pipefd[1]);
 	close(cgsem->pipefd[0]);
 	close(cgsem->pipefd[0]);
 }
 }
+
+/* This is similar to sem_timedwait but takes a millisecond value */
+int _cgsem_mswait(cgsem_t *cgsem, int ms, const char *file, const char *func, const int line)
+{
+	struct timeval timeout;
+	int ret, fd;
+	fd_set rd;
+	char buf;
+
+	fd = cgsem->pipefd[0];
+	FD_ZERO(&rd);
+	FD_SET(fd, &rd);
+	ms_to_timeval(&timeout, ms);
+	ret = select(fd + 1, &rd, NULL, NULL, &timeout);
+
+	if (ret > 0) {
+		ret = read(fd, &buf, 1);
+		return 0;
+	}
+	if (likely(!ret))
+		return ETIMEDOUT;
+	quitfrom(1, file, func, line, "Failed to sem_timedwait errno=%d cgsem=0x%p", errno, cgsem);
+	/* We don't reach here */
+	return 0;
+}
 #else
 #else
 void _cgsem_init(cgsem_t *cgsem, const char *file, const char *func, const int line)
 void _cgsem_init(cgsem_t *cgsem, const char *file, const char *func, const int line)
 {
 {
@@ -2427,6 +2460,23 @@ void _cgsem_wait(cgsem_t *cgsem, const char *file, const char *func, const int l
 		quitfrom(1, file, func, line, "Failed to sem_wait errno=%d cgsem=0x%p", errno, cgsem);
 		quitfrom(1, file, func, line, "Failed to sem_wait errno=%d cgsem=0x%p", errno, cgsem);
 }
 }
 
 
+int _cgsem_mswait(cgsem_t *cgsem, int ms, const char *file, const char *func, const int line)
+{
+	struct timespec abs_timeout, ts_now;
+	struct timeval tv_now;
+	int ret;
+
+	cgtime(&tv_now);
+	timeval_to_spec(&ts_now, &tv_now);
+	ms_to_timespec(&abs_timeout, ms);
+	timeraddspec(&abs_timeout, &ts_now);
+	ret = sem_timedwait(cgsem, &abs_timeout);
+
+	if (unlikely(ret && ret != ETIMEDOUT))
+		quitfrom(1, file, func, line, "Failed to sem_timedwait errno=%d cgsem=0x%p", errno, cgsem);
+	return ret;
+}
+
 void _cgsem_destroy(cgsem_t *cgsem)
 void _cgsem_destroy(cgsem_t *cgsem)
 {
 {
 	sem_destroy(cgsem);
 	sem_destroy(cgsem);

+ 1 - 0
util.h

@@ -129,6 +129,7 @@ void _cgsem_destroy(cgsem_t *cgsem);
 #define cgsem_init(_sem) _cgsem_init(_sem, __FILE__, __func__, __LINE__)
 #define cgsem_init(_sem) _cgsem_init(_sem, __FILE__, __func__, __LINE__)
 #define cgsem_post(_sem) _cgsem_post(_sem, __FILE__, __func__, __LINE__)
 #define cgsem_post(_sem) _cgsem_post(_sem, __FILE__, __func__, __LINE__)
 #define cgsem_wait(_sem) _cgsem_wait(_sem, __FILE__, __func__, __LINE__)
 #define cgsem_wait(_sem) _cgsem_wait(_sem, __FILE__, __func__, __LINE__)
+#define cgmsem_mswait(_sem, _timeout) _cgsem_mswait(_sem, _timeout, __FILE__, __func__, __LINE__)
 #define cgsem_destroy(_sem) _cgsem_destroy(_sem)
 #define cgsem_destroy(_sem) _cgsem_destroy(_sem)
 
 
 /* Align a size_t to 4 byte boundaries for fussy arches */
 /* Align a size_t to 4 byte boundaries for fussy arches */