Ejemplo n.º 1
0
/*
 * msgget system call.
 */
static int
msgget(key_t key, int msgflg)
{
    kmsqid_t	*qp;
    kmutex_t	*lock;
    int		id, error;
    int		ii;
    proc_t		*pp = curproc;

top:
    if (error = ipc_get(msq_svc, key, msgflg, (kipc_perm_t **)&qp, &lock))
        return (set_errno(error));

    if (IPC_FREE(&qp->msg_perm)) {
        mutex_exit(lock);
        mutex_exit(&pp->p_lock);

        list_create(&qp->msg_list, sizeof (struct msg),
                    offsetof(struct msg, msg_node));
        qp->msg_qnum = 0;
        qp->msg_lspid = qp->msg_lrpid = 0;
        qp->msg_stime = qp->msg_rtime = 0;
        qp->msg_ctime = gethrestime_sec();
        qp->msg_ngt_cnt = 0;
        qp->msg_neg_copy = 0;
        for (ii = 0; ii <= MSG_MAX_QNUM; ii++) {
            list_create(&qp->msg_wait_snd[ii],
                        sizeof (msgq_wakeup_t),
                        offsetof(msgq_wakeup_t, msgw_list));
            list_create(&qp->msg_wait_snd_ngt[ii],
                        sizeof (msgq_wakeup_t),
                        offsetof(msgq_wakeup_t, msgw_list));
        }
        /*
         * The proper initialization of msg_lowest_type is to the
         * highest possible value.  By doing this we guarantee that
         * when the first send happens, the lowest type will be set
         * properly.
         */
        qp->msg_lowest_type = -1;
        list_create(&qp->msg_cpy_block,
                    sizeof (msgq_wakeup_t),
                    offsetof(msgq_wakeup_t, msgw_list));
        qp->msg_fnd_sndr = &msg_fnd_sndr[0];
        qp->msg_fnd_rdr = &msg_fnd_rdr[0];
        qp->msg_rcv_cnt = 0;
        qp->msg_snd_cnt = 0;

        if (error = ipc_commit_begin(msq_svc, key, msgflg,
                                     (kipc_perm_t *)qp)) {
            if (error == EAGAIN)
                goto top;
            return (set_errno(error));
        }
        qp->msg_qbytes = rctl_enforced_value(rc_process_msgmnb,
                                             pp->p_rctls, pp);
        qp->msg_qmax = rctl_enforced_value(rc_process_msgtql,
                                           pp->p_rctls, pp);
        lock = ipc_commit_end(msq_svc, &qp->msg_perm);
    }
Ejemplo n.º 2
0
/*
 * semexit - Called by exit() to clean up on process exit.
 */
void
semexit(proc_t *pp)
{
    avl_tree_t	*tree;
    struct sem_undo	*undo;
    void		*cookie = NULL;

    mutex_enter(&pp->p_lock);
    tree = pp->p_semacct;
    pp->p_semacct = NULL;
    mutex_exit(&pp->p_lock);

    while (undo = avl_destroy_nodes(tree, &cookie)) {
        ksemid_t *sp = undo->un_sp;
        size_t size = SEM_UNDOSZ(sp->sem_nsems);
        int i;

        (void) ipc_lock(sem_svc, sp->sem_perm.ipc_id);
        if (!IPC_FREE(&sp->sem_perm)) {
            for (i = 0; i < sp->sem_nsems; i++) {
                int adj = undo->un_aoe[i];
                if (adj) {
                    struct sem *semp = &sp->sem_base[i];
                    int v = (int)semp->semval + adj;

                    if (v < 0 || v > USHRT_MAX)
                        continue;
                    semp->semval = (ushort_t)v;
                    if (v == 0 && semp->semzcnt)
                        cv_broadcast(&semp->semzcnt_cv);
                    if (adj > 0 && semp->semncnt)
                        cv_broadcast(&semp->semncnt_cv);
                }
            }
            list_remove(&sp->sem_undos, undo);
        }
        ipc_rele(sem_svc, (kipc_perm_t *)sp);
        kmem_free(undo, size);
    }

    avl_destroy(tree);
    kmem_free(tree, sizeof (avl_tree_t));
}
Ejemplo n.º 3
0
/*
 * semget - Semget system call.
 */
static int
semget(key_t key, int nsems, int semflg)
{
    ksemid_t	*sp;
    kmutex_t	*lock;
    int		id, error;
    proc_t		*pp = curproc;

top:
    if (error = ipc_get(sem_svc, key, semflg, (kipc_perm_t **)&sp, &lock))
        return (set_errno(error));

    if (!IPC_FREE(&sp->sem_perm)) {
        /*
         * A semaphore with the requested key exists.
         */
        if (!((nsems >= 0) && (nsems <= sp->sem_nsems))) {
            mutex_exit(lock);
            return (set_errno(EINVAL));
        }
    } else {
        /*
         * This is a new semaphore set.  Finish initialization.
         */
        if (nsems <= 0 || (rctl_test(rc_process_semmsl, pp->p_rctls, pp,
                                     nsems, RCA_SAFE) & RCT_DENY)) {
            mutex_exit(lock);
            mutex_exit(&pp->p_lock);
            ipc_cleanup(sem_svc, (kipc_perm_t *)sp);
            return (set_errno(EINVAL));
        }
        mutex_exit(lock);
        mutex_exit(&pp->p_lock);

        /*
         * We round the allocation up to coherency granularity
         * so that multiple semaphore allocations won't result
         * in the false sharing of their sem structures.
         */
        sp->sem_base =
            kmem_zalloc(P2ROUNDUP(nsems * sizeof (struct sem), 64),
                        KM_SLEEP);
        sp->sem_binary = (nsems == 1);
        sp->sem_nsems = (ushort_t)nsems;
        sp->sem_ctime = gethrestime_sec();
        sp->sem_otime = 0;
        list_create(&sp->sem_undos, sizeof (struct sem_undo),
                    offsetof(struct sem_undo, un_list));

        if (error = ipc_commit_begin(sem_svc, key, semflg,
                                     (kipc_perm_t *)sp)) {
            if (error == EAGAIN)
                goto top;
            return (set_errno(error));
        }
        sp->sem_maxops =
            rctl_enforced_value(rc_process_semopm, pp->p_rctls, pp);
        if (rctl_test(rc_process_semmsl, pp->p_rctls, pp, nsems,
                      RCA_SAFE) & RCT_DENY) {
            ipc_cleanup(sem_svc, (kipc_perm_t *)sp);
            return (set_errno(EINVAL));
        }
        lock = ipc_commit_end(sem_svc, &sp->sem_perm);
    }
    if (audit_active)
        audit_ipcget(AT_IPC_SEM, (void *)sp);
    id = sp->sem_perm.ipc_id;
    mutex_exit(lock);
    return (id);
}