int s_qmidms_meid_resp(void *buf, u16 size, char *meid, int meidsize) { int result; u8 offset = sizeof(struct qmux) + 3; if (!buf || size < offset || meidsize < 14) return -ENOMEM; buf = buf + offset; size -= offset; result = s_qmi_msgid(buf, size); if (result != 0x25) return -EFAULT; result = s_qmi_msgisvalid(buf, size); if (result) return -EFAULT; result = tlv_get(buf, size, 0x12, meid, 14); if (result != 14) return -EFAULT; return 0; }
int qmiwds_event_resp(void *buf, u16 size, struct qmiwds_stats *stats) { int result; u8 status[2]; u8 offset = sizeof(struct qmux) + 3; if (!buf || size < offset || !stats) return -ENOMEM; buf = buf + offset; size -= offset; result = qmi_msgid(buf, size); if (result == 0x22) { result = tlv_get(buf, size, 0x01, &status[0], 2); if (result >= 1) stats->linkstate = status[0] == 0x02; if (result == 2) stats->reconfigure = status[1] == 0x01; if (result < 0) return result; } else { return -EFAULT; } return 0; }
static void control_destroy(struct sml_control *control) { assert(tlv_get(current_control) == control); #ifndef WITHOUT_MULTITHREAD /* To release the thread local heap exclusively, it must be * occupied by the current thread. */ assert(IS_ACTIVE(load_relaxed(&control->state))); #endif /* !WITHOUT_MULTITHREAD */ if (control->thread_local_heap) { sml_heap_mutator_destroy(control->thread_local_heap); control->thread_local_heap = NULL; } /* Pointers in the stack is safely ignored since the thread has * been terminated. */ control->frame_stack = NULL; control_leave(control); control_unregister(control); tlv_set(current_control, NULL); mutex_destroy(&control->inactive_wait_lock); cond_destroy(&control->inactive_wait_cond); free(control); }
int s_qmictl_alloccid_resp(void *buf, u16 size, u16 *cid) { int result; u8 offset = sizeof(struct qmux) + 2; if (!buf || size < offset) return -ENOMEM; buf = buf + offset; size -= offset; result = s_qmi_msgid(buf, size); if (result != 0x22) return -EFAULT; result = s_qmi_msgisvalid(buf, size); if (result != 0) return -EFAULT; result = tlv_get(buf, size, 0x01, cid, 2); if (result != 2) return -EFAULT; return 0; }
void sml_enter_internal(void *old_frame_top) { struct sml_control *control = tlv_get(current_control); control_enter(control); control->frame_stack->top = old_frame_top; }
void * sml_save_exn_internal(void *obj) { struct sml_control *control = tlv_get(current_control); void *old = control->exn_object; control->exn_object = obj; return old; }
SML_PRIMITIVE void sml_enter() { struct sml_control *control = tlv_get(current_control); control_enter(control); assert(control->frame_stack->top == CALLER_FRAME_END_ADDRESS()); control->frame_stack->top = NULL; }
SML_PRIMITIVE void sml_unsave() { struct sml_control *control = tlv_get(current_control); #ifndef WITHOUT_MULTITHREAD assert(IS_ACTIVE(load_relaxed(&control->state))); #endif /* !WITHOUT_MULTITHREAD */ assert(control->frame_stack->top == CALLER_FRAME_END_ADDRESS()); control->frame_stack->top = NULL; }
enum sml_sync_phase sml_current_phase() { struct sml_control *control = tlv_get(current_control); /* Thanks to memory coherency, control->state always indicates * the current status of this mutator regardless of the fact that * both the mutator and collector updates it. * If control->state is SYNC1, then the thread is in SYNC1. */ return PHASE(load_relaxed(&control->state)); }
int s_qmi_msgisvalid(void *msg, u16 size) { char tlv[4]; if (tlv_get(msg, size, 2, &tlv[0], 4) == 4) { if (*(u16 *)&tlv[0] != 0) return *(u16 *)&tlv[2]; else return 0; } return -ENOMSG; }
void * sml_leave_internal(void *frame_pointer) { struct sml_control *control = tlv_get(current_control); void *old_frame_top; old_frame_top = control->frame_stack->top; if (!old_frame_top) control->frame_stack->top = frame_pointer; control_leave(control); return old_frame_top; }
int s_qmiwds_event_resp(void *buf, u16 size, struct qmiwds_stats *stats) { int result; u8 status[2]; u8 offset = sizeof(struct qmux) + 3; if (!buf || size < offset || !stats) return -ENOMEM; buf = buf + offset; size -= offset; result = s_qmi_msgid(buf, size); if (result == 0x01) { tlv_get(buf, size, 0x10, &stats->txok, 4); tlv_get(buf, size, 0x11, &stats->rxok, 4); tlv_get(buf, size, 0x12, &stats->txerr, 4); tlv_get(buf, size, 0x13, &stats->rxerr, 4); tlv_get(buf, size, 0x14, &stats->txofl, 4); tlv_get(buf, size, 0x15, &stats->rxofl, 4); tlv_get(buf, size, 0x19, &stats->txbytesok, 8); tlv_get(buf, size, 0x1A, &stats->rxbytesok, 8); } else if (result == 0x22) { result = tlv_get(buf, size, 0x01, &status[0], 2); if (result >= 1) stats->linkstate = status[0] == 0x02; if (result == 2) stats->reconfigure = status[1] == 0x01; if (result < 0) return result; } else { return -EFAULT; } return 0; }
SML_PRIMITIVE void sml_end() { struct sml_control *control = tlv_get(current_control); #ifndef WITHOUT_MULTITHREAD assert(IS_ACTIVE(load_relaxed(&control->state))); #endif /* !WITHOUT_MULTITHREAD */ assert(control->frame_stack->bottom == CALLER_FRAME_END_ADDRESS()); control->frame_stack = control->frame_stack->next; if (control->frame_stack) { control_leave(control); } else { control_destroy(control); } }
void sml_check_internal(void *frame_pointer) { struct sml_control *control = tlv_get(current_control); void *old_frame_top; assert(load_relaxed(&control->state) == ACTIVE(ASYNC)); if (load_relaxed(&stop_the_world_flag)) { old_frame_top = control->frame_stack->top; if (!old_frame_top) control->frame_stack->top = frame_pointer; store_release(&control->state, INACTIVE(SYNC1)); mutex_lock(&control->inactive_wait_lock); cond_signal(&control->inactive_wait_cond); mutex_unlock(&control->inactive_wait_lock); control_enter(control); control->frame_stack->top = old_frame_top; } }
/* lock; all updates so far must be acquired */ old = INACTIVE(ASYNC); if (cmpswap_weak_acquire(&control->state, &old, ACTIVE(ASYNC))) return; mutex_lock(&control->inactive_wait_lock); pthread_cleanup_push(cleanup_mutex_unlock, &control->inactive_wait_lock); old = INACTIVE(ASYNC); while (!cmpswap_weak_acquire(&control->state, &old, ACTIVE(ASYNC))) { cond_wait(&control->inactive_wait_cond, &control->inactive_wait_lock); old = INACTIVE(ASYNC); } pthread_cleanup_pop(1); } #else /* !WITHOUT_MULTITHREAD && !WITHOUT_CONCURRENCY */ static void control_enter(struct sml_control *control) { activate(control); } #endif /* !WITHOUT_MULTITHREAD && !WITHOUT_CONCURRENCY */ SML_PRIMITIVE void sml_leave() { struct sml_control *control = tlv_get(current_control); assert(control->frame_stack->top == NULL); control->frame_stack->top = CALLER_FRAME_END_ADDRESS(); control_leave(control); } SML_PRIMITIVE void sml_enter() { struct sml_control *control = tlv_get(current_control); control_enter(control); assert(control->frame_stack->top == CALLER_FRAME_END_ADDRESS()); control->frame_stack->top = NULL; } void * sml_leave_internal(void *frame_pointer) { struct sml_control *control = tlv_get(current_control); void *old_frame_top; old_frame_top = control->frame_stack->top; if (!old_frame_top) control->frame_stack->top = frame_pointer; control_leave(control); return old_frame_top; } void sml_enter_internal(void *old_frame_top) { struct sml_control *control = tlv_get(current_control); control_enter(control); control->frame_stack->top = old_frame_top; } #if defined WITHOUT_MULTITHREAD void sml_check_internal(void *frame_pointer ATTR_UNUSED) { } #elif defined WITHOUT_CONCURRENCY void sml_check_internal(void *frame_pointer) { struct sml_control *control = tlv_get(current_control); void *old_frame_top; assert(load_relaxed(&control->state) == ACTIVE(ASYNC)); if (load_relaxed(&stop_the_world_flag)) { old_frame_top = control->frame_stack->top; if (!old_frame_top) control->frame_stack->top = frame_pointer; store_release(&control->state, INACTIVE(SYNC1)); mutex_lock(&control->inactive_wait_lock); cond_signal(&control->inactive_wait_cond); mutex_unlock(&control->inactive_wait_lock); control_enter(control); control->frame_stack->top = old_frame_top; } } #else /* !WITHOUT_MULTITHREAD && !WITHOUT_CONCURRENCY */ void sml_check_internal(void *frame_pointer) { struct sml_control *control = tlv_get(current_control); unsigned int state = load_relaxed(&control->state); void *old_frame_top; assert(IS_ACTIVE(state)); if (state == ACTIVE(PRESYNC1)) { store_relaxed(&control->state, ACTIVE(SYNC1)); sync1_action(); } else if (state == ACTIVE(PRESYNC2)) { store_relaxed(&control->state, ACTIVE(SYNC2)); old_frame_top = control->frame_stack->top; if (!old_frame_top) control->frame_stack->top = frame_pointer; sync2_action(control); control->frame_stack->top = old_frame_top; } }
/* for debug */ int sml_saved() { struct sml_control *control = tlv_get(current_control); return control->frame_stack->top != NULL; }
SML_PRIMITIVE void sml_check() { assert(tlv_get(current_control)->frame_stack->top == NULL); sml_check_internal(CALLER_FRAME_END_ADDRESS()); }