Browse Source

Merge branch 'strerror' into bfgminer

Luke Dashjr 12 years ago
parent
commit
6a0a7a5bb9
9 changed files with 179 additions and 120 deletions
  1. 1 76
      api.c
  2. 0 8
      compat.h
  3. 1 1
      driver-avalon.c
  4. 1 1
      fpgautils.c
  5. 5 5
      ft232r.c
  6. 12 11
      libztex.c
  7. 3 0
      miner.c
  8. 145 15
      util.c
  9. 11 3
      util.h

+ 1 - 76
api.c

@@ -48,81 +48,6 @@
 // However lots of PGA's may mean more
 #define QUEUE	100
 
-#if defined WIN32
-static char WSAbuf[1024];
-
-struct WSAERRORS {
-	int id;
-	char *code;
-} WSAErrors[] = {
-	{ 0,			"No error" },
-	{ WSAEINTR,		"Interrupted system call" },
-	{ WSAEBADF,		"Bad file number" },
-	{ WSAEACCES,		"Permission denied" },
-	{ WSAEFAULT,		"Bad address" },
-	{ WSAEINVAL,		"Invalid argument" },
-	{ WSAEMFILE,		"Too many open sockets" },
-	{ WSAEWOULDBLOCK,	"Operation would block" },
-	{ WSAEINPROGRESS,	"Operation now in progress" },
-	{ WSAEALREADY,		"Operation already in progress" },
-	{ WSAENOTSOCK,		"Socket operation on non-socket" },
-	{ WSAEDESTADDRREQ,	"Destination address required" },
-	{ WSAEMSGSIZE,		"Message too long" },
-	{ WSAEPROTOTYPE,	"Protocol wrong type for socket" },
-	{ WSAENOPROTOOPT,	"Bad protocol option" },
-	{ WSAEPROTONOSUPPORT,	"Protocol not supported" },
-	{ WSAESOCKTNOSUPPORT,	"Socket type not supported" },
-	{ WSAEOPNOTSUPP,	"Operation not supported on socket" },
-	{ WSAEPFNOSUPPORT,	"Protocol family not supported" },
-	{ WSAEAFNOSUPPORT,	"Address family not supported" },
-	{ WSAEADDRINUSE,	"Address already in use" },
-	{ WSAEADDRNOTAVAIL,	"Can't assign requested address" },
-	{ WSAENETDOWN,		"Network is down" },
-	{ WSAENETUNREACH,	"Network is unreachable" },
-	{ WSAENETRESET,		"Net connection reset" },
-	{ WSAECONNABORTED,	"Software caused connection abort" },
-	{ WSAECONNRESET,	"Connection reset by peer" },
-	{ WSAENOBUFS,		"No buffer space available" },
-	{ WSAEISCONN,		"Socket is already connected" },
-	{ WSAENOTCONN,		"Socket is not connected" },
-	{ WSAESHUTDOWN,		"Can't send after socket shutdown" },
-	{ WSAETOOMANYREFS,	"Too many references, can't splice" },
-	{ WSAETIMEDOUT,		"Connection timed out" },
-	{ WSAECONNREFUSED,	"Connection refused" },
-	{ WSAELOOP,		"Too many levels of symbolic links" },
-	{ WSAENAMETOOLONG,	"File name too long" },
-	{ WSAEHOSTDOWN,		"Host is down" },
-	{ WSAEHOSTUNREACH,	"No route to host" },
-	{ WSAENOTEMPTY,		"Directory not empty" },
-	{ WSAEPROCLIM,		"Too many processes" },
-	{ WSAEUSERS,		"Too many users" },
-	{ WSAEDQUOT,		"Disc quota exceeded" },
-	{ WSAESTALE,		"Stale NFS file handle" },
-	{ WSAEREMOTE,		"Too many levels of remote in path" },
-	{ WSASYSNOTREADY,	"Network system is unavailable" },
-	{ WSAVERNOTSUPPORTED,	"Winsock version out of range" },
-	{ WSANOTINITIALISED,	"WSAStartup not yet called" },
-	{ WSAEDISCON,		"Graceful shutdown in progress" },
-	{ WSAHOST_NOT_FOUND,	"Host not found" },
-	{ WSANO_DATA,		"No host data of that type was found" },
-	{ -1,			"Unknown error code" }
-};
-
-char *WSAErrorMsg(void) {
-	int i;
-	int id = WSAGetLastError();
-
-	/* Assume none of them are actually -1 */
-	for (i = 0; WSAErrors[i].id != -1; i++)
-		if (WSAErrors[i].id == id)
-			break;
-
-	sprintf(WSAbuf, "Socket Error: (%d) %s", id, WSAErrors[i].code);
-
-	return &(WSAbuf[0]);
-}
-#endif
-
 static const char *UNAVAILABLE = " - API will not be available";
 
 static const char *BLANK = "";
