Optimized thread cancellation - removed should_stop polling for maximum mining performance

This commit is contained in:
Your Name
2025-08-17 14:28:26 -04:00
parent 6568d4465a
commit 7d1500a49c
4 changed files with 19 additions and 110 deletions

View File

@@ -1 +1 @@
0.1.35 0.1.36

View File

@@ -1,27 +0,0 @@
PoW mining: 0 attempts, best this round: 0, overall best: 0, goal: 18
PoW mining: 0 attempts, best this round: 0, overall best: 0, goal: 18
PoW mining: 0 attempts, best this round: 0, overall best: 0, goal: 18
PoW mining: 0 attempts, best this round: 0, overall best: 0, goal: 18
PoW mining: 0 attempts, best this round: 0, overall best: 0, goal: 18
PoW mining: 0 attempts, best this round: 0, overall best: 0, goal: 18
PoW mining: 0 attempts, best this round: 0, overall best: 0, goal: 18
PoW mining: 0 attempts, best this round: 0, overall best: 0, goal: 18
PoW mining: 0 attempts, best this round: 0, overall best: 0, goal: 18
PoW mining: 0 attempts, best this round: 0, overall best: 0, goal: 18
PoW mining: 0 attempts, best this round: 0, overall best: 0, goal: 18
PoW mining: 0 attempts, best this round: 0, overall best: 0, goal: 18
PoW mining: 0 attempts, best this round: 0, overall best: 0, goal: 18
PoW mining: 0 attempts, best this round: 0, overall best: 0, goal: 18
PoW mining: 0 attempts, best this round: 0, overall best: 0, goal: 18
PoW mining: 0 attempts, best this round: 0, overall best: 0, goal: 18
PoW mining: 30 attempts, best this round: 8, overall best: 8, goal: 18
PoW mining: 30 attempts, best this round: 8, overall best: 8, goal: 18
PoW mining: 30 attempts, best this round: 8, overall best: 8, goal: 18
PoW mining: 30 attempts, best this round: 8, overall best: 8, goal: 18
PoW mining: 30 attempts, best this round: 8, overall best: 8, goal: 18
PoW mining: 30 attempts, best this round: 8, overall best: 8, goal: 18
PoW mining: 30 attempts, best this round: 8, overall best: 8, goal: 18
PoW mining: 30 attempts, best this round: 8, overall best: 8, goal: 18
PoW mining: 30 attempts, best this round: 8, overall best: 8, goal: 18
PoW mining: 30 attempts, best this round: 8, overall best: 8, goal: 18
PoW mining: 30 attempts, best this round: 8, overall best: 8, goal: 18

Binary file not shown.

View File

