Example #1
0
static int ipc_thread_exit (IDTYPE vmid, IDTYPE tid, unsigned int exitcode)
{
    assert(vmid != cur_process.vmid);

    struct shim_thread * thread = __lookup_thread(tid);

    if (thread) {
        int ret = 0;
        //assert(thread->vmid == vmid && !thread->in_vm);
        thread->exit_code = -exitcode;
        ret = thread_exit(thread, false);
        put_thread(thread);
        return ret;
    }

    struct shim_simple_thread * sthread = __lookup_simple_thread(tid);

    if (!sthread) {
        sthread = get_new_simple_thread();
        sthread->vmid = vmid;
        sthread->tid = tid;
        add_simple_thread(sthread);
    }

    sthread->is_alive = 0;
    sthread->exit_code = -exitcode;
    DkEventSet(sthread->exit_event);
    put_simple_thread(sthread);
    return 0;
}
Example #2
0
static int msg_balance_migrate (struct shim_handle * hdl,
                                struct sysv_client * src)
{
    struct shim_msg_handle * msgq = &hdl->info.msg;
    int ret = 0;

    debug("trigger msg queue balancing, migrate to process %u\n", src->vmid);

    if ((ret = __store_msg_persist(msgq)) < 0)
        return 0;

    struct shim_ipc_info * info = discover_client(src->port, src->vmid);
    if (!info)
        goto failed;

    ipc_sysv_sublease_send(src->vmid, msgq->msqid,
                           qstrgetstr(&info->uri),
                           &msgq->lease);

    ret = ipc_sysv_msgmov_send(src->port, src->vmid, msgq->msqid, msgq->lease,
                               msgq->scores, MAX_SYSV_CLIENTS);
    if (ret < 0)
        goto failed_info;

    msgq->owner = info;

    for (struct msg_type * mtype = msgq->types ;
         mtype < &msgq->types[msgq->ntypes] ; mtype++) {
        struct msg_req * req = mtype->reqs;
        mtype->reqs = mtype->req_tail = NULL;
        while (req) {
            struct msg_req * next = req->next;

            ipc_sysv_movres_send(&req->dest, info->vmid, qstrgetstr(&info->uri),
                                 msgq->lease, msgq->msqid, SYSV_MSGQ);

            put_ipc_port(req->dest.port);
            __free_msg_qobj(msgq, req);
            req = next;
        }
    }

    ret = 0;
    DkEventSet(msgq->event);
    goto out;

failed_info:
    put_ipc_info(info);
failed:
    ret = __load_msg_persist(msgq, true);
out:
    return ret;
}
Example #3
0
int remove_child_thread (IDTYPE vmid, unsigned int exitcode)
{
    assert(vmid != cur_process.vmid);

    struct thread_info {
        IDTYPE vmid;
        unsigned int exitcode;
    };

    int child_sthread_exit (struct shim_simple_thread * thread, void * arg,
                            bool * unlocked)
    {
        struct thread_info * info = (struct thread_info *) arg;
        if (thread->vmid == info->vmid) {
            if (thread->is_alive) {
                thread->exit_code = -info->exitcode;
                thread->is_alive = false;
                DkEventSet(thread->exit_event);
            }
            return 1;
        }
        return 0;
    }

    int child_thread_exit (struct shim_thread * thread, void * arg,
                           bool * unlocked)
    {
        struct thread_info * info = (struct thread_info *) arg;
        if (thread->vmid == info->vmid) {
            if (thread->is_alive) {
                thread->exit_code = -info->exitcode;
                thread_exit(thread, false);
            }
            return 1;
        }
        return 0;
    }

    struct thread_info info = { .vmid = vmid, .exitcode = exitcode };
    int nkilled = 0, ret;

    if ((ret = walk_thread_list(&child_thread_exit, &info, false)) > 0)
        nkilled += ret;

    if ((ret = walk_simple_thread_list(&child_sthread_exit, &info, false)) > 0)
        nkilled += ret;

    if (!nkilled)
        debug("child port closed, no thread exited\n");

    return 0;
}
Example #4
0
int thread_1(void* args)
{
    DkThreadDelayExecution(1000);

    pal_printf("In Thread 1\n");

    while (count < 100)
        count++;

    DkEventSet(event1);
    DkThreadExit();

    return 0;
}
Example #5
0
int recover_msg_ownership (struct shim_msg_handle * msgq)
{
    struct shim_handle * hdl = MSG_TO_HANDLE(msgq);
    lock(hdl->lock);
    assert(!msgq->owned);
    int ret = __load_msg_persist(msgq, true);

    if (ret < 0) {
        ret = (ret == -ENOENT) ? -EIDRM : ret;
        goto out;
    }

    msgq->owned = true;
    DkEventSet(msgq->event);
out:
    unlock(hdl->lock);
    return 0;
}
Example #6
0
int add_sysv_msg (struct shim_msg_handle * msgq,
                  long type, int size, const void * data,
                  struct sysv_client * src)
{
    BEGIN_PROFILE_INTERVAL();