@@ -3607,7 +3532,7 @@ void api(int api_thr_id)
 	SOCKETTYPE c;
 	int n, bound;
 	char *connectaddr;
-	char *binderror;
+	const char *binderror;
 	time_t bindstart;
 	short int port = opt_api_port;
 	struct sockaddr_in serv;

+ 0 - 8
compat.h

@@ -18,14 +18,6 @@
 
 #include <stdbool.h>
 
-// NOTE: Nested preprocessor checks since the latter isn't defined at all without the former
-#ifdef HAVE_LIBUSB
-#	if ! HAVE_DECL_LIBUSB_ERROR_NAME
-		static char my_libusb_error_name_buf[0x10];
-#		define libusb_error_name(x) (sprintf(my_libusb_error_name_buf, "%d", x), my_libusb_error_name_buf)
-#	endif
-#endif
-
 #ifdef WIN32
 #include <errno.h>
 #include <time.h>

+ 1 - 1
driver-avalon.c

@@ -233,7 +233,7 @@ static inline int avalon_gets(int fd, uint8_t *buf, int read_count,
 		ret = read(fd, buf, 1);
 		if (ret < 0)
 		{
-			applog(LOG_ERR, "Avalon: Error %d on read in avalon_gets", errno);
+			applog(LOG_ERR, "Avalon: Error on read in avalon_gets: %s", bfg_strerror(errno, BST_ERRNO));
 			return AVA_GETS_ERROR;
 		}
 

+ 1 - 1
fpgautils.c

@@ -680,7 +680,7 @@ int serial_open(const char *devpath, unsigned long baud, uint8_t timeout, bool p
 		if (errno == EACCES)
 			applog(LOG_ERR, "Do not have user privileges required to open %s", devpath);
 		else
-			applog(LOG_DEBUG, "Open %s failed, errno:%d", devpath, errno);
+			applog(LOG_DEBUG, "Open %s failed: %s", devpath, bfg_strerror(errno, BST_ERRNO));
 
 		return -1;
 	}

+ 5 - 5
ft232r.c

@@ -68,7 +68,7 @@ void ft232r_scan()
 
 	count = libusb_get_device_list(NULL, &list);
 	if (unlikely(count < 0)) {
-		applog(LOG_ERR, "ft232r_scan: Error getting USB device list: %s", libusb_error_name(count));
+		applog(LOG_ERR, "ft232r_scan: Error getting USB device list: %s", bfg_strerror(count, BST_LIBUSB));
 		ft232r_devinfo_list = calloc(1, sizeof(struct ft232r_device_info *));
 		return;
 	}
@@ -78,7 +78,7 @@ void ft232r_scan()
 	for (i = 0; i < count; ++i) {
 		err = libusb_get_device_descriptor(list[i], &desc);
 		if (unlikely(err)) {
-			applog(LOG_ERR, "ft232r_scan: Error getting device descriptor: %s", libusb_error_name(err));
+			applog(LOG_ERR, "ft232r_scan: Error getting device descriptor: %s", bfg_strerror(err, BST_LIBUSB));
 			continue;
 		}
 		if (!(desc.idVendor == FT232R_IDVENDOR && desc.idProduct == FT232R_IDPRODUCT)) {
@@ -88,14 +88,14 @@ void ft232r_scan()
 
 		err = libusb_open(list[i], &handle);
 		if (unlikely(err)) {
-			applog(LOG_ERR, "ft232r_scan: Error opening device: %s", libusb_error_name(err));
+			applog(LOG_ERR, "ft232r_scan: Error opening device: %s", bfg_strerror(err, BST_LIBUSB));
 			continue;
 		}
 
 		n = libusb_get_string_descriptor_ascii(handle, desc.iProduct, buf, sizeof(buf)-1);
 		if (unlikely(n < 0)) {
 			libusb_close(handle);
-			applog(LOG_ERR, "ft232r_scan: Error getting iProduct string: %s", libusb_error_name(n));
+			applog(LOG_ERR, "ft232r_scan: Error getting iProduct string: %s", bfg_strerror(n, BST_LIBUSB));
 			continue;
 		}
 		buf[n] = '\0';
@@ -105,7 +105,7 @@ void ft232r_scan()
 		n = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, buf, sizeof(buf)-1);
 		libusb_close(handle);
 		if (unlikely(n < 0)) {
-			applog(LOG_ERR, "ft232r_scan: Error getting iSerialNumber string: %s", libusb_error_name(n));
+			applog(LOG_ERR, "ft232r_scan: Error getting iSerialNumber string: %s", bfg_strerror(n, BST_LIBUSB));
 			n = 0;
 		}
 		buf[n] = '\0';

+ 12 - 11
libztex.c

@@ -34,6 +34,7 @@
 #include "miner.h"
 #include "fpgautils.h"
 #include "libztex.h"
+#include "util.h"
 
 //* Capability index for EEPROM support.
 #define CAPABILITY_EEPROM 0,0
@@ -72,7 +73,7 @@ static int libztex_get_string_descriptor_ascii(libusb_device_handle *dev, uint8_
 	    LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_STRING << 8) | 0,
 	    0x0000, buf, sizeof(buf), 1000);
 	if (cnt < 0) {
-		applog(LOG_ERR, "%s: Failed to read LANGIDs: %s", __func__, libusb_error_name(cnt));
+		applog(LOG_ERR, "%s: Failed to read LANGIDs: %s", __func__, bfg_strerror(cnt, BST_LIBUSB));
 		return cnt;
 	}
 
@@ -82,7 +83,7 @@ static int libztex_get_string_descriptor_ascii(libusb_device_handle *dev, uint8_
 	    LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_STRING << 8) | desc_index,
 	    langid, buf, sizeof(buf), 1000);
 	if (cnt < 0) {
-		applog(LOG_ERR, "%s: Failed to read string descriptor: %s", __func__, libusb_error_name(cnt));
+		applog(LOG_ERR, "%s: Failed to read string descriptor: %s", __func__, bfg_strerror(cnt, BST_LIBUSB));
 		return cnt;
 	}
 