@@ -57,7 +57,7 @@ struct main_context {
}; };
// Mining context for workers (keeping legacy fields for now during transition) // Mining context for workers
struct mining_context { struct mining_context {
cJSON* event; cJSON* event;
unsigned char private_key[32]; unsigned char private_key[32];
@@ -68,9 +68,6 @@ struct mining_context {
solution_callback_t solution_callback; solution_callback_t solution_callback;
void* user_data; void* user_data;
// Control flag (only main thread modifies)
volatile int should_stop;
// Verbose mode and progress tracking // Verbose mode and progress tracking
int verbose_enabled; int verbose_enabled;
int best_leading_zeros; int best_leading_zeros;
@@ -298,13 +295,7 @@ static void emergency_shutdown(void) {
// Set global shutdown flag // Set global shutdown flag
g_shutdown_requested = 1; g_shutdown_requested = 1;
// Signal all worker threads to stop if contexts are available // No need to signal individual threads - they check g_shutdown_requested
if (g_worker_contexts) {
mining_context_t* contexts = (mining_context_t*)g_worker_contexts;
for (int i = 0; i < g_thread_count; i++) {
contexts[i].should_stop = 1;
}
}
} }
static void signal_handler(int sig) { static void signal_handler(int sig) {
@@ -438,8 +429,8 @@ static void* miner_thread(void* arg) {
uint64_t attempts = 0; uint64_t attempts = 0;
// Mine until solution found or signaled to stop by main thread // Mine until solution found or emergency shutdown
while (!ctx->should_stop && !g_shutdown_requested) { while (!g_shutdown_requested) {
// Attempt mining with verbose callback if enabled // Attempt mining with verbose callback if enabled
void (*progress_cb)(int, uint64_t, void*) = ctx->verbose_enabled ? verbose_pow_callback : NULL; void (*progress_cb)(int, uint64_t, void*) = ctx->verbose_enabled ? verbose_pow_callback : NULL;
@@ -462,21 +453,14 @@ static void* miner_thread(void* arg) {
break; // Exit after reporting solution break; // Exit after reporting solution
} }
// Check for emergency shutdown // Check for emergency shutdown (signals only)
if (g_shutdown_requested) { if (g_shutdown_requested) {
exit_status = (void*)(intptr_t)THREAD_EXIT_STOPPED; exit_status = (void*)(intptr_t)THREAD_EXIT_STOPPED;
log_thread_exit(ctx->thread_id, exit_status, "Emergency shutdown", ctx->verbose_enabled); log_thread_exit(ctx->thread_id, exit_status, "Emergency shutdown", ctx->verbose_enabled);
break; break;
} }
// Small delay to prevent CPU overuse and allow responsive stopping // No delay - run at maximum speed for optimal mining performance
usleep(100); // 0.1ms - more responsive to should_stop signal
}
// Normal stop by main thread
if (ctx->should_stop && !g_shutdown_requested) {
exit_status = (void*)(intptr_t)THREAD_EXIT_STOPPED;
log_thread_exit(ctx->thread_id, exit_status, "Stopped by main thread", ctx->verbose_enabled);
} }
cJSON_Delete(local_event); cJSON_Delete(local_event);
@@ -501,7 +485,6 @@ static int mine_event(mining_context_t* ctx) {
// Set up callback system // Set up callback system
ctx->solution_callback = solution_found_callback; ctx->solution_callback = solution_found_callback;
ctx->user_data = &main_ctx; ctx->user_data = &main_ctx;
ctx->should_stop = 0;
// Create individual worker contexts (each gets its own thread_id) // Create individual worker contexts (each gets its own thread_id)
mining_context_t* worker_contexts = malloc(ctx->thread_count * sizeof(mining_context_t)); mining_context_t* worker_contexts = malloc(ctx->thread_count * sizeof(mining_context_t));
@@ -542,10 +525,8 @@ static int mine_event(mining_context_t* ctx) {
for (int i = 0; i < ctx->thread_count; i++) { for (int i = 0; i < ctx->thread_count; i++) {
if (pthread_create(&threads[i], NULL, miner_thread, &worker_contexts[i]) != 0) { if (pthread_create(&threads[i], NULL, miner_thread, &worker_contexts[i]) != 0) {
fprintf(stderr, "Error: Failed to create thread %d\n", i); fprintf(stderr, "Error: Failed to create thread %d\n", i);
// Stop already running threads // Set global shutdown to stop any running threads
for (int j = 0; j < ctx->thread_count; j++) { g_shutdown_requested = 1;
worker_contexts[j].should_stop = 1;
}
// Wait for threads that were created // Wait for threads that were created
for (int j = 0; j < i; j++) { for (int j = 0; j < i; j++) {
void* exit_status; void* exit_status;
@@ -589,89 +570,44 @@ static int mine_event(mining_context_t* ctx) {
// Handle results - OUTPUT IMMEDIATELY when solution is found // Handle results - OUTPUT IMMEDIATELY when solution is found
if (main_ctx.solution_found && main_ctx.result_event) { if (main_ctx.solution_found && main_ctx.result_event) {
// Transfer ownership for cleanup
ctx->result_event = main_ctx.result_event;
result = 1; // Success
if (ctx->verbose_enabled) { if (ctx->verbose_enabled) {
fprintf(stderr, "Solution found successfully by Thread %d\n", main_ctx.solution_thread_id); fprintf(stderr, "Solution found successfully by Thread %d\n", main_ctx.solution_thread_id);
} }
// Output the solution JSON immediately to stdout // Output the solution JSON immediately to stdout
char* output_json = cJSON_Print(ctx->result_event); char* output_json = cJSON_Print(main_ctx.result_event);
if (output_json) { if (output_json) {
printf("%s\n", output_json); printf("%s\n", output_json);
fflush(stdout); // Ensure immediate output fflush(stdout); // Ensure immediate output
free(output_json); free(output_json);
} }
// Solution found - exit immediately, let OS clean up all threads and resources
exit(0);
} else if (main_ctx.timeout_reached) { } else if (main_ctx.timeout_reached) {
result = -1; // Timeout
if (ctx->verbose_enabled) { if (ctx->verbose_enabled) {
fprintf(stderr, "Mining timed out\n"); fprintf(stderr, "Mining timed out\n");
} }
// Output timeout message // Output timeout message and exit
printf("timeout\n"); printf("timeout\n");
fflush(stdout); fflush(stdout);
exit(1);
} else if (g_shutdown_requested || g_signal_received) { } else if (g_shutdown_requested || g_signal_received) {
result = -3; // Signal/emergency shutdown
if (ctx->verbose_enabled) { if (ctx->verbose_enabled) {
fprintf(stderr, "Emergency shutdown completed\n"); fprintf(stderr, "Emergency shutdown completed\n");
} }
exit(1);
} else { } else {
result = -2; // Error
if (ctx->verbose_enabled) { if (ctx->verbose_enabled) {
fprintf(stderr, "Mining failed with error\n"); fprintf(stderr, "Mining failed with error\n");
} }
exit(1);
} }
// Now terminate other threads quickly - use pthread_cancel for immediate termination // This code should never be reached due to exit() calls above
if (ctx->verbose_enabled) { return -1;
fprintf(stderr, "Terminating remaining threads...\n");
}
// First try graceful shutdown
for (int i = 0; i < ctx->thread_count; i++) {
worker_contexts[i].should_stop = 1;
}
// Wait briefly for graceful shutdown, then force cancellation
struct timespec timeout_spec = {0, 50000000}; // 50ms timeout
for (int i = 0; i < ctx->thread_count; i++) {
void* exit_status;
// Try timed join for graceful exit
int join_result = pthread_timedjoin_np(threads[i], &exit_status, &timeout_spec);
if (join_result == ETIMEDOUT) {
// Thread didn't exit gracefully, cancel it
if (ctx->verbose_enabled) {
fprintf(stderr, "Force-canceling Thread %d\n", i);
}
pthread_cancel(threads[i]);
pthread_join(threads[i], &exit_status); // Wait for cancellation to complete
log_thread_exit(i, exit_status, "Force-canceled", ctx->verbose_enabled);
} else if (join_result == 0) {
// Thread exited gracefully
long status_code = (long)exit_status;
if (status_code == THREAD_EXIT_ERROR) {
log_thread_exit(i, exit_status, "Thread error (not previously logged)", ctx->verbose_enabled);
}
}
}
// Clear global debugging variables
g_thread_handles = NULL;
g_thread_count = 0;
g_worker_contexts = NULL;
// Cleanup
free(threads);
free(worker_contexts);
pthread_mutex_destroy(&main_ctx.result_mutex);
return result;
} }
// Cleanup context // Cleanup context