Пример #1
0
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;
}
Пример #2
0
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;
}