@@ -109,7 +110,7 @@ static bool libztex_firmwareReset(struct libusb_device_handle *hndl, bool enable
 	int cnt = libusb_control_transfer(hndl, 0x40, 0xA0, 0xE600, 0, &reset, 1, 1000);
 	if (cnt < 0)
 	{
-		applog(LOG_ERR, "Ztex reset %d failed: %s", enable, libusb_error_name(cnt));
+		applog(LOG_ERR, "Ztex reset %d failed: %s", enable, bfg_strerror(cnt, BST_LIBUSB));
 		return 1;
 	}
 
@@ -139,7 +140,7 @@ static enum check_result libztex_checkDevice(struct libusb_device *dev)
 
 	err = libusb_open(dev, &hndl);
 	if (err != LIBUSB_SUCCESS) {
-		applog(LOG_ERR, "%s: Can not open ZTEX device: %s", __func__, libusb_error_name(err));
+		applog(LOG_ERR, "%s: Can not open ZTEX device: %s", __func__, bfg_strerror(err, BST_LIBUSB));
 		goto done;
 	}
 
@@ -224,7 +225,7 @@ static enum check_result libztex_checkDevice(struct libusb_device *dev)
 	}
 
 	if (0 != fseek(fp, 0, SEEK_END)) {
-		applog(LOG_ERR, "Ztex firmware fseek: %s", strerror(errno));
+		applog(LOG_ERR, "Ztex firmware fseek: %s", bfg_strerror(errno, BST_ERRNO));
 		goto done;
 	}
 
