Example #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);
    }
Example #2
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);
}