void direct_trap( const char *domain, int sig ) { sigval_t val; if (direct_config->delay_trap_ms) { D_LOG( Direct_Trap, VERBOSE, "NOT RAISING signal %d from %s, waiting for %dms... attach gdb --pid=%d\n", sig, domain, direct_config->delay_trap_ms, getpid() ); direct_thread_sleep( direct_config->delay_trap_ms * 1000LL ); return; } D_LOG( Direct_Trap, VERBOSE, "Raising signal %d from %s...\n", sig, domain ); val.sival_int = direct_gettid(); #ifndef DIRECT_BUILD_NO_SIGQUEUE sigqueue( direct_gettid(), sig, val ); #endif // direct_tgkill( direct_getpid(), direct_gettid(), sig ); D_LOG( Direct_Trap, VERBOSE, "...tgkill(%d) on ourself returned, maybe blocked, calling abort()!\n", sig ); abort(); D_LOG( Direct_Trap, VERBOSE, "...abort() returned as well, calling %s()!\n", #ifdef __NR_exit_group "exit_group" ); syscall( __NR_exit_group, DR_BUG ); #else "_exit" ); _exit( DR_BUG ); #endif }
DirectResult fusion_property_purchase (FusionProperty *property) { int count = 0; D_ASSERT( property != NULL ); if (property->multi.builtin.destroyed) return DR_DESTROYED; D_ASSUME( property->multi.builtin.owner != direct_gettid() ); asm( "" ::: "memory" ); while (property->multi.builtin.state == FUSION_PROPERTY_LEASED) { /* Check whether owner exited without releasing. */ if (kill( property->multi.builtin.owner, 0 ) < 0 && errno == ESRCH) { property->multi.builtin.state = FUSION_PROPERTY_AVAILABLE; property->multi.builtin.requested = false; break; } property->multi.builtin.requested = true; asm( "" ::: "memory" ); if (++count > 1000) { usleep( 10000 ); count = 0; } else { direct_sched_yield(); } if (property->multi.builtin.destroyed) return DR_DESTROYED; } if (property->multi.builtin.state == FUSION_PROPERTY_PURCHASED) { /* Check whether owner exited without releasing. */ if (!(kill( property->multi.builtin.owner, 0 ) < 0 && errno == ESRCH)) return DR_BUSY; } property->multi.builtin.state = FUSION_PROPERTY_PURCHASED; property->multi.builtin.owner = direct_gettid(); asm( "" ::: "memory" ); return DR_OK; }
void direct_thread_set_name( const char *name ) { char *copy; DirectThread *thread = pthread_getspecific( thread_key ); D_DEBUG_AT( Direct_Thread, "%s( '%s' )\n", __FUNCTION__, name ); /* Support this function for non-direct threads. */ if (!thread) { D_DEBUG_AT( Direct_Thread, " -> attaching unknown thread %d\n", direct_gettid() ); /* Create the key for the TSD (thread specific data). */ pthread_mutex_lock( &key_lock ); if (thread_key == -1) pthread_key_create( &thread_key, NULL ); pthread_mutex_unlock( &key_lock ); thread = D_CALLOC( 1, sizeof(DirectThread) ); if (!thread) { D_OOM(); return; } thread->thread = pthread_self(); thread->tid = direct_gettid(); D_MAGIC_SET( thread, DirectThread ); pthread_setspecific( thread_key, thread ); } else D_DEBUG_AT( Direct_Thread, " -> was '%s' (%d)\n", thread->name, direct_gettid() ); /* Duplicate string. */ copy = D_STRDUP( name ); if (!copy) { D_OOM(); return; } /* Free old string. */ if (thread->name) D_FREE( thread->name ); /* Keep the copy. */ thread->name = copy; }
DirectResult fusion_ref_zero_lock (FusionRef *ref) { DirectResult ret = DR_OK; D_ASSERT( ref != NULL ); direct_mutex_lock (&ref->single.lock); do { if (ref->single.destroyed) ret = DR_DESTROYED; else if (ref->single.locked) ret = DR_LOCKED; else if (ref->single.refs) direct_waitqueue_wait (&ref->single.cond, &ref->single.lock); else { ref->single.locked = direct_gettid(); break; } } while (ret == DR_OK); direct_mutex_unlock (&ref->single.lock); return ret; }
DirectThread * direct_thread_self( void ) { DirectThread *thread; direct_once( &thread_init_once, init_once ); thread = pthread_getspecific( thread_key ); // D_MAGIC_ASSERT_IF( thread, DirectThread ); /* Support this function for non-direct threads. */ if (!thread) { // D_DEBUG_AT( Direct_Thread, " -> attaching unknown thread %d\n", direct_gettid() ); thread = direct_calloc( 1, sizeof(DirectThread) ); if (!thread) { D_OOM(); return NULL; } thread->handle.thread = pthread_self(); thread->tid = direct_gettid(); D_MAGIC_SET( thread, DirectThread ); pthread_setspecific( thread_key, thread ); } return thread; }
void direct_thread_set_name( const char *name ) { char *copy; DirectThread *thread; D_DEBUG_AT( Direct_Thread, "%s( '%s' )\n", __FUNCTION__, name ); direct_once( &thread_init_once, init_once ); thread = pthread_getspecific( thread_key ); /* Support this function for non-direct threads. */ if (!thread) { D_DEBUG_AT( Direct_Thread, " -> attaching unknown thread %d\n", direct_gettid() ); thread = D_CALLOC( 1, sizeof(DirectThread) ); if (!thread) { D_OOM(); return; } thread->handle.thread = pthread_self(); thread->tid = direct_gettid(); D_MAGIC_SET( thread, DirectThread ); pthread_setspecific( thread_key, thread ); } else D_DEBUG_AT( Direct_Thread, " -> was '%s' (%d)\n", thread->name, direct_gettid() ); /* Duplicate string. */ copy = D_STRDUP( name ); if (!copy) { D_OOM(); return; } /* Free old string. */ if (thread->name) D_FREE( thread->name ); /* Keep the copy. */ thread->name = copy; }
void one_debug_printk( const char *format, ... ) { char buf[512]; unsigned long micros = direct_clock_get_micros(); const char *name = "NO NAME"; va_list ap; va_start( ap, format ); vsnprintf( buf, sizeof(buf), format, ap ); va_end( ap ); printk( KERN_DEBUG "(-) [%-16.16s %03lu] (%5d) %s: %*s%s", name, micros, direct_gettid(), "One", /*indent*/ 0, "", buf ); }
DirectResult fusion_ref_unlock (FusionRef *ref) { DirectResult ret = DR_OK; D_ASSERT( ref != NULL ); direct_mutex_lock (&ref->single.lock); if (ref->single.locked == direct_gettid()) { ref->single.locked = 0; direct_waitqueue_broadcast (&ref->single.cond); } else ret = DR_ACCESSDENIED; direct_mutex_unlock (&ref->single.lock); return ret; }
DirectResult fusion_property_cede (FusionProperty *property) { D_ASSERT( property != NULL ); if (property->multi.builtin.destroyed) return DR_DESTROYED; D_ASSUME( property->multi.builtin.state != FUSION_PROPERTY_AVAILABLE ); D_ASSUME( property->multi.builtin.owner == direct_gettid() ); property->multi.builtin.state = FUSION_PROPERTY_AVAILABLE; property->multi.builtin.owner = 0; asm( "" ::: "memory" ); if (property->multi.builtin.requested) { property->multi.builtin.requested = false; asm( "" ::: "memory" ); direct_sched_yield(); }
DirectResult fusion_ref_zero_trylock (FusionRef *ref) { DirectResult ret = DR_OK; D_ASSERT( ref != NULL ); direct_mutex_lock (&ref->single.lock); if (ref->single.destroyed) ret = DR_DESTROYED; else if (ref->single.locked) ret = DR_LOCKED; else if (ref->single.refs) ret = DR_BUSY; else ref->single.locked = direct_gettid(); direct_mutex_unlock (&ref->single.lock); return ret; }
DirectResult fusion_skirmish_prevail( FusionSkirmish *skirmish ) { D_ASSERT( skirmish != NULL ); if (skirmish->multi.builtin.destroyed) return DR_DESTROYED; asm( "" ::: "memory" ); if (skirmish->multi.builtin.locked && skirmish->multi.builtin.owner != direct_gettid()) { int count = 0; while (skirmish->multi.builtin.locked) { /* Check whether owner exited without unlocking. */ if (kill( skirmish->multi.builtin.owner, 0 ) < 0 && errno == ESRCH) { skirmish->multi.builtin.locked = 0; skirmish->multi.builtin.requested = false; break; } skirmish->multi.builtin.requested = true; asm( "" ::: "memory" ); if (++count > 1000) { usleep( 10000 ); count = 0; } else { direct_sched_yield(); } if (skirmish->multi.builtin.destroyed) return DR_DESTROYED; } }
static void * direct_thread_main( void *arg ) { void *ret; DirectThread *thread = arg; prctl( PR_SET_NAME, thread->name, 0, 0, 0 ); pthread_setspecific( thread_key, thread ); D_DEBUG_AT( Direct_ThreadInit, "%s( %p )\n", __FUNCTION__, arg ); D_DEBUG_AT( Direct_ThreadInit, " -> starting...\n" ); D_MAGIC_ASSERT( thread, DirectThread ); pthread_cleanup_push( direct_thread_cleanup, thread ); thread->tid = direct_gettid(); D_DEBUG_AT( Direct_ThreadInit, " -> tid %d\n", thread->tid ); __D_direct_thread_call_init_handlers( thread ); /* Have all signals handled by the main thread. */ if (direct_config->thread_block_signals) direct_signals_block_all(); /* Lock the thread mutex. */ D_DEBUG_AT( Direct_ThreadInit, " -> locking...\n" ); direct_mutex_lock( &thread->lock ); /* Indicate that our initialization has completed. */ D_ASSERT( !thread->init ); thread->init = true; D_DEBUG_AT( Direct_ThreadInit, " -> signalling...\n" ); direct_waitqueue_signal( &thread->cond ); /* Unlock the thread mutex. */ D_DEBUG_AT( Direct_ThreadInit, " -> unlocking...\n" ); direct_mutex_unlock( &thread->lock ); if (thread->joining) { D_DEBUG_AT( Direct_Thread, " -> Being joined before entering main routine!\n" ); return NULL; } D_MAGIC_ASSERT( thread, DirectThread ); /* Call main routine. */ D_DEBUG_AT( Direct_ThreadInit, " -> running...\n" ); ret = thread->main( thread, thread->arg ); D_DEBUG_AT( Direct_Thread, " -> Returning %p from '%s' (%s, %d)...\n", ret, thread->name, direct_thread_type_name(thread->type), thread->tid ); D_MAGIC_ASSERT( thread, DirectThread ); pthread_cleanup_pop( 1 ); return ret; }
static void * direct_thread_main( void *arg ) { void *ret; DirectThread *thread = arg; DirectThreadInitHandler *handler; pid_t tid; tid = direct_gettid(); D_DEBUG_AT( Direct_ThreadInit, "%s( %p ) <- tid %d\n", __FUNCTION__, arg, tid ); D_DEBUG_AT( Direct_ThreadInit, " -> starting...\n" ); D_MAGIC_ASSERT( thread, DirectThread ); pthread_cleanup_push( direct_thread_cleanup, thread ); pthread_setspecific( thread_key, thread ); thread->tid = tid; /* Call all init handlers. */ pthread_mutex_lock( &handler_lock ); direct_list_foreach (handler, handlers) handler->func( thread, handler->arg ); pthread_mutex_unlock( &handler_lock ); /* Have all signals handled by the main thread. */ if (direct_config->thread_block_signals) direct_signals_block_all(); /* Lock the thread mutex. */ D_DEBUG_AT( Direct_ThreadInit, " -> locking...\n" ); pthread_mutex_lock( &thread->lock ); /* Indicate that our initialization has completed. */ thread->init = true; #ifdef DIRECT_THREAD_WAIT_INIT D_DEBUG_AT( Direct_ThreadInit, " -> signalling...\n" ); pthread_cond_signal( &thread->cond ); #endif /* Unlock the thread mutex. */ D_DEBUG_AT( Direct_ThreadInit, " -> unlocking...\n" ); pthread_mutex_unlock( &thread->lock ); if (thread->joining) { D_DEBUG_AT( Direct_Thread, " -> Being joined before entering main routine!\n" ); return NULL; } D_MAGIC_ASSERT( thread, DirectThread ); /* Call main routine. */ D_DEBUG_AT( Direct_ThreadInit, " -> running...\n" ); ret = thread->main( thread, thread->arg ); D_DEBUG_AT( Direct_Thread, " -> Returning %p from '%s' (%s, %d)...\n", ret, thread->name, direct_thread_type_name(thread->type), thread->tid ); D_MAGIC_ASSERT( thread, DirectThread ); pthread_cleanup_pop( 1 ); return ret; }
if (++count > 1000) { usleep( 10000 ); count = 0; } else { direct_sched_yield(); } if (skirmish->multi.builtin.destroyed) return DR_DESTROYED; } } skirmish->multi.builtin.locked++; skirmish->multi.builtin.owner = direct_gettid(); asm( "" ::: "memory" ); return DR_OK; } DirectResult fusion_skirmish_swoop( FusionSkirmish *skirmish ) { D_ASSERT( skirmish != NULL ); if (skirmish->multi.builtin.destroyed) return DR_DESTROYED; asm( "" ::: "memory" );