@@ -232,7 +233,7 @@ static enum check_result libztex_checkDevice(struct libusb_device *dev)
 	rewind(fp);
 	fw_buf = malloc(length);
 	if (!fw_buf) {
-		applog(LOG_ERR, "%s: Can not allocate memory: %s", __func__, strerror(errno));
+		applog(LOG_ERR, "%s: Can not allocate memory: %s", __func__, bfg_strerror(errno, BST_ERRNO));
 		goto done;
 	}
 
@@ -271,7 +272,7 @@ static enum check_result libztex_checkDevice(struct libusb_device *dev)
 		int k = libusb_control_transfer(hndl, 0x40, 0xA0, i, 0, fw_buf + i, numbytes, 1000);
 		if (k < numbytes)
 		{
-			applog(LOG_ERR, "Ztex device: Failed to write firmware at %d with: %s", i, libusb_error_name(k));
+			applog(LOG_ERR, "Ztex device: Failed to write firmware at %d with: %s", i, bfg_strerror(k, BST_LIBUSB));
 			goto done;
 		}
 	}
@@ -611,7 +612,7 @@ int libztex_prepare_device(struct libusb_device *dev, struct libztex_device** zt
 	dclk_prepare(&newdev->dclk);
 	err = libusb_open(dev, &newdev->hndl);
 	if (err != LIBUSB_SUCCESS) {
-		applog(LOG_ERR, "%s: Can not open ZTEX device: %s", __func__, libusb_error_name(err));
+		applog(LOG_ERR, "%s: Can not open ZTEX device: %s", __func__, bfg_strerror(err, BST_LIBUSB));
 		return CHECK_ERROR;
 	}
 
@@ -749,7 +750,7 @@ int libztex_scanDevices(struct libztex_dev_list*** devs_p)
 			err = libztex_checkDevice(list[i]);
 			switch (err) {
 			case CHECK_ERROR:
-				applog(LOG_ERR, "Ztex: Can not check device: %s", libusb_error_name(err));
+				applog(LOG_ERR, "Ztex: Can not check device: %s", bfg_strerror(err, BST_LIBUSB));
 				continue;
 			case CHECK_IS_NOT_ZTEX:
 				continue;
@@ -786,7 +787,7 @@ int libztex_scanDevices(struct libztex_dev_list*** devs_p)
 		if (!ztex) {
 			ztex = malloc(sizeof(*ztex));
 			if (!ztex) {
-				applog(LOG_ERR, "%s: Can not allocate memory for device struct: %s", __func__, strerror(errno));
+				applog(LOG_ERR, "%s: Can not allocate memory for device struct: %s", __func__, bfg_strerror(errno, BST_ERRNO));
 				goto done;
 			}
 		}
@@ -804,7 +805,7 @@ int libztex_scanDevices(struct libztex_dev_list*** devs_p)
 
 		devs[pos] = malloc(sizeof(struct libztex_dev_list));
 		if (NULL == devs[pos]) {
-			applog(LOG_ERR, "%s: Can not allocate memory for device: %s", __func__, strerror(errno));
+			applog(LOG_ERR, "%s: Can not allocate memory for device: %s", __func__, bfg_strerror(errno, BST_ERRNO));
 			libztex_destroy_device(ztex);
 			ztex = NULL;
 			continue;

+ 3 - 0
miner.c

@@ -8592,6 +8592,8 @@ static void raise_fd_limits(void)
 #endif
 }
 
+extern void bfg_init_threadlocal();
+
 int main(int argc, char *argv[])
 {
 	struct sigaction handler;
@@ -8607,6 +8609,7 @@ int main(int argc, char *argv[])
 
 	blkmk_sha256_impl = my_blkmaker_sha256_callback;
 
+	bfg_init_threadlocal();
 #ifndef HAVE_PTHREAD_CANCEL
 	setup_pthread_cancel_workaround();
 #endif

+ 145 - 15
util.c

@@ -1383,9 +1383,9 @@ char *recv_line(struct pool *pool)
 			if (n < 0) {
 				//Save errno from being overweitten bei socket_ commands 
 				int socket_recv_errno;
-				socket_recv_errno = errno;
+				socket_recv_errno = SOCKERR;
 				if (!sock_blocks() || !socket_full(pool, false)) {
-					applog(LOG_DEBUG, "Failed to recv sock in recv_line: %d", socket_recv_errno);
+					applog(LOG_DEBUG, "Failed to recv sock in recv_line: %s", bfg_strerror(socket_recv_errno, BST_SOCKET));
 					suspend_stratum(pool);
 					break;
 				}
@@ -2239,26 +2239,156 @@ void RenameThread(const char* name)
 #endif
 }
 
+static pthread_key_t key_bfgtls;
+struct bfgtls_data {
+	char *bfg_strerror_result;
+	size_t bfg_strerror_resultsz;
 #ifdef WIN32
-static const char *WindowsErrorStr(DWORD dwMessageId)
-{
-	static LPSTR msg = NULL;
-	if (msg)
-		LocalFree(msg);
-	if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, dwMessageId, 0, (LPSTR)&msg, 0, 0))
-		return msg;
-	static const char fmt[] = "Error #%ld";
-	signed long ldMsgId = dwMessageId;
-	int sz = snprintf((char*)&sz, 0, fmt, ldMsgId) + 1;
-	msg = (LPTSTR)LocalAlloc(LMEM_FIXED, sz);
-	sprintf((char*)msg, fmt, ldMsgId);
-	return msg;
+	LPSTR bfg_strerror_socketresult;
+#endif
+};
+
+void bfg_init_threadlocal()
+{
+	struct bfgtls_data *bfgtls;
+	void *p;
+	
+	bfgtls = malloc(sizeof(*bfgtls));
+	if (!bfgtls)
+		quit(1, "malloc bfgtls failed");
+	p = malloc(64);
+	if (!p)
+		quit(1, "malloc bfg_strerror_result failed");
+	*bfgtls = (struct bfgtls_data){
+		.bfg_strerror_resultsz = 64,
+		.bfg_strerror_result = p,
+	};
+	if (pthread_key_create(&key_bfgtls, NULL))
+		quit(1, "pthread_key_create failed");
+	if (pthread_setspecific(key_bfgtls, bfgtls))
+		quit(1, "pthread_setspecific failed");
+}
+
+static
+struct bfgtls_data *get_bfgtls()
+{
+	return pthread_getspecific(key_bfgtls);
+}
+
+static
+bool bfg_grow_buffer(char ** const bufp, size_t * const bufszp, size_t minimum)
+{
+	if (minimum <= *bufszp)
+		return false;
+	
+	while (minimum > *bufszp)
+		*bufszp = 2;
+	*bufp = realloc(*bufp, *bufszp);
+	if (unlikely(!*bufp))
+		quit(1, "realloc failed in bfg_grow_buffer");
+	
+	return true;
+}
+
+static
+const char *bfg_strcpy_growing_buffer(char ** const bufp, size_t * const bufszp, const char *src)
+{
+	if (!src)
+		return NULL;
+	
+	const size_t srcsz = strlen(src) + 1;
+	
+	bfg_grow_buffer(bufp, bufszp, srcsz);
+	memcpy(*bufp, src, srcsz);
+	
+	return *bufp;
 }
+
+// Guaranteed to always return some string (or quit)
+const char *bfg_strerror(int e, enum bfg_strerror_type type)
+{
+	static __maybe_unused pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+	struct bfgtls_data *bfgtls = get_bfgtls();
+	size_t * const bufszp = &bfgtls->bfg_strerror_resultsz;
+	char ** const bufp = &bfgtls->bfg_strerror_result;
+	const char *have = NULL;
+	
+	switch (type) {
+		case BST_LIBUSB:
+// NOTE: Nested preprocessor checks since the latter isn't defined at all without the former
+#ifdef HAVE_LIBUSB
+#	if HAVE_DECL_LIBUSB_ERROR_NAME
+			// libusb makes no guarantees for thread-safety or persistence
+			mutex_lock(&mutex);
+			have = bfg_strcpy_growing_buffer(bufp, bufszp, libusb_error_name(e));
+			mutex_unlock(&mutex);
+#	endif
 #endif
+			break;
+		case BST_SOCKET:
+		{
+#ifdef WIN32
+			// Windows has a different namespace for socket errors
+			LPSTR *msg = &bfgtls->bfg_strerror_socketresult;
+			if (*msg)
+				LocalFree(*msg);
+			if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, e, 0, (LPSTR)msg, 0, 0))
+				return *msg;
+			*msg = NULL;
+			
+			break;
+#endif
+		}
+			// Fallthru on non-WIN32
+		case BST_ERRNO:
+		{
+#ifdef __STRERROR_S_WORKS
+			// FIXME: Not sure how to get this on MingW64
+retry:
+			if (likely(!strerror_s(*bufp, *bufszp, e)))
+			{
+				if (bfg_grow_buffer(bufp, bufszp, strlen(*bufp) + 2))
+					goto retry;
+				return *bufp;
+			}
+// TODO: XSI strerror_r
+// TODO: GNU strerror_r
+#else
+			mutex_lock(&mutex);
+			have = bfg_strcpy_growing_buffer(bufp, bufszp, strerror(e));
+			mutex_unlock(&mutex);
+#endif
+		}
+	}
+	
+	if (have)
+		return *bufp;
+	
+	// Failback: Stringify the number
+	static const char fmt[] = "%s error #%d", *typestr;
+	switch (type) {
+		case BST_ERRNO:
+			typestr = "System";
+			break;
+		case BST_SOCKET:
+			typestr = "Socket";
+			break;
+		case BST_LIBUSB:
+			typestr = "libusb";
+			break;
+		default:
+			typestr = "Unexpected";
+	}
+	int sz = snprintf((char*)bfgtls, 0, fmt, typestr, e) + 1;
+	bfg_grow_buffer(bufp, bufszp, sz);
+	sprintf(*bufp, fmt, typestr, e);
+	return *bufp;
+}
 
 void notifier_init(notifier_t pipefd)
 {
 #ifdef WIN32
+#define WindowsErrorStr(e)  bfg_strerror(e, true)
 	SOCKET listener, connecter, acceptor;
 	listener = socket(AF_INET, SOCK_STREAM, 0);
 	if (listener == INVALID_SOCKET)

+ 11 - 3
util.h

@@ -30,7 +30,8 @@
 	#define INVINETADDR -1
 	#define CLOSESOCKET close
 
-	#define SOCKERRMSG strerror(errno)
+	#define SOCKERR (errno)
+	#define SOCKERRMSG bfg_strerror(errno, BST_SOCKET)
 	static inline bool sock_blocks(void)
 	{
 		return (errno == EAGAIN || errno == EWOULDBLOCK);
@@ -45,8 +46,8 @@
 	#define INVINETADDR INADDR_NONE
 	#define CLOSESOCKET closesocket
 
-	extern char *WSAErrorMsg(void);
-	#define SOCKERRMSG WSAErrorMsg()
+	#define SOCKERR (WSAGetLastError())
+	#define SOCKERRMSG bfg_strerror(WSAGetLastError(), BST_SOCKET)
 
 	static inline bool sock_blocks(void)
 	{
@@ -111,6 +112,13 @@ void *realloc_strcat(char *ptr, char *s);
 extern char *sanestr(char *o, char *s);
 void RenameThread(const char* name);
 
+enum bfg_strerror_type {
+	BST_ERRNO,
+	BST_SOCKET,
+	BST_LIBUSB,
+};
+extern const char *bfg_strerror(int, enum bfg_strerror_type);
+
 typedef SOCKETTYPE notifier_t[2];
 extern void notifier_init(notifier_t);
 extern void notifier_wake(notifier_t);