From b59c33800b75d0c84842dcc2f369aaecbb8db227 Mon Sep 17 00:00:00 2001 From: ckolivas Date: Thu, 6 Jun 2013 13:08:00 +1000 Subject: [PATCH] Implement cgminer specific cgsem semaphores to imitate unnamed semaphore behaviour on osx which does not support them. --- cgminer.c | 5 ++-- driver-avalon.c | 17 ++++++------ driver-avalon.h | 6 ++--- miner.h | 2 +- usbutils.c | 8 +++--- util.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++ util.h | 18 +++++++++++++ 7 files changed, 109 insertions(+), 18 deletions(-) diff --git a/cgminer.c b/cgminer.c index 63e0dc25..5f02d4e6 100644 --- a/cgminer.c +++ b/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)) diff --git a/driver-avalon.c b/driver-avalon.c index 789fc539..ea112ca8 100644 --- a/driver-avalon.c +++ b/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) diff --git a/driver-avalon.h b/driver-avalon.h index 6f101c99..b5ff3e5e 100644 --- a/driver-avalon.h +++ b/driver-avalon.h @@ -13,7 +13,7 @@ #ifdef USE_AVALON -#include +#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; diff --git a/miner.h b/miner.h index 725c1ab9..752de5ee 100644 --- a/miner.h +++ b/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; diff --git a/usbutils.c b/usbutils.c index c793b9ab..323bd7c3 100644 --- a/usbutils.c +++ b/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) diff --git a/util.c b/util.c index 14334771..f91763a9 100644 --- a/util.c +++ b/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 diff --git a/util.h b/util.h index 5facbc5a..8f82b87b 100644 --- a/util.h +++ b/util.h @@ -1,6 +1,8 @@ #ifndef __UTIL_H__ #define __UTIL_H__ +#include + #if defined(unix) || defined(__APPLE__) #include #include @@ -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)