Optimized thread cancellation - removed should_stop polling for maximum mining performance
This commit is contained in:
27
debug.log
27
debug.log
@@ -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
|
||||
BIN
event_miner
BIN
event_miner
Binary file not shown.
100
event_miner.c
100
event_miner.c
@@ -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 {
|
||||
cJSON* event;
|
||||
unsigned char private_key[32];
|
||||
@@ -68,9 +68,6 @@ struct mining_context {
|
||||
solution_callback_t solution_callback;
|
||||
void* user_data;
|
||||
|
||||
// Control flag (only main thread modifies)
|
||||
volatile int should_stop;
|
||||
|
||||
// Verbose mode and progress tracking
|
||||
int verbose_enabled;
|
||||
int best_leading_zeros;
|
||||
@@ -298,13 +295,7 @@ static void emergency_shutdown(void) {
|
||||
// Set global shutdown flag
|
||||
g_shutdown_requested = 1;
|
||||
|
||||
// Signal all worker threads to stop if contexts are available
|
||||
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;
|
||||
}
|
||||
}
|
||||
// No need to signal individual threads - they check g_shutdown_requested
|
||||
}
|
||||
|
||||
static void signal_handler(int sig) {
|
||||
@@ -438,8 +429,8 @@ static void* miner_thread(void* arg) {
|
||||
|
||||
uint64_t attempts = 0;
|
||||
|
||||
// Mine until solution found or signaled to stop by main thread
|
||||
while (!ctx->should_stop && !g_shutdown_requested) {
|
||||
// Mine until solution found or emergency shutdown
|
||||
while (!g_shutdown_requested) {
|
||||
// Attempt mining with verbose callback if enabled
|
||||
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
|
||||
}
|
||||
|
||||
// Check for emergency shutdown
|
||||
// Check for emergency shutdown (signals only)
|
||||
if (g_shutdown_requested) {
|
||||
exit_status = (void*)(intptr_t)THREAD_EXIT_STOPPED;
|
||||
log_thread_exit(ctx->thread_id, exit_status, "Emergency shutdown", ctx->verbose_enabled);
|
||||
break;
|
||||
}
|
||||
|
||||
// Small delay to prevent CPU overuse and allow responsive stopping
|
||||
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);
|
||||
// No delay - run at maximum speed for optimal mining performance
|
||||
}
|
||||
|
||||
cJSON_Delete(local_event);
|
||||
@@ -501,7 +485,6 @@ static int mine_event(mining_context_t* ctx) {
|
||||
// Set up callback system
|
||||
ctx->solution_callback = solution_found_callback;
|
||||
ctx->user_data = &main_ctx;
|
||||
ctx->should_stop = 0;
|
||||
|
||||
// Create individual worker contexts (each gets its own thread_id)
|
||||
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++) {
|
||||
if (pthread_create(&threads[i], NULL, miner_thread, &worker_contexts[i]) != 0) {
|
||||
fprintf(stderr, "Error: Failed to create thread %d\n", i);
|
||||
// Stop already running threads
|
||||
for (int j = 0; j < ctx->thread_count; j++) {
|
||||
worker_contexts[j].should_stop = 1;
|
||||
}
|
||||
// Set global shutdown to stop any running threads
|
||||
g_shutdown_requested = 1;
|
||||
// Wait for threads that were created
|
||||
for (int j = 0; j < i; j++) {
|
||||
void* exit_status;
|
||||
@@ -589,89 +570,44 @@ static int mine_event(mining_context_t* ctx) {
|
||||
|
||||
// Handle results - OUTPUT IMMEDIATELY when solution is found
|
||||
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) {
|
||||
fprintf(stderr, "Solution found successfully by Thread %d\n", main_ctx.solution_thread_id);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
printf("%s\n", output_json);
|
||||
fflush(stdout); // Ensure immediate output
|
||||
free(output_json);
|
||||
}
|
||||
|
||||
// Solution found - exit immediately, let OS clean up all threads and resources
|
||||
exit(0);
|
||||
|
||||
} else if (main_ctx.timeout_reached) {
|
||||
result = -1; // Timeout
|
||||
if (ctx->verbose_enabled) {
|
||||
fprintf(stderr, "Mining timed out\n");
|
||||
}
|
||||
// Output timeout message
|
||||
// Output timeout message and exit
|
||||
printf("timeout\n");
|
||||
fflush(stdout);
|
||||
exit(1);
|
||||
|
||||
} else if (g_shutdown_requested || g_signal_received) {
|
||||
result = -3; // Signal/emergency shutdown
|
||||
if (ctx->verbose_enabled) {
|
||||
fprintf(stderr, "Emergency shutdown completed\n");
|
||||
}
|
||||
exit(1);
|
||||
} else {
|
||||
result = -2; // Error
|
||||
if (ctx->verbose_enabled) {
|
||||
fprintf(stderr, "Mining failed with error\n");
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Now terminate other threads quickly - use pthread_cancel for immediate termination
|
||||
if (ctx->verbose_enabled) {
|
||||
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;
|
||||
// This code should never be reached due to exit() calls above
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Cleanup context
|
||||
|
||||
Reference in New Issue
Block a user