void _procstart(Proc *p, void (*fn)(Proc*)) { void **a; uchar *stk; int pid; dofreestacks(); a = malloc(3*sizeof a[0]); if(a == nil) sysfatal("_procstart malloc: %r"); stk = malloc(65536); if(stk == nil) sysfatal("_procstart malloc stack: %r"); a[0] = fn; a[1] = p; a[2] = stk; pid = rfork_thread(RFPROC|RFMEM|RFNOWAIT, stk+65536-64, startprocfn, a); if(pid < 0){ fprint(2, "_procstart rfork_thread: %r\n"); abort(); } }
ngx_err_t ngx_create_thread(ngx_tid_t *tid, ngx_thread_value_t (*func)(void *arg), void *arg, ngx_log_t *log) { ngx_pid_t id; ngx_err_t err; char *stack, *stack_top; if (nthreads >= max_threads) { ngx_log_error(NGX_LOG_CRIT, log, 0, "no more than %ui threads can be created", max_threads); return NGX_ERROR; } last_stack -= ngx_thread_stack_size; stack = mmap(last_stack, usable_stack_size, PROT_READ|PROT_WRITE, MAP_STACK, -1, 0); if (stack == MAP_FAILED) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "mmap(%p:%uz, MAP_STACK) thread stack failed", last_stack, usable_stack_size); return NGX_ERROR; } if (stack != last_stack) { ngx_log_error(NGX_LOG_ALERT, log, 0, "stack %p address was changed to %p", last_stack, stack); return NGX_ERROR; } stack_top = stack + usable_stack_size; ngx_log_debug2(NGX_LOG_DEBUG_CORE, log, 0, "thread stack: %p-%p", stack, stack_top); ngx_set_errno(0); id = rfork_thread(RFPROC|RFTHREAD|RFMEM, stack_top, (ngx_rfork_thread_func_pt) func, arg); err = ngx_errno; if (id == -1) { ngx_log_error(NGX_LOG_ALERT, log, err, "rfork() failed"); } else { *tid = id; nthreads = (ngx_freebsd_kern_usrstack - stack_top) / ngx_thread_stack_size; tids[nthreads] = id; ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, "rfork()ed thread: %P", id); } return err; }
void kproc(char *name, void (*func)(void*), void *arg, int flags) { Proc *p; Pgrp *pg; Fgrp *fg; Egrp *eg; int pid; void *tos; p = newproc(); if(flags & KPDUPPG) { pg = up->env->pgrp; incref(&pg->r); p->env->pgrp = pg; } if(flags & KPDUPFDG) { fg = up->env->fgrp; incref(&fg->r); p->env->fgrp = fg; } if(flags & KPDUPENVG) { eg = up->env->egrp; incref(&eg->r); p->env->egrp = eg; } p->env->uid = up->env->uid; p->env->gid = up->env->gid; kstrdup(&p->env->user, up->env->user); strcpy(p->text, name); p->func = func; p->arg = arg; lock(&procs.l); if(procs.tail != nil) { p->prev = procs.tail; procs.tail->next = p; } else { procs.head = p; p->prev = nil; } procs.tail = p; unlock(&procs.l); if(flags & KPX11){ p->kstack = nil; /* never freed; also up not defined */ tos = (char*)mallocz(X11STACK, 0) + X11STACK - sizeof(void*); }else p->kstack = stackalloc(p, &tos); pid = rfork_thread(RFPROC|RFMEM|RFNOWAIT, tos, tramp, p); if(pid < 0) panic("rfork"); }
void dispatch_to_scheduler(th_t* thread) { int pri, currentPri; th_queue_t* foundQueueTh; int flag = 1; if(num_Thread ==0) { init_scheduler(); } thread->tid = num_Thread++; thread->mctx.status = TH_WAITING; th_queue_insert(ready_queueHead, pri, thread); printf("*** %d thread insert ***\n", num_Thread); //Choose kernel thread to be added if(num_kernel_thread < maxKernelThreads) { //Create a new kernel thread //Create scheduler stack for new kernel thread th_t *scheduleThread; int pid; if((scheduleThread = thread_alloc()) == NULL) abort(); scheduleThread->mctx.status = TH_SCHED; pid = scheduleThread->tid = getpid()+1; scheduleThread->current_tid = 0; num_kernel_thread++; if((scheduleThread->mctx.stackAddr = stack_alloc()) == NULL) abort(); th_queue_insert(sched_queueHead, PRIORITY_SCHEDULER, scheduleThread); rfork_thread(RFPROC | RFNOTEG|RFMEM, scheduleThread->mctx.stackAddr, (int(*)(void*))start_kernel_thread, pid); } return; /* if(pri > currentPri) { foundQueueTh->thread->mctx.status = TH_WAITING; currentTid = thread->tid; thread->mctx.status = TH_RUNNING; enable_timer(); mctx_switch(&(foundQueueTh->thread->mctx), &(thread->mctx)); } else switch_to_scheduler(); */ }
void runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void)) { int32 flags; int32 ret; flags = RFPROC | RFTHREAD | RFMEM | RFNOWAIT; if (0) { runtime·printf( "newosproc stk=%p m=%p g=%p fn=%p id=%d/%d ostk=%p\n", stk, m, g, fn, m->id, m->tls[0], &m); } m->tls[0] = m->id; // so 386 asm can find it if((ret = runtime·rfork_thread(flags, stk, m, g, fn)) < 0) { runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount() - 1, -ret); if (ret == -ENOTSUP) runtime·printf("runtime: is kern.rthreads disabled?\n"); runtime·throw("runtime.newosproc"); } }
int pthread_create(pthread_t *threadp, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) { pthread_t thread; pid_t tid; int rc = 0; if (!_threads_ready) if ((rc = _rthread_init())) return (rc); thread = malloc(sizeof(*thread)); if (!thread) return (errno); memset(thread, 0, sizeof(*thread)); thread->donesem.lock = _SPINLOCK_UNLOCKED; thread->flags_lock = _SPINLOCK_UNLOCKED; thread->fn = start_routine; thread->arg = arg; if (attr) thread->attr = *(*attr); else { thread->attr.stack_size = RTHREAD_STACK_SIZE_DEF; thread->attr.guard_size = sysconf(_SC_PAGESIZE); thread->attr.stack_size -= thread->attr.guard_size; } if (thread->attr.detach_state == PTHREAD_CREATE_DETACHED) thread->flags |= THREAD_DETACHED; _spinlock(&_thread_lock); thread->stack = _rthread_alloc_stack(thread); if (!thread->stack) { rc = errno; goto fail1; } LIST_INSERT_HEAD(&_thread_list, thread, threads); tid = rfork_thread(RFPROC | RFTHREAD | RFMEM | RFNOWAIT, thread->stack->sp, _rthread_start, thread); if (tid == -1) { rc = errno; goto fail2; } /* new thread will appear _rthread_start */ thread->tid = tid; thread->flags |= THREAD_CANCEL_ENABLE|THREAD_CANCEL_DEFERRED; *threadp = thread; /* * Since _rthread_start() aquires the thread lock and due to the way * signal delivery is implemented, this is not a race. */ if (thread->attr.create_suspended) kill(thread->tid, SIGSTOP); _spinunlock(&_thread_lock); return (0); fail2: _rthread_free_stack(thread->stack); LIST_REMOVE(thread, threads); fail1: _spinunlock(&_thread_lock); _rthread_free(thread); return (rc); }