    struct shim_handle * hdl = MSG_TO_HANDLE(msgq);
    int ret = 0;
    lock(hdl->lock);

    if (msgq->deleted) {
        ret = -EIDRM;
        goto out_locked;
    }

    if (!msgq->owned) {
        unlock(hdl->lock);
        ret = ipc_sysv_msgsnd_send(src->port, src->vmid, msgq->msqid,
                                   type, data, size, src->seq);
        goto out;
    }

    struct msg_type * mtype = __add_msg_type(type, &msgq->types,
                                             &msgq->ntypes,
                                             &msgq->maxtypes);

    if ((ret = __store_msg_qobjs(msgq, mtype, size, data)) < 0)
        goto out_locked;

    if (msgq->owned)
        __balance_sysv_score(&msg_policy, hdl, msgq->scores, MAX_SYSV_CLIENTS,
                             src, MSG_SND_SCORE);

    DkEventSet(msgq->event);
    ret  = 0;
out_locked:
    unlock(hdl->lock);
out:
    SAVE_PROFILE_INTERVAL(add_sysv_msg);
    return ret;
}
Example #7
0
static int __store_msg_persist (struct shim_msg_handle * msgq)
{
    int ret = 0;

   if (msgq->deleted)
        goto out;

    debug("store msgq %d to persistent store\n", msgq->msqid);

    char fileuri[20];
    snprintf(fileuri, 20, "file:msgq.%08x", msgq->msqid);

    PAL_HANDLE file = DkStreamOpen(fileuri, PAL_ACCESS_RDWR, 0600,
                                   PAL_CREAT_TRY, 0);
    if (!file) {
        ret = -PAL_ERRNO;
        goto out;
    }

    int expected_size = sizeof(struct msg_handle_backup) +
                        sizeof(struct msg_backup) * msgq->nmsgs +
                        msgq->currentsize;

    if (DkStreamSetLength(file, expected_size) != expected_size)
        goto err_file;

    void * mem = (void *) DkStreamMap(file, NULL,
                                      PAL_PROT_READ|PAL_PROT_WRITE,
                                      0, ALIGN_UP(expected_size));
    if (!mem) {
        ret = -EFAULT;
        goto err_file;
    }

    struct msg_handle_backup * mback = mem;
    mem += sizeof(struct msg_handle_backup);

    mback->perm        = msgq->perm;
    mback->nmsgs       = msgq->nmsgs;
    mback->currentsize = msgq->currentsize;

    struct msg_type * mtype;
    for (mtype = msgq->types ; mtype < &msgq->types[msgq->ntypes] ;
         mtype++) {
        while (mtype->msgs) {
            struct msg_backup * msg = mem;
            mem += sizeof(struct msg_backup) + mtype->msgs->size;

            msg->type = mtype->type;
            msg->size = mtype->msgs->size;
            __load_msg_qobjs(msgq, mtype, mtype->msgs, msg->data);
        }

        mtype->msgs = mtype->msg_tail = NULL;
    }

    DkStreamUnmap(mem, ALIGN_UP(expected_size));

    if (msgq->owned)
        for (mtype = msgq->types ; mtype < &msgq->types[msgq->ntypes] ;
             mtype++) {
            struct msg_req * req = mtype->reqs;
            mtype->reqs = mtype->req_tail = NULL;
            while (req) {
                struct sysv_client * c = &req->dest;
                struct msg_req * next = req->next;

                __response_ipc_message(c->port, c->vmid, -EIDRM, c->seq);

                put_ipc_port(c->port);
                __free_msg_qobj(msgq, req);
                req = next;
            }
        }

    msgq->owned = false;
    ret = 0;
    goto out;

err_file:
    DkStreamDelete(file, 0);
    DkObjectClose(file);

out:
    // To wake up any receiver waiting on local message which must
    // now be requested from new owner.
    DkEventSet(msgq->event);
    return ret;
}
Example #8
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;
}