void random_thread_deallocate( void ) { if( !get_thread_state() ) return; mutex_lock( _random_mutex ); array_push( _random_available_state, get_thread_state() ); mutex_unlock( _random_mutex ); set_thread_state( 0 ); }
static inline void trace_state_change_with_func (const char *transition, MonoThreadInfo *info, int cur_raw_state, int next_state, int suspend_count_delta, const char *func) { check_thread_state (info); THREADS_STATE_MACHINE_DEBUG ("[%s][%p] %s -> %s (%d -> %d) %s\n", transition, mono_thread_info_get_tid (info), state_name (get_thread_state (cur_raw_state)), state_name (next_state), get_thread_suspend_count (cur_raw_state), get_thread_suspend_count (cur_raw_state) + suspend_count_delta, func); CHECKED_BUILD_THREAD_TRANSITION (transition, info, get_thread_state (cur_raw_state), get_thread_suspend_count (cur_raw_state), next_state, suspend_count_delta); }
static PyObject* faulthandler_py_enable(PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"file", "all_threads", NULL}; PyObject *file = NULL; int all_threads = 1; int fd; PyThreadState *tstate; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:enable", kwlist, &file, &all_threads)) return NULL; fd = faulthandler_get_fileno(&file); if (fd < 0) return NULL; tstate = get_thread_state(); if (tstate == NULL) return NULL; Py_XINCREF(file); Py_XSETREF(fatal_error.file, file); fatal_error.fd = fd; fatal_error.all_threads = all_threads; fatal_error.interp = tstate->interp; if (faulthandler_enable() < 0) { return NULL; } Py_RETURN_NONE; }
static PyObject* faulthandler_register_py(PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"signum", "file", "all_threads", "chain", NULL}; int signum; PyObject *file = NULL; int all_threads = 1; int chain = 0; int fd; user_signal_t *user; _Py_sighandler_t previous; PyThreadState *tstate; int err; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|Oii:register", kwlist, &signum, &file, &all_threads, &chain)) return NULL; if (!check_signum(signum)) return NULL; tstate = get_thread_state(); if (tstate == NULL) return NULL; file = faulthandler_get_fileno(file, &fd); if (file == NULL) return NULL; if (user_signals == NULL) { user_signals = PyMem_Malloc(NSIG * sizeof(user_signal_t)); if (user_signals == NULL) return PyErr_NoMemory(); memset(user_signals, 0, NSIG * sizeof(user_signal_t)); } user = &user_signals[signum]; if (!user->enabled) { err = faulthandler_register(signum, chain, &previous); if (err) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } user->previous = previous; } Py_XDECREF(user->file); Py_INCREF(file); user->file = file; user->fd = fd; user->all_threads = all_threads; user->chain = chain; user->interp = tstate->interp; user->enabled = 1; Py_RETURN_NONE; }
static PyObject* faulthandler_dump_traceback_later(PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"timeout", "repeat", "file", "exit", NULL}; int timeout; PyOS_sighandler_t previous; int repeat = 0; PyObject *file = NULL; int exit = 0; PyThreadState *tstate; int fd; char *header; size_t header_len; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iOi:dump_traceback_later", kwlist, &timeout, &repeat, &file, &exit)) return NULL; if (timeout <= 0) { PyErr_SetString(PyExc_ValueError, "timeout must be greater than 0"); return NULL; } tstate = get_thread_state(); if (tstate == NULL) return NULL; fd = faulthandler_get_fileno(&file); if (fd < 0) return NULL; /* format the timeout */ header = format_timeout(timeout); if (header == NULL) return PyErr_NoMemory(); header_len = strlen(header); previous = signal(SIGALRM, faulthandler_alarm); if (previous == SIG_ERR) { PyErr_SetString(PyExc_RuntimeError, "unable to set SIGALRM handler"); free(header); return NULL; } Py_XDECREF(fault_alarm.file); Py_XINCREF(file); fault_alarm.file = file; fault_alarm.fd = fd; fault_alarm.timeout = timeout; fault_alarm.repeat = repeat; fault_alarm.interp = tstate->interp; fault_alarm.exit = exit; fault_alarm.header = header; fault_alarm.header_len = header_len; alarm(timeout); Py_RETURN_NONE; }
/** * set thread_state * @brief Set the thread state * * Set the given thread to the desired state. This just writes "1" or "0" * to /sys/devices/system/cpu/cpu[id]/online. * * @param thread * @param state * @returns 0 on success, !0 otherwise */ int set_thread_state(struct thread *thread, int state) { char path[DR_PATH_MAX]; FILE *file; int rc = 0; say(DEBUG, "%slining thread id %d\n", ((state == ONLINE) ? "On" : "Off"), thread->id); sprintf(path, DR_THREAD_ONLINE_PATH, thread->id); file = fopen(path, "w"); if (file == NULL) { say(ERROR, "Could not open %s, unable to set thread state " "to %d\n", path); return -1; } fprintf(file, "%d", state); fclose(file); /* fprintf apparently does not return negative number * if the write() gets an -EBUSY, so explicitly check the * thread state. */ if (state != get_thread_state(thread)) { say(ERROR, "Failure setting thread state for %s\n", path); rc = -1; } return rc; }
/** * online_first_dead_cpu * @brief Find the first cpu with attributes online and physical_id both * set to 0 and online it. * * @param nthreads * @returns 0 on success, !0 otherwise */ int online_first_dead_cpu(int nthreads, struct dr_info *dr_info) { struct thread *thread; int rc = 1; for (thread = dr_info->all_threads; thread; thread = thread->next) { if (OFFLINE == get_thread_state(thread) && ((thread->phys_id == 0xffffffff) || (thread->phys_id == 0))) { /* just assume that there will be nthreads to online. */ while (nthreads--) { set_thread_state(thread, ONLINE); thread = thread->next; } rc = 0; break; } } if (rc) say(ERROR, "Could not find any threads to online\n"); return rc; }
/** * online cpu * * @param cpu * @param dr_info * @returns 0 on success, !0 otherwise */ int online_cpu(struct dr_node *cpu, struct dr_info *dr_info) { int rc = 0; struct thread *thread = NULL; int found = 0; say(DEBUG, "Onlining cpu %s (%d threads)\n", cpu->name, cpu->cpu_nthreads); /* Hack to work around kernel brain damage (LTC 7692) */ for (thread = dr_info->all_threads; thread; thread = thread->next) { if (thread->cpu == cpu) { found = 1; break; } } if (!found) { /* There are no threads which match this cpu because * the physical_id attribute is not updated until the * cpu is onlined -- this case is for cpus which are * not present at boot but are added afterwards. */ return online_first_dead_cpu(cpu->cpu_nthreads, dr_info); } for (thread = cpu->cpu_threads; thread; thread = thread->sibling) { if (get_thread_state(thread) != ONLINE) rc |= set_thread_state(thread, ONLINE); } return rc; }
thread_callback_t XPLCALL thread_callback(void *param) { assert(param); xpl_thread_id tid = *(xpl_thread_id *)param; int state = get_thread_state(tid); while (state != ts_terminate_request) { callback_handle_status(tid, state); state = get_thread_state(tid); } #ifdef XPL_PLATFORM_WINDOWS _endthreadex(0); #endif return 0; }
/** * Return TRUE is the thread is in an usable (suspendable) state */ gboolean mono_thread_info_is_live (MonoThreadInfo *info) { switch (get_thread_state (info->thread_state)) { case STATE_STARTING: case STATE_DETACHED: return FALSE; } return TRUE; }
static inline void trace_state_change (const char *transition, MonoThreadInfo *info, int cur_raw_state, int next_state, int suspend_count_delta) { check_thread_state (info); THREADS_STATE_MACHINE_DEBUG ("[%s][%p] %s -> %s (%d -> %d)\n", transition, mono_thread_info_get_tid (info), state_name (get_thread_state (cur_raw_state)), state_name (next_state), get_thread_suspend_count (cur_raw_state), get_thread_suspend_count (cur_raw_state) + suspend_count_delta); }
/** * Return TRUE is the thread is in a runnable state. */ gboolean mono_thread_info_is_running (MonoThreadInfo *info) { switch (get_thread_state (info->thread_state)) { case STATE_RUNNING: case STATE_ASYNC_SUSPEND_REQUESTED: case STATE_BLOCKING_SUSPEND_REQUESTED: case STATE_BLOCKING: return TRUE; } return FALSE; }
/** * cpu_diable_smt * @brief Disable all but one of a cpu's threads * * @param cpu cpu to disable smt on * @returns 0 on success, !0 otherwise */ int cpu_disable_smt(struct dr_node *cpu) { int rc = 0; struct thread *t; int survivor_found = 0; /* Ensure that the first thread of the processor is the thread that is left online * when disabling SMT. */ t = cpu->cpu_threads; if (get_thread_state(t) == OFFLINE) rc |= set_thread_state(t, ONLINE); for (t = cpu->cpu_threads; t != NULL; t = t->sibling) { if (ONLINE == get_thread_state(t)) { if (survivor_found) rc |= set_thread_state(t, OFFLINE); survivor_found = 1; } } return rc; }
/** * offline_cpu * @brief Mark the specified cpu as offline * * @param cpu * @param dr_info * @returns 0 on success, !0 otherwise */ int offline_cpu(struct dr_node *cpu) { int rc = 0; struct thread *thread; say(DEBUG, "Offlining cpu %s (%d threads)\n", cpu->name, cpu->cpu_nthreads); for (thread = cpu->cpu_threads; thread; thread = thread->sibling) { if (get_thread_state(thread) != OFFLINE) rc |= set_thread_state(thread, OFFLINE); } return rc; }
static const char* state_name (int state) { static const char *state_names [] = { "STARTING", "RUNNING", "DETACHED", "ASYNC_SUSPENDED", "SELF_SUSPENDED", "ASYNC_SUSPEND_REQUESTED", "SELF_SUSPEND_REQUESTED", "STATE_BLOCKING", "STATE_BLOCKING_AND_SUSPENDED", }; return state_names [get_thread_state (state)]; }
static PyObject* faulthandler_dump_traceback_py(PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"file", "all_threads", NULL}; PyObject *file = NULL; int all_threads = 1; PyThreadState *tstate; const char *errmsg; int fd; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:dump_traceback", kwlist, &file, &all_threads)) return NULL; fd = faulthandler_get_fileno(&file); if (fd < 0) return NULL; tstate = get_thread_state(); if (tstate == NULL) return NULL; if (all_threads) { errmsg = _Py_DumpTracebackThreads(fd, NULL, tstate); if (errmsg != NULL) { PyErr_SetString(PyExc_RuntimeError, errmsg); return NULL; } } else { _Py_DumpTraceback(fd, tstate); } if (PyErr_CheckSignals()) return NULL; Py_RETURN_NONE; }
static PyObject* faulthandler_dump_tracebacks_later(PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"timeout", "repeat", "file", "exit", NULL}; double timeout; PY_TIMEOUT_T timeout_us; int repeat = 0; PyObject *file = NULL; int fd; int exit = 0; PyThreadState *tstate; char *header; size_t header_len; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "d|iOi:dump_tracebacks_later", kwlist, &timeout, &repeat, &file, &exit)) return NULL; if ((timeout * 1e6) >= (double) PY_TIMEOUT_MAX) { PyErr_SetString(PyExc_OverflowError, "timeout value is too large"); return NULL; } timeout_us = (PY_TIMEOUT_T)(timeout * 1e6); if (timeout_us <= 0) { PyErr_SetString(PyExc_ValueError, "timeout must be greater than 0"); return NULL; } tstate = get_thread_state(); if (tstate == NULL) return NULL; file = faulthandler_get_fileno(file, &fd); if (file == NULL) return NULL; /* format the timeout */ header = format_timeout(timeout); if (header == NULL) return PyErr_NoMemory(); header_len = strlen(header); /* Cancel previous thread, if running */ cancel_dump_tracebacks_later(); Py_XDECREF(thread.file); Py_INCREF(file); thread.file = file; thread.fd = fd; thread.timeout_us = timeout_us; thread.repeat = repeat; thread.interp = tstate->interp; thread.exit = exit; thread.header = header; thread.header_len = header_len; /* Arm these locks to serve as events when released */ PyThread_acquire_lock(thread.running, 1); if (PyThread_start_new_thread(faulthandler_thread, NULL) == -1) { PyThread_release_lock(thread.running); Py_CLEAR(thread.file); free(header); thread.header = NULL; PyErr_SetString(PyExc_RuntimeError, "unable to start watchdog thread"); return NULL; } Py_RETURN_NONE; }
static PyObject* faulthandler_enable(PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"file", "all_threads", NULL}; PyObject *file = NULL; int all_threads = 1; unsigned int i; fault_handler_t *handler; #ifdef HAVE_SIGACTION struct sigaction action; #endif int err; int fd; PyThreadState *tstate; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:enable", kwlist, &file, &all_threads)) return NULL; file = faulthandler_get_fileno(file, &fd); if (file == NULL) return NULL; tstate = get_thread_state(); if (tstate == NULL) return NULL; Py_XDECREF(fatal_error.file); Py_INCREF(file); fatal_error.file = file; fatal_error.fd = fd; fatal_error.all_threads = all_threads; fatal_error.interp = tstate->interp; if (!fatal_error.enabled) { fatal_error.enabled = 1; for (i=0; i < faulthandler_nsignals; i++) { handler = &faulthandler_handlers[i]; #ifdef HAVE_SIGACTION action.sa_handler = faulthandler_fatal_error; sigemptyset(&action.sa_mask); /* Do not prevent the signal from being received from within its own signal handler */ action.sa_flags = SA_NODEFER; #ifdef HAVE_SIGALTSTACK if (stack.ss_sp != NULL) { /* Call the signal handler on an alternate signal stack provided by sigaltstack() */ action.sa_flags |= SA_ONSTACK; } #endif err = sigaction(handler->signum, &action, &handler->previous); #else handler->previous = signal(handler->signum, faulthandler_fatal_error); err = (handler->previous == SIG_ERR); #endif if (err) { PyErr_SetFromErrno(PyExc_RuntimeError); return NULL; } handler->enabled = 1; } } Py_RETURN_NONE; }
int main(int argc, char **argv) { /* Slave threads */ sgcomm_thread *st_rd; // Reader sgcomm_thread *st_tx; // Transmitter shared_buffer *sbtx; // shared buffer for read+transmit /* Reader message parameters */ char *fmtstr = "/mnt/disks/%u/%u/data/%s"; char *pattern_read = "input.vdif"; char *host = "localhost"; uint16_t port = 61234; int n_mod = 4; int mod_list[4] = { 1, 2, 3, 4}; int n_disk = 8; int disk_list_read[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; int disk_list_write[8] = { 1, 0, 2, 3, 4, 5, 6, 7 }; /* Transmitter message parameters */ if (argc > 1) pattern_read = argv[1]; if (argc > 2) fmtstr = argv[2]; if (argc > 3) host = argv[3]; if (argc > 4) port = atoi(argv[4]); log_message(RL_NOTICE,"%s:Using input file '%s' matching pattern '%s'",__FUNCTION__,pattern_read,fmtstr); log_message(RL_NOTICE,"%s:Transmitting to %s:%u",__FUNCTION__,host,port); /* This thread */ sgcomm_thread *st = &st_main; ctrl_state state; log_message(RL_DEBUG,"%s:Creating shared buffer",__FUNCTION__); /* Initialize shared data buffer */ sbtx = create_shared_buffer(SHARED_BUFFER_SIZE_TX); if (sbtx == NULL) set_thread_state(st,CS_ERROR,"%s(%d):Cannot create shared buffer for read+transmit",__FUNCTION__,__LINE__); log_message(RL_DEBUG,"%s:Creating slave threads",__FUNCTION__); /* Create thread instances */ st_rd = create_thread(TT_READER); if (st_rd == NULL) set_thread_state(st,CS_ERROR,"%s(%d):Cannot create reader thread",__FUNCTION__,__LINE__); st_tx = create_thread(TT_TRANSMITTER); if (st_tx == NULL) set_thread_state(st,CS_ERROR,"%s(%d):Cannot create transmitter thread",__FUNCTION__,__LINE__); log_message(RL_DEBUG,"%s:Initializing thread messages",__FUNCTION__); /* Initialize thread messages */ init_reader_msg((reader_msg *)st_rd->type_msg, sbtx, pattern_read, fmtstr, mod_list, n_mod, disk_list_read, n_disk); init_transmitter_msg((transmitter_msg *)st_tx->type_msg, sbtx, host, port); /* Start transmitter thread */ if (start_thread(st_tx) != 0) set_thread_state(st,CS_ERROR,"%s(%d):Cannot start transmitter thread",__FUNCTION__,__LINE__); /* Pause, then see if transmitter has error, if so, abort */ usleep(MAIN_WAIT_PERIOD_US); if ((get_thread_state(st_tx,&state) == 0) && (state >= CS_STOP)) { set_thread_state(st,CS_ERROR,"%s(%d):Transmitter terminated prematurely, aborting start.",__FUNCTION__,__LINE__); } else { if (start_thread(st_rd) != 0) set_thread_state(st,CS_ERROR,"%s(%d):Cannot start reader thread",__FUNCTION__,__LINE__); } //~ log_message(RL_DEBUG,"%s:Entering main thread run loop",__FUNCTION__); if ((get_thread_state(st,&state) == 0) && !(state >= CS_STOP)) set_thread_state(st,CS_RUN,"%s:Thread running",__FUNCTION__); while ((get_thread_state(st,&state) == 0) && !(state >= CS_STOP)) { // TODO: do something usleep(MAIN_WAIT_PERIOD_US); /* If any thread has a problem, stop all of them */ if ( ((get_thread_state(st_rd,&state) == 0) && (state >= CS_ERROR)) || ((get_thread_state(st_tx,&state) == 0) && (state >= CS_ERROR)) ) { // TODO: Some cleanup? break; } /* If all threads are stopped, break */ if ( ((get_thread_state(st_rd,&state) == 0) && (state >= CS_STOP)) && ((get_thread_state(st_tx,&state) == 0) && (state >= CS_STOP)) ) { log_message(RL_NOTICE,"%s:All threads stopped of their own volition",__FUNCTION__); break; } /* If reader thread is done, stop transmitter */ if ( (get_thread_state(st_rd,&state) == 0) && (state >= CS_STOP) && (get_thread_state(st_tx,&state) == 0) && (state < CS_STOP)) { log_message(RL_NOTICE,"%s:Reader is done, stop transmitter",__FUNCTION__); /* Two wait periods should be enough - reader is the only * other thread that can cause transmitter to wait on a * resource, and then it will only be a single wait. */ usleep(MAIN_WAIT_PERIOD_US); usleep(MAIN_WAIT_PERIOD_US); if (stop_thread(st_tx) != 0) set_thread_state(st,CS_ERROR,"%s(%d):Cannot stop transmitter thread",__FUNCTION__,__LINE__); } } log_message(RL_DEBUG,"%s:Stopping slave threads",__FUNCTION__); /* Stop slave threads on tx side */ if ( (get_thread_state(st_rd,&state) == 0) && (state < CS_STOP) && (state > CS_INIT) && stop_thread(st_rd) != 0) set_thread_state(st,CS_ERROR,"%s(%d):Cannot stop reader thread",__FUNCTION__,__LINE__); log_message(RL_DEBUGVVV,"%s:Reader thread stopped",__FUNCTION__); if ( (get_thread_state(st_tx,&state) == 0) && (state < CS_STOP) && (state > CS_INIT) && stop_thread(st_tx) != 0) set_thread_state(st,CS_ERROR,"%s(%d):Cannot stop transmitter thread",__FUNCTION__,__LINE__); log_message(RL_DEBUGVVV,"%s:Transmitter thread stopped",__FUNCTION__); log_message(RL_DEBUG,"%s:Destroying shared buffer",__FUNCTION__); /* Destroy shared data buffer */ if (destroy_shared_buffer(&sbtx) != 0) set_thread_state(st,CS_ERROR,"%s(%d):Cannot destroy shared buffer for read+transmit",__FUNCTION__,__LINE__); log_message(RL_DEBUG,"%s:Destroying slave threads",__FUNCTION__); /* Destroy threads */ destroy_thread(&st_rd); destroy_thread(&st_tx); log_message(RL_DEBUG,"%s:Everything is done, goodbye",__FUNCTION__); /* That's all folks! */ // TODO: Report that we're done return EXIT_SUCCESS; }
int mono_thread_info_current_state (MonoThreadInfo *info) { return get_thread_state (info->thread_state); }