Browse Source

Provide a cg_completion_timeout helper function for unreliable functions that takes arbitrary functions and parameters and reliably returns.

ckolivas 12 years ago
parent
commit
f826e35765
2 changed files with 43 additions and 0 deletions
  1. 41 0
      util.c
  2. 2 0
      util.h

+ 41 - 0
util.c

@@ -2485,3 +2485,44 @@ void _cgsem_destroy(cgsem_t *cgsem)
 	sem_destroy(cgsem);
 }
 #endif
+
+/* Provide a completion_timeout helper function for unreliable functions that
+ * may die due to driver issues etc that time out if the function fails and
+ * can then reliably return. */
+struct cg_completion {
+	cgsem_t cgsem;
+	void (*fn)(void *fnarg);
+	void *fnarg;
+};
+
+void *completion_thread(void *arg)
+{
+	struct cg_completion *cgc = (struct cg_completion *)arg;
+
+	pthread_detach(pthread_self());
+	cgc->fn(cgc->fnarg);
+	cgsem_post(&cgc->cgsem);
+
+	return NULL;
+}
+
+bool _cg_completion_timeout(void *fn, void *fnarg, int timeout, const char *file, const char *func, const int line)
+{
+	struct cg_completion *cgc;
+	pthread_t pthread;
+	bool ret;
+
+	cgc = malloc(sizeof(struct cg_completion));
+	if (unlikely(!cgc))
+		return false;
+	cgsem_init(&cgc->cgsem);
+	cgc->fn = fn;
+	cgc->fnarg = fnarg;
+
+	pthread_create(&pthread, NULL, completion_thread, (void *)cgc);
+
+	ret = cgsem_mswait(&cgc->cgsem, timeout);
+	if (ret)
+		free(cgc);
+	return ret;
+}

+ 2 - 0
util.h

@@ -134,12 +134,14 @@ void _cgsem_post(cgsem_t *cgsem, const char *file, const char *func, const int l
 void _cgsem_wait(cgsem_t *cgsem, const char *file, const char *func, const int line);
 int _cgsem_mswait(cgsem_t *cgsem, int ms, const char *file, const char *func, const int line);
 void _cgsem_destroy(cgsem_t *cgsem);
+bool _cg_completion_timeout(void *fn, void *fnarg, int timeout, const char *file, const char *func, const int line);
 
 #define cgsem_init(_sem) _cgsem_init(_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_mswait(_sem, _timeout) _cgsem_mswait(_sem, _timeout, __FILE__, __func__, __LINE__)
 #define cgsem_destroy(_sem) _cgsem_destroy(_sem)
+#define cg_completion_timeout(fn, fnarg, timeout) _cg_completion_timeout(fn, fnarg, timeout, __FILE__, __func__, __LINE__)
 
 /* Align a size_t to 4 byte boundaries for fussy arches */
 static inline void align_len(size_t *len)