int ipc_cld_profile_send (void) { IDTYPE dest; struct shim_ipc_port * port = get_parent_port(&dest); if (!port) return -ESRCH; unsigned long time = GET_PROFILE_INTERVAL(); int nsending = 0; for (int i = 0 ; i < N_PROFILE ; i++) switch (PROFILES[i].type) { case OCCURENCE: if (atomic_read(&PROFILES[i].val.occurence.count)) nsending++; break; case INTERVAL: if (atomic_read(&PROFILES[i].val.interval.count)) nsending++; break; case CATAGORY: break; } struct shim_ipc_msg * msg = create_ipc_msg_on_stack( IPC_CLD_PROFILE, sizeof(struct shim_ipc_cld_profile) + sizeof(struct profile_val) * nsending, dest); struct shim_ipc_cld_profile * msgin = (struct shim_ipc_cld_profile *) &msg->msg; int nsent = 0; for (int i = 0 ; i < N_PROFILE && nsent < nsending ; i++) switch (PROFILES[i].type) { case OCCURENCE: { unsigned long count = atomic_read(&PROFILES[i].val.occurence.count); if (count) { msgin->profile[nsent].idx = i + 1; msgin->profile[nsent].val.occurence.count = count; debug("send %s: %lu times\n", PROFILES[i].name, count); nsent++; } break; } case INTERVAL: { unsigned long count = atomic_read(&PROFILES[i].val.interval.count); if (count) { msgin->profile[nsent].idx = i + 1; msgin->profile[nsent].val.interval.count = count; msgin->profile[nsent].val.interval.time = atomic_read(&PROFILES[i].val.interval.time); debug("send %s: %lu times, %lu msec\n", PROFILES[i].name, count, msgin->profile[nsent].val.interval.time); nsent++; } break; } case CATAGORY: break; } msgin->time = time; msgin->nprofile = nsent; debug("ipc send to %u: IPC_CLD_PROFILE\n", dest); int ret = send_ipc_message(msg, port); put_ipc_port(port); return ret; }
int thread_exit(struct shim_thread * self, bool send_ipc) { /* Chia-Che: Broadcast exit message as early as possible, so other process can start early on responding. */ if (self->in_vm && send_ipc) ipc_cld_exit_send(self->ppid, self->tid, self->exit_code, self->term_signal); lock(&self->lock); if (!self->is_alive) { debug("thread %d is dead\n", self->tid); out: unlock(&self->lock); return 0; } #ifdef PROFILE self->exit_time = GET_PROFILE_INTERVAL(); #endif int exit_code = self->exit_code; self->is_alive = false; if (is_internal(self)) goto out; struct shim_handle_map * handle_map = self->handle_map; struct shim_handle * exec = self->exec; struct shim_thread * parent = self->parent; self->handle_map = NULL; self->exec = NULL; if (parent) { assert(parent != self); assert(parent->child_exit_event); debug("thread exits, notifying thread %d\n", parent->tid); lock(&parent->lock); LISTP_DEL_INIT(self, &parent->children, siblings); LISTP_ADD_TAIL(self, &parent->exited_children, siblings); if (!self->in_vm) { debug("deliver SIGCHLD (thread = %d, exitval = %d)\n", self->tid, exit_code); siginfo_t info; memset(&info, 0, sizeof(siginfo_t)); info.si_signo = SIGCHLD; info.si_pid = self->tid; info.si_uid = self->uid; info.si_status = (exit_code & 0xff) << 8; append_signal(parent, SIGCHLD, &info, true); } unlock(&parent->lock); DkEventSet(parent->child_exit_event); } else { debug("parent not here, need to tell another process\n"); ipc_cld_exit_send(self->ppid, self->tid, self->exit_code, self->term_signal); } struct robust_list_head * robust_list = (void *) self->robust_list; self->robust_list = NULL; unlock(&self->lock); if (handle_map) put_handle_map(handle_map); if (exec) put_handle(exec); if (robust_list) release_robust_list(robust_list); if (self->clear_child_tid) release_clear_child_id (self->clear_child_tid); DkEventSet(self->exit_event); return 0; }