|
|
@ -62,10 +62,10 @@ static void keep_sockalive(SOCKETTYPE fd) |
|
|
|
ioctlsocket(fd, FIONBIO, &flags); |
|
|
|
ioctlsocket(fd, FIONBIO, &flags); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (const void *)&tcp_one, sizeof(tcp_one)); |
|
|
|
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (const char *)&tcp_one, sizeof(tcp_one)); |
|
|
|
if (!opt_delaynet) |
|
|
|
if (!opt_delaynet) |
|
|
|
#ifndef __linux |
|
|
|
#ifndef __linux |
|
|
|
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const void *)&tcp_one, sizeof(tcp_one)); |
|
|
|
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char *)&tcp_one, sizeof(tcp_one)); |
|
|
|
#else /* __linux */ |
|
|
|
#else /* __linux */ |
|
|
|
setsockopt(fd, SOL_TCP, TCP_NODELAY, (const void *)&tcp_one, sizeof(tcp_one)); |
|
|
|
setsockopt(fd, SOL_TCP, TCP_NODELAY, (const void *)&tcp_one, sizeof(tcp_one)); |
|
|
|
setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &tcp_one, sizeof(tcp_one)); |
|
|
|
setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &tcp_one, sizeof(tcp_one)); |
|
|
@ -120,7 +120,7 @@ static void databuf_free(struct data_buffer *db) |
|
|
|
static size_t all_data_cb(const void *ptr, size_t size, size_t nmemb, |
|
|
|
static size_t all_data_cb(const void *ptr, size_t size, size_t nmemb, |
|
|
|
void *user_data) |
|
|
|
void *user_data) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct data_buffer *db = user_data; |
|
|
|
struct data_buffer *db = (struct data_buffer *)user_data; |
|
|
|
size_t len = size * nmemb; |
|
|
|
size_t len = size * nmemb; |
|
|
|
size_t oldlen, newlen; |
|
|
|
size_t oldlen, newlen; |
|
|
|
void *newmem; |
|
|
|
void *newmem; |
|
|
@ -135,8 +135,8 @@ static size_t all_data_cb(const void *ptr, size_t size, size_t nmemb, |
|
|
|
|
|
|
|
|
|
|
|
db->buf = newmem; |
|
|
|
db->buf = newmem; |
|
|
|
db->len = newlen; |
|
|
|
db->len = newlen; |
|
|
|
memcpy(db->buf + oldlen, ptr, len); |
|
|
|
memcpy((uint8_t*)db->buf + oldlen, ptr, len); |
|
|
|
memcpy(db->buf + newlen, &zero, 1); /* null terminate */ |
|
|
|
memcpy((uint8_t*)db->buf + newlen, &zero, 1); /* null terminate */ |
|
|
|
|
|
|
|
|
|
|
|
return len; |
|
|
|
return len; |
|
|
|
} |
|
|
|
} |
|
|
@ -144,7 +144,7 @@ static size_t all_data_cb(const void *ptr, size_t size, size_t nmemb, |
|
|
|
static size_t upload_data_cb(void *ptr, size_t size, size_t nmemb, |
|
|
|
static size_t upload_data_cb(void *ptr, size_t size, size_t nmemb, |
|
|
|
void *user_data) |
|
|
|
void *user_data) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct upload_buffer *ub = user_data; |
|
|
|
struct upload_buffer *ub = (struct upload_buffer *)user_data; |
|
|
|
unsigned int len = size * nmemb; |
|
|
|
unsigned int len = size * nmemb; |
|
|
|
|
|
|
|
|
|
|
|
if (len > ub->len) |
|
|
|
if (len > ub->len) |
|
|
@ -152,7 +152,7 @@ static size_t upload_data_cb(void *ptr, size_t size, size_t nmemb, |
|
|
|
|
|
|
|
|
|
|
|
if (len) { |
|
|
|
if (len) { |
|
|
|
memcpy(ptr, ub->buf, len); |
|
|
|
memcpy(ptr, ub->buf, len); |
|
|
|
ub->buf += len; |
|
|
|
ub->buf = (uint8_t*)ub->buf + len; |
|
|
|
ub->len -= len; |
|
|
|
ub->len -= len; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -161,26 +161,26 @@ static size_t upload_data_cb(void *ptr, size_t size, size_t nmemb, |
|
|
|
|
|
|
|
|
|
|
|
static size_t resp_hdr_cb(void *ptr, size_t size, size_t nmemb, void *user_data) |
|
|
|
static size_t resp_hdr_cb(void *ptr, size_t size, size_t nmemb, void *user_data) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct header_info *hi = user_data; |
|
|
|
struct header_info *hi = (struct header_info *)user_data; |
|
|
|
size_t remlen, slen, ptrlen = size * nmemb; |
|
|
|
size_t remlen, slen, ptrlen = size * nmemb; |
|
|
|
char *rem, *val = NULL, *key = NULL; |
|
|
|
char *rem, *val = NULL, *key = NULL; |
|
|
|
void *tmp; |
|
|
|
void *tmp; |
|
|
|
|
|
|
|
|
|
|
|
val = calloc(1, ptrlen); |
|
|
|
val = (char *)calloc(1, ptrlen); |
|
|
|
key = calloc(1, ptrlen); |
|
|
|
key = (char *)calloc(1, ptrlen); |
|
|
|
if (!key || !val) |
|
|
|
if (!key || !val) |
|
|
|
goto out; |
|
|
|
goto out; |
|
|
|
|
|
|
|
|
|
|
|
tmp = memchr(ptr, ':', ptrlen); |
|
|
|
tmp = memchr(ptr, ':', ptrlen); |
|
|
|
if (!tmp || (tmp == ptr)) /* skip empty keys / blanks */ |
|
|
|
if (!tmp || (tmp == ptr)) /* skip empty keys / blanks */ |
|
|
|
goto out; |
|
|
|
goto out; |
|
|
|
slen = tmp - ptr; |
|
|
|
slen = (uint8_t*)tmp - (uint8_t*)ptr; |
|
|
|
if ((slen + 1) == ptrlen) /* skip key w/ no value */ |
|
|
|
if ((slen + 1) == ptrlen) /* skip key w/ no value */ |
|
|
|
goto out; |
|
|
|
goto out; |
|
|
|
memcpy(key, ptr, slen); /* store & nul term key */ |
|
|
|
memcpy(key, ptr, slen); /* store & nul term key */ |
|
|
|
key[slen] = 0; |
|
|
|
key[slen] = 0; |
|
|
|
|
|
|
|
|
|
|
|
rem = ptr + slen + 1; /* trim value's leading whitespace */ |
|
|
|
rem = (char*)ptr + slen + 1; /* trim value's leading whitespace */ |
|
|
|
remlen = ptrlen - slen - 1; |
|
|
|
remlen = ptrlen - slen - 1; |
|
|
|
while ((remlen > 0) && (isspace(*rem))) { |
|
|
|
while ((remlen > 0) && (isspace(*rem))) { |
|
|
|
remlen--; |
|
|
|
remlen--; |
|
|
@ -456,7 +456,7 @@ json_t *json_rpc_call(CURL *curl, const char *url, |
|
|
|
pool->sgminer_pool_stats.canroll = hi.canroll; |
|
|
|
pool->sgminer_pool_stats.canroll = hi.canroll; |
|
|
|
pool->sgminer_pool_stats.hadexpire = hi.hadexpire; |
|
|
|
pool->sgminer_pool_stats.hadexpire = hi.hadexpire; |
|
|
|
|
|
|
|
|
|
|
|
val = JSON_LOADS(all_data.buf, &err); |
|
|
|
val = JSON_LOADS((const char *)all_data.buf, &err); |
|
|
|
if (!val) { |
|
|
|
if (!val) { |
|
|
|
applog(LOG_INFO, "JSON decode failed(%d): %s", err.line, err.text); |
|
|
|
applog(LOG_INFO, "JSON decode failed(%d): %s", err.line, err.text); |
|
|
|
|
|
|
|
|
|
|
@ -539,7 +539,7 @@ static struct { |
|
|
|
{ "socks5:", PROXY_SOCKS5 }, |
|
|
|
{ "socks5:", PROXY_SOCKS5 }, |
|
|
|
{ "socks4a:", PROXY_SOCKS4A }, |
|
|
|
{ "socks4a:", PROXY_SOCKS4A }, |
|
|
|
{ "socks5h:", PROXY_SOCKS5H }, |
|
|
|
{ "socks5h:", PROXY_SOCKS5H }, |
|
|
|
{ NULL, 0 } |
|
|
|
{ NULL, (proxytypes_t)NULL } |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const char *proxytype(proxytypes_t proxytype) |
|
|
|
const char *proxytype(proxytypes_t proxytype) |
|
|
@ -568,7 +568,7 @@ char *get_proxy(char *url, struct pool *pool) |
|
|
|
|
|
|
|
|
|
|
|
*split = '\0'; |
|
|
|
*split = '\0'; |
|
|
|
len = split - url; |
|
|
|
len = split - url; |
|
|
|
pool->rpc_proxy = malloc(1 + len - plen); |
|
|
|
pool->rpc_proxy = (char *)malloc(1 + len - plen); |
|
|
|
if (!(pool->rpc_proxy)) |
|
|
|
if (!(pool->rpc_proxy)) |
|
|
|
quithere(1, "Failed to malloc rpc_proxy"); |
|
|
|
quithere(1, "Failed to malloc rpc_proxy"); |
|
|
|
|
|
|
|
|
|
|
@ -606,7 +606,7 @@ char *bin2hex(const unsigned char *p, size_t len) |
|
|
|
slen = len * 2 + 1; |
|
|
|
slen = len * 2 + 1; |
|
|
|
if (slen % 4) |
|
|
|
if (slen % 4) |
|
|
|
slen += 4 - (slen % 4); |
|
|
|
slen += 4 - (slen % 4); |
|
|
|
s = calloc(slen, 1); |
|
|
|
s = (char *)calloc(slen, 1); |
|
|
|
if (unlikely(!s)) |
|
|
|
if (unlikely(!s)) |
|
|
|
quithere(1, "Failed to calloc"); |
|
|
|
quithere(1, "Failed to calloc"); |
|
|
|
|
|
|
|
|
|
|
@ -712,7 +712,7 @@ struct thread_q *tq_new(void) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct thread_q *tq; |
|
|
|
struct thread_q *tq; |
|
|
|
|
|
|
|
|
|
|
|
tq = calloc(1, sizeof(*tq)); |
|
|
|
tq = (struct thread_q *)calloc(1, sizeof(*tq)); |
|
|
|
if (!tq) |
|
|
|
if (!tq) |
|
|
|
return NULL; |
|
|
|
return NULL; |
|
|
|
|
|
|
|
|
|
|
@ -765,7 +765,7 @@ bool tq_push(struct thread_q *tq, void *data) |
|
|
|
struct tq_ent *ent; |
|
|
|
struct tq_ent *ent; |
|
|
|
bool rc = true; |
|
|
|
bool rc = true; |
|
|
|
|
|
|
|
|
|
|
|
ent = calloc(1, sizeof(*ent)); |
|
|
|
ent = (struct tq_ent *)calloc(1, sizeof(*ent)); |
|
|
|
if (!ent) |
|
|
|
if (!ent) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
@ -1368,20 +1368,20 @@ static void clear_sock(struct pool *pool) |
|
|
|
* and zeroing the new memory */ |
|
|
|
* and zeroing the new memory */ |
|
|
|
static void recalloc_sock(struct pool *pool, size_t len) |
|
|
|
static void recalloc_sock(struct pool *pool, size_t len) |
|
|
|
{ |
|
|
|
{ |
|
|
|
size_t old, new; |
|
|
|
size_t old, newlen; |
|
|
|
|
|
|
|
|
|
|
|
old = strlen(pool->sockbuf); |
|
|
|
old = strlen(pool->sockbuf); |
|
|
|
new = old + len + 1; |
|
|
|
newlen = old + len + 1; |
|
|
|
if (new < pool->sockbuf_size) |
|
|
|
if (newlen < pool->sockbuf_size) |
|
|
|
return; |
|
|
|
return; |
|
|
|
new = new + (RBUFSIZE - (new % RBUFSIZE)); |
|
|
|
newlen = newlen + (RBUFSIZE - (newlen % RBUFSIZE)); |
|
|
|
// Avoid potentially recursive locking
|
|
|
|
// Avoid potentially recursive locking
|
|
|
|
// applog(LOG_DEBUG, "Recallocing pool sockbuf to %d", new);
|
|
|
|
// applog(LOG_DEBUG, "Recallocing pool sockbuf to %d", new);
|
|
|
|
pool->sockbuf = realloc(pool->sockbuf, new); |
|
|
|
pool->sockbuf = (char *)realloc(pool->sockbuf, newlen); |
|
|
|
if (!pool->sockbuf) |
|
|
|
if (!pool->sockbuf) |
|
|
|
quithere(1, "Failed to realloc pool sockbuf"); |
|
|
|
quithere(1, "Failed to realloc pool sockbuf"); |
|
|
|
memset(pool->sockbuf + old, 0, new - old); |
|
|
|
memset(pool->sockbuf + old, 0, newlen - old); |
|
|
|
pool->sockbuf_size = new; |
|
|
|
pool->sockbuf_size = newlen; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Peeks at a socket to find the first end of line and then reads just that
|
|
|
|
/* Peeks at a socket to find the first end of line and then reads just that
|
|
|
@ -1552,12 +1552,12 @@ static bool parse_notify(struct pool *pool, json_t *val) |
|
|
|
for (i = 0; i < pool->swork.merkles; i++) |
|
|
|
for (i = 0; i < pool->swork.merkles; i++) |
|
|
|
free(pool->swork.merkle_bin[i]); |
|
|
|
free(pool->swork.merkle_bin[i]); |
|
|
|
if (merkles) { |
|
|
|
if (merkles) { |
|
|
|
pool->swork.merkle_bin = realloc(pool->swork.merkle_bin, |
|
|
|
pool->swork.merkle_bin = (unsigned char **)realloc(pool->swork.merkle_bin, |
|
|
|
sizeof(char *) * merkles + 1); |
|
|
|
sizeof(char *) * merkles + 1); |
|
|
|
for (i = 0; i < merkles; i++) { |
|
|
|
for (i = 0; i < merkles; i++) { |
|
|
|
char *merkle = json_array_string(arr, i); |
|
|
|
char *merkle = json_array_string(arr, i); |
|
|
|
|
|
|
|
|
|
|
|
pool->swork.merkle_bin[i] = malloc(32); |
|
|
|
pool->swork.merkle_bin[i] = (unsigned char *)malloc(32); |
|
|
|
if (unlikely(!pool->swork.merkle_bin[i])) |
|
|
|
if (unlikely(!pool->swork.merkle_bin[i])) |
|
|
|
quit(1, "Failed to malloc pool swork merkle_bin"); |
|
|
|
quit(1, "Failed to malloc pool swork merkle_bin"); |
|
|
|
hex2bin(pool->swork.merkle_bin[i], merkle, 32); |
|
|
|
hex2bin(pool->swork.merkle_bin[i], merkle, 32); |
|
|
@ -1578,7 +1578,7 @@ static bool parse_notify(struct pool *pool, json_t *val) |
|
|
|
pool->merkle_offset /= 2; |
|
|
|
pool->merkle_offset /= 2; |
|
|
|
pool->swork.header_len = pool->swork.header_len * 2 + 1; |
|
|
|
pool->swork.header_len = pool->swork.header_len * 2 + 1; |
|
|
|
align_len(&pool->swork.header_len); |
|
|
|
align_len(&pool->swork.header_len); |
|
|
|
header = alloca(pool->swork.header_len); |
|
|
|
header = (char *)alloca(pool->swork.header_len); |
|
|
|
snprintf(header, pool->swork.header_len, |
|
|
|
snprintf(header, pool->swork.header_len, |
|
|
|
"%s%s%s%s%s%s%s", |
|
|
|
"%s%s%s%s%s%s%s", |
|
|
|
pool->swork.bbversion, |
|
|
|
pool->swork.bbversion, |
|
|
@ -1591,17 +1591,17 @@ static bool parse_notify(struct pool *pool, json_t *val) |
|
|
|
if (unlikely(!hex2bin(pool->header_bin, header, 128))) |
|
|
|
if (unlikely(!hex2bin(pool->header_bin, header, 128))) |
|
|
|
quit(1, "Failed to convert header to header_bin in parse_notify"); |
|
|
|
quit(1, "Failed to convert header to header_bin in parse_notify"); |
|
|
|
|
|
|
|
|
|
|
|
cb1 = calloc(cb1_len, 1); |
|
|
|
cb1 = (unsigned char *)calloc(cb1_len, 1); |
|
|
|
if (unlikely(!cb1)) |
|
|
|
if (unlikely(!cb1)) |
|
|
|
quithere(1, "Failed to calloc cb1 in parse_notify"); |
|
|
|
quithere(1, "Failed to calloc cb1 in parse_notify"); |
|
|
|
hex2bin(cb1, coinbase1, cb1_len); |
|
|
|
hex2bin(cb1, coinbase1, cb1_len); |
|
|
|
cb2 = calloc(cb2_len, 1); |
|
|
|
cb2 = (unsigned char *)calloc(cb2_len, 1); |
|
|
|
if (unlikely(!cb2)) |
|
|
|
if (unlikely(!cb2)) |
|
|
|
quithere(1, "Failed to calloc cb2 in parse_notify"); |
|
|
|
quithere(1, "Failed to calloc cb2 in parse_notify"); |
|
|
|
hex2bin(cb2, coinbase2, cb2_len); |
|
|
|
hex2bin(cb2, coinbase2, cb2_len); |
|
|
|
free(pool->coinbase); |
|
|
|
free(pool->coinbase); |
|
|
|
align_len(&alloc_len); |
|
|
|
align_len(&alloc_len); |
|
|
|
pool->coinbase = calloc(alloc_len, 1); |
|
|
|
pool->coinbase = (unsigned char *)calloc(alloc_len, 1); |
|
|
|
if (unlikely(!pool->coinbase)) |
|
|
|
if (unlikely(!pool->coinbase)) |
|
|
|
quit(1, "Failed to calloc pool coinbase in parse_notify"); |
|
|
|
quit(1, "Failed to calloc pool coinbase in parse_notify"); |
|
|
|
memcpy(pool->coinbase, cb1, cb1_len); |
|
|
|
memcpy(pool->coinbase, cb1, cb1_len); |
|
|
@ -2159,7 +2159,7 @@ static bool setup_stratum_socket(struct pool *pool) |
|
|
|
int err, n; |
|
|
|
int err, n; |
|
|
|
|
|
|
|
|
|
|
|
len = sizeof(err); |
|
|
|
len = sizeof(err); |
|
|
|
n = getsockopt(sockd, SOL_SOCKET, SO_ERROR, (void *)&err, &len); |
|
|
|
n = getsockopt(sockd, SOL_SOCKET, SO_ERROR, (char *)&err, &len); |
|
|
|
if (!n && !err) { |
|
|
|
if (!n && !err) { |
|
|
|
applog(LOG_DEBUG, "Succeeded delayed connect"); |
|
|
|
applog(LOG_DEBUG, "Succeeded delayed connect"); |
|
|
|
block_socket(sockd); |
|
|
|
block_socket(sockd); |
|
|
@ -2215,7 +2215,7 @@ static bool setup_stratum_socket(struct pool *pool) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!pool->sockbuf) { |
|
|
|
if (!pool->sockbuf) { |
|
|
|
pool->sockbuf = calloc(RBUFSIZE, 1); |
|
|
|
pool->sockbuf = (char *)calloc(RBUFSIZE, 1); |
|
|
|
if (!pool->sockbuf) |
|
|
|
if (!pool->sockbuf) |
|
|
|
quithere(1, "Failed to calloc pool sockbuf"); |
|
|
|
quithere(1, "Failed to calloc pool sockbuf"); |
|
|
|
pool->sockbuf_size = RBUFSIZE; |
|
|
|
pool->sockbuf_size = RBUFSIZE; |
|
|
@ -2358,7 +2358,7 @@ resend: |
|
|
|
pool->nonce1 = nonce1; |
|
|
|
pool->nonce1 = nonce1; |
|
|
|
pool->n1_len = strlen(nonce1) / 2; |
|
|
|
pool->n1_len = strlen(nonce1) / 2; |
|
|
|
free(pool->nonce1bin); |
|
|
|
free(pool->nonce1bin); |
|
|
|
pool->nonce1bin = calloc(pool->n1_len, 1); |
|
|
|
pool->nonce1bin = (unsigned char *)calloc(pool->n1_len, 1); |
|
|
|
if (unlikely(!pool->nonce1bin)) |
|
|
|
if (unlikely(!pool->nonce1bin)) |
|
|
|
quithere(1, "Failed to calloc pool->nonce1bin"); |
|
|
|
quithere(1, "Failed to calloc pool->nonce1bin"); |
|
|
|
hex2bin(pool->nonce1bin, pool->nonce1, pool->n1_len); |
|
|
|
hex2bin(pool->nonce1bin, pool->nonce1, pool->n1_len); |
|
|
@ -2466,7 +2466,7 @@ void *realloc_strcat(char *ptr, char *s) |
|
|
|
len += old + 1; |
|
|
|
len += old + 1; |
|
|
|
align_len(&len); |
|
|
|
align_len(&len); |
|
|
|
|
|
|
|
|
|
|
|
ret = malloc(len); |
|
|
|
ret = (char *)malloc(len); |
|
|
|
if (unlikely(!ret)) |
|
|
|
if (unlikely(!ret)) |
|
|
|
quithere(1, "Failed to malloc"); |
|
|
|
quithere(1, "Failed to malloc"); |
|
|
|
|
|
|
|
|
|
|
@ -2492,7 +2492,7 @@ void *str_text(char *ptr) |
|
|
|
|
|
|
|
|
|
|
|
uptr = (unsigned char *)ptr; |
|
|
|
uptr = (unsigned char *)ptr; |
|
|
|
|
|
|
|
|
|
|
|
ret = txt = malloc(strlen(ptr)*4+5); // Guaranteed >= needed
|
|
|
|
ret = txt = (char *)malloc(strlen(ptr) * 4 + 5); // Guaranteed >= needed
|
|
|
|
if (unlikely(!txt)) |
|
|
|
if (unlikely(!txt)) |
|
|
|
quithere(1, "Failed to malloc txt"); |
|
|
|
quithere(1, "Failed to malloc txt"); |
|
|
|
|
|
|
|
|
|
|
@ -2696,11 +2696,17 @@ bool cg_completion_timeout(void *fn, void *fnarg, int timeout) |
|
|
|
pthread_t pthread; |
|
|
|
pthread_t pthread; |
|
|
|
bool ret = false; |
|
|
|
bool ret = false; |
|
|
|
|
|
|
|
|
|
|
|
cgc = malloc(sizeof(struct cg_completion)); |
|
|
|
cgc = (struct cg_completion *)malloc(sizeof(struct cg_completion)); |
|
|
|
if (unlikely(!cgc)) |
|
|
|
if (unlikely(!cgc)) |
|
|
|
return ret; |
|
|
|
return ret; |
|
|
|
cgsem_init(&cgc->cgsem); |
|
|
|
cgsem_init(&cgc->cgsem); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef _MSC_VER |
|
|
|
|
|
|
|
cgc->fn = (void(__cdecl *)(void *))fn; |
|
|
|
|
|
|
|
#else |
|
|
|
cgc->fn = fn; |
|
|
|
cgc->fn = fn; |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
cgc->fnarg = fnarg; |
|
|
|
cgc->fnarg = fnarg; |
|
|
|
|
|
|
|
|
|
|
|
pthread_create(&pthread, NULL, completion_thread, (void *)cgc); |
|
|
|
pthread_create(&pthread, NULL, completion_thread, (void *)cgc); |
|
|
|