void vm_signal_pause(struct vm *vm, bool pause) { pthread_mutex_lock(&vm->hv_pause_mtx); // Lock as we are modifying hv_is_paused if (pause) { if (atomic_cmpset_rel_int(&vm->hv_is_paused, FALSE, TRUE) == 0) { // All vcpus should wait after next interrupt fprintf(stderr, "freeze signal received, but we are already frozen\n"); } } else { if (atomic_cmpset_rel_int(&vm->hv_is_paused, TRUE, FALSE) == 0) { fprintf(stderr, "thaw signal received, but we are not frozen\n"); } else { pthread_cond_broadcast(&vm->hv_pause_cnd); // wake paused threads } } pthread_mutex_unlock(&vm->hv_pause_mtx); }
int _pthread_once(pthread_once_t *once_control, void (*init_routine) (void)) { struct pthread *curthread; int state; _thr_check_init(); for (;;) { state = once_control->state; if (state == ONCE_DONE) return (0); if (state == ONCE_NEVER_DONE) { if (atomic_cmpset_acq_int(&once_control->state, state, ONCE_IN_PROGRESS)) break; } else if (state == ONCE_IN_PROGRESS) { if (atomic_cmpset_acq_int(&once_control->state, state, ONCE_WAIT)) _thr_umtx_wait_uint(&once_control->state, ONCE_WAIT, NULL, 0); } else if (state == ONCE_WAIT) { _thr_umtx_wait_uint(&once_control->state, state, NULL, 0); } else return (EINVAL); } curthread = _get_curthread(); THR_CLEANUP_PUSH(curthread, once_cancel_handler, once_control); init_routine(); THR_CLEANUP_POP(curthread, 0); if (atomic_cmpset_rel_int(&once_control->state, ONCE_IN_PROGRESS, ONCE_DONE)) return (0); atomic_store_rel_int(&once_control->state, ONCE_DONE); _thr_umtx_wake(&once_control->state, INT_MAX, 0); return (0); }
static void once_cancel_handler(void *arg) { pthread_once_t *once_control = arg; if (atomic_cmpset_rel_int(&once_control->state, ONCE_IN_PROGRESS, ONCE_NEVER_DONE)) return; atomic_store_rel_int(&once_control->state, ONCE_NEVER_DONE); _thr_umtx_wake(&once_control->state, INT_MAX, 0); }
/* * Append a character to a message buffer. This function can be * considered fully reentrant so long as the number of concurrent * callers is less than the number of characters in the buffer. * However, the message buffer is only guaranteed to be consistent * for reading when there are no callers in this function. */ void msgbuf_addchar(struct msgbuf *mbp, int c) { u_int new_seq, pos, seq; do { seq = mbp->msg_wseq; new_seq = MSGBUF_SEQNORM(mbp, seq + 1); } while (atomic_cmpset_rel_int(&mbp->msg_wseq, seq, new_seq) == 0); pos = MSGBUF_SEQ_TO_POS(mbp, seq); atomic_add_int(&mbp->msg_cksum, (u_int)(u_char)c - (u_int)(u_char)mbp->msg_ptr[pos]); mbp->msg_ptr[pos] = c; }
void ktr_tracepoint(u_int mask, const char *file, int line, const char *format, u_long arg1, u_long arg2, u_long arg3, u_long arg4, u_long arg5, u_long arg6) { struct ktr_entry *entry; #ifdef KTR_ALQ struct ale *ale = NULL; #endif int newindex, saveindex; #if defined(KTR_VERBOSE) || defined(KTR_ALQ) struct thread *td; #endif int cpu; if (panicstr) return; if ((ktr_mask & mask) == 0) return; cpu = KTR_CPU; if (((1 << cpu) & ktr_cpumask) == 0) return; #if defined(KTR_VERBOSE) || defined(KTR_ALQ) td = curthread; if (td->td_pflags & TDP_INKTR) return; td->td_pflags |= TDP_INKTR; #endif #ifdef KTR_ALQ if (ktr_alq_enabled) { if (td->td_critnest == 0 && (td->td_flags & TDF_IDLETD) == 0 && td != ald_thread) { if (ktr_alq_max && ktr_alq_cnt > ktr_alq_max) goto done; if ((ale = alq_get(ktr_alq, ALQ_NOWAIT)) == NULL) { ktr_alq_failed++; goto done; } ktr_alq_cnt++; entry = (struct ktr_entry *)ale->ae_data; } else { goto done; } } else #endif { do { saveindex = ktr_idx; newindex = (saveindex + 1) & (KTR_ENTRIES - 1); } while (atomic_cmpset_rel_int(&ktr_idx, saveindex, newindex) == 0); entry = &ktr_buf[saveindex]; } entry->ktr_timestamp = KTR_TIME; entry->ktr_cpu = cpu; entry->ktr_thread = curthread; if (file != NULL) while (strncmp(file, "../", 3) == 0) file += 3; entry->ktr_file = file; entry->ktr_line = line; #ifdef KTR_VERBOSE if (ktr_verbose) { #ifdef SMP printf("cpu%d ", cpu); #endif if (ktr_verbose > 1) { printf("%s.%d\t", entry->ktr_file, entry->ktr_line); } printf(format, arg1, arg2, arg3, arg4, arg5, arg6); printf("\n"); } #endif entry->ktr_desc = format; entry->ktr_parms[0] = arg1; entry->ktr_parms[1] = arg2; entry->ktr_parms[2] = arg3; entry->ktr_parms[3] = arg4; entry->ktr_parms[4] = arg5; entry->ktr_parms[5] = arg6; #ifdef KTR_ALQ if (ktr_alq_enabled && ale) alq_post(ktr_alq, ale); done: #endif #if defined(KTR_VERBOSE) || defined(KTR_ALQ) td->td_pflags &= ~TDP_INKTR; #endif }