[BACK]Return to callcontext.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libpuffs

Annotation of src/lib/libpuffs/callcontext.c, Revision 1.7.4.2

1.7.4.2 ! matt        1: /*     $NetBSD$        */
1.1       pooka       2:
                      3: /*
                      4:  * Copyright (c) 2006 Antti Kantee.  All Rights Reserved.
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
                     14:  *
                     15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
                     16:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     18:  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     19:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     20:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     21:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     22:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     23:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     24:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     25:  * SUCH DAMAGE.
                     26:  */
                     27:
                     28: #include <sys/cdefs.h>
                     29: #if !defined(lint)
1.7.4.2 ! matt       30: __RCSID("$NetBSD$");
1.1       pooka      31: #endif /* !lint */
                     32:
                     33: #include <sys/types.h>
1.7.4.1   matt       34: #include <sys/mman.h>
1.1       pooka      35:
                     36: #include <assert.h>
1.7.4.1   matt       37: #include <errno.h>
                     38: #ifdef PUFFS_WITH_THREADS
                     39: #include <pthread.h>
                     40: #endif
1.1       pooka      41: #include <puffs.h>
                     42: #include <stdio.h>
                     43: #include <stdlib.h>
                     44: #include <string.h>
1.3       pooka      45: #include <ucontext.h>
1.7.4.2 ! matt       46: #include <unistd.h>
1.1       pooka      47:
                     48: #include "puffs_priv.h"
                     49:
                     50: /*
                     51:  * user stuff
                     52:  */
                     53:
                     54: void
                     55: puffs_cc_yield(struct puffs_cc *pcc)
                     56: {
                     57:
1.5       pooka      58:        assert(pcc->pcc_flags & PCC_REALCC);
1.6       pooka      59:        pcc->pcc_flags &= ~PCC_BORROWED;
1.1       pooka      60:
                     61:        /* romanes eunt domus */
                     62:        swapcontext(&pcc->pcc_uc, &pcc->pcc_uc_ret);
                     63: }
                     64:
                     65: void
                     66: puffs_cc_continue(struct puffs_cc *pcc)
                     67: {
                     68:
1.5       pooka      69:        assert(pcc->pcc_flags & PCC_REALCC);
                     70:
1.1       pooka      71:        /* ramble on */
                     72:        swapcontext(&pcc->pcc_uc_ret, &pcc->pcc_uc);
                     73: }
                     74:
1.6       pooka      75: /*
                     76:  * "Borrows" pcc, *NOT* called from pcc owner.  Acts like continue.
                     77:  * So the idea is to use this, give something the context back to
                     78:  * run to completion and then jump back to where ever this was called
                     79:  * from after the op dispatching is complete (or if the pcc decides to
                     80:  * yield again).
                     81:  */
                     82: void
                     83: puffs_goto(struct puffs_cc *loanpcc)
                     84: {
                     85:
                     86:        assert(loanpcc->pcc_flags & PCC_REALCC);
                     87:        loanpcc->pcc_flags |= PCC_BORROWED;
                     88:
                     89:        swapcontext(&loanpcc->pcc_uc_ret, &loanpcc->pcc_uc);
                     90: }
                     91:
1.7.4.1   matt       92: void
                     93: puffs_cc_schedule(struct puffs_cc *pcc)
                     94: {
                     95:        struct puffs_usermount *pu = pcc->pcc_pu;
                     96:
                     97:        assert(pu->pu_state & PU_INLOOP);
                     98:        TAILQ_INSERT_TAIL(&pu->pu_sched, pcc, entries);
                     99: }
                    100:
                    101: int
                    102: puffs_cc_getcaller(struct puffs_cc *pcc, pid_t *pid, lwpid_t *lid)
                    103: {
                    104:
                    105:        if ((pcc->pcc_flags & PCC_HASCALLER) == 0) {
                    106:                errno = ESRCH;
                    107:                return -1;
                    108:        }
                    109:
                    110:        if (pid)
                    111:                *pid = pcc->pcc_pid;
                    112:        if (lid)
                    113:                *lid = pcc->pcc_lid;
                    114:        return 0;
                    115: }
                    116:
                    117: #ifdef PUFFS_WITH_THREADS
                    118: int pthread__stackid_setup(void *, size_t, pthread_t *);
                    119: #endif
                    120:
1.7.4.2 ! matt      121: /* for fakecc-users, need only one */
        !           122: static struct puffs_cc fakecc;
        !           123:
1.7.4.1   matt      124: int
1.7.4.2 ! matt      125: puffs_cc_create(struct puffs_usermount *pu, struct puffs_framebuf *pb,
1.7.4.1   matt      126:        int type, struct puffs_cc **pccp)
1.1       pooka     127: {
                    128:        struct puffs_cc *volatile pcc;
1.7.4.1   matt      129:        size_t stacksize = 1<<pu->pu_cc_stackshift;
1.7.4.2 ! matt      130:        long psize = sysconf(_SC_PAGESIZE);
1.1       pooka     131:        stack_t *st;
1.7.4.2 ! matt      132:        void *volatile sp;
1.7.4.1   matt      133:
                    134: #ifdef PUFFS_WITH_THREADS
                    135:        extern size_t pthread__stacksize;
                    136:        stacksize = pthread__stacksize;
                    137: #endif
1.1       pooka     138:
1.7.4.2 ! matt      139:        /*
        !           140:         * There are two paths and in the long run we don't have time to
        !           141:         * change the one we're on.  For non-real cc's, we just simply use
        !           142:         * a static copy.  For the other cases, we mmap the stack and
        !           143:         * manually reserve a bit from the top for the data structure
        !           144:         * (or, well, the bottom).
        !           145:         *
        !           146:         * XXX: threaded mode doesn't work very well now.  Not that it's
        !           147:         * supported anyhow.
        !           148:         */
        !           149:        if (type == PCC_FAKECC) {
        !           150:                pcc = &fakecc;
        !           151:                sp = NULL;
        !           152:        } else {
        !           153:                sp = mmap(NULL, stacksize, PROT_READ|PROT_WRITE,
        !           154:                    MAP_ANON|MAP_PRIVATE|MAP_ALIGNED(pu->pu_cc_stackshift),
        !           155:                    -1, 0);
        !           156:                if (sp == MAP_FAILED)
        !           157:                        return -1;
        !           158:
        !           159:                pcc = sp;
        !           160:                sp = (uint8_t *)sp + psize;
        !           161:        }
        !           162:
1.1       pooka     163:        memset(pcc, 0, sizeof(struct puffs_cc));
                    164:        pcc->pcc_pu = pu;
1.7.4.2 ! matt      165:        pcc->pcc_pb = pb;
1.7.4.1   matt      166:        pcc->pcc_flags = type;
1.7.4.2 ! matt      167:
        !           168:        /* Not a real cc?  Don't need to init more */
1.7.4.1   matt      169:        if (pcc->pcc_flags != PCC_REALCC)
                    170:                goto out;
1.1       pooka     171:
                    172:        /* initialize both ucontext's */
                    173:        if (getcontext(&pcc->pcc_uc) == -1) {
1.7.4.2 ! matt      174:                munmap(pcc, stacksize);
1.7.4.1   matt      175:                return -1;
1.1       pooka     176:        }
                    177:        if (getcontext(&pcc->pcc_uc_ret) == -1) {
1.7.4.2 ! matt      178:                munmap(pcc, stacksize);
1.7.4.1   matt      179:                return -1;
1.1       pooka     180:        }
                    181:        /* return here.  it won't actually be "here" due to swapcontext() */
                    182:        pcc->pcc_uc.uc_link = &pcc->pcc_uc_ret;
                    183:
                    184:        /* allocate stack for execution */
                    185:        st = &pcc->pcc_uc.uc_stack;
1.7.4.2 ! matt      186:
1.7.4.1   matt      187:        st->ss_sp = pcc->pcc_stack = sp;
1.7.4.2 ! matt      188:        st->ss_size = stacksize - psize;
1.1       pooka     189:        st->ss_flags = 0;
                    190:
1.7.4.1   matt      191: #ifdef PUFFS_WITH_THREADS
                    192:        {
                    193:        pthread_t pt;
                    194:        extern int __isthreaded;
                    195:        if (__isthreaded)
1.7.4.2 ! matt      196:                pthread__stackid_setup(sp, stacksize /* XXXb0rked */, &pt);
1.7.4.1   matt      197:        }
                    198: #endif
                    199:
1.1       pooka     200:        /*
                    201:         * Give us an initial context to jump to.
                    202:         *
                    203:         * XXX: Our manual page says that portable code shouldn't rely on
                    204:         * being able to pass pointers through makecontext().  kjk says
                    205:         * that NetBSD code doesn't need to worry about this.  uwe says
                    206:         * it would be like putting a "keep away from children" sign on a
                    207:         * box of toys.  I didn't ask what simon says; he's probably busy
                    208:         * "fixing" typos in comments.
                    209:         */
                    210:        makecontext(&pcc->pcc_uc, (void *)puffs_calldispatcher,
                    211:            1, (uintptr_t)pcc);
                    212:
1.7.4.1   matt      213:  out:
                    214:        *pccp = pcc;
                    215:        return 0;
                    216: }
                    217:
                    218: void
                    219: puffs_cc_setcaller(struct puffs_cc *pcc, pid_t pid, lwpid_t lid)
                    220: {
                    221:
                    222:        pcc->pcc_pid = pid;
                    223:        pcc->pcc_lid = lid;
                    224:        pcc->pcc_flags |= PCC_HASCALLER;
1.1       pooka     225: }
                    226:
                    227: void
                    228: puffs_cc_destroy(struct puffs_cc *pcc)
                    229: {
1.7.4.1   matt      230:        struct puffs_usermount *pu = pcc->pcc_pu;
                    231:        size_t stacksize = 1<<pu->pu_cc_stackshift;
1.1       pooka     232:
1.7.4.1   matt      233: #ifdef PUFFS_WITH_THREADS
                    234:        extern size_t pthread__stacksize;
                    235:        stacksize = pthread__stacksize;
                    236: #endif
                    237:
1.7.4.2 ! matt      238:        if ((pcc->pcc_flags & PCC_FAKECC) == 0)
        !           239:                munmap(pcc, stacksize);
        !           240: }
        !           241:
        !           242: struct puffs_cc *
        !           243: puffs_cc_getcc(struct puffs_usermount *pu)
        !           244: {
        !           245:        extern int puffs_fakecc, puffs_usethreads;
        !           246:        size_t stacksize = 1<<pu->pu_cc_stackshift;
        !           247:        uintptr_t bottom;
        !           248:
        !           249:        if (puffs_fakecc)
        !           250:                return &fakecc;
        !           251: #ifndef PUFFS_WITH_THREADS
        !           252:        if (puffs_usethreads)
        !           253:                return &fakecc;
        !           254: #endif
        !           255:
        !           256:        bottom = ((uintptr_t)&bottom) & ~(stacksize-1);
        !           257:        return (struct puffs_cc *)bottom;
1.1       pooka     258: }

CVSweb <webmaster@jp.NetBSD.org>