Browse Source

Implement cgminer specific cgsem semaphores to imitate unnamed semaphore behaviour on osx which does not support them.

ckolivas 12 years ago
parent
commit
b59c33800b
7 changed files with 109 additions and 18 deletions
  1. 2 3
      cgminer.c
  2. 9 8
      driver-avalon.c
  3. 3 3
      driver-avalon.h
  4. 1 1
      miner.h
  5. 5 3
      usbutils.c
  6. 71 0
      util.c
  7. 18 0
      util.h

+ 2 - 3
cgminer.c

@@ -150,7 +150,7 @@ char *opt_avalon_options = NULL;
 char *opt_usb_select = NULL;
 int opt_usbdump = -1;
 bool opt_usb_list_all;
-sem_t usb_resource_sem;
+cgsem_t usb_resource_sem;
 #endif
 
 char *opt_kernel_path;
@@ -7442,8 +7442,7 @@ int main(int argc, char *argv[])
 
 	// before device detection
 	if (!opt_scrypt) {
-		if (sem_init(&usb_resource_sem, 0, 0))
-			quit(1, "Failed to sem_init usb_resource_sem");
+		cgsem_init(&usb_resource_sem);
 		usbres_thr_id = 1;
 		thr = &control_thr[usbres_thr_id];
 		if (thr_info_create(thr, NULL, usb_resource_thread, thr))

+ 9 - 8
driver-avalon.c

@@ -769,8 +769,8 @@ static void *avalon_get_results(void *userdata)
 
 		if (unlikely(info->reset)) {
 			/* Tell the write thread it can start the reset */
-			sem_post(&info->write_sem);
-			sem_wait(&info->read_sem);
+			cgsem_post(&info->write_sem);
+			cgsem_wait(&info->read_sem);
 
 			/* Discard anything in the buffer */
 			offset = 0;
@@ -820,9 +820,9 @@ static void *avalon_send_tasks(void *userdata)
 		if (unlikely(info->reset)) {
 			/* Wait till read thread tells us it's received the
 			 * reset message */
-			sem_wait(&info->write_sem);
+			cgsem_wait(&info->write_sem);
 			avalon_running_reset(avalon, info);
-			sem_post(&info->read_sem);
+			cgsem_post(&info->read_sem);
 		}
 
 		mutex_lock(&info->qlock);
@@ -890,10 +890,8 @@ static bool avalon_prepare(struct thr_info *thr)
 	mutex_init(&info->qlock);
 	if (unlikely(pthread_cond_init(&info->qcond, NULL)))
 		quit(1, "Failed to pthread_cond_init avalon qcond");
-	if (unlikely(sem_init(&info->read_sem, 0, 0)))
-		quit(1, "Failed to sem_init avalon read_sem");
-	if (unlikely(sem_init(&info->write_sem, 0, 0)))
-		quit(1, "Failed to sem_init avalon write_sem");
+	cgsem_init(&info->read_sem);
+	cgsem_init(&info->write_sem);
 
 	if (pthread_create(&info->read_thr, NULL, avalon_get_results, (void *)avalon))
 		quit(1, "Failed to create avalon read_thr");
@@ -918,6 +916,9 @@ static void do_avalon_close(struct thr_info *thr)
 	avalon_running_reset(avalon, info);
 
 	info->no_matching_work = 0;
+
+	cgsem_destroy(&info->read_sem);
+	cgsem_destroy(&info->write_sem);
 }
 
 static inline void record_temp_fan(struct avalon_info *info, struct avalon_result *ar, float *temp_avg)

+ 3 - 3
driver-avalon.h

@@ -13,7 +13,7 @@
 
 #ifdef USE_AVALON
 
-#include <semaphore.h>
+#include "util.h"
 
 #define AVALON_RESET_FAULT_DECISECONDS 1
 #define AVALON_MINER_THREADS 1
@@ -110,8 +110,8 @@ struct avalon_info {
 	pthread_mutex_t lock;
 	pthread_mutex_t qlock;
 	pthread_cond_t qcond;
-	sem_t read_sem;
-	sem_t write_sem;
+	cgsem_t read_sem;
+	cgsem_t write_sem;
 	int nonces;
 
 	bool idle;

+ 1 - 1
miner.h

@@ -855,7 +855,7 @@ extern char *opt_avalon_options;
 extern char *opt_usb_select;
 extern int opt_usbdump;
 extern bool opt_usb_list_all;
-extern sem_t usb_resource_sem;
+extern cgsem_t usb_resource_sem;
 #endif
 #ifdef USE_BITFORCE
 extern bool opt_bfl_noncerange;

+ 5 - 3
usbutils.c

@@ -1225,7 +1225,7 @@ static bool cgminer_usb_lock_bd(struct device_drv *drv, uint8_t bus_number, uint
 	res_work_head = res_work;
 	mutex_unlock(&cgusbres_lock);
 
-	sem_post(&usb_resource_sem);
+	cgsem_post(&usb_resource_sem);
 
 	// TODO: add a timeout fail - restart the resource thread?
 	while (true) {
@@ -1284,7 +1284,7 @@ static void cgminer_usb_unlock_bd(struct device_drv *drv, uint8_t bus_number, ui
 	res_work_head = res_work;
 	mutex_unlock(&cgusbres_lock);
 
-	sem_post(&usb_resource_sem);
+	cgsem_post(&usb_resource_sem);
 
 	return;
 }
@@ -2610,6 +2610,8 @@ void usb_cleanup()
 		}
 		mutex_unlock(&cgusbres_lock);
 	}
+
+	cgsem_destroy(&usb_resource_sem);
 }
 
 void usb_initialise()
@@ -3115,7 +3117,7 @@ void *usb_resource_thread(void __maybe_unused *userdata)
 
 	while (42) {
 		/* Wait to be told we have work to do */
-		sem_wait(&usb_resource_sem);
+		cgsem_wait(&usb_resource_sem);
 
 		mutex_lock(&cgusbres_lock);
 		while (res_work_head)

+ 71 - 0
util.c

@@ -1870,3 +1870,74 @@ void RenameThread(const char* name)
 #endif
 }
 
+/* cgminer specific wrappers for true unnamed semaphore usage on platforms
+ * that support them and for apple which does not. We use a single byte across
+ * a pipe to emulate semaphore behaviour there. */
+#ifdef __APPLE__
+void cgsem_init(cgsem_t *cgsem)
+{
+	int flags, fd, i;
+
+	if (pipe(cgsem->pipefd) == -1)
+		quit(1, "Failed pipe in cgsem_init");
+
+	/* Make the pipes FD_CLOEXEC to allow them to close should we call
+	 * execv on restart. */
+	for (i = 0; i < 2; i++) {
+		fd = cgsem->pipefd[i];
+		flags = fcntl(fd, F_GETFD, 0);
+		flags |= FD_CLOEXEC;
+		if (fcntl(fd, F_SETFD, flags) == -1)
+			quit(1, "Failed to fcntl in cgsem_init");
+	}
+}
+
+void cgsem_post(cgsem_t *cgsem)
+{
+	const char buf = 1;
+	int ret;
+
+	ret = write(cgsem->pipefd[1], &buf, 1);
+	if (ret == 0)
+		quit(1, "Failed to write in cgsem_post");
+}
+
+void cgsem_wait(cgsem_t *cgsem)
+{
+	char buf;
+	int ret;
+
+	ret = read(cgsem->pipefd[0], &buf, 1);
+	if (ret == 0)
+		quit(1, "Failed to read in cgsem_wait");
+}
+
+void cgsem_destroy(cgsem_t *cgsem)
+{
+	close(cgsem->pipefd[1]);
+	close(cgsem->pipefd[0]);
+}
+#else
+void cgsem_init(cgsem_t *cgsem)
+{
+	if (sem_init(cgsem, 0, 0))
+		quit(1, "Failed to sem_init in cgsem_init");
+}
+
+void cgsem_post(cgsem_t *cgsem)
+{
+	if (unlikely(sem_post(cgsem)))
+		quit(1, "Failed to sem_post in cgsem_post");
+}
+
+void cgsem_wait(cgsem_t *cgsem)
+{
+	if (unlikely(sem_wait(cgsem)))
+		quit(1, "Failed to sem_wait in cgsem_wait");
+}
+
+void cgsem_destroy(cgsem_t *cgsem)
+{
+	sem_destroy(cgsem);
+}
+#endif

+ 18 - 0
util.h

@@ -1,6 +1,8 @@
 #ifndef __UTIL_H__
 #define __UTIL_H__
 
+#include <semaphore.h>
+
 #if defined(unix) || defined(__APPLE__)
 	#include <errno.h>
 	#include <sys/socket.h>
@@ -50,6 +52,18 @@
 #define JSON_LOADS(str, err_ptr) json_loads((str), (err_ptr))
 #endif
 
+/* cgminer specific unnamed semaphore implementations to cope with osx not
+ * implementing them. */
+#ifdef __APPLE__
+struct cgsem {
+	int pipefd[2];
+};
+
+typedef struct cgsem cgsem_t;
+#else
+typedef sem_t cgsem_t;
+#endif
+
 struct thr_info;
 struct pool;
 enum dev_reason;
@@ -80,6 +94,10 @@ void dev_error(struct cgpu_info *dev, enum dev_reason reason);
 void *realloc_strcat(char *ptr, char *s);
 void *str_text(char *ptr);
 void RenameThread(const char* name);
+void cgsem_init(cgsem_t *cgsem);
+void cgsem_post(cgsem_t *cgsem);
+void cgsem_wait(cgsem_t *cgsem);
+void cgsem_destroy(cgsem_t *cgsem);
 
 /* Align a size_t to 4 byte boundaries for fussy arches */
 static inline void align_len(size_t *len)