mirror of
https://github.com/GOSTSec/sgminer
synced 2025-01-22 20:44:19 +00:00
usb separate thread for resource locking and modified windows locking code
This commit is contained in:
parent
64b6b7cbef
commit
2f94ec8025
48
cgminer.c
48
cgminer.c
@ -169,6 +169,7 @@ static int input_thr_id;
|
|||||||
int gpur_thr_id;
|
int gpur_thr_id;
|
||||||
static int api_thr_id;
|
static int api_thr_id;
|
||||||
#ifdef USE_USBUTILS
|
#ifdef USE_USBUTILS
|
||||||
|
static int usbres_thr_id;
|
||||||
static int hotplug_thr_id;
|
static int hotplug_thr_id;
|
||||||
#endif
|
#endif
|
||||||
static int total_control_threads;
|
static int total_control_threads;
|
||||||
@ -180,6 +181,7 @@ int hotplug_time = 5;
|
|||||||
|
|
||||||
#ifdef USE_USBUTILS
|
#ifdef USE_USBUTILS
|
||||||
pthread_mutex_t cgusb_lock;
|
pthread_mutex_t cgusb_lock;
|
||||||
|
pthread_mutex_t cgusbres_lock;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pthread_mutex_t hash_lock;
|
pthread_mutex_t hash_lock;
|
||||||
@ -2843,6 +2845,10 @@ static void __kill_work(void)
|
|||||||
if (!opt_scrypt) {
|
if (!opt_scrypt) {
|
||||||
applog(LOG_DEBUG, "Releasing all USB devices");
|
applog(LOG_DEBUG, "Releasing all USB devices");
|
||||||
usb_cleanup();
|
usb_cleanup();
|
||||||
|
|
||||||
|
applog(LOG_DEBUG, "Killing off usbres thread");
|
||||||
|
thr = &control_thr[usbres_thr_id];
|
||||||
|
thr_info_cancel(thr);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -7189,6 +7195,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
#ifdef USE_USBUTILS
|
#ifdef USE_USBUTILS
|
||||||
mutex_init(&cgusb_lock);
|
mutex_init(&cgusb_lock);
|
||||||
|
mutex_init(&cgusbres_lock);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -7315,8 +7322,25 @@ int main(int argc, char *argv[])
|
|||||||
/* Use a shorter scantime for scrypt */
|
/* Use a shorter scantime for scrypt */
|
||||||
if (opt_scantime < 0)
|
if (opt_scantime < 0)
|
||||||
opt_scantime = opt_scrypt ? 30 : 60;
|
opt_scantime = opt_scrypt ? 30 : 60;
|
||||||
|
|
||||||
|
total_control_threads = 9;
|
||||||
|
control_thr = calloc(total_control_threads, sizeof(*thr));
|
||||||
|
if (!control_thr)
|
||||||
|
quit(1, "Failed to calloc control_thr");
|
||||||
|
|
||||||
|
gwsched_thr_id = 0;
|
||||||
|
|
||||||
#ifdef USE_USBUTILS
|
#ifdef USE_USBUTILS
|
||||||
usb_initialise();
|
usb_initialise();
|
||||||
|
|
||||||
|
// before device detection
|
||||||
|
if (!opt_scrypt) {
|
||||||
|
usbres_thr_id = 1;
|
||||||
|
thr = &control_thr[usbres_thr_id];
|
||||||
|
if (thr_info_create(thr, NULL, usb_resource_thread, thr))
|
||||||
|
quit(1, "usb resource thread create failed");
|
||||||
|
pthread_detach(thr->pth);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_OPENCL
|
#ifdef HAVE_OPENCL
|
||||||
@ -7456,13 +7480,7 @@ int main(int argc, char *argv[])
|
|||||||
quit(1, "Failed to calloc mining_thr[%d]", i);
|
quit(1, "Failed to calloc mining_thr[%d]", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
total_control_threads = 8;
|
stage_thr_id = 2;
|
||||||
control_thr = calloc(total_control_threads, sizeof(*thr));
|
|
||||||
if (!control_thr)
|
|
||||||
quit(1, "Failed to calloc control_thr");
|
|
||||||
|
|
||||||
gwsched_thr_id = 0;
|
|
||||||
stage_thr_id = 1;
|
|
||||||
thr = &control_thr[stage_thr_id];
|
thr = &control_thr[stage_thr_id];
|
||||||
thr->q = tq_new();
|
thr->q = tq_new();
|
||||||
if (!thr->q)
|
if (!thr->q)
|
||||||
@ -7583,14 +7601,14 @@ begin_bench:
|
|||||||
cgtime(&total_tv_start);
|
cgtime(&total_tv_start);
|
||||||
cgtime(&total_tv_end);
|
cgtime(&total_tv_end);
|
||||||
|
|
||||||
watchpool_thr_id = 2;
|
watchpool_thr_id = 3;
|
||||||
thr = &control_thr[watchpool_thr_id];
|
thr = &control_thr[watchpool_thr_id];
|
||||||
/* start watchpool thread */
|
/* start watchpool thread */
|
||||||
if (thr_info_create(thr, NULL, watchpool_thread, NULL))
|
if (thr_info_create(thr, NULL, watchpool_thread, NULL))
|
||||||
quit(1, "watchpool thread create failed");
|
quit(1, "watchpool thread create failed");
|
||||||
pthread_detach(thr->pth);
|
pthread_detach(thr->pth);
|
||||||
|
|
||||||
watchdog_thr_id = 3;
|
watchdog_thr_id = 4;
|
||||||
thr = &control_thr[watchdog_thr_id];
|
thr = &control_thr[watchdog_thr_id];
|
||||||
/* start watchdog thread */
|
/* start watchdog thread */
|
||||||
if (thr_info_create(thr, NULL, watchdog_thread, NULL))
|
if (thr_info_create(thr, NULL, watchdog_thread, NULL))
|
||||||
@ -7599,7 +7617,7 @@ begin_bench:
|
|||||||
|
|
||||||
#ifdef HAVE_OPENCL
|
#ifdef HAVE_OPENCL
|
||||||
/* Create reinit gpu thread */
|
/* Create reinit gpu thread */
|
||||||
gpur_thr_id = 4;
|
gpur_thr_id = 5;
|
||||||
thr = &control_thr[gpur_thr_id];
|
thr = &control_thr[gpur_thr_id];
|
||||||
thr->q = tq_new();
|
thr->q = tq_new();
|
||||||
if (!thr->q)
|
if (!thr->q)
|
||||||
@ -7609,14 +7627,14 @@ begin_bench:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Create API socket thread */
|
/* Create API socket thread */
|
||||||
api_thr_id = 5;
|
api_thr_id = 6;
|
||||||
thr = &control_thr[api_thr_id];
|
thr = &control_thr[api_thr_id];
|
||||||
if (thr_info_create(thr, NULL, api_thread, thr))
|
if (thr_info_create(thr, NULL, api_thread, thr))
|
||||||
quit(1, "API thread create failed");
|
quit(1, "API thread create failed");
|
||||||
|
|
||||||
#ifdef USE_USBUTILS
|
#ifdef USE_USBUTILS
|
||||||
if (!opt_scrypt) {
|
if (!opt_scrypt) {
|
||||||
hotplug_thr_id = 6;
|
hotplug_thr_id = 7;
|
||||||
thr = &control_thr[hotplug_thr_id];
|
thr = &control_thr[hotplug_thr_id];
|
||||||
if (thr_info_create(thr, NULL, hotplug_thread, thr))
|
if (thr_info_create(thr, NULL, hotplug_thread, thr))
|
||||||
quit(1, "hotplug thread create failed");
|
quit(1, "hotplug thread create failed");
|
||||||
@ -7628,7 +7646,7 @@ begin_bench:
|
|||||||
/* Create curses input thread for keyboard input. Create this last so
|
/* Create curses input thread for keyboard input. Create this last so
|
||||||
* that we know all threads are created since this can call kill_work
|
* that we know all threads are created since this can call kill_work
|
||||||
* to try and shut down all previous threads. */
|
* to try and shut down all previous threads. */
|
||||||
input_thr_id = 7;
|
input_thr_id = 8;
|
||||||
thr = &control_thr[input_thr_id];
|
thr = &control_thr[input_thr_id];
|
||||||
if (thr_info_create(thr, NULL, input_thread, thr))
|
if (thr_info_create(thr, NULL, input_thread, thr))
|
||||||
quit(1, "input thread create failed");
|
quit(1, "input thread create failed");
|
||||||
@ -7636,8 +7654,8 @@ begin_bench:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Just to be sure */
|
/* Just to be sure */
|
||||||
if (total_control_threads != 8)
|
if (total_control_threads != 9)
|
||||||
quit(1, "incorrect total_control_threads (%d) should be 8", total_control_threads);
|
quit(1, "incorrect total_control_threads (%d) should be 9", total_control_threads);
|
||||||
|
|
||||||
/* Once everything is set up, main() becomes the getwork scheduler */
|
/* Once everything is set up, main() becomes the getwork scheduler */
|
||||||
while (42) {
|
while (42) {
|
||||||
|
1
miner.h
1
miner.h
@ -881,6 +881,7 @@ extern int opt_expiry;
|
|||||||
|
|
||||||
#ifdef USE_USBUTILS
|
#ifdef USE_USBUTILS
|
||||||
extern pthread_mutex_t cgusb_lock;
|
extern pthread_mutex_t cgusb_lock;
|
||||||
|
extern pthread_mutex_t cgusbres_lock;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern cglock_t control_lock;
|
extern cglock_t control_lock;
|
||||||
|
768
usbutils.c
768
usbutils.c
@ -319,6 +319,8 @@ static struct driver_count {
|
|||||||
static struct usb_busdev {
|
static struct usb_busdev {
|
||||||
int bus_number;
|
int bus_number;
|
||||||
int device_address;
|
int device_address;
|
||||||
|
void *resource1;
|
||||||
|
void *resource2;
|
||||||
} *busdev;
|
} *busdev;
|
||||||
|
|
||||||
static int busdev_count = 0;
|
static int busdev_count = 0;
|
||||||
@ -336,6 +338,27 @@ struct usb_in_use_list {
|
|||||||
// List of in use devices
|
// List of in use devices
|
||||||
static struct usb_in_use_list *in_use_head = NULL;
|
static struct usb_in_use_list *in_use_head = NULL;
|
||||||
|
|
||||||
|
struct resource_work {
|
||||||
|
bool lock;
|
||||||
|
const char *dname;
|
||||||
|
uint8_t bus_number;
|
||||||
|
uint8_t device_address;
|
||||||
|
struct resource_work *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Pending work for the reslock thread
|
||||||
|
struct resource_work *res_work_head = NULL;
|
||||||
|
|
||||||
|
struct resource_reply {
|
||||||
|
uint8_t bus_number;
|
||||||
|
uint8_t device_address;
|
||||||
|
bool got;
|
||||||
|
struct resource_reply *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Replies to lock requests
|
||||||
|
struct resource_reply *res_reply_head = NULL;
|
||||||
|
|
||||||
// Set this to 0 to remove stats processing
|
// Set this to 0 to remove stats processing
|
||||||
#define DO_USB_STATS 1
|
#define DO_USB_STATS 1
|
||||||
|
|
||||||
@ -956,6 +979,80 @@ void usb_applog(struct cgpu_info *cgpu, enum usb_cmds cmd, char *msg, int amount
|
|||||||
err, amount);
|
err, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
static void in_use_store_ress(uint8_t bus_number, uint8_t device_address, void *resource1, void *resource2)
|
||||||
|
{
|
||||||
|
struct usb_in_use_list *in_use_tmp;
|
||||||
|
bool found = false, empty = true;
|
||||||
|
|
||||||
|
mutex_lock(&cgusb_lock);
|
||||||
|
in_use_tmp = in_use_head;
|
||||||
|
while (in_use_tmp) {
|
||||||
|
if (in_use_tmp->in_use.bus_number == (int)bus_number &&
|
||||||
|
in_use_tmp->in_use.device_address == (int)device_address) {
|
||||||
|
found = true;
|
||||||
|
|
||||||
|
if (in_use_tmp->in_use.resource1)
|
||||||
|
empty = false;
|
||||||
|
in_use_tmp->in_use.resource1 = resource1;
|
||||||
|
|
||||||
|
if (in_use_tmp->in_use.resource2)
|
||||||
|
empty = false;
|
||||||
|
in_use_tmp->in_use.resource2 = resource2;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
in_use_tmp = in_use_tmp->next;
|
||||||
|
}
|
||||||
|
mutex_unlock(&cgusb_lock);
|
||||||
|
|
||||||
|
if (found == false)
|
||||||
|
applog(LOG_ERR, "FAIL: USB store_ress not found (%d:%d)",
|
||||||
|
(int)bus_number, (int)device_address);
|
||||||
|
|
||||||
|
if (empty == false)
|
||||||
|
applog(LOG_ERR, "FAIL: USB store_ress not empty (%d:%d)",
|
||||||
|
(int)bus_number, (int)device_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void in_use_get_ress(uint8_t bus_number, uint8_t device_address, void **resource1, void **resource2)
|
||||||
|
{
|
||||||
|
struct usb_in_use_list *in_use_tmp;
|
||||||
|
bool found = false, empty = false;
|
||||||
|
|
||||||
|
mutex_lock(&cgusb_lock);
|
||||||
|
in_use_tmp = in_use_head;
|
||||||
|
while (in_use_tmp) {
|
||||||
|
if (in_use_tmp->in_use.bus_number == (int)bus_number &&
|
||||||
|
in_use_tmp->in_use.device_address == (int)device_address) {
|
||||||
|
found = true;
|
||||||
|
|
||||||
|
if (!in_use_tmp->in_use.resource1)
|
||||||
|
empty = true;
|
||||||
|
*resource1 = in_use_tmp->in_use.resource1;
|
||||||
|
in_use_tmp->in_use.resource1 = NULL;
|
||||||
|
|
||||||
|
if (!in_use_tmp->in_use.resource2)
|
||||||
|
empty = true;
|
||||||
|
*resource2 = in_use_tmp->in_use.resource2;
|
||||||
|
in_use_tmp->in_use.resource2 = NULL;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
in_use_tmp = in_use_tmp->next;
|
||||||
|
}
|
||||||
|
mutex_unlock(&cgusb_lock);
|
||||||
|
|
||||||
|
if (found == false)
|
||||||
|
applog(LOG_ERR, "FAIL: USB get_lock not found (%d:%d)",
|
||||||
|
(int)bus_number, (int)device_address);
|
||||||
|
|
||||||
|
if (empty == true)
|
||||||
|
applog(LOG_ERR, "FAIL: USB get_lock empty (%d:%d)",
|
||||||
|
(int)bus_number, (int)device_address);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static bool __is_in_use(uint8_t bus_number, uint8_t device_address)
|
static bool __is_in_use(uint8_t bus_number, uint8_t device_address)
|
||||||
{
|
{
|
||||||
struct usb_in_use_list *in_use_tmp;
|
struct usb_in_use_list *in_use_tmp;
|
||||||
@ -1049,178 +1146,61 @@ static void remove_in_use(uint8_t bus_number, uint8_t device_address)
|
|||||||
(int)bus_number, (int)device_address);
|
(int)bus_number, (int)device_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/ipc.h>
|
|
||||||
#include <sys/sem.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
union semun {
|
|
||||||
int sem;
|
|
||||||
struct semid_ds *seminfo;
|
|
||||||
ushort *all;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Any errors should always be printed since they will rarely if ever occur
|
|
||||||
// and thus it is best to always display them
|
|
||||||
static bool cgminer_usb_lock_bd(struct device_drv *drv, uint8_t bus_number, uint8_t device_address)
|
static bool cgminer_usb_lock_bd(struct device_drv *drv, uint8_t bus_number, uint8_t device_address)
|
||||||
{
|
{
|
||||||
applog(LOG_DEBUG, "USB lock %s %d-%d", drv->name, (int)bus_number, (int)device_address);
|
struct resource_work *res_work;
|
||||||
|
bool ret;
|
||||||
|
|
||||||
#ifdef WIN32
|
applog(LOG_DEBUG, "USB lock %s %d-%d", drv->dname, (int)bus_number, (int)device_address);
|
||||||
struct cgpu_info *cgpu;
|
|
||||||
HANDLE usbMutex;
|
|
||||||
char name[64];
|
|
||||||
DWORD res;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (is_in_use_bd(bus_number, device_address))
|
res_work = calloc(1, sizeof(*res_work));
|
||||||
return false;
|
res_work->lock = true;
|
||||||
|
res_work->dname = (const char *)(drv->dname);
|
||||||
|
res_work->bus_number = bus_number;
|
||||||
|
res_work->device_address = device_address;
|
||||||
|
|
||||||
sprintf(name, "cgminer-usb-%d-%d", (int)bus_number, (int)device_address);
|
mutex_lock(&cgusbres_lock);
|
||||||
|
|
||||||
usbMutex = CreateMutex(NULL, FALSE, name);
|
res_work->next = res_work_head;
|
||||||
if (usbMutex == NULL) {
|
res_work_head = res_work;
|
||||||
applog(LOG_ERR,
|
|
||||||
"MTX: %s USB failed to get '%s' err (%d)",
|
|
||||||
drv->dname, name, GetLastError());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = WaitForSingleObject(usbMutex, 0);
|
mutex_unlock(&cgusbres_lock);
|
||||||
switch(res) {
|
|
||||||
case WAIT_OBJECT_0:
|
nmsleep(46);
|
||||||
case WAIT_ABANDONED:
|
|
||||||
// Am I using it already?
|
// TODO: add a timeout fail - restart the resource thread?
|
||||||
for (i = 0; i < total_devices; i++) {
|
while (true) {
|
||||||
cgpu = get_devices(i);
|
mutex_lock(&cgusbres_lock);
|
||||||
if (cgpu->usbinfo.bus_number == bus_number &&
|
|
||||||
cgpu->usbinfo.device_address == device_address &&
|
if (res_reply_head) {
|
||||||
cgpu->usbinfo.nodev == false) {
|
struct resource_reply *res_reply_prev = NULL;
|
||||||
if (ReleaseMutex(usbMutex)) {
|
struct resource_reply *res_reply = res_reply_head;
|
||||||
applog(LOG_WARNING,
|
while (res_reply) {
|
||||||
"MTX: %s USB can't get '%s' - device in use",
|
if (res_reply->bus_number == bus_number &&
|
||||||
drv->dname, name);
|
res_reply->device_address == device_address) {
|
||||||
goto fail;
|
|
||||||
}
|
if (res_reply_prev)
|
||||||
applog(LOG_ERR,
|
res_reply_prev->next = res_reply->next;
|
||||||
"MTX: %s USB can't get '%s' - device in use - failure (%d)",
|
else
|
||||||
drv->dname, name, GetLastError());
|
res_reply_head = res_reply->next;
|
||||||
goto fail;
|
|
||||||
|
mutex_unlock(&cgusbres_lock);
|
||||||
|
|
||||||
|
ret = res_reply->got;
|
||||||
|
|
||||||
|
free(res_reply);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
res_reply_prev = res_reply;
|
||||||
|
res_reply = res_reply->next;
|
||||||
}
|
}
|
||||||
add_in_use(bus_number, device_address);
|
|
||||||
return true;
|
|
||||||
case WAIT_TIMEOUT:
|
|
||||||
if (!hotplug_mode)
|
|
||||||
applog(LOG_WARNING,
|
|
||||||
"MTX: %s USB failed to get '%s' - device in use",
|
|
||||||
drv->dname, name);
|
|
||||||
goto fail;
|
|
||||||
case WAIT_FAILED:
|
|
||||||
applog(LOG_ERR,
|
|
||||||
"MTX: %s USB failed to get '%s' err (%d)",
|
|
||||||
drv->dname, name, GetLastError());
|
|
||||||
goto fail;
|
|
||||||
default:
|
|
||||||
applog(LOG_ERR,
|
|
||||||
"MTX: %s USB failed to get '%s' unknown reply (%d)",
|
|
||||||
drv->dname, name, res);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(usbMutex);
|
|
||||||
add_in_use(bus_number, device_address);
|
|
||||||
return true;
|
|
||||||
fail:
|
|
||||||
CloseHandle(usbMutex);
|
|
||||||
return false;
|
|
||||||
#else
|
|
||||||
struct semid_ds seminfo;
|
|
||||||
union semun opt;
|
|
||||||
char name[64];
|
|
||||||
key_t key;
|
|
||||||
int fd, sem, count;
|
|
||||||
|
|
||||||
if (is_in_use_bd(bus_number, device_address))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
sprintf(name, "/tmp/cgminer-usb-%d-%d", (int)bus_number, (int)device_address);
|
|
||||||
fd = open(name, O_CREAT|O_RDONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
|
|
||||||
if (fd == -1) {
|
|
||||||
applog(LOG_ERR,
|
|
||||||
"SEM: %s USB open failed '%s' err (%d) %s",
|
|
||||||
drv->dname, name, errno, strerror(errno));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
key = ftok(name, 'K');
|
|
||||||
sem = semget(key, 1, IPC_CREAT | IPC_EXCL | 438);
|
|
||||||
if (sem < 0) {
|
|
||||||
if (errno != EEXIST) {
|
|
||||||
applog(LOG_ERR,
|
|
||||||
"SEM: %s USB failed to get '%s' err (%d) %s",
|
|
||||||
drv->dname, name, errno, strerror(errno));
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sem = semget(key, 1, 0);
|
mutex_unlock(&cgusbres_lock);
|
||||||
if (sem < 0) {
|
|
||||||
applog(LOG_ERR,
|
|
||||||
"SEM: %s USB failed to access '%s' err (%d) %s",
|
|
||||||
drv->dname, name, errno, strerror(errno));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
opt.seminfo = &seminfo;
|
nmsleep(45);
|
||||||
count = 0;
|
|
||||||
while (++count) {
|
|
||||||
// Should NEVER take 100ms
|
|
||||||
if (count > 99) {
|
|
||||||
applog(LOG_ERR,
|
|
||||||
"SEM: %s USB timeout waiting for (%d) '%s'",
|
|
||||||
drv->dname, sem, name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (semctl(sem, 0, IPC_STAT, opt) == -1) {
|
|
||||||
applog(LOG_ERR,
|
|
||||||
"SEM: %s USB failed to wait for (%d) '%s' count %d err (%d) %s",
|
|
||||||
drv->dname, sem, name, count, errno, strerror(errno));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (opt.seminfo->sem_otime != 0)
|
|
||||||
break;
|
|
||||||
nmsleep(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sembuf sops[] = {
|
|
||||||
{ 0, 0, IPC_NOWAIT | SEM_UNDO },
|
|
||||||
{ 0, 1, IPC_NOWAIT | SEM_UNDO }
|
|
||||||
};
|
|
||||||
|
|
||||||
if (semop(sem, sops, 2)) {
|
|
||||||
if (errno == EAGAIN) {
|
|
||||||
if (!hotplug_mode)
|
|
||||||
applog(LOG_WARNING,
|
|
||||||
"SEM: %s USB failed to get (%d) '%s' - device in use",
|
|
||||||
drv->dname, sem, name);
|
|
||||||
} else {
|
|
||||||
applog(LOG_DEBUG,
|
|
||||||
"SEM: %s USB failed to get (%d) '%s' err (%d) %s",
|
|
||||||
drv->dname, sem, name, errno, strerror(errno));
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
add_in_use(bus_number, device_address);
|
|
||||||
return true;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cgminer_usb_lock(struct device_drv *drv, libusb_device *dev)
|
static bool cgminer_usb_lock(struct device_drv *drv, libusb_device *dev)
|
||||||
@ -1228,76 +1208,26 @@ static bool cgminer_usb_lock(struct device_drv *drv, libusb_device *dev)
|
|||||||
return cgminer_usb_lock_bd(drv, libusb_get_bus_number(dev), libusb_get_device_address(dev));
|
return cgminer_usb_lock_bd(drv, libusb_get_bus_number(dev), libusb_get_device_address(dev));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Any errors should always be printed since they will rarely if ever occur
|
|
||||||
// and thus it is best to always display them
|
|
||||||
static void cgminer_usb_unlock_bd(struct device_drv *drv, uint8_t bus_number, uint8_t device_address)
|
static void cgminer_usb_unlock_bd(struct device_drv *drv, uint8_t bus_number, uint8_t device_address)
|
||||||
{
|
{
|
||||||
applog(LOG_DEBUG, "USB unlock %s %d-%d", drv->name, (int)bus_number, (int)device_address);
|
struct resource_work *res_work;
|
||||||
|
|
||||||
#ifdef WIN32
|
applog(LOG_DEBUG, "USB unlock %s %d-%d", drv->dname, (int)bus_number, (int)device_address);
|
||||||
HANDLE usbMutex;
|
|
||||||
char name[64];
|
|
||||||
|
|
||||||
sprintf(name, "cgminer-usb-%d-%d", (int)bus_number, (int)device_address);
|
res_work = calloc(1, sizeof(*res_work));
|
||||||
|
res_work->lock = false;
|
||||||
|
res_work->dname = (const char *)(drv->dname);
|
||||||
|
res_work->bus_number = bus_number;
|
||||||
|
res_work->device_address = device_address;
|
||||||
|
|
||||||
usbMutex = CreateMutex(NULL, FALSE, name);
|
mutex_lock(&cgusbres_lock);
|
||||||
if (usbMutex == NULL) {
|
|
||||||
applog(LOG_ERR,
|
|
||||||
"MTX: %s USB failed to get '%s' for release err (%d)",
|
|
||||||
drv->dname, name, GetLastError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ReleaseMutex(usbMutex))
|
res_work->next = res_work_head;
|
||||||
applog(LOG_ERR,
|
res_work_head = res_work;
|
||||||
"MTX: %s USB failed to release '%s' err (%d)",
|
|
||||||
drv->dname, name, GetLastError());
|
mutex_unlock(&cgusbres_lock);
|
||||||
|
|
||||||
CloseHandle(usbMutex);
|
|
||||||
remove_in_use(bus_number, device_address);
|
|
||||||
return;
|
return;
|
||||||
#else
|
|
||||||
char name[64];
|
|
||||||
key_t key;
|
|
||||||
int fd, sem;
|
|
||||||
|
|
||||||
sprintf(name, "/tmp/cgminer-usb-%d-%d", (int)bus_number, (int)device_address);
|
|
||||||
fd = open(name, O_CREAT|O_RDONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
|
|
||||||
if (fd == -1) {
|
|
||||||
applog(LOG_ERR,
|
|
||||||
"SEM: %s USB open failed '%s' for release err (%d) %s",
|
|
||||||
drv->dname, name, errno, strerror(errno));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
key = ftok(name, 'K');
|
|
||||||
|
|
||||||
sem = semget(key, 1, 0);
|
|
||||||
if (sem < 0) {
|
|
||||||
applog(LOG_ERR,
|
|
||||||
"SEM: %s USB failed to get '%s' for release err (%d) %s",
|
|
||||||
drv->dname, name, errno, strerror(errno));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sembuf sops[] = {
|
|
||||||
{ 0, -1, SEM_UNDO }
|
|
||||||
};
|
|
||||||
|
|
||||||
// Allow a 10ms timeout
|
|
||||||
// exceeding this timeout means it would probably never succeed anyway
|
|
||||||
struct timespec timeout = { 0, 10000000 };
|
|
||||||
|
|
||||||
// Wait forever since we shoud be the one who has it
|
|
||||||
if (semtimedop(sem, sops, 1, &timeout)) {
|
|
||||||
applog(LOG_ERR,
|
|
||||||
"SEM: %s USB failed to release '%s' err (%d) %s",
|
|
||||||
drv->dname, name, errno, strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
remove_in_use(bus_number, device_address);
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cgminer_usb_unlock(struct device_drv *drv, libusb_device *dev)
|
static void cgminer_usb_unlock(struct device_drv *drv, libusb_device *dev)
|
||||||
@ -2512,3 +2442,399 @@ void usb_initialise()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ipc.h>
|
||||||
|
#include <sys/sem.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
union semun {
|
||||||
|
int sem;
|
||||||
|
struct semid_ds *seminfo;
|
||||||
|
ushort *all;
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
static LPSECURITY_ATTRIBUTES unsec(LPSECURITY_ATTRIBUTES sec)
|
||||||
|
{
|
||||||
|
FreeSid(((PSECURITY_DESCRIPTOR)(sec->lpSecurityDescriptor))->Group);
|
||||||
|
free(sec->lpSecurityDescriptor);
|
||||||
|
free(sec);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LPSECURITY_ATTRIBUTES mksec(const char *dname, uint8_t bus_number, uint8_t device_address)
|
||||||
|
{
|
||||||
|
SID_IDENTIFIER_AUTHORITY SIDAuthWorld = {SECURITY_WORLD_SID_AUTHORITY};
|
||||||
|
PSID gsid = NULL;
|
||||||
|
LPSECURITY_ATTRIBUTES sec_att = NULL;
|
||||||
|
PSECURITY_DESCRIPTOR sec_des = NULL;
|
||||||
|
|
||||||
|
sec_des = malloc(sizeof(*sec_des));
|
||||||
|
if (unlikely(!sec_des))
|
||||||
|
quit(1, "MTX: Failed to malloc LPSECURITY_DESCRIPTOR");
|
||||||
|
|
||||||
|
if (!InitializeSecurityDescriptor(sec_des, SECURITY_DESCRIPTOR_REVISION)) {
|
||||||
|
applog(LOG_ERR,
|
||||||
|
"MTX: %s (%d:%d) USB failed to init secdes err (%d)",
|
||||||
|
dname, (int)bus_number, (int)device_address,
|
||||||
|
GetLastError());
|
||||||
|
free(sec_des);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SetSecurityDescriptorDacl(sec_des, TRUE, NULL, FALSE)) {
|
||||||
|
applog(LOG_ERR,
|
||||||
|
"MTX: %s (%d:%d) USB failed to secdes dacl err (%d)",
|
||||||
|
dname, (int)bus_number, (int)device_address,
|
||||||
|
GetLastError());
|
||||||
|
free(sec_des);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &gsid)) {
|
||||||
|
applog(LOG_ERR,
|
||||||
|
"MTX: %s (%d:%d) USB failed to create gsid err (%d)",
|
||||||
|
dname, (int)bus_number, (int)device_address,
|
||||||
|
GetLastError());
|
||||||
|
free(sec_des);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SetSecurityDescriptorGroup(sec_des, gsid, FALSE)) {
|
||||||
|
applog(LOG_ERR,
|
||||||
|
"MTX: %s (%d:%d) USB failed to secdes grp err (%d)",
|
||||||
|
dname, (int)bus_number, (int)device_address,
|
||||||
|
GetLastError());
|
||||||
|
FreeSid(gsid);
|
||||||
|
free(sec_des);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sec_att = malloc(sizeof(*sec_att));
|
||||||
|
if (unlikely(!sec_att))
|
||||||
|
quit(1, "MTX: Failed to malloc LPSECURITY_ATTRIBUTES");
|
||||||
|
|
||||||
|
sec_att->nLength = sizeof(*sec_att);
|
||||||
|
sec_att->lpSecurityDescriptor = sec_des;
|
||||||
|
sec_att->bInheritHandle = FALSE;
|
||||||
|
|
||||||
|
return sec_att;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Any errors should always be printed since they will rarely if ever occur
|
||||||
|
// and thus it is best to always display them
|
||||||
|
static bool resource_lock(const char *dname, uint8_t bus_number, uint8_t device_address)
|
||||||
|
{
|
||||||
|
applog(LOG_DEBUG, "USB res lock %s %d-%d", dname, (int)bus_number, (int)device_address);
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
struct cgpu_info *cgpu;
|
||||||
|
LPSECURITY_ATTRIBUTES sec;
|
||||||
|
HANDLE usbMutex;
|
||||||
|
char name[64];
|
||||||
|
DWORD res;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (is_in_use_bd(bus_number, device_address))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
sprintf(name, "cg-usb-%d-%d", (int)bus_number, (int)device_address);
|
||||||
|
|
||||||
|
sec = mksec(dname, bus_number, device_address);
|
||||||
|
if (!sec)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
usbMutex = CreateMutex(sec, FALSE, name);
|
||||||
|
if (usbMutex == NULL) {
|
||||||
|
applog(LOG_ERR,
|
||||||
|
"MTX: %s USB failed to get '%s' err (%d)",
|
||||||
|
dname, name, GetLastError());
|
||||||
|
sec = unsec(sec);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = WaitForSingleObject(usbMutex, 0);
|
||||||
|
|
||||||
|
switch(res) {
|
||||||
|
case WAIT_OBJECT_0:
|
||||||
|
case WAIT_ABANDONED:
|
||||||
|
// Am I using it already?
|
||||||
|
for (i = 0; i < total_devices; i++) {
|
||||||
|
cgpu = get_devices(i);
|
||||||
|
if (cgpu->usbinfo.bus_number == bus_number &&
|
||||||
|
cgpu->usbinfo.device_address == device_address &&
|
||||||
|
cgpu->usbinfo.nodev == false) {
|
||||||
|
if (ReleaseMutex(usbMutex)) {
|
||||||
|
applog(LOG_WARNING,
|
||||||
|
"MTX: %s USB can't get '%s' - device in use",
|
||||||
|
dname, name);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
applog(LOG_ERR,
|
||||||
|
"MTX: %s USB can't get '%s' - device in use - failure (%d)",
|
||||||
|
dname, name, GetLastError());
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WAIT_TIMEOUT:
|
||||||
|
if (!hotplug_mode)
|
||||||
|
applog(LOG_WARNING,
|
||||||
|
"MTX: %s USB failed to get '%s' - device in use",
|
||||||
|
dname, name);
|
||||||
|
goto fail;
|
||||||
|
case WAIT_FAILED:
|
||||||
|
applog(LOG_ERR,
|
||||||
|
"MTX: %s USB failed to get '%s' err (%d)",
|
||||||
|
dname, name, GetLastError());
|
||||||
|
goto fail;
|
||||||
|
default:
|
||||||
|
applog(LOG_ERR,
|
||||||
|
"MTX: %s USB failed to get '%s' unknown reply (%d)",
|
||||||
|
dname, name, res);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_in_use(bus_number, device_address);
|
||||||
|
in_use_store_ress(bus_number, device_address, (void *)usbMutex, (void *)sec);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
fail:
|
||||||
|
sec = unsec(sec);
|
||||||
|
CloseHandle(usbMutex);
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
struct semid_ds seminfo;
|
||||||
|
union semun opt;
|
||||||
|
char name[64];
|
||||||
|
key_t key;
|
||||||
|
int fd, sem, count;
|
||||||
|
|
||||||
|
if (is_in_use_bd(bus_number, device_address))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
sprintf(name, "/tmp/cgminer-usb-%d-%d", (int)bus_number, (int)device_address);
|
||||||
|
fd = open(name, O_CREAT|O_RDONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
|
||||||
|
if (fd == -1) {
|
||||||
|
applog(LOG_ERR,
|
||||||
|
"SEM: %s USB open failed '%s' err (%d) %s",
|
||||||
|
dname, name, errno, strerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
key = ftok(name, 'K');
|
||||||
|
sem = semget(key, 1, IPC_CREAT | IPC_EXCL | 438);
|
||||||
|
if (sem < 0) {
|
||||||
|
if (errno != EEXIST) {
|
||||||
|
applog(LOG_ERR,
|
||||||
|
"SEM: %s USB failed to get '%s' err (%d) %s",
|
||||||
|
dname, name, errno, strerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sem = semget(key, 1, 0);
|
||||||
|
if (sem < 0) {
|
||||||
|
applog(LOG_ERR,
|
||||||
|
"SEM: %s USB failed to access '%s' err (%d) %s",
|
||||||
|
dname, name, errno, strerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
opt.seminfo = &seminfo;
|
||||||
|
count = 0;
|
||||||
|
while (++count) {
|
||||||
|
// Should NEVER take 100ms
|
||||||
|
if (count > 99) {
|
||||||
|
applog(LOG_ERR,
|
||||||
|
"SEM: %s USB timeout waiting for (%d) '%s'",
|
||||||
|
dname, sem, name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (semctl(sem, 0, IPC_STAT, opt) == -1) {
|
||||||
|
applog(LOG_ERR,
|
||||||
|
"SEM: %s USB failed to wait for (%d) '%s' count %d err (%d) %s",
|
||||||
|
dname, sem, name, count, errno, strerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (opt.seminfo->sem_otime != 0)
|
||||||
|
break;
|
||||||
|
nmsleep(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sembuf sops[] = {
|
||||||
|
{ 0, 0, IPC_NOWAIT | SEM_UNDO },
|
||||||
|
{ 0, 1, IPC_NOWAIT | SEM_UNDO }
|
||||||
|
};
|
||||||
|
|
||||||
|
if (semop(sem, sops, 2)) {
|
||||||
|
if (errno == EAGAIN) {
|
||||||
|
if (!hotplug_mode)
|
||||||
|
applog(LOG_WARNING,
|
||||||
|
"SEM: %s USB failed to get (%d) '%s' - device in use",
|
||||||
|
dname, sem, name);
|
||||||
|
} else {
|
||||||
|
applog(LOG_DEBUG,
|
||||||
|
"SEM: %s USB failed to get (%d) '%s' err (%d) %s",
|
||||||
|
dname, sem, name, errno, strerror(errno));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_in_use(bus_number, device_address);
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any errors should always be printed since they will rarely if ever occur
|
||||||
|
// and thus it is best to always display them
|
||||||
|
static void resource_unlock(const char *dname, uint8_t bus_number, uint8_t device_address)
|
||||||
|
{
|
||||||
|
applog(LOG_DEBUG, "USB res unlock %s %d-%d", dname, (int)bus_number, (int)device_address);
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
LPSECURITY_ATTRIBUTES sec = NULL;
|
||||||
|
HANDLE usbMutex = NULL;
|
||||||
|
char name[64];
|
||||||
|
|
||||||
|
sprintf(name, "cg-usb-%d-%d", (int)bus_number, (int)device_address);
|
||||||
|
|
||||||
|
in_use_get_ress(bus_number, device_address, (void **)(&usbMutex), (void **)(&sec));
|
||||||
|
|
||||||
|
if (!usbMutex || !sec)
|
||||||
|
goto fila;
|
||||||
|
|
||||||
|
usbMutex = CreateMutex(sec, FALSE, name);
|
||||||
|
if (usbMutex == NULL) {
|
||||||
|
applog(LOG_ERR,
|
||||||
|
"MTX: %s USB failed to get '%s' for release err (%d)",
|
||||||
|
dname, name, GetLastError());
|
||||||
|
goto fila;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ReleaseMutex(usbMutex))
|
||||||
|
applog(LOG_ERR,
|
||||||
|
"MTX: %s USB failed to release '%s' err (%d)",
|
||||||
|
dname, name, GetLastError());
|
||||||
|
|
||||||
|
fila:
|
||||||
|
|
||||||
|
if (sec)
|
||||||
|
unsec(sec);
|
||||||
|
if (usbMutex)
|
||||||
|
CloseHandle(usbMutex);
|
||||||
|
remove_in_use(bus_number, device_address);
|
||||||
|
return;
|
||||||
|
#else
|
||||||
|
char name[64];
|
||||||
|
key_t key;
|
||||||
|
int fd, sem;
|
||||||
|
|
||||||
|
sprintf(name, "/tmp/cgminer-usb-%d-%d", (int)bus_number, (int)device_address);
|
||||||
|
fd = open(name, O_CREAT|O_RDONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
|
||||||
|
if (fd == -1) {
|
||||||
|
applog(LOG_ERR,
|
||||||
|
"SEM: %s USB open failed '%s' for release err (%d) %s",
|
||||||
|
dname, name, errno, strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
key = ftok(name, 'K');
|
||||||
|
|
||||||
|
sem = semget(key, 1, 0);
|
||||||
|
if (sem < 0) {
|
||||||
|
applog(LOG_ERR,
|
||||||
|
"SEM: %s USB failed to get '%s' for release err (%d) %s",
|
||||||
|
dname, name, errno, strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sembuf sops[] = {
|
||||||
|
{ 0, -1, SEM_UNDO }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Allow a 10ms timeout
|
||||||
|
// exceeding this timeout means it would probably never succeed anyway
|
||||||
|
struct timespec timeout = { 0, 10000000 };
|
||||||
|
|
||||||
|
// Wait forever since we shoud be the one who has it
|
||||||
|
if (semtimedop(sem, sops, 1, &timeout)) {
|
||||||
|
applog(LOG_ERR,
|
||||||
|
"SEM: %s USB failed to release '%s' err (%d) %s",
|
||||||
|
dname, name, errno, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_in_use(bus_number, device_address);
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void resource_process()
|
||||||
|
{
|
||||||
|
struct resource_work *res_work = NULL;
|
||||||
|
struct resource_reply *res_reply = NULL;
|
||||||
|
bool ok;
|
||||||
|
|
||||||
|
applog(LOG_DEBUG, "RES: %s (%d:%d) lock=%d",
|
||||||
|
res_work_head->dname,
|
||||||
|
(int)res_work_head->bus_number,
|
||||||
|
(int)res_work_head->device_address,
|
||||||
|
res_work_head->lock);
|
||||||
|
|
||||||
|
if (res_work_head->lock) {
|
||||||
|
ok = resource_lock(res_work_head->dname,
|
||||||
|
res_work_head->bus_number,
|
||||||
|
res_work_head->device_address);
|
||||||
|
|
||||||
|
applog(LOG_DEBUG, "RES: %s (%d:%d) lock ok=%d",
|
||||||
|
res_work_head->dname,
|
||||||
|
(int)res_work_head->bus_number,
|
||||||
|
(int)res_work_head->device_address,
|
||||||
|
ok);
|
||||||
|
|
||||||
|
res_reply = calloc(1, sizeof(*res_reply));
|
||||||
|
|
||||||
|
res_reply->bus_number = res_work_head->bus_number;
|
||||||
|
res_reply->device_address = res_work_head->device_address;
|
||||||
|
res_reply->got = ok;
|
||||||
|
res_reply->next = res_reply_head;
|
||||||
|
|
||||||
|
res_reply_head = res_reply;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
resource_unlock(res_work_head->dname,
|
||||||
|
res_work_head->bus_number,
|
||||||
|
res_work_head->device_address);
|
||||||
|
|
||||||
|
res_work = res_work_head;
|
||||||
|
res_work_head = res_work_head->next;
|
||||||
|
free(res_work);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *usb_resource_thread(void __maybe_unused *userdata)
|
||||||
|
{
|
||||||
|
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
|
||||||
|
|
||||||
|
RenameThread("usbresource");
|
||||||
|
|
||||||
|
applog(LOG_DEBUG, "RES: thread starting");
|
||||||
|
|
||||||
|
while (0*1337+1) {
|
||||||
|
mutex_lock(&cgusbres_lock);
|
||||||
|
|
||||||
|
while (res_work_head)
|
||||||
|
resource_process();
|
||||||
|
|
||||||
|
mutex_unlock(&cgusbres_lock);
|
||||||
|
|
||||||
|
nmsleep(45);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
@ -230,6 +230,7 @@ int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest
|
|||||||
int _usb_transfer_read(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, char *buf, int bufsiz, int *amount, unsigned int timeout, enum usb_cmds cmd);
|
int _usb_transfer_read(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, char *buf, int bufsiz, int *amount, unsigned int timeout, enum usb_cmds cmd);
|
||||||
void usb_cleanup();
|
void usb_cleanup();
|
||||||
void usb_initialise();
|
void usb_initialise();
|
||||||
|
void *usb_resource_thread(void *userdata);
|
||||||
|
|
||||||
#define usb_read(cgpu, buf, bufsiz, read, cmd) \
|
#define usb_read(cgpu, buf, bufsiz, read, cmd) \
|
||||||
_usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, NULL, cmd, false)
|
_usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, NULL, cmd, false)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user