⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pth_lib.c

📁 Linux下的中文输入法
💻 C
📖 第 1 页 / 共 2 页
字号:
/***  GNU Pth - The GNU Portable Threads**  Copyright (c) 1999-2004 Ralf S. Engelschall <rse@engelschall.com>****  This file is part of GNU Pth, a non-preemptive thread scheduling**  library which can be found at http://www.gnu.org/software/pth/.****  This library is free software; you can redistribute it and/or**  modify it under the terms of the GNU Lesser General Public**  License as published by the Free Software Foundation; either**  version 2.1 of the License, or (at your option) any later version.****  This library is distributed in the hope that it will be useful,**  but WITHOUT ANY WARRANTY; without even the implied warranty of**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU**  Lesser General Public License for more details.****  You should have received a copy of the GNU Lesser General Public**  License along with this library; if not, write to the Free Software**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307**  USA, or contact Ralf S. Engelschall <rse@engelschall.com>.****  pth_lib.c: Pth main library code*/                             /* ``It took me fifteen years to discover                                  I had no talent for programming, but                                  I couldn't give it up because by that                                  time I was too famous.''                                            -- Unknown                */#include "pth_p.h"/* return the hexadecimal Pth library version number */long pth_version(void){    return PTH_VERSION;}/* implicit initialization support */intern int pth_initialized = FALSE;#if cpp#define pth_implicit_init() \    if (!pth_initialized) \        pth_init();#endif#ifdef PTH_EX/* exception handling callback functions */static ex_ctx_t *pth_ex_ctx(void){    return &(pth_current->ex_ctx);}static void pth_ex_terminate(ex_t *ex){    pth_exit(ex->ex_value);}#endif/* initialize the package */int pth_init(void){    pth_attr_t t_attr;    /* support for implicit initialization calls       and to prevent multiple explict initialization, too */    if (pth_initialized)        return pth_error(FALSE, EPERM);    else        pth_initialized = TRUE;    pth_debug1("pth_init: enter");    /* initialize syscall wrapping */    pth_syscall_init();    /* initialize the scheduler */    if (!pth_scheduler_init()) {        pth_shield { pth_syscall_kill(); }        return pth_error(FALSE, EAGAIN);    }#ifdef PTH_EX    /* optional support for exceptional handling */    __ex_ctx       = pth_ex_ctx;    __ex_terminate = pth_ex_terminate;#endif    /* spawn the scheduler thread */    t_attr = pth_attr_new();    pth_attr_set(t_attr, PTH_ATTR_PRIO,         PTH_PRIO_MAX);    pth_attr_set(t_attr, PTH_ATTR_NAME,         "**SCHEDULER**");    pth_attr_set(t_attr, PTH_ATTR_JOINABLE,     FALSE);    pth_attr_set(t_attr, PTH_ATTR_CANCEL_STATE, PTH_CANCEL_DISABLE);    pth_attr_set(t_attr, PTH_ATTR_STACK_SIZE,   64*1024);    pth_attr_set(t_attr, PTH_ATTR_STACK_ADDR,   NULL);    pth_sched = pth_spawn(t_attr, pth_scheduler, NULL);    if (pth_sched == NULL) {        pth_shield {            pth_attr_destroy(t_attr);            pth_scheduler_kill();            pth_syscall_kill();        }        return FALSE;    }    /* spawn a thread for the main program */    pth_attr_set(t_attr, PTH_ATTR_PRIO,         PTH_PRIO_STD);    pth_attr_set(t_attr, PTH_ATTR_NAME,         "main");    pth_attr_set(t_attr, PTH_ATTR_JOINABLE,     TRUE);    pth_attr_set(t_attr, PTH_ATTR_CANCEL_STATE, PTH_CANCEL_ENABLE|PTH_CANCEL_DEFERRED);    pth_attr_set(t_attr, PTH_ATTR_STACK_SIZE,   0 /* special */);    pth_attr_set(t_attr, PTH_ATTR_STACK_ADDR,   NULL);    pth_main = pth_spawn(t_attr, (void *(*)(void *))(-1), NULL);    if (pth_main == NULL) {        pth_shield {            pth_attr_destroy(t_attr);            pth_scheduler_kill();            pth_syscall_kill();        }        return FALSE;    }    pth_attr_destroy(t_attr);    /*     * The first time we've to manually switch into the scheduler to start     * threading. Because at this time the only non-scheduler thread is the     * "main thread" we will come back immediately. We've to also initialize     * the pth_current variable here to allow the pth_spawn_trampoline     * function to find the scheduler.     */    pth_current = pth_sched;    pth_mctx_switch(&pth_main->mctx, &pth_sched->mctx);    /* came back, so let's go home... */    pth_debug1("pth_init: leave");    return TRUE;}/* kill the package internals */int pth_kill(void){    if (pth_current != pth_main)        return pth_error(FALSE, EPERM);    pth_debug1("pth_kill: enter");    pth_thread_cleanup(pth_main);    pth_scheduler_kill();    pth_initialized = FALSE;    pth_tcb_free(pth_sched);    pth_tcb_free(pth_main);    pth_syscall_kill();#ifdef PTH_EX    __ex_ctx       = __ex_ctx_default;    __ex_terminate = __ex_terminate_default;#endif    pth_debug1("pth_kill: leave");    return TRUE;}/* scheduler control/query */long pth_ctrl(unsigned long query, ...){    long rc;    va_list ap;    rc = 0;    va_start(ap, query);    if (query & PTH_CTRL_GETTHREADS) {        if (query & PTH_CTRL_GETTHREADS_NEW)            rc += pth_pqueue_elements(&pth_NQ);        if (query & PTH_CTRL_GETTHREADS_READY)            rc += pth_pqueue_elements(&pth_RQ);        if (query & PTH_CTRL_GETTHREADS_RUNNING)            rc += 1; /* pth_current only */        if (query & PTH_CTRL_GETTHREADS_WAITING)            rc += pth_pqueue_elements(&pth_WQ);        if (query & PTH_CTRL_GETTHREADS_SUSPENDED)            rc += pth_pqueue_elements(&pth_SQ);        if (query & PTH_CTRL_GETTHREADS_DEAD)            rc += pth_pqueue_elements(&pth_DQ);    }    else if (query & PTH_CTRL_GETAVLOAD) {        float *pload = va_arg(ap, float *);        *pload = pth_loadval;    }    else if (query & PTH_CTRL_GETPRIO) {        pth_t t = va_arg(ap, pth_t);        rc = t->prio;    }    else if (query & PTH_CTRL_GETNAME) {        pth_t t = va_arg(ap, pth_t);        rc = (long)t->name;    }    else if (query & PTH_CTRL_DUMPSTATE) {        FILE *fp = va_arg(ap, FILE *);        pth_dumpstate(fp);    }    else if (query & PTH_CTRL_FAVOURNEW) {        int favournew = va_arg(ap, int);        pth_favournew = (favournew ? 1 : 0);    }    else        rc = -1;    va_end(ap);    if (rc == -1)        return pth_error(-1, EINVAL);    return rc;}/* create a new thread of execution by spawning a cooperative thread */static void pth_spawn_trampoline(void){    void *data;    /* just jump into the start routine */    data = (*pth_current->start_func)(pth_current->start_arg);    /* and do an implicit exit of the thread with the result value */    pth_exit(data);    /* NOTREACHED */    abort();}pth_t pth_spawn(pth_attr_t attr, void *(*func)(void *), void *arg){    pth_t t;    unsigned int stacksize;    void *stackaddr;    pth_time_t ts;    pth_debug1("pth_spawn: enter");    /* consistency */    if (func == NULL)        return pth_error((pth_t)NULL, EINVAL);    /* support the special case of main() */    if (func == (void *(*)(void *))(-1))        func = NULL;    /* allocate a new thread control block */    stacksize = (attr == PTH_ATTR_DEFAULT ? 64*1024 : attr->a_stacksize);    stackaddr = (attr == PTH_ATTR_DEFAULT ? NULL    : attr->a_stackaddr);    if ((t = pth_tcb_alloc(stacksize, stackaddr)) == NULL)        return pth_error((pth_t)NULL, errno);    /* configure remaining attributes */    if (attr != PTH_ATTR_DEFAULT) {        /* overtake fields from the attribute structure */        t->prio        = attr->a_prio;        t->joinable    = attr->a_joinable;        t->cancelstate = attr->a_cancelstate;        t->dispatches  = attr->a_dispatches;        pth_util_cpystrn(t->name, attr->a_name, PTH_TCB_NAMELEN);    }    else if (pth_current != NULL) {        /* overtake some fields from the parent thread */        t->prio        = pth_current->prio;        t->joinable    = pth_current->joinable;        t->cancelstate = pth_current->cancelstate;        t->dispatches  = 0;        pth_snprintf(t->name, PTH_TCB_NAMELEN, "%s.child@%d=0x%lx",                     pth_current->name, (unsigned int)time(NULL),                     (unsigned long)pth_current);    }    else {        /* defaults */        t->prio        = PTH_PRIO_STD;        t->joinable    = TRUE;        t->cancelstate = PTH_CANCEL_DEFAULT;        t->dispatches  = 0;        pth_snprintf(t->name, PTH_TCB_NAMELEN,                     "user/%x", (unsigned int)time(NULL));    }    /* initialize the time points and ranges */    pth_time_set(&ts, PTH_TIME_NOW);    pth_time_set(&t->spawned, &ts);    pth_time_set(&t->lastran, &ts);    pth_time_set(&t->running, PTH_TIME_ZERO);    /* initialize events */    t->events = NULL;    /* clear raised signals */    sigemptyset(&t->sigpending);    t->sigpendcnt = 0;    /* remember the start routine and arguments for our trampoline */    t->start_func = func;    t->start_arg  = arg;    /* initialize join argument */    t->join_arg = NULL;    /* initialize thread specific storage */    t->data_value = NULL;    t->data_count = 0;    /* initialize cancellation stuff */    t->cancelreq   = FALSE;    t->cleanups    = NULL;    /* initialize mutex stuff */    pth_ring_init(&t->mutexring);#ifdef PTH_EX    /* initialize exception handling context */    EX_CTX_INITIALIZE(&t->ex_ctx);#endif    /* initialize the machine context of this new thread */    if (t->stacksize > 0) { /* the "main thread" (indicated by == 0) is special! */        if (!pth_mctx_set(&t->mctx, pth_spawn_trampoline,                          t->stack, ((char *)t->stack+t->stacksize))) {            pth_shield { pth_tcb_free(t); }            return pth_error((pth_t)NULL, errno);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -