示例#1
0
文件: clone.cpp 项目: nehz/google-arc
// The entry point of new threads.
static void run_thread() {
    void **tls = (void **)__nacl_irt_tls_get();
    int (*fn)(void *) = (int (*)(void *))tls[TLS_SLOT_THREAD_FUNC];
    void *arg = tls[TLS_SLOT_THREAD_ARGS];
    tls[TLS_SLOT_THREAD_FUNC] = tls[TLS_SLOT_THREAD_ARGS] = NULL;
    __start_thread(fn, arg);
}
示例#2
0
int __clone (int (*fn) (void *), void *child_stack, int flags, void *arg)
{
    int rfork_flags = RFPROC;

    if (fn == NULL || child_stack == NULL)
    {
        __set_errno (EINVAL);
        return -1;
    }

    /* This implementation of clone() does not support all Linux flags.  */
    if (flags & ~(CSIGNAL | CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND
                  | CLONE_VFORK | CLONE_SYSVSEM))
    {
        __set_errno (EINVAL);
        return -1;
    }

    if ((flags & CSIGNAL) != SIGCHLD)
    {
        if (__kernel_getosreldate() >= 802510)
            /* we slightly cheat here, */
            /* the 9.x snapshot prior to r223966 does not support it too */
        {
            if ((flags & CSIGNAL) & ~RFTSIGMASK)
            {
                __set_errno (EINVAL);
                return -1;
            }
            rfork_flags |= (RFTSIGZMB | RFTSIGFLAGS(flags & CSIGNAL));
        }
        else
        {
            if ((flags & CSIGNAL) & ~RFTHPNMASK)
            {
                __set_errno (EINVAL);
                return -1;
            }
            if ((flags & CSIGNAL) == 0)
                rfork_flags |= (RFLINUXTHPN | ((SIGCHLD) <<  RFTHPNSHIFT));
            else
                rfork_flags |= (RFLINUXTHPN | ((flags & CSIGNAL) <<  RFTHPNSHIFT));
        }
    }
    if (flags & CLONE_VM)
        rfork_flags |= RFMEM;

    if (flags & CLONE_FS)
        /* Sharing the filesystem related info (umask, cwd, root dir)
           is not supported by rfork.  Ignore this; let's hope programs
           will set their umask and cwd before spawning threads.  */
        ;

    if (flags & CLONE_SYSVSEM)
        /* Ignore this; it has been introduced into linuxthreads in post 2.4 glibc */
        ;

    if (!(flags & CLONE_FILES))
        rfork_flags |= RFFDG;

    if (flags & CLONE_SIGHAND)
    {
        rfork_flags |= RFSIGSHARE;
        /* Also set the undocumented flag RFTHREAD.  It has the effect that when
        the thread leader exits, all threads belonging to it are killed.  */
        rfork_flags |= RFTHREAD;
    }

    if (flags & CLONE_VFORK)
        rfork_flags |= RFPPWAIT;

    return __start_thread (rfork_flags, child_stack, fn, arg